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

603 Commits
v3.2 ... v4.5

Author SHA1 Message Date
Matias Fontanini
142b6f62cb Add CHANGES for v4.5 2023-08-20 09:47:12 -07:00
James R T
dfd2701ee4 Add vxlan.h to CMakeLists.txt (#508) 2023-06-08 12:39:15 -07:00
James R T
850bb9b642 Add VXLAN support (#501)
This patch adds a new PDU class to support VXLAN. Several VXLAN-related
tests have also been added.

Signed-off-by: James Raphael Tiovalen <jamestiotio@gmail.com>
2023-05-03 18:21:59 -07:00
Ed Catmur
b7e61f4c76 Qualify calls to std::move (clang 15) (#488)
Co-authored-by: Ed Catmur <edward.catmur@mavensecurities.com>
2023-04-30 10:13:56 -07:00
Ed Catmur
e2a14d8898 Remove use of deprecated std::iterator (#481)
Co-authored-by: Ed Catmur <edward.catmur@mavensecurities.com>
2023-04-30 10:11:57 -07:00
Tobias Specht
ba0c820852 Add FileSniffer constructor with FILE pointer as pcap source (#499) 2023-04-30 09:44:49 -07:00
James R T
df509e7e36 Ignore IPv6 packets with payload after one with no Next Header (#500)
IPv6 data packets with payload or padded bytes received after one with
no Next Header were not being parsed correctly, resulting in NULL PDU.

This commit fixes the IPv6 parser to be compliant with RFC 2460 Section
4.7 by adding a check in the IPv6 constructor to ignore the subsequent
packets if an IPv6 packet contains no Next Header.

Signed-off-by: James Raphael Tiovalen <jamestiotio@gmail.com>
2023-04-20 21:22:01 -07:00
Ed Catmur
fa87e1b6f6 Add missing include (#497)
`<algorithm>` is needed for std::fill (error in clang-16)
2023-01-31 10:02:50 -08:00
Vasiliy Glazov
812be7966d Fix build with GCC13 (#496)
Due to changes in GCC13 need fix include.
2023-01-24 08:29:36 -08:00
Bill Willcox
f89cc9f076 Validate high order two bits of first dns label octet (#494) 2023-01-03 09:10:41 -08:00
Matias Fontanini
638bf9b34b Trigger actions on pull requests (#495) 2023-01-03 09:04:03 -08:00
mbcdev
eb997f5438 fix incorrect IP address range calculation when using /0 prefix (#484) (#486)
According to the C/C++ Standard, for shift operations, the behavior is undefined if the right operand is equal to the width of the promoted left operand.
On a 64-bit Windows machine, this causes IP addresses 0.0.0.0 and 255.255.255.255 to have the same internal representation, leading to various issues when using a /0 prefix.
2022-08-30 08:27:42 -07:00
Scott K Logan
18cbab4fc7 Use CMAKE_INSTALL_LIBDIR in CONF_CMAKE_INSTALL_DIR (#472)
On some platforms (like RedHat ones), CMAKE_INSTALL_LIBDIR is set to
`lib64` instead of `lib`. The CMake files should also be installed to
`lib64`, but because CONF_CMAKE_INSTALL_DIR is set unconditionally to
use `lib`, the proper path can't be configured.

This change makes CONF_CMAKE_INSTALL_DIR use the configured
CMAKE_INSTALL_LIBDIR value, which defaults to `lib`.
2022-05-14 11:09:58 -07:00
Scott K Logan
7cd2b2c396 Fall back to system GTest if available (#473)
Using a submodule to download and build GTest is a great approach for
most circumstances, but some may prefer to use the system-provided GTest
if it is available.

This change adds a fallback to using the system's GTest if the submodule
is absent.
2022-05-14 11:07:39 -07:00
Lattice 0
2601493752 android workaround (#471) 2022-04-24 08:44:52 -07:00
Bill Willcox
7204fbd688 dns: parser reads into garbage on misreported packet size (#468)
Co-authored-by: Bill Willcox <billwcorp@gmail.com>
2022-02-26 14:29:22 -08:00
Bill Willcox
c302e659d7 dns: bad label size interpreted as decompression pointer (#466)
Co-authored-by: Bill Willcox <billwcorp@gmail.com>
2022-02-20 15:18:00 -08:00
Matias Fontanini
54e4e4b0f4 Add github actions for ubuntu (#467) 2022-02-19 17:01:37 -08:00
Matias Fontanini
6a17e59032 Bump version to 4.5 2022-02-17 06:55:48 -08:00
Matias Fontanini
e3aedc56ed Update CHANGES.md for v4.4 2022-02-17 06:55:02 -08:00
Matias Fontanini
3b006c15db Merge pull request #458 from demiquartz/fix-macro-name-conflict
Fix conflict between variable and macro name
2022-01-30 09:04:08 -08:00
Takaaki Sato
177d0b4621 Fix conflict between variable and macro name 2021-10-31 12:03:24 +09:00
Matias Fontanini
24ac038c30 Merge pull request #448 from FlukeCorp/link-local-uses-interface
IPv6 use interface when sending to link-local dest
2021-07-22 19:23:51 -07:00
Prosper Van
a619e4ff98 IPv6 use interface when sending to link-local dest 2021-07-22 11:18:48 -07:00
Matias Fontanini
14bb185d7a Merge pull request #444 from gaya-cohen/decompression-bug-fix
Fix DNS decompression bug and add descriptive exceptions
2021-06-09 08:30:50 -07:00
Gaya Cohen
137b56d5a7 fix exception inheritance and change exception names in DNS code 2021-06-09 15:57:04 +03:00
Gaya Cohen
ed2b3c12d5 Make new exceptions inherit from malformed_packet and change exception names 2021-06-09 11:46:07 +03:00
Gaya Cohen
1650b60234 change counter variable type and add exception description comment 2021-05-24 17:04:11 +03:00
Gaya Cohen
c20c82bcb5 Fix pointer loop bug and add descriptive exceptions 2021-05-24 15:12:23 +03:00
Matias Fontanini
5858132261 Merge pull request #439 from adriancostin6/dns-comment-fix
Fix getter being labeled as setter in dns header file comments
2021-05-14 08:59:54 -07:00
Adrian Costin
16f5795243 Fix getter being labeled as setter in dns header file comments 2021-04-24 01:04:24 +03:00
Matias Fontanini
e90e377b73 Merge pull request #437 from ceerRep/master
Fix wrong address endian
2021-03-28 09:08:30 -07:00
ceerrep
222611b377 Fix wrong address endian
Host endian has been implicitly converted to big endian in "IPv4Address::operator uint32_t()"
2021-03-24 18:41:59 +08:00
Matias Fontanini
b447c664e1 Merge pull request #433 from visuve/master
Close socket when setsockopt fails
2021-03-06 11:34:51 -08:00
visuve
468159e6d2 Close socket when setsockopt fails
- Prevent resource leak
2021-03-04 23:55:29 +02:00
Matias Fontanini
cd40b232e7 Merge pull request #427 from nhutchinson-te/bsd-routing-table
Fix infinite loop when querying BSD routing table
2021-01-04 18:44:06 -08:00
Nick Hutchinson
1166094a2f Fix infinite loop when querying BSD routing table
Fix `query_route_table()` returning a buffer padded with extra '\0'
bytes because it ignored the buffer size returned by `sysctl()`.

This caused `route_entries()` / `route6_entries()` to fall into an
infinite loop, forever trying to parse a 0-length routing entry.
2021-01-04 12:02:03 +00:00
Matias Fontanini
b3d874d6a8 Merge pull request #426 from theDogOfPavlov/master
Added RFC8335 Extended echo types to headers
2020-12-29 08:52:34 -08:00
Martin O'Neal
553b1fb255 Added RFC8335 Extended Echo types 2020-12-29 08:36:30 +00:00
Martin O'Neal
94939dd0fa Added RFC8355 ICMP Extended Echo support
Added RFC8355 ICMP Extended Echo request/reply to Flags (no other changes made)
2020-12-29 08:32:29 +00:00
Matias Fontanini
0774a8dcad Bump version to 4.4 in CMakeLists.txt 2020-09-17 22:20:32 -07:00
Matias Fontanini
f46dee9f19 Add changelog for version 4.3 2020-09-17 22:20:10 -07:00
Matias Fontanini
5b082a82b2 Merge pull request #420 from mfontanini/control-ta-fix
Assign a PDUType for Dot11ControlTA
2020-09-10 08:44:05 -07:00
Matias Fontanini
07012648fb Assign a PDUType for Dot11ControlTA 2020-09-10 07:34:54 -07:00
Matias Fontanini
ce409dbc7e Merge pull request #374 from almikhayl/373-esp
Fix malformed packet exception on esp header
2020-02-01 11:04:00 -08:00
Matias Fontanini
16e77146ab Merge pull request #382 from laudrup/fix-install-without-libpcap
Don't include non-existing headers when installed without libpcap
2020-02-01 11:01:16 -08:00
Matias Fontanini
a87c4a64f5 Merge pull request #383 from laudrup/silence-msvc2017-warnings
Fix compiler warnings from MSVC 2017
2020-02-01 10:59:38 -08:00
Kasper Laudrup
9e61286a59 Fix compiler warnings from MSVC 2017
The MS C++ compiler doesn't seem to understand that a small constant
like 0, although strictly being an integer, will fit perfectly fine
into an 8 bit type so add some safe casts to silence that warning.
2019-12-20 14:37:38 +01:00
Kasper Laudrup
8da102fb48 Don't include non-existing headers when installed without libpcap
If libpcap support has been disabled (LIBTINS_ENABLE_PCAP=OFF)
then the headers requiring that library will not be installed,
but they will still be included from the main tins.h convenience
header.

This fixes that by sorrounding the includes with an #ifdef the
same way it has been done for DOT11 support.
2019-12-20 14:18:07 +01:00
Aleksey Mikhaylov
750c3556d9 Fix malformed packet exception on esp header 2019-10-19 19:56:20 +03:00
Matias Fontanini
28663b0e93 Merge pull request #369 from avast/ipv6-local-unicast
add IPv6 check for Link-Local unicast address
2019-10-02 08:33:25 -07:00
Matias Fontanini
731e36e373 Fix "fi" in comment 2019-10-02 08:32:54 -07:00
Karas Lukáš
608b48f25c add IPv6 check for Link-Local unicast address 2019-10-01 17:08:01 +02:00
Matias Fontanini
de247fcbc8 Merge pull request #346 from pallas/avoid-unused-variable-warning
radiotap: avoid unused variable warning
2019-04-25 18:17:48 -07:00
Derrick Lyndon Pallas
7bc4d38470 radiotap: remove unused variable 2019-04-24 02:32:09 +00:00
Matias Fontanini
a926b75224 Merge pull request #343 from pallas/fix-several-leaks
Fix several leaks
2019-04-12 07:35:01 -07:00
Derrick Lyndon Pallas
064439236c OfflinePacketFilter: avoid leak during copy-construction or assignment 2019-04-11 18:20:53 +00:00
Derrick Lyndon Pallas
0c40a0714b PacketWriter: avoid use-after-free on error in init 2019-04-11 18:20:53 +00:00
Derrick Lyndon Pallas
d74520768b OfflinePacketFilter: avoid leaks on error in init 2019-04-11 18:20:53 +00:00
Matias Fontanini
3385df9cc9 Merge pull request #342 from pallas/avoid-gcc-warning
tests/dhcp: avoid warning: type qualifiers ignored on cast result type
2019-04-10 19:45:03 -07:00
Derrick Lyndon Pallas
18c31b20f5 tests/dhcp: avoid warning: type qualifiers ignored on cast result type 2019-04-10 23:14:48 +00:00
Matias Fontanini
7387912ca1 Merge pull request #341 from m-peko/master
Fix possible memory leak in active tests
2019-04-08 09:49:52 -07:00
Marin Peko
0d52763a61 Fix possible memory leak in active tests 2019-04-08 15:57:51 +02:00
Matias Fontanini
86b505f998 Merge pull request #335 from avast/stream-syn
Fix detection of a new TCP flow
2019-03-20 10:55:44 -07:00
Martin Beran
62a803c55c fix detection of a new TCP stream 2019-03-18 13:44:51 +01:00
Matias Fontanini
0573808aeb Merge pull request #333 from DDoSolitary/patch-radiotap-writer
Overhaul RadioTapWriter
2019-03-14 18:36:31 -07:00
Lukáš Karas
22b4435c81 simplify tcp flag checks, fix stream_follower (#334)
* simplify tcp flag checks, fix stream_follower

On various places was used simple comparison for checking state of flags.

tcp.flags() == (TCP::SYN | TCP::ACK)

This is not what you want usually, because this check is false
in case that another flag is set also. Correct check for syn-ack
packet should be:

(tcp.flags() & (TCP::SYN | TCP::ACK)) == (TCP::SYN | TCP::ACK)

To simplify this kind of check, add new has_flags method:

bool TCP::has_flags(small_uint<12> check_flags) const

* remove duplicate TCP::SYN flag check
2019-03-14 18:18:12 -07:00
DDoSolitary
b803959e11 Add tests for 2f16497bf8 and 78aa7d1787. 2019-03-12 14:18:59 +08:00
DDoSolitary
2f16497bf8 Fix alignment padding calculation. 2019-03-10 11:48:56 +08:00
DDoSolitary
78aa7d1787 Correct option upper bound testing. 2019-03-10 11:46:38 +08:00
DDoSolitary
ba2216e6e9 Avoid float precision problems of logarithm. 2019-03-10 11:45:36 +08:00
Matias Fontanini
74e3d909e6 Bump library version in CMake file to 4.3 2019-03-07 20:18:04 -08:00
Matias Fontanini
5e52091ecf Use version 4.2 in CMake 2019-03-07 20:16:02 -08:00
Matias Fontanini
dafb299ea3 Update changelog for version 4.2 2019-03-07 20:15:34 -08:00
Matias Fontanini
659bec56d7 Merge pull request #331 from Kaisrlik/cmake_config_file_location
cmake: update location of cmake configuration files for unix subsystems
2019-02-20 18:29:14 -08:00
Jan Kaisrlik
8c1bea6f84 cmake: update location of cmake configuration files for unix subsystems 2019-02-20 12:22:49 +01:00
Matias Fontanini
d8d1dc003b Merge pull request #330 from danvratil/fix-crosscompilation-check
Fix check whether we are crosscompiling
2019-02-07 09:01:47 -08:00
Daniel Vrátil
c2bb52b82f Fix check whether we are crosscompiling
CMake defines CMAKE_CROSSCOMPILING when crosscompiling so
use that instead of the undefined CROSS_COMPILING variable.
2019-02-07 13:20:39 +01:00
Matias Fontanini
1f5456b18b Merge pull request #324 from pepper-jk/fix_frame_length
Fix frame length
2019-01-27 09:20:58 -08:00
Jens Keim
dc702f4fd6 use advertised_size to determine frame length 2019-01-22 19:33:08 +01:00
Jens Keim
2a8101eef3 add advertised_size method 2019-01-22 19:32:51 +01:00
Matias Fontanini
20702ddaff Merge pull request #326 from solvingj/fix_install_dll_copy_win
add runtime destination to install, and provide default
2019-01-22 09:33:40 -08:00
Jerry W
f4e2701705 add runtime destination to install, and provide default consistent with existing lib default 2019-01-19 12:25:57 -05:00
Matias Fontanini
776ae4e83b Merge pull request #305 from christophert/master
Add comprehensive list of 802.11 Element IDs
2019-01-07 18:53:41 -08:00
Matias Fontanini
2158c7a92e Merge pull request #313 from fflexo/raw_ip
add support for libpcap's DLT_RAW link type
2019-01-07 18:49:10 -08:00
Matias Fontanini
b53bad7b29 Merge pull request #322 from DDoSolitary/patch-radiotap-overflow-2
Buffer overflow fixes for radiotap.
2019-01-07 18:47:30 -08:00
DDoSolitary
6c92bcdad1 Clarify pointer's validity for documentation of current_option_ptr(). 2018-12-25 10:38:44 +08:00
DDoSolitary
b949e56d15 Remove the overflow check in align_buffer().
Reasons stated in https://github.com/mfontanini/libtins/pull/320#discussion_r242049560.
2018-12-24 15:20:30 +08:00
DDoSolitary
18ff3e7b6a Remove "+ 1" for MAX_RADIOTAP_FIELD.
current_flags_ starts from 0.
2018-12-13 17:27:01 +08:00
Matias Fontanini
559b1fb89a Update changelog for version 4.1 2018-12-10 18:11:37 -08:00
Matias Fontanini
1e78ef0752 Bump version to 4.1.0 2018-12-10 18:07:08 -08:00
Saxon Parker
602ada7820 Fix Dot1Q serialization for non-qinq packets (#319) 2018-12-01 15:56:16 -08:00
Teodoro Vargas
57ac099703 Fix serialization for QinQ (#316)
* Add QinQ Frame

* Fix serialization for QinQ
2018-10-09 14:02:01 -07:00
fflexo
eb7628eca4 add support for libpcap's DLT_RAW link type 2018-09-08 15:11:06 +01:00
Ulf Wetzker
c26e4943c2 Added base class access specifier for socket_close_error (#306) 2018-08-02 09:17:07 -07:00
Christopher Tran
7e90c8be6a add comprehensive list of Element IDs per 802.11-2016 9.4.2/T9-77 2018-07-26 13:29:23 -04:00
Stefan Schmidt
3659d89c25 Rewrote hw_address_to_string to not require a stringstream (#299) 2018-05-31 13:28:06 -07:00
Matias Fontanini
db992d42e5 Set TINS_HAVE_DOT11 as predefined in Doxyfile
Fixes #294
2018-05-18 20:41:40 -07:00
Matias Fontanini
5571a270d4 Make RadioTapParser::skip_to_field check for end of buffer (#296)
Fixes #295
2018-05-16 12:30:16 -07:00
Matias Fontanini
b18c2cefec Remove note regarding develop branch
This was useful at some point but now it's more of a burden to keep up to date. PRs should use `master` as base directly.
2018-05-09 20:33:40 -07:00
Jim Hague
3f204321ce Ensure local include directory comes before system. (#293)
If building (say) libtins 4.0 on a system with 3.4 installed, you need
the libtins include files to come from the repository include, not the
system include directory. The OpenSSL and PCAP includes may be from
the system include, so we need to ensure the libtins include is the
first on the list - which means the last on the before list.
2018-05-09 20:30:58 -07:00
Matias Fontanini
63603b8ac8 Calculate IP option sizes properly
Fixes #288
2018-04-08 08:12:52 -07:00
Kasper Laudrup
fa79582b89 Add parsing of well known IPv6 extension headers (#287)
* Add parsing of well known IPv6 extension headers

Add classes for IPv6 extension headers defined in the IPv6 protocol
specification (RFC 2460) as well as functions for creating them from
the IPv6 class' ext_header type.

The currently known extension headers are Hop-By-Hop Option,
Destination Routing, Routing and Fragment.

* Cleanup after PR #287 comments

Pull in stuff from the std namespace with "using" instead of
qualifying with std::.

Keep starting braces on the same line.

Avoid potential copy when appending to vector.
2018-03-28 21:05:01 -07:00
stubbfel
342e2c77a7 Add missing operators to address classes (#275)
* * add or-operator and a simlple unit test for hw_address, ip_address, ipv6_address
* add not-operator and a simlple unit test for hw_address, ip_address, ipv6_address
* add greater-then-operator and a simlple unit test for ipv6_address
* add new constructor and a simlple unit test for network_interface, which use a ipv6_address to find the nic
* add override the function gateway_from_ip for ipv6_address parameter (untested)

* change the ipv6_address in NotMaskAdress_Test, so that the expceted addresses are valid for the winsock api

* Delete CMakeLists.txt.user

* * add  <=, >, >= operator for HWAddress with tests

* add  <=, >, >= operator for IPv4Address with tests
* add  <=,>= operator for IPv6Address with tests

* refactoring the  & , |, ~ operator of ipv6_address to "regular" operator
2018-03-28 20:44:28 -07:00
Matias Fontanini
7848e28b62 Add version macros in config.h
Fixes #286
2018-03-20 18:50:42 -07:00
Matias Fontanini
544aa1b339 Don't assume IPv6 uses ICMPv6 underneath 2018-03-18 12:56:12 -07:00
Matias Fontanini
de4791f0c7 Allow users to specify library install dir
Fixes #273
2018-03-17 15:35:04 -07:00
Matias Fontanini
915f506f3a Use Sleep windows function passing milliseconds as parameter
Fixes #271
2018-03-14 18:47:40 -07:00
Matias Fontanini
f29566d6d9 Implement IPv6::recv_response 2018-02-25 10:42:16 -08:00
Matias Fontanini
e4f747164c Merge remote-tracking branch 'origin/master' into develop 2018-02-21 09:49:44 -08:00
Matias Fontanini
683550b297 Don't use nullptr in non C++11 code 2018-02-21 09:47:09 -08:00
Ed Catmur
971fdf7d1c Ignore (possibly malformed) options after EOL (#281) 2018-02-03 09:33:20 -08:00
Ed Catmur
1038c6f7f3 Don't call &* on PDUIterator 2018-02-03 09:32:43 -08:00
Jeff Ebert
8efc0271f5 Don't include dot11.h in tins.h if it is not configured in the library (#277) 2018-02-03 09:31:24 -08:00
Matias Fontanini
9ac5e597e6 Merge branch 'develop'
Ugh
2017-12-20 07:05:44 -08:00
Matias Fontanini
f7fc5fae1d Update CHANGES.md file using v4.0 changes 2017-12-20 07:04:55 -08:00
Matias Fontanini
f44b253a42 Fix memory leak in PDU's move assignment operator
Fixes #272
2017-12-14 14:42:46 -03:00
Matias Fontanini
8f85a6e557 Append padding to IPv6 options
Relates to #270
2017-12-12 10:33:17 -03:00
Matias Fontanini
8fd25e23a6 Update CHANGES.md file using v4.0 changes 2017-12-03 16:04:42 -08:00
Matias Fontanini
a3dd057147 Use first IP fragment as base for reassembly
Fixes #225 for good
2017-12-03 13:50:02 -08:00
Matias Fontanini
e16fe46d7a Fix invalid memory accesses when parsing bogus RadioTap 2017-11-25 17:12:30 -08:00
mavrikiy
39f3b24058 Fix dhcpv6::duid_type constructor from duid_ll (#266) 2017-11-06 09:29:57 -08:00
Santiago Alessandri
8e50756afa Add MPLS experimental field (#265)
* Add experimental field to MPLS PDU

See RFC-4950 https://tools.ietf.org/html/rfc4950

* Add tests for MPLS' experimental field
2017-11-04 12:08:34 -07:00
Alex Collins
c07cd40234 Fix #263 - Install only the headers which are enabled. (#264)
* Fix #263 - Install only the headers which are enabled.

* Fix #263 - Install only the headers which are enabled. Fix clumsy typo!
2017-10-28 10:23:09 -07:00
Alex Collins
d2addea9cf Reorders SOURCE includes alphanumerically, and adds HEADERS as source (#260)
* Reorders SOURCE includes alphanumerically, and adds HEADERS as sources to enable code completion in CLion.

* Add forward slash after variable to clarify path.

* Separate out DOT11 headers and sources.

* Reposition some sources as per general alpha sorting.
2017-10-26 16:23:20 -07:00
Alex Collins
f88c024b2f Fix minor typo in comment. (#261) 2017-10-24 14:31:45 -07:00
Ed Catmur
983325bfdf Ensure TCP::OptionTypes has 8-bit range (#259)
When reading TCP packets with esoteric (or corrupt) values for option types, the asan fsanitize=enum will trigger if the read value is not in range of the enum. The range of a classic (pre-C++11) enum with no negative enumerators is determined by the highest bit set in any of its enumerators, so if `TCP::OptionTypes` has highest enumerator `ALTCHK  = 14` it cannot take values above 15.

Define enumerators (per IANA) with bit 7 set to ensure that `TCP::OptionTypes` can take any 8-bit value.

An alternative (C++11 only) would be to give `TCP::OptionTypes` underlying type `uint8_t`.
2017-10-19 10:17:51 -07:00
Matias Fontanini
f4635a696e Fix build issues when disabling Dot11
Fixes #258
2017-10-18 06:40:51 -07:00
Steven
c439eccdf8 Implemented matching for ND protocol related ICMPv6 messages (#257)
- ROUTER_SOLICIT -> ROUTER_ADVERTIST
- NEIGHBOUR_SOLICIT -> NEIGHBOUR_ADVERTIST

Check if code equals zero according to https://tools.ietf.org/html/rfc4861#page-39
2017-10-12 20:03:10 -07:00
Alex Collins
04e29858ee Add RawPDU c'tor for const payload_type&. (#253)
* Add RawPDU c'tor for const payload_type &.

* Correct indentation.
2017-10-12 20:02:28 -07:00
Alex Collins
ab2850e22e Fix header install location. (#256) 2017-10-11 13:37:23 -07:00
Alex Collins
6429dcd03f Correct "promiscuous" spelling in comments (#254) 2017-10-09 14:25:21 -07:00
juno0812
b43d2f74e4 Add getter/setter for more data field in Dot11Base (#252) 2017-10-04 07:03:17 -07:00
Matias Fontanini
2aab4cf126 Fix warnings in tests 2017-10-01 20:47:52 -07:00
Matias Fontanini
f2766db829 Add IPv4/6Address::size member function 2017-10-01 20:38:54 -07:00
Matias Fontanini
db0fb7f20d Don't convert IPv6Address to string when hashing 2017-10-01 20:33:06 -07:00
Matias Fontanini
a6817528bc Use absolute include paths
Fixes #250
2017-09-21 20:48:57 -07:00
solvingj
a7dd867503 Fix hash<IPv4/6Address> build issues in VC
* fixed compile failure due to macro

* add functional to cxxstd.h to try to fix mac

* clang bug identified, moving functional include to later

* last step, move hash def to header

* avoid allocation on hash

* set ipv6 back to string hash
2017-09-19 19:00:28 -07:00
solvingj
e48f64daac Remove include directories CMakeLists files
* simply consolidate 6 files into 6 lines

* narrowed glob on inc and simplified
2017-09-14 09:32:27 -07:00
Matias Fontanini
171067eb22 Keep first fragment during IPv4 reassembly
Fixes #225
2017-09-10 16:39:15 -07:00
Matias Fontanini
78b94fa350 Serialize Loopback on Windows and use proper flag for IPv6 2017-08-13 10:46:36 -07:00
Matias Fontanini
c84652af40 Add IPv6 layer parsing on Loopback packets 2017-08-13 10:35:24 -07:00
Matias Fontanini
19fd9a7c1d Don't skip inner PDU parsing on LLC when building on Windows
Relates to issue #236
2017-08-13 10:34:41 -07:00
Christopher Tran
5df1c354f0 added cipher and akm suites from 802.11-2016 2017-08-12 13:34:13 -07:00
Matias Fontanini
eb0d82ce89 Add more documentation on partial stream following
Fixes #227
2017-08-05 19:21:21 -07:00
Matias Fontanini
f89e922d72 Add missing TINS_API on address types
Fixes #229
2017-08-05 19:12:12 -07:00
Matias Fontanini
ecacd4aee5 Only use IFF_POINTOPOINT on BSD when getting broadcast address
Fixes #232
2017-08-05 19:05:46 -07:00
Matias Fontanini
a17ec89332 Set pcap sniffing method on FileSniffer
Fixes #230
2017-07-26 10:27:54 -07:00
Matias Fontanini
7003541284 Fix merge conflicts with master
Conflicts:
	src/pdu_option.cpp
2017-07-23 14:32:15 -07:00
Andrea Barberio
87c0e3a337 Add set_pcap_sniffing_method to specify either pcap_loop or pcap_dispatch 2017-07-23 09:38:11 -07:00
Jeff Puckett
cfb9b646cc doc fix typo 2017-06-11 10:58:34 -07:00
Matias Fontanini
eed8229a04 Use InputMemoryStream when parsing PDU options and ICMP extensions 2017-06-08 20:15:08 -07:00
Matias Fontanini
3e6e25d0aa Add support for XChannel field on RadioTap 2017-06-05 20:44:03 -07:00
Matias Fontanini
77ca5c2701 Add missing radiotap parsing fields 2017-06-05 20:44:03 -07:00
Matias Fontanini
ca3127ffbc Fix some big endian issues 2017-06-05 20:44:03 -07:00
Matias Fontanini
77d965784e Add support for DLT_RAW on BaseSniffer
Fixes #210
2017-06-05 20:44:03 -07:00
Matias Fontanini
edd289c645 Don't dereference vector if empty on RadioTapWriter 2017-06-05 20:44:03 -07:00
Matias Fontanini
2f528876ad Add back RadioTap::TSTF 2017-06-05 20:44:03 -07:00
Matias Fontanini
aa64e34880 Keep current flags as member in RadioTapParser 2017-06-05 20:44:03 -07:00
Matias Fontanini
5fcde41023 Use RadioTapParser/Writer in RadioTap 2017-06-05 20:44:03 -07:00
Matias Fontanini
63e22fc349 Add RadioTapWriter class 2017-06-05 20:44:03 -07:00
Matias Fontanini
7af1ec0984 Add some useful member functions to RadioTapParser 2017-06-05 20:44:03 -07:00
Matias Fontanini
4e95797710 Allow constructing RadioTapParser from an empty buffer 2017-06-05 20:44:03 -07:00
Matias Fontanini
a641589b09 Make RadioTapParser work using only the options buffer 2017-06-05 20:44:03 -07:00
Matias Fontanini
b8e4c7248b Add RadioTapParser class 2017-06-05 20:44:03 -07:00
Matias Fontanini
d29296935e Fix C++03 build issues on PDU option 2017-06-05 20:44:03 -07:00
Matias Fontanini
1da2c1dcdc Add overload of Sniffer ctor taking only the device 2017-06-05 20:44:03 -07:00
Matias Fontanini
76395370de Use the right checks to consider an interface up on Windows
Fixes #182

Thanks @gvanem!
2017-06-05 20:44:03 -07:00
Matias Fontanini
7589a0a108 Rename IPv6::add_ext_header to IPv6::add_header (deprecate former) 2017-06-05 20:44:03 -07:00
Matias Fontanini
34072f733c Fix next header handling on IPv6
This was broken by design. Each header held the next header's
type, which made iterating through them very tricky (you'd have
to look at the previous header's next header value to know the
current one while doing so).

Now each header contains its own value and the next header
value is computed during serialization and then reverted back
after that.
2017-06-05 20:44:03 -07:00
Matias Fontanini
9442233a8a Calculate IPv6 headers size on demand 2017-06-05 20:44:03 -07:00
Matias Fontanini
993831709d Improve DNS class performance slightly 2017-06-05 20:44:03 -07:00
Matias Fontanini
4def995185 Fix build issue on VS 2017-06-05 20:44:03 -07:00
Matias Fontanini
fa85aa3f8b Performance improvements
* Remove option size memers on IP/TCP and instead calculate
these when they're needed
* Reorder members on IP/TCP so as to remove/decrease padding
* Move most memory helpers impl into header file so they
can be inlined
* Make PDUOption's move ctor/assignment operator noexcept
2017-06-05 20:44:03 -07:00
Matias Fontanini
8021112fea Use vector instead of lists everywhere 2017-06-05 20:44:03 -07:00
Matias Fontanini
80f424b6b3 Use TINS_DEPRECATED on old Sniffer constructors 2017-06-05 20:44:03 -07:00
Matias Fontanini
1ef5be352a Use custom exceptions everywhere 2017-06-05 20:44:03 -07:00
Matias Fontanini
1a83801722 Remove useless includes 2017-06-05 20:44:03 -07:00
Matias Fontanini
3c2f40ec02 Split pdu_option.h into a source file as well 2017-06-05 20:44:03 -07:00
Matias Fontanini
b47dc3f77c Only call memcpy in PDUOption if size > 0 2017-06-05 20:44:03 -07:00
Matias Fontanini
f1e726f503 Don't dereference iterator in memory helpers if size == 0 2017-06-05 20:44:03 -07:00
Matias Fontanini
afb6ad488c Use TINS_IS_CXX11 macro properly 2017-06-05 20:44:03 -07:00
Matias Fontanini
5d68211af2 Include iterator in network_interface 2017-06-05 20:44:03 -07:00
Matias Fontanini
887bccf0af Fix undefined std::min use in PPPoE 2017-06-05 20:44:03 -07:00
Matias Fontanini
7eb067338f Try to make VC happy with std::hash definition 2017-06-05 20:44:03 -07:00
Matias Fontanini
6896cc6346 Fix more build issues on appveyor 2017-06-05 20:44:03 -07:00
Matias Fontanini
de2f29b797 Fix build issue on appveyor 2017-06-05 20:44:03 -07:00
Matias Fontanini
1ec6006f33 Add missing stdexcept include in routing_utils.cpp 2017-06-05 20:44:03 -07:00
Matias Fontanini
d9f92c46c4 Fix missing include for sstream on packet_sender.cpp 2017-06-05 20:44:03 -07:00
Matias Fontanini
9677c06036 Fix build issues due to std::hash missing 2017-06-05 20:44:03 -07:00
Matias Fontanini
a07b3e8a3a Remove inclusion of algorithm almost everywhere 2017-06-05 20:44:03 -07:00
Matias Fontanini
58a4d336b9 Move memory helpers implementation into a source file 2017-06-05 20:44:03 -07:00
Matias Fontanini
86da3818ff Remove useless includes 2017-06-05 20:44:03 -07:00
Matias Fontanini
815889bd22 Move seq_compare into its own header file 2017-06-05 20:44:03 -07:00
Matias Fontanini
be48947ead Move is_dot3 into details/pdu_helpers.h 2017-06-05 20:44:03 -07:00
Matias Fontanini
3e7188edf7 Move internals' PDU helpers into their own files 2017-06-05 20:44:03 -07:00
Matias Fontanini
3d4f9285c9 Move PDU utils into their own file 2017-06-05 20:44:03 -07:00
Matias Fontanini
e556f4147f Move resolution utils into their own file 2017-06-05 20:44:03 -07:00
Matias Fontanini
4e4f7a2390 Move Utils::gateway_from_ip into routing utils files 2017-06-05 20:44:03 -07:00
Matias Fontanini
35e65d018c Move routing related functions into their own header file 2017-06-05 20:44:03 -07:00
Matias Fontanini
714b8d9810 Use checksum utils on crypto and icmp extension source files 2017-06-05 20:44:03 -07:00
Matias Fontanini
d061fced7e Move frequency (channel) utils into their own file 2017-06-05 20:44:03 -07:00
Matias Fontanini
36fedf4f65 Remove useless includes for utils.h on tests 2017-06-05 20:44:03 -07:00
Matias Fontanini
89202c5dd5 Move checksum utils into their own file 2017-06-05 20:44:03 -07:00
Matias Fontanini
110adc58dc Move ICMP extension helpers into their own file 2017-06-05 20:44:03 -07:00
Matias Fontanini
6f32a1982a Remove useless stdexcept includes 2017-06-05 20:44:03 -07:00
Matias Fontanini
c50c4c105c Add relative includes on detail headers 2017-06-05 20:44:03 -07:00
Matias Fontanini
ac69278676 Move helpers for address types in internals.h to their own header 2017-06-05 20:44:03 -07:00
Matias Fontanini
af325f00d9 Move functions to parse /proc/net/routes into utils.cpp 2017-06-05 20:44:03 -07:00
Matias Fontanini
28fa1b2f7e Move internal crypto stuff from the header into the source file 2017-06-05 20:44:03 -07:00
Matias Fontanini
ab51787323 Move Internals::byte_array into crypto.cpp 2017-06-05 20:44:03 -07:00
Matias Fontanini
92bda42ac1 Move sniffer callback traits into detail/type_traits.h 2017-06-05 20:44:03 -07:00
Matias Fontanini
730e69463c Include detail/type_traits.h rather than internals.h on pdu_option 2017-06-05 20:44:03 -07:00
Matias Fontanini
07f000f65a Move type traits into a separate file 2017-06-05 20:44:03 -07:00
Matias Fontanini
3e7d30e01c Don't include heavy STL headers like <algorithm> in header files
This provides a considerable compilation time reduction and most
of these were just using std::copy/fill which can be replaced by
memcpy/memset, as all of their uses were applied to POD types
2017-06-05 20:44:03 -07:00
Matias Fontanini
22c72955f5 Remove Storage template parameter from HWAddress, move impl to cpp
This is a breaking ABI change. This might break some forward
declarations and hopefully no one was actually using the
Storage type for anything.
2017-06-05 20:44:03 -07:00
Matias Fontanini
6f681f6519 Move smart_ptr definition into new file detail/smart_ptr.h 2017-06-05 20:44:03 -07:00
Matias Fontanini
c7273ddd30 Add PDU iterator class 2017-06-05 20:44:03 -07:00
Matias Fontanini
2c6ef2a5c0 Update license date to 2017 2017-06-05 20:44:03 -07:00
Matias Fontanini
4eb4dfe5fa Remove parent parameter from write_serialization
This is no longer needed as each PDU knows its parent PDU already
2017-06-05 20:44:03 -07:00
Matias Fontanini
8838ddf921 Add parent PDU member to PDU class
Now this is a bidirectional list of PDUs
2017-06-05 20:44:03 -07:00
Matias Fontanini
6b3875ae39 Bump version to 4.0
Next release will be a major one
2017-06-05 20:44:03 -07:00
Grégoire Péan
ab763f25a4 Add CMake options LIBTINS_BUILD_EXAMPLES/TESTS 2017-06-05 20:44:03 -07:00
Matias Fontanini
550eea98b1 Merge remote-tracking branch 'origin/master' into develop
Conflicts:
	CMakeLists.txt
2017-06-03 10:37:51 -07:00
Matias Fontanini
ecfed8db44 Add support for XChannel field on RadioTap 2017-06-03 09:17:29 -07:00
Matias Fontanini
fe6e575158 Add missing radiotap parsing fields 2017-06-03 08:55:08 -07:00
Matias Fontanini
d0b4383a0d Fix some big endian issues 2017-05-31 19:42:22 -07:00
Matias Fontanini
83e2c8dc47 Add support for DLT_RAW on BaseSniffer
Fixes #210
2017-05-30 21:17:55 -07:00
Matias Fontanini
57787649d7 Don't dereference vector if empty on RadioTapWriter 2017-05-30 19:45:20 -07:00
Matias Fontanini
c9e7237184 Add back RadioTap::TSTF 2017-05-29 20:50:45 -07:00
Matias Fontanini
52be4b0e8a Keep current flags as member in RadioTapParser 2017-05-29 20:48:05 -07:00
Matias Fontanini
e1571e19a8 Use RadioTapParser/Writer in RadioTap 2017-05-25 07:56:23 -07:00
Matias Fontanini
8c7bf7d779 Add RadioTapWriter class 2017-05-23 20:55:18 -07:00
Matias Fontanini
406e458c3a Add some useful member functions to RadioTapParser 2017-05-23 19:07:49 -07:00
Matias Fontanini
3f26974563 Allow constructing RadioTapParser from an empty buffer 2017-05-21 13:09:53 -07:00
Matias Fontanini
988f2382c4 Make RadioTapParser work using only the options buffer 2017-05-21 12:56:22 -07:00
Matias Fontanini
b983fe0bb3 Add RadioTapParser class 2017-05-21 10:06:13 -07:00
Matias Fontanini
5a3f3e43a6 Fix C++03 build issues on PDU option 2017-05-21 09:16:41 -07:00
Matias Fontanini
49d6e42324 Add overload of Sniffer ctor taking only the device 2017-05-20 13:43:16 -07:00
Matias Fontanini
d7a7877bfe Use the right checks to consider an interface up on Windows
Fixes #182

Thanks @gvanem!
2017-05-14 15:01:36 -07:00
Matias Fontanini
d8ead95070 Rename IPv6::add_ext_header to IPv6::add_header (deprecate former) 2017-05-14 10:33:04 -07:00
Matias Fontanini
5404e9f004 Fix next header handling on IPv6
This was broken by design. Each header held the next header's
type, which made iterating through them very tricky (you'd have
to look at the previous header's next header value to know the
current one while doing so).

Now each header contains its own value and the next header
value is computed during serialization and then reverted back
after that.
2017-05-14 10:25:59 -07:00
Matias Fontanini
f0aaec98f3 Calculate IPv6 headers size on demand 2017-05-14 09:04:58 -07:00
Matias Fontanini
348371e43c Improve DNS class performance slightly 2017-05-13 19:44:57 -07:00
Matias Fontanini
4763486523 Fix build issue on VS 2017-05-13 17:48:22 -07:00
Matias Fontanini
7250c7a03d Performance improvements
* Remove option size memers on IP/TCP and instead calculate
these when they're needed
* Reorder members on IP/TCP so as to remove/decrease padding
* Move most memory helpers impl into header file so they
can be inlined
* Make PDUOption's move ctor/assignment operator noexcept
2017-05-13 16:21:18 -07:00
Matias Fontanini
cedd127e8f Use vector instead of lists everywhere 2017-05-13 11:14:11 -07:00
Matias Fontanini
fcad90b5e9 Use TINS_DEPRECATED on old Sniffer constructors 2017-05-13 11:04:05 -07:00
Matias Fontanini
64778f5412 Use custom exceptions everywhere 2017-05-13 10:59:15 -07:00
Matias Fontanini
a5766a19c2 Remove useless includes 2017-05-13 10:43:29 -07:00
Matias Fontanini
c6f4e816aa Split pdu_option.h into a source file as well 2017-05-13 10:22:24 -07:00
Matias Fontanini
ce6ef3186b Only call memcpy in PDUOption if size > 0 2017-05-10 19:13:55 -07:00
Matias Fontanini
6a66008153 Don't dereference iterator in memory helpers if size == 0 2017-05-10 18:44:55 -07:00
Matias Fontanini
6c6b345ba0 Use TINS_IS_CXX11 macro properly 2017-05-09 08:09:41 -07:00
Matias Fontanini
734b874dab Include iterator in network_interface 2017-05-08 22:23:45 -07:00
Matias Fontanini
6d573d8327 Fix undefined std::min use in PPPoE 2017-05-08 22:22:48 -07:00
Matias Fontanini
11eca1816a Try to make VC happy with std::hash definition 2017-05-08 22:14:39 -07:00
Matias Fontanini
b0d66a01d2 Fix more build issues on appveyor 2017-05-08 21:51:27 -07:00
Matias Fontanini
bd0db1354e Fix build issue on appveyor 2017-05-07 13:33:52 -07:00
Matias Fontanini
01475679d1 Add missing stdexcept include in routing_utils.cpp 2017-04-30 20:09:47 -07:00
Matias Fontanini
b2173ffb86 Fix missing include for sstream on packet_sender.cpp 2017-04-30 20:01:30 -07:00
Matias Fontanini
3f2f6438fd Fix build issues due to std::hash missing 2017-04-30 19:55:23 -07:00
Matias Fontanini
60b5f3e6e4 Remove inclusion of algorithm almost everywhere 2017-04-30 18:51:55 -07:00
Matias Fontanini
82e97addb1 Move memory helpers implementation into a source file 2017-04-30 18:15:50 -07:00
Matias Fontanini
19ae1f366b Remove useless includes 2017-04-30 17:34:02 -07:00
Matias Fontanini
a9747a349a Move seq_compare into its own header file 2017-04-30 16:52:59 -07:00
Matias Fontanini
fe38bba477 Move is_dot3 into details/pdu_helpers.h 2017-04-30 16:46:28 -07:00
Matias Fontanini
a20f9d3e81 Move internals' PDU helpers into their own files 2017-04-30 13:49:50 -07:00
Matias Fontanini
39e9f0542d Move PDU utils into their own file 2017-04-30 13:29:33 -07:00
Matias Fontanini
1c2c5d7dd4 Move resolution utils into their own file 2017-04-30 13:21:13 -07:00
Matias Fontanini
1c2ac61bb0 Move Utils::gateway_from_ip into routing utils files 2017-04-30 13:12:39 -07:00
Matias Fontanini
f764f68e9c Move routing related functions into their own header file 2017-04-30 12:32:16 -07:00
Matias Fontanini
2453e57436 Use checksum utils on crypto and icmp extension source files 2017-04-30 12:07:06 -07:00
Matias Fontanini
500ef1088b Move frequency (channel) utils into their own file 2017-04-30 12:06:42 -07:00
Matias Fontanini
c83cff36d8 Remove useless includes for utils.h on tests 2017-04-30 11:59:10 -07:00
Matias Fontanini
589adba798 Move checksum utils into their own file 2017-04-30 11:59:02 -07:00
Matias Fontanini
6e1d1d3dc4 Move ICMP extension helpers into their own file 2017-04-30 10:53:21 -07:00
Matias Fontanini
ec59194232 Remove useless stdexcept includes 2017-04-30 10:31:11 -07:00
Matias Fontanini
7de4474996 Add relative includes on detail headers 2017-04-30 10:30:55 -07:00
Matias Fontanini
95626a867e Move helpers for address types in internals.h to their own header 2017-04-30 10:21:26 -07:00
Matias Fontanini
c072ffe421 Move functions to parse /proc/net/routes into utils.cpp 2017-04-30 10:13:58 -07:00
Matias Fontanini
ac797a836e Move internal crypto stuff from the header into the source file 2017-04-30 10:11:04 -07:00
Matias Fontanini
0cda2287a8 Move Internals::byte_array into crypto.cpp 2017-04-30 09:53:11 -07:00
Matias Fontanini
6bfc0c84f0 Move sniffer callback traits into detail/type_traits.h 2017-04-30 09:45:06 -07:00
Matias Fontanini
1bd0cd504e Include detail/type_traits.h rather than internals.h on pdu_option 2017-04-30 09:40:40 -07:00
Matias Fontanini
a3e863942b Move type traits into a separate file 2017-04-30 09:36:50 -07:00
Matias Fontanini
f88cf9b025 Don't include heavy STL headers like <algorithm> in header files
This provides a considerable compilation time reduction and most
of these were just using std::copy/fill which can be replaced by
memcpy/memset, as all of their uses were applied to POD types
2017-04-30 09:28:00 -07:00
Matias Fontanini
1ad245238f Remove Storage template parameter from HWAddress, move impl to cpp
This is a breaking ABI change. This might break some forward
declarations and hopefully no one was actually using the
Storage type for anything.
2017-04-30 09:25:57 -07:00
Matias Fontanini
4c54a69e64 Move smart_ptr definition into new file detail/smart_ptr.h 2017-04-30 09:25:03 -07:00
Matias Fontanini
77a31ca6b5 Add PDU iterator class 2017-04-29 11:23:15 -07:00
Matias Fontanini
c06787ca22 Update license date to 2017 2017-04-29 09:56:26 -07:00
Matias Fontanini
15a353c123 Remove parent parameter from write_serialization
This is no longer needed as each PDU knows its parent PDU already
2017-04-29 09:53:33 -07:00
Matias Fontanini
1b4d22314d Add parent PDU member to PDU class
Now this is a bidirectional list of PDUs
2017-04-29 09:27:08 -07:00
Matias Fontanini
35383ac359 Bump version to 4.0
Next release will be a major one
2017-04-29 09:22:04 -07:00
Matias Fontanini
d2b00990fe Bump minor version 2017-04-29 08:41:51 -07:00
Matias Fontanini
97a11073d4 Add release notes for v3.5 2017-04-29 08:41:43 -07:00
Grégoire Péan
95b6261324 Add CMake options LIBTINS_BUILD_EXAMPLES/TESTS 2017-04-16 14:53:06 -07:00
Matias Fontanini
37c92fcf5c Bump minor version 2017-04-01 09:21:33 -07:00
Matias Fontanini
18281e614d Add release notes for v3.5 2017-04-01 09:12:28 -07:00
Matias Fontanini
7f8644cb39 Merge branch 'develop' 2017-03-23 19:31:10 -07:00
Matias Fontanini
799ba2b4b6 Allow disabling pcap packet capture 2017-03-21 19:04:33 -07:00
Matias Fontanini
ad0a1ca97d Use QoS TID when building AAD for CCMP decryption
Fixes #190
2017-03-11 10:43:12 -08:00
Matias Fontanini
7607610cf9 Merge branch 'develop' 2017-01-31 21:37:41 -08:00
Kyle Fazzari
a71a3d29ff Fix -Wextra compiler warnings. (#184)
* Fix -Wextra compiler warnings.

Fix #183.

Signed-off-by: Kyle Fazzari <github@status.e4ward.com>

* Comment out unused parameters.

This is done everywhere possible instead of using Internals::unused().
Note that this involved moving some implementations into the
corresponding .cpp file.

Signed-off-by: Kyle Fazzari <github@status.e4ward.com>

* Fix warnings in tests as well.

Signed-off-by: Kyle Fazzari <github@status.e4ward.com>

* Leave IPv4Reassembler alone, it's growing.

Signed-off-by: Kyle Fazzari <github@status.e4ward.com>
2017-01-25 13:26:11 -08:00
Ed Catmur
9051197603 Use actual payload length to construct inner PDU. (#179)
Fixes #178
2017-01-16 09:36:33 -08:00
Matias Fontanini
94e5ac2109 Check expected size properly on DNS::extract_metadata
Thanks @shshzi for finding this one
2017-01-15 09:04:19 -08:00
Matias Fontanini
84cb686928 Use markdown for CHANGES file 2016-12-11 10:11:05 -08:00
Matias Fontanini
da07ad3b13 Remove AUTHORS file
This file is very outdated. Check contributions on github to
see the actual contributors.
2016-12-11 10:02:48 -08:00
Matias Fontanini
d5cba00ce0 Use immediate mode on DNS spoof example 2016-11-04 08:00:13 -07:00
Matias Fontanini
ba9d0b34c6 Fix build issue on FreeBSD 11
This fixes #174 temporarily, so at least it won't fail to build
2016-11-04 07:55:58 -07:00
Matias Fontanini
f2850cc0b9 Execute original ooo callback first on recovery mode 2016-11-01 07:35:56 -07:00
Matias Fontanini
c69ea0c1fb Keep original out of order callback on recovery mode 2016-10-30 13:08:17 -07:00
Matias Fontanini
a63387f85e Add Stream recovery mode 2016-10-30 11:38:50 -07:00
Matias Fontanini
df7e7b391d Add flag to Stream to know whether it was attached 2016-10-30 10:31:16 -07:00
Matias Fontanini
5d6431d2d9 Allow enabling attachment to partial streams 2016-10-30 10:21:58 -07:00
Matias Fontanini
a61a361eb1 Add check for noexcept when checking C++11 features 2016-10-23 11:34:10 -07:00
Matias Fontanini
9dbad2a26f Cleanup tests names and CMake script 2016-10-23 10:21:58 -07:00
Patrick Michel
aaba3dd46a Feature - Skipping ahead in TCP flows. (#163)
* Skipping forward in TCP streams, from an out-of-order callback.

- Added the ability to skip forward in a flow to a sequence number, with the intention of doing so in an out of order callback.
- Re-ordered Flow packet processing, to allow skipTo in out of order callback on stream start (flow sequence number is 0).
- Fixed missing seq_compare in flow code.

* Renamed skipTo to advance_sequence.
2016-10-23 09:47:56 -07:00
Matias Fontanini
2e013847d9 Use proper IPv6 flag when opening l3 socket
Fixes #166
2016-10-21 07:34:20 -07:00
Matias Fontanini
22e569d430 Fix buffer length check issue on Dot11QosData
Fixes #167
2016-10-18 07:24:11 -07:00
Matias Fontanini
2847039ffe Set last next protocol to 0 if no inner_pdu on IPv6 2016-09-29 07:37:46 -07:00
Matias Fontanini
54ce11629c Set payload type to 0 if no inner_pdu on Dot1Q 2016-09-29 07:37:46 -07:00
Matias Fontanini
8dcfd6aae0 Set protocol to 0 if no inner_pdu on IP 2016-09-29 07:37:46 -07:00
Patrick Michel
838a4a5cb9 Refactored code related to stream/flow initialization. (#170)
- Removed client_flow().process_packet() in Stream constructor, in favor of processing on SYN in stream follower.
- Moved +1 to seq on SYN/ACK.
2016-09-28 07:30:16 -07:00
Matias Fontanini
e82b72e931 Use relative include for config.h 2016-09-27 22:06:09 -07:00
Matias Fontanini
fdc6ccdf5c Only enable TCP stream's custom data if boost.any is found 2016-09-27 21:46:38 -07:00
Patrick Michel
52b389afe8 Allow setting custom user data to each TCP stream 2016-09-27 21:33:10 -07:00
Matias Fontanini
552006c876 Set EthernetII payload type to UNKNOWN if no inner_pdu 2016-09-27 07:47:32 -07:00
Matias Fontanini
f0b32edaa9 Use boost include paths/libs on appveyor build 2016-09-26 20:29:14 -07:00
Matias Fontanini
5a901ca155 Merge branch 'develop' 2016-09-26 19:52:12 -07:00
Jim Hague
9593cf4cf6 Correct typo preventing user buffer management for server TCP streams. (#160) 2016-08-31 09:13:43 -07:00
Huemac
64725e2ed9 Fix Cppcheck 1.75 warnings (#159)
- The scope of the variable 'last_index' & 'index' could be reduced.
- Prefer prefix ++/-- operators for non-primitive types.
2016-08-14 12:29:53 -07:00
Vikas Kumar
9260f9374a Variable Boost_INCLUDE_DIRS incorrectly used in cmake file (#158)
`s/Boost_INCLUDE_DIRS/${Boost_INCLUDE_DIRS}/ inside `INCLUDE_DIRECTORIES`
2016-08-13 13:41:25 -07:00
Sergey Kovalevich
2ccf50db3e Allow including libtins using add_subdirectory via CMake 2016-07-20 09:12:48 -07:00
ps790
e843ee7117 Added cmake compiling support for MinGW (#155)
* Added cmake compiling support for MinGW

These modificaitons allow to build Libtins on Windows with cmake directly by running 
cmake ../ -DPCAP_ROOT_DIR="PATH_TO_WpdPack" -DLIBTINS_ENABLE_WPA2=0 -DLIBTINS_BUILD_SHARED=0 -G "MinGW Makefiles"

* Update CMakeLists.txt
2016-06-24 18:00:09 -07:00
Matias Fontanini
a192e814bf Allow configuring pcap timestamp precision 2016-06-17 09:20:43 -07:00
Matias Fontanini
ccda631708 Fix timestamp integer overflow issue 2016-06-16 17:12:04 -07:00
Jacob Parker
1552e33c67 Add helper function to create StreamIdentifier from const Stream& (#152) 2016-06-07 13:19:55 -07:00
Wouter Overmeire
8afc784956 Fix typo in arp.h comment (#151) 2016-06-06 10:36:36 -07:00
Rolf Winter
5b00916f83 fixed: superfluous includes, docu (#148) 2016-05-26 09:11:48 -07:00
Matias Fontanini
6b7bc76603 Forward NetworkInterface argument when calling PacketSender::send_l2 2016-05-08 20:46:11 -07:00
Matias Fontanini
732c665af5 Fix compilation warning on VC 2016-05-08 10:34:49 -07:00
Matias Fontanini
8cf367d68c Make Timestamp::current_time work on Windows 2016-05-08 10:26:57 -07:00
Matias Fontanini
d070978a54 Add TINS_API to DataTracker and AckTracker classes 2016-05-08 09:38:52 -07:00
Matias Fontanini
7f30efab38 Fix typo in macros.h
[ci skip]
2016-05-05 12:40:11 -07:00
Matias Fontanini
d7fed87ebb Use recvfrom on BSD/OSX when capturing layer 3 packets
Fixes #147
2016-05-03 19:35:24 -07:00
Matias Fontanini
269ac164ed Use exception strings on std::runtime_error's constructor
Fixes #146
2016-05-03 14:50:28 -07:00
Matias Fontanini
55edf31aa6 Move TCP data tracking into a separate class 2016-05-03 14:50:28 -07:00
Patrick Michel
364782b8af Don't set Dot1Q's payload type if next proto type is UNKNOWN 2016-04-12 07:56:31 -07:00
Matias Fontanini
d3c576f6de Properly handle out of order SACKs on AckTracker 2016-04-03 09:39:11 -07:00
Matias Fontanini
8d52d73968 Allow disabling TCPIP classes 2016-04-02 09:35:42 -07:00
Matias Fontanini
48022d3a3f Rename and undef symbols that conflict with macro names on DNS
The undefs are a temporary fix until we get rid of the old,
conflicting, names

Fixes #141
Fixes #58
2016-04-02 09:16:28 -07:00
Matias Fontanini
ec1634d6d8 Move stream_id into a new file and rename it to StreamIdentifier 2016-03-28 21:38:43 -07:00
Matias Fontanini
688bb7094e Rename BSD enum value so it doesn't conflict with macro 2016-03-28 20:31:48 -07:00
Matias Fontanini
928e66eb27 Fix issue considering an interface down when it's up 2016-03-27 08:21:05 -07:00
Matias Fontanini
d80c27de29 Add active test for TCP over ethernet 2016-03-26 16:11:03 -07:00
Matias Fontanini
6aac22fa74 Make Utils::resolve_hwaddress work on Windows 2016-03-22 20:34:06 -07:00
Matias Fontanini
7bc1ab41f7 Add TCP and Utils::resolve_hwaddress active tests
[ci skip]
2016-03-22 19:49:26 -07:00
Matias Fontanini
068e304baa Fix active tests build issues 2016-03-20 19:01:58 -07:00
Matias Fontanini
5dc7b20a43 Add active tests for IPv4 2016-03-20 16:27:43 -07:00
Matias Fontanini
a70ce10bed Add IPv4Address::from_prefix_length 2016-03-19 16:26:00 -07:00
Matias Fontanini
3773443fc8 Allow masking IPv4/6 and HW addresses 2016-03-19 15:44:55 -07:00
Matias Fontanini
1f4be63d08 Properly handle MLDv1 on ICMP 2016-03-17 21:49:06 -07:00
Matias Fontanini
6a69d1ff6c Export proper artifacts for VS 2015 2016-03-17 21:46:56 -07:00
Matias Fontanini
85102b4546 Merge pull request #140 from asjadsyed/develop
don't set key_t to 0 when setting a key, because the two fields are unrelated
2016-03-17 21:07:15 -07:00
Asjad Syed
f188ea4d2a don't set key_t to 0 when setting a key, because the two fields are unrelated 2016-03-17 22:26:16 -04:00
Matias Fontanini
a75dd9e3f9 Add Visual Studio 2015 to appveyor build 2016-03-16 22:51:50 -07:00
Matias Fontanini
dda673cad4 Merge branch 'develop' 2016-03-16 21:01:27 -07:00
Matias Fontanini
8b125d31f2 Add TINS_API to operator<< for IPv4Address 2016-03-16 20:51:37 -07:00
Matias Fontanini
67ee3e8a7d Merge pull request #137 from stubbfel/pullrequest/first_address_from_mask
calc the complete addressrange of a network when call AddressRange::from_mask
2016-03-16 20:51:03 -07:00
stubbfel
d70536f9ab add first_address_from_mask in internals and call them from addressrange::from_mask 2016-03-16 22:28:21 +01:00
Matias Fontanini
bfe9f9f4a5 Update changelog 2016-03-09 20:25:09 -08:00
Matias Fontanini
97e24131c6 Fix issues pointed out by scan.coverity 2016-03-07 20:29:12 -08:00
Matias Fontanini
42b6c40433 Add Utils::route6_entries on OSX/BSD 2016-03-07 19:40:38 -08:00
Matias Fontanini
4dcef0f15d Add Utils::route6_entries 2016-03-06 19:18:33 -08:00
Matias Fontanini
c082dfad67 Minor changes on TCPIP::StreamFollower 2016-03-06 13:40:10 -08:00
Matias Fontanini
331bc57b44 Update version 2016-03-05 16:07:11 -08:00
Matias Fontanini
b7e20f550e Use proper bssid/client hw when calling handshake captured callback 2016-03-05 10:56:03 -08:00
Matias Fontanini
e15ef0d837 Add info members directly into NetworkInterface 2016-03-05 10:33:50 -08:00
Matias Fontanini
08fd9e2d69 Check the secure bit on HandshakeCapturer to detect 2nd packet 2016-03-05 09:37:22 -08:00
Matias Fontanini
3a99213c0b Rename IPv6AddressPrefix to IPv6Prefix 2016-03-02 21:34:21 -08:00
Matias Fontanini
ad71158268 Add IPv6 addresses to NetworkInterface::Info 2016-03-02 21:13:50 -08:00
Matias Fontanini
186d23c920 Set OPENSSL_* variables to empty string if not found 2016-02-28 08:51:44 -08:00
Matias Fontanini
cfbf88bb5f Make *MemoryStream use size_t rather than uint32_t 2016-02-28 08:12:05 -08:00
Matias Fontanini
1681981fe8 Add WPA2Decrypter callback interface 2016-02-28 08:01:04 -08:00
Matias Fontanini
3e84b07a01 Set MACOSX_RPATH to ON 2016-02-27 07:57:07 -08:00
Matias Fontanini
b087c964d4 Don't fail configuration if openssl is missing 2016-02-27 07:50:56 -08:00
Matias Fontanini
bf70a94921 Build layer 5 as RawPDU if IPv6 has fragment header 2016-02-22 20:37:48 -08:00
Matias Fontanini
e5282f8a3c Fix compilation warnings 2016-02-21 18:50:47 -08:00
Matias Fontanini
5920185288 Add defragmenter example 2016-02-21 18:28:59 -08:00
Matias Fontanini
92f0249d2b Cleanup IPv4Reassembler 2016-02-21 18:20:06 -08:00
Matias Fontanini
016cfeecc6 Don't build examples on travis
Clang on OSX uses gcc 4.6's headers and apparently the chrono header
fails to build
2016-02-21 15:12:00 -08:00
Matias Fontanini
8bf0c355f4 Fix examples so they build on gcc 4.6 2016-02-21 14:59:19 -08:00
Matias Fontanini
fa4178de09 Fix flag value for sniffer's immediate mode 2016-02-21 14:42:24 -08:00
Matias Fontanini
04578b109f Build examples on travis 2016-02-21 09:44:00 -08:00
Matias Fontanini
9dabb6f570 Fix IP fragment reassemble when packet has flags DF+MF 2016-02-21 09:23:44 -08:00
Matias Fontanini
8812153491 Remove extra include on tins.h 2016-02-21 09:14:14 -08:00
Matias Fontanini
17da10d76e Add extract_metadata to main PDU classes 2016-02-20 22:19:12 -08:00
Matias Fontanini
dae25b3381 Fix examples to make them work on Windows 2016-02-20 11:13:04 -08:00
Matias Fontanini
745071af65 Use Utils::sum_range straight into ICMP checksum value 2016-02-20 11:02:20 -08:00
Matias Fontanini
f3448f1797 Use timercmp/sub and std::chrono to subtract timevals 2016-02-20 10:51:35 -08:00
Matias Fontanini
dad6091706 Build examples against local libtins build 2016-02-20 09:55:48 -08:00
Matias Fontanini
6d6eb9c5d7 Add uninstall target 2016-02-20 09:19:42 -08:00
Matias Fontanini
64b84fa91d Prefix HAVE_ config.h macros with TINS_ 2016-02-20 09:10:48 -08:00
Matias Fontanini
bac8388cec Merge pull request #130 from jopann/develop
Fixed comment spelling
2016-02-19 09:02:14 -08:00
Josh Hunter
e69d0d7ce9 Fixed comment spelling 2016-02-19 10:27:56 -06:00
Matias Fontanini
b326546229 Add checks for std::chrono and std::function 2016-02-18 20:52:18 -08:00
Matias Fontanini
5c22cc7985 Use compiler intrinsics to swap bytes 2016-02-18 20:35:37 -08:00
Matias Fontanini
bd31b3648f Change CheckCXX11Features into CheckCXXFeatures 2016-02-18 20:11:36 -08:00
Matias Fontanini
3c595e6225 Merge pull request #129 from einarjon/master
Add missing TINS_API to PDU classes. Fix ICMPv6 enums
2016-02-18 14:55:33 -08:00
Einar Gunnarsson
ed40dd423d Merge remote-tracking branch 'upstream/master' 2016-02-18 15:34:32 +01:00
Matias Fontanini
0e5d7d7ae0 Use C++11 mode by default 2016-02-17 21:04:28 -08:00
Matias Fontanini
9ef6f7a612 Initialize ACK tracker correctly 2016-02-17 20:10:22 -08:00
Matias Fontanini
da923aa63c Update Doxygen file to enable C++11 support flag 2016-02-17 20:02:07 -08:00
Einar Jón
f88d94cbaa Remove TINS_API from template PDU class 2016-02-17 19:16:15 +01:00
Einar Gunnarsson
6403d1908d add missing TINS_API to PDU classes. Extend/fix ICMPv6 enum values and unify naming 2016-02-17 17:51:54 +01:00
Matias Fontanini
423dbf2404 Return an empty string for dot11 ssid, if ssid is present but empty
References issue mentioned in #128
2016-02-16 21:28:59 -08:00
Matias Fontanini
af6b0fdbb2 Update README.md for TCP ACK tracker disabling 2016-02-15 18:19:38 -08:00
Matias Fontanini
8e7eb25558 Implement new TCP stream follower mechanism 2016-02-15 18:10:33 -08:00
Matias Fontanini
91a724fe2d Add HTTP requests example 2016-02-15 08:29:14 -08:00
Matias Fontanini
eb1c43d293 Throw proper exceptions 2016-02-14 16:51:10 -08:00
Matias Fontanini
4123764a48 Execute out of order callback even for seq < current_seq 2016-02-14 08:56:25 -08:00
Matias Fontanini
abe94ece52 Allow asking whether segment was acked 2016-02-13 22:45:11 -08:00
Matias Fontanini
2498ebf7d6 Fix ACK tracker tests build 2016-02-13 21:26:46 -08:00
Matias Fontanini
f8445c2e5c Fix travis build script 2016-02-13 20:34:39 -08:00
Matias Fontanini
116eb9f1c1 Add initial ACK tracking code 2016-02-13 20:24:15 -08:00
Matias Fontanini
48c068b84a Add callbacks for stream termination events 2016-02-13 11:23:08 -08:00
Matias Fontanini
20a3868e82 Track Stream timestamps and add timeout to StreamFollower 2016-02-11 21:18:48 -08:00
Matias Fontanini
85d7401520 Store MSS value on Flows 2016-02-10 21:24:15 -08:00
Matias Fontanini
3b848060aa Change tcp_ip directory structure 2016-02-10 20:56:13 -08:00
Matias Fontanini
69fc5ff54b Add support for out of order data packet detection 2016-02-10 20:56:13 -08:00
Matias Fontanini
8db6032303 Add hardware addresses to Stream 2016-02-10 20:56:13 -08:00
Matias Fontanini
549c0e97d0 Add Flow::ignore_data_packets 2016-02-10 20:56:13 -08:00
Matias Fontanini
c3861cf54e Fill address arrays with 0x00 2016-02-10 20:56:13 -08:00
Matias Fontanini
7c1453662f Fix compilation issues 2016-02-10 20:56:13 -08:00
Matias Fontanini
5b60b79fd8 Document new TCP stream classes 2016-02-10 20:56:13 -08:00
Matias Fontanini
07b5d74179 Refactor TCP stream code and add http_dump example 2016-02-10 20:56:13 -08:00
Matias Fontanini
76b0c919b9 Add initial code for new TCP reassembly mechanism 2016-02-10 20:56:13 -08:00
Matias Fontanini
785ee7b47b Use ExternalProject_Add rather than including the gtest directory 2016-02-09 20:35:15 -08:00
Matias Fontanini
64b267c7ea Add friendly name to interface info example 2016-02-06 16:04:51 -08:00
Matias Fontanini
0832184896 Add CONTRIBUTING.md file 2016-02-06 16:04:07 -08:00
Matias Fontanini
5d41316b9a Rename IP header member to header_ 2016-02-04 20:37:24 -08:00
Matias Fontanini
602ead5de5 Fix invalid private method name on PacketSender 2016-02-04 20:27:51 -08:00
Matias Fontanini
72e038b9bf Fix invalid endian on IP fragment offset on OSX 2016-02-04 20:20:14 -08:00
Matias Fontanini
4b0976571e Fix invalid FCS serialization offset on RadioTap 2016-02-02 22:43:28 -08:00
Matias Fontanini
8ab48106d6 Update changelog 2016-01-31 21:04:29 -08:00
Matias Fontanini
3036f9ce91 Merge branch 'master' of github.com:mfontanini/libtins into develop
Conflicts:
	examples/dns_stats.cpp
	include/tins/sniffer.h
	src/sniffer.cpp
2016-01-31 21:03:57 -08:00
Matias Fontanini
88d8f99676 Replace "wether" with "whether" on doc strings 2016-01-31 20:45:30 -08:00
Matias Fontanini
fb4e5086fd Update copyright notice 2016-01-31 20:03:49 -08:00
Matias Fontanini
58e3a7a687 Don't use pcap_setdirection on Windows 2016-01-25 12:50:29 -08:00
Matias Fontanini
f54399c45c Add TCP connection close example 2016-01-24 20:49:58 -08:00
Matias Fontanini
0cf3dd3342 Move utils.h implementations to utils.cpp 2016-01-24 14:13:34 -08:00
Matias Fontanini
d7df3a449e Move utils.h implementations to utils.cpp 2016-01-24 11:37:05 -08:00
Matias Fontanini
dc1a5a6982 Add ICMPv6 Multicast Listener Query Messages support 2016-01-20 20:27:37 -08:00
Matias Fontanini
3d21ad7bec Remove useless friend class declarations 2016-01-14 12:49:42 -08:00
Matias Fontanini
757e54dc08 Use lower case names for DNS query/record and change type to query_type 2016-01-14 12:40:00 -08:00
Matias Fontanini
ced645fb02 Add DNS SOA record parsing and serialization
Fixes #48
2016-01-14 12:18:43 -08:00
Matias Fontanini
c1e479f523 Merge pull request #114 from jllorente/master
Added pcap_setdirection to sniffer
2016-01-12 10:31:40 -03:00
Matias Fontanini
ca56cc10dd Parse and serialize MX preference field correctly 2016-01-11 15:48:03 -08:00
Matias Fontanini
75add84741 Add NetworkInterface::friendly_name to get Windows friendly names
Fixes #103
2016-01-10 17:44:32 -08:00
Matias Fontanini
3d3d7b8506 Mask 16 bits on random number generated on traceroute example
Fixes #121
2016-01-10 16:42:07 -08:00
Matias Fontanini
b21154a926 Fix sequence number addition/subtraction when wrapping around
Fixes #115
2016-01-10 16:31:48 -08:00
Matias Fontanini
2169b1f71f Use 802.1ad protocol flag when seralizing stacked Dot1Q
Fixes #68
2016-01-09 14:30:43 -08:00
Matias Fontanini
d84f10cf08 Code cleanup and use same syntax on the entire project
Initial code cleanup

More code cleanup

Cleanup more code

Cleanup Dot11 code

Fix OSX build issue

Cleanup examples

Fix ref and pointer declaration syntax

Fix braces
2016-01-09 10:01:58 -08:00
Matias Fontanini
f5a82b1a17 Correctly serialize PPPoE session packets 2016-01-01 14:49:32 -08:00
Matias Fontanini
2c16aaaecd Fix IPv6 extension headers parsing/serialization 2016-01-01 14:39:09 -08:00
Matias Fontanini
d7e0d17154 Add ICMPv6 multicast listener report message structure 2016-01-01 10:24:45 -08:00
Matias Fontanini
2b7714500c Include examples before src to avoid duplicate tins target issue 2015-12-31 14:43:30 -08:00
Matias Fontanini
03ad7f3ae7 Fix big endian issue on MPLS 2015-12-31 06:18:44 -08:00
Matias Fontanini
756dd97fc7 Add copyright to files that didn't have it 2015-12-31 06:05:42 -08:00
Matias Fontanini
7bffa7801d Add MPLS PDU and hook it up with ICMP extensions 2015-12-31 05:57:18 -08:00
Matias Fontanini
4ba9085eeb Set UDP checksum to 0xffff if it's 0 2015-12-29 09:00:46 -08:00
Matias Fontanini
c4a2fed112 Don't define TINS_STATIC in config.h 2015-12-29 07:43:46 -08:00
Matias Fontanini
df3bca099a Fix invalid RSNEAPOL parsing issue 2015-12-29 07:07:38 -08:00
Matias Fontanini
53e2c58f0b Remove special clang on OSX case when building gtest 2015-12-29 06:11:03 -08:00
Matias Fontanini
d7a9816246 Update pseudoheader_checksum signature 2015-12-29 05:58:58 -08:00
Matias Fontanini
67d31fd62c Fix overall checksum calculation 2015-12-29 09:57:42 -03:00
Matias Fontanini
afe778d03c Set ICMP payload length without padding if no extensions are present 2015-12-28 14:18:26 -03:00
Matias Fontanini
7a2ae6b7d5 Export classes on Windows shared lib builds
Fixes #120
2015-12-28 06:28:52 -08:00
Matias Fontanini
481c51b4c7 Use google/googletest submodule and update to HEAD 2015-12-27 16:17:05 -08:00
Matias Fontanini
38239be472 Remove unused cassert header inclusions 2015-12-27 04:38:31 -08:00
Matias Fontanini
31ca9a6cc8 Port Dot11 classes to use OutputMemoryStream 2015-12-26 16:54:35 -08:00
Matias Fontanini
49af3714e8 Add padding at the end of the line on dns_stats
Fixes #118
2015-12-26 07:31:53 -08:00
Matias Fontanini
36216107ec Catch exceptions on arpmonitor
Fixes #119
2015-12-26 07:30:29 -08:00
Matias Fontanini
02e2b278de Add OutputMemoryStream and port most classes to use it 2015-12-26 06:30:00 -08:00
Matias Fontanini
9750f46c6d Port all PDUs to use InputMemoryStream on constructors from buffer 2015-12-25 06:30:27 -08:00
Matias Fontanini
13c05fbdb1 Add input memory stream class and port some PDUs to use it 2015-12-24 15:21:07 -08:00
Matias Fontanini
6d90b0ce32 Add extensions for ICMPv6 2015-12-21 12:33:52 -08:00
Jesus Llorente
6b82e50c03 Modified set_direction to return a bool 2015-12-21 17:56:18 +02:00
Matias Fontanini
530cc56922 Set proper value for length field 2015-12-19 16:46:13 -08:00
Matias Fontanini
0a16d8f462 Add ICMP extensions to ICMP PDU
The length field is still not being set
2015-12-17 20:42:57 -08:00
Matias Fontanini
e3c382efa0 Fix sum_range issue on big endian 2015-12-16 20:03:27 -08:00
Matias Fontanini
fb43cb738b Add ICMP extensions to ICMP PDU 2015-12-14 21:18:42 -08:00
Matias Fontanini
6e026fcb66 Add missing member functions to ICMP extension classes 2015-12-14 20:22:50 -08:00
Matias Fontanini
187e7b1ca3 Add ICMP extensions structure class 2015-12-13 21:49:26 -08:00
Matias Fontanini
8aff1b4afe Add ICMPExtension class 2015-12-13 19:46:58 -08:00
Matias Fontanini
45546eee39 Fix RSNInformation issues on big endian architectures 2015-12-08 08:36:24 -08:00
Matias Fontanini
a35b086d12 Use endian independent way of setting IP fragment offset and flags 2015-12-07 22:11:28 -08:00
Matias Fontanini
3e23bcc73c Add IP::fragment_offset and IP::flags 2015-12-07 21:10:41 -08:00
Matias Fontanini
35d5045db4 Don't set Ethernet type if inner PDU type is unknown
Fixes #116
2015-11-27 20:31:12 -08:00
Matias Fontanini
65b7919ebf Don't run IP source address overwrite tests on OSX 2015-11-25 09:31:19 -08:00
Jesus Llorente
4b9f998784 Removed tins_direction_t typedef in favor of native pcap_direction_t 2015-11-24 20:09:41 +02:00
Jesus Llorente
b07deba105 Added pcap_setdirection to sniffer 2015-11-23 23:10:34 +02:00
Matias Fontanini
534bdaf30b Always calculate IP checksum
Fixes #105
2015-11-08 10:25:49 -08:00
Matias Fontanini
87c4963533 Fix invalid constant value on PPPoE
Fixes #109
2015-11-01 07:55:57 -08:00
Matias Fontanini
978041a9a2 Define default constructor for PKTAP
Fixes #106
2015-10-16 10:04:42 -07:00
Matias Fontanini
30445f1e97 Guard 802.11 parsing code on PPI around HAVE_DOT11 2015-09-21 21:06:57 -07:00
Matias Fontanini
693cef04df Fix parsing of Dot11 packets encapsulated on PPI having FCS-at-end 2015-09-21 20:49:17 -07:00
Matias Fontanini
9d0a2d4f3e Fix DataLinkType typo on doxygen docs
[ci skip]
2015-09-19 09:00:33 -07:00
Matias Fontanini
2cf61403e1 Update docs on sniff_loop handle persistency
[ci skip]
2015-08-25 20:15:04 -07:00
Matias Fontanini
69b26bd637 Migrate .travis to new container infrastructure 2015-08-22 11:05:06 -07:00
Matias Fontanini
cec69ee261 Fixes #99: Use uint32_t for DNS resource TTL setter 2015-08-22 10:59:33 -07:00
Matias Fontanini
891f4ac4d7 Fixes #98: Erase streams when they're reassembed on IPv4Reassembler 2015-08-22 10:57:45 -07:00
Matias Fontanini
af71a4eca7 Make all exceptions derive from exception_base 2015-08-17 21:46:07 -07:00
Matias Fontanini
dd0b9ecde4 Merge pull request #96 from mfontanini/remove_option
Add remove_option member to IP, TCP, Dot11, ICMPv6, DHCP and DHCPv6
2015-08-17 16:36:30 -07:00
Matias Fontanini
6dec68128d Add remove_option member to IP, TCP, Dot11, ICMPv6, DHCP and DHCPv6 2015-08-17 15:19:03 -07:00
Matias Fontanini
ab61907a06 Merge pull request #91 from rklabs/fix_tunnel_interface
Allow no HW address on interfaces when looking up their info (TUN ifaces)
2015-07-22 10:11:55 -07:00
rklabs
9c9994f129 Restoring deleted comment 2015-07-22 22:24:53 +05:30
rklabs
97e6a99c5e Add additional check for found_ip in case of tunnel interface and then raise exception 2015-07-22 22:06:21 +05:30
rklabs
d09450980a Incase of tunnel interface(VPN) mac address can be 0 2015-07-22 21:08:40 +05:30
Matias Fontanini
79c0023f75 Merge pull request #90 from bkambach/master
Increment option size when adding a new option
2015-07-13 16:37:56 -07:00
bkambach
3b23d68a10 Remove code, instead of commenting it out 2015-07-13 17:52:44 -04:00
bkambach
fe48586eef Remove update of options size in constructor 2015-07-13 17:49:29 -04:00
bkambach
848d8348ae Increment option size when adding a new option 2015-07-13 17:28:33 -04:00
Matias Fontanini
da3bf12671 Add NOMINMAX on examples. 2015-06-22 21:50:58 -07:00
Matias Fontanini
d447009779 Add metric to RouteEntry. 2015-06-21 14:32:23 -07:00
Matias Fontanini
2c2c92325d Fix traceroute example. 2015-06-20 10:58:36 -07:00
Matias Fontanini
b451a9eae0 Detect if pcap version defines pcap_set_immediate_mode. 2015-06-14 11:23:32 -07:00
Matias Fontanini
c42c18f5df Allow setting immediate mode on Sniffer. 2015-06-14 10:56:00 -07:00
Matias Fontanini
8bb837eda8 Use one flags field for all flags on SnifferConfiguration. 2015-06-14 10:41:07 -07:00
Matias Fontanini
6b6636b0bb Add ICMP responses example. 2015-06-13 11:34:59 -07:00
Matias Fontanini
316bb12946 Add interfaces_info example. 2015-06-13 10:31:31 -07:00
Matias Fontanini
cab0ba8b9a Fix bug on SessionKeys::SessionKeys. 2015-06-12 20:09:23 -07:00
Matias Fontanini
0a2fdfcd42 Fix compilation errors on android. 2015-06-07 15:25:57 -07:00
Matias Fontanini
43217549eb Fix example compilation on Windows.
Fixes #75.
2015-06-02 21:52:40 -07:00
Matias Fontanini
0f3441ccf6 Add PacketWriter::write overload that takes a Packet. 2015-05-26 21:33:13 -07:00
Matias Fontanini
9c25f635eb Add travis CI status image on README.md. 2015-05-23 13:19:47 -07:00
Matias Fontanini
3ec8ab868e Use different IP addresses on IP tests depending on OS. 2015-05-23 12:48:57 -07:00
Matias Fontanini
8d28bfe7a1 Fix compilation warnings shown on travis. 2015-05-23 11:56:31 -07:00
Matias Fontanini
46f5d7a0cd Fix tests failing on travis. 2015-05-23 11:17:20 -07:00
Matias Fontanini
8400079bce Add .travis.yml. 2015-05-23 10:53:20 -07:00
Matias Fontanini
68c750810f Update documentation for WPA2::SupplicantData. 2015-05-22 20:48:25 -07:00
Matias Fontanini
0dee5618f2 Allow retrieving keys on WPA2Decrypter. 2015-05-21 21:14:24 -07:00
Matias Fontanini
76c6511e0c Add NetworkInterface::is_up and NetworkInterface::info. 2015-05-19 18:52:42 -07:00
Matias Fontanini
2f2a705127 Add NetworkInterface::Info::is_up. 2015-05-19 18:44:24 -07:00
Matias Fontanini
b0faebd135 Include appveyor build status icon 2015-05-18 21:14:34 -07:00
Matias Fontanini
2bf2b222e0 Add appveyor.yml. 2015-05-17 17:35:45 -07:00
Matias Fontanini
c42cd0114f Fix compilation warnings on Windows x64. 2015-05-17 17:30:54 -07:00
Matias Fontanini
5cd0c8e41b Fix FindPCAP.cmake to find winpcap on x64. 2015-05-17 11:52:30 -07:00
Matias Fontanini
8276dca22e Fix more tests warnings triggered on Windows. 2015-05-16 11:18:54 -07:00
Matias Fontanini
d4e632f513 Fix tests compilation warnings on Windows. 2015-05-16 11:08:52 -07:00
Matias Fontanini
325de4abca Fix error on VC triggered by pcap redefining the "inline" keyword. 2015-05-12 19:03:52 -07:00
Matias Fontanini
e651770018 Fix warning on test added on last commit. 2015-05-10 13:36:29 -07:00
Matias Fontanini
d1ffecb132 Soften DNS parsing rules. Fixes #74. 2015-05-10 12:19:58 -07:00
Matias Fontanini
460e87cb43 Remove VC insecure warnings on header files. 2015-05-02 17:39:53 -07:00
Matias Fontanini
a607ab380c Replace WIN32 macro with _WIN32. 2015-05-02 16:25:59 -07:00
Matias Fontanini
a7a63483df Fix gtest compilation issues on OSX. 2015-04-25 19:39:22 -07:00
Matias Fontanini
9de57e1b23 Update README.md. 2015-04-25 19:01:40 -07:00
Matias Fontanini
f229f9a81e Merge pull request #72 from mfontanini/googletest-submodule
Googletest submodule
2015-04-25 18:57:57 -07:00
Matias Fontanini
62260ab93b Fix more compilation warnings on Windows. 2015-04-25 18:54:43 -07:00
Matias Fontanini
c108f6e4e6 Fix compilation warnings on Windows. 2015-04-25 18:44:38 -07:00
Matias Fontanini
5c8fdd2b6c Build googletest using /MD on Windows. 2015-04-25 17:44:56 -07:00
Matias Fontanini
34bf1f23f7 Improve tests CMake build files. 2015-04-25 17:26:02 -07:00
Matias Fontanini
ae503523e4 Fix tests that failed on Windows. 2015-04-25 17:05:36 -07:00
Matias Fontanini
e64e0ce27b Fix IPv6Address::to_string on Windows. 2015-04-25 12:20:47 -07:00
Matias Fontanini
93ed4f537e Fix TCP test on Windows. 2015-04-25 12:15:04 -07:00
Matias Fontanini
995abd4d00 Fix DNS issues triggered on VC. 2015-04-25 11:32:47 -07:00
Matias Fontanini
0dcbe6ffbe Prefix googletest directory with CMake source dir. 2015-04-23 19:45:32 -07:00
Matias Fontanini
745ebfb904 Only include googletest if the git submodule has been fetched. 2015-04-23 19:43:00 -07:00
Matias Fontanini
c5b9afaf83 Add google test as git submodule. 2015-04-23 19:39:58 -07:00
Matias Fontanini
f4ccba93e6 Merge branch 'master' of github.com:mfontanini/libtins 2015-04-23 19:12:25 -07:00
Matias Fontanini
308cbcdc40 Merge pull request #70 from benmcmorran/master
Perserve IP protocol when using RawPDU
2015-04-21 09:00:57 -07:00
Ben McMorran
eb5598be7c Perserve IP protocol when using RawPDU
Previously, the IP protocol field for non-fragmented packets was forcibly overwritten to the protocol of the inner PDU even if that PDU was a RawPDU. This behavior contradicts the documentation.
2015-04-20 02:45:27 -04:00
Matias Fontanini
830da2488b Update project version to 3.3. 2015-04-19 13:54:37 -07:00
Matias Fontanini
530ac79ba4 Improve documentation for PacketSender. 2015-04-19 10:54:18 -07:00
Matias Fontanini
213b812520 Use pcap_sendpacket by default on Windows. 2015-04-18 19:52:25 -07:00
Matias Fontanini
8c2b56e286 Allow sending Dot3 on Windows using pcap_sendpacket. 2015-04-18 19:37:57 -07:00
Matias Fontanini
147c1a4315 Don't allow receiving l2 packets on windows. 2015-04-18 18:56:16 -07:00
Matias Fontanini
2fa4c2ade3 Soften more precompiler conditionals on PacketSender. 2015-04-18 18:26:49 -07:00
Matias Fontanini
621af33a81 Fix more precompiler conditionals. 2015-04-18 18:19:56 -07:00
Matias Fontanini
0d9fe13166 Fix macro conditional. 2015-04-18 18:17:28 -07:00
Matias Fontanini
1a9cd63397 Remove more WIN32 guards. 2015-04-18 18:15:00 -07:00
Matias Fontanini
e2f96123a3 Remove some WIN32-guarded code. 2015-04-18 18:08:22 -07:00
Matias Fontanini
96fc1a3749 Use pcap_sendpacket to send packets if this mode is enabled. 2015-04-18 17:46:14 -07:00
Matias Fontanini
f2ed64293b Merge pull request #67 from UlfWetzker/channel_map
Added channel_map_type
2015-04-12 09:52:13 -07:00
Ulf Wetzker
bf807be7bd Fixed typo and copy&past nonsense 2015-04-09 20:26:01 +02:00
Ulf Wetzker
437911eacd Added Doxygen documentation and fixed arrangement 2015-04-09 19:51:05 +02:00
Ulf Wetzker
2d89f1548d Added channel map type 2015-04-09 19:39:55 +02:00
Matias Fontanini
c8b3b8d2b8 Merge pull request #66 from UlfWetzker/rsn_const
Made rsn_information() a const member function
2015-04-08 08:56:38 -07:00
Ulf Wetzker
7d7aae5929 Made rsn_information() a const member function to make Dot11ManagementFrame immutable 2015-04-08 14:45:56 +02:00
Matias Fontanini
fc950f643b Merge pull request #65 from blazeable/master
Ensure HAVE_CXX11 is checked when defining TINS_IS_CXX11
2015-04-06 14:53:08 -07:00
blazeable
4bfec7b358 Ensure HAVE_CXX11 is checked when defining TINS_IS_CXX11
Include config.h in cxxstd.h
2015-04-06 23:43:48 +02:00
Matias Fontanini
3478c7b09a Don't define Sniffer callback traits when using VS. 2015-04-06 09:33:30 -07:00
Matias Fontanini
a326463160 Add one integer field for all flags on TCP. 2015-04-05 11:53:12 -07:00
Matias Fontanini
ebad686987 Add test for partial TCP packet. 2015-04-05 09:43:50 -07:00
Matias Fontanini
3791fc0ee6 Fix ICMPv6 issue on big endian. 2015-04-02 23:02:28 -07:00
Matias Fontanini
40a8354125 Fix Dot11/RSNInformation big endian issues. 2015-04-02 22:59:47 -07:00
Matias Fontanini
bb683c9f79 Fix invalid DNS IPv4 address parsing on big endian arch. 2015-04-02 22:43:35 -07:00
Matias Fontanini
5edd5932ba Don't compile WPA2 test if LIBTINS_ENABLE_WPA2=0. 2015-04-02 21:58:52 -07:00
Matias Fontanini
021f596cf0 Remove enable_if_t. 2015-04-02 21:58:41 -07:00
Matias Fontanini
992d187b04 Merge pull request #63 from UlfWetzker/radio_measurement
Fixed field name corresponding to IEEE 802.11-2012
2015-04-02 09:15:39 -07:00
Ulf Wetzker
d6d2434482 Fixed field name corresponding to IEEE 802.11-2012 (8.4.1.4 Capability Information field) 2015-03-31 16:37:28 +02:00
Matias Fontanini
811270760a Don't define enable_if_t, since it's not really necessary. 2015-03-29 15:47:44 -07:00
321 changed files with 36128 additions and 18608 deletions

28
.github/workflows/tests.yaml vendored Normal file
View File

@@ -0,0 +1,28 @@
name: Tests
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
Ubuntu-Tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install libpcap
run: sudo apt-get install -y libpcap-dev
- name: Initialize submodules
run: git submodule init && git submodule update
- name: Initialize build system
run: mkdir build && cd build && cmake ..
- name: Build tests
run: cmake --build build --target tests
- name: Run tests
run: ctest build

4
.gitmodules vendored Normal file
View File

@@ -0,0 +1,4 @@
[submodule "googletest"]
path = googletest
url = https://github.com/google/googletest.git
ignore = dirty

27
.travis.yml Normal file
View File

@@ -0,0 +1,27 @@
language: cpp
sudo: false
compiler:
- gcc
- clang
os:
- linux
- osx
addons:
apt:
packages:
- libpcap-dev
- libssl-dev
- libboost-all-dev
before_script:
- mkdir build
- cd build
- cmake .. -DLIBTINS_ENABLE_CXX11=1
- make tests
script:
- ctest -V

View File

@@ -1,9 +0,0 @@
# Below is a list of people and organizations that have contributed source
# code to libtins. Names are listed using the following format:
#
# Name/Organization <email address>
Matias Fontanini <matias.fontanini@gmail.com>
Santiago Alessandri <san.lt.ss@gmail.com>
Bruno Nery <brunonery@brunonery.com>
Piotr Haber <piotr.haber@sens.us>

339
CHANGES
View File

@@ -1,339 +0,0 @@
v3.2
- Added include guard for config.h.
- The functor used on BaseSniffer::sniff_loop can now take a Packet.
- Added mcs, tx_flags, ext and data_retries options to RadioTap.
- Fixed big endian representation of RadioTap header.
- RadioTap's dbm_signal and dbm_noise are now signed.
- RadioTap now throws if an option is not present when getting
its value.
- TKIP decryption now works correctly on packets from AP to STA.
- Added support for PKTAP header.
- Fixed endian issue on IPv4Address::ip_to_int on Windows.
- Fixed IP parsing when total length is 0 due to TCP segmentation offload.
- Re-added support for pkg-config.
- TCPStreamFollower now calls PDU::find_pdu instead of PDU::rfind_pdu.
- Fixed assertion throw caused by DNS parsing on Windows on debug mode.
- Added throw on BSD when trying to send_recv L3 packets.
- Added Loopback::matches_response.
- Removed obsolete autotools files.
- Fixed exception thrown when an interface didn't have an IP address
on NetworkInterface.
- Added NetworkInterface::is_loopback.
- Moved all headers to the directory include/tins.
- Fixed compilation warning on TCPStramFollower due to signed to unsigned
conversion on integral constant.
- BaseSniffer::get_pcap_handle is now public.
- PPPoE session packets are now parsed correctly.
- Fixed invalid Loopback protocol detection on FreeBSD/OSX.
- Fixed OSX IP packet sending issue.
- Added useful constructors to RawPDU.
- Fixed compilation errors on FreeBSD.
- Improved documentation on several classes.
- Fixed parsing bug when allocating IP over IP packets.
- Fixed Windows network interface naming.
- Utils::network_interface returns pcap compatible names on Windows.
- NetworkInterface::name now works on Windows.
- Added documentation generation through the build system.
- Added SnifferConfiguration class.
- Fixed bug on Dot3 serialization.
- Added OfflinePacketFilter class.
- Renamed NOEXCEPT macro to TINS_NOEXCEPT.
- Added DataLinkType class.
- 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.
- Fixed empty domain name encoding on DNS.
- 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.
- Packets can now be constructed from a PDU pointer and take ownership
of it.
- All protocols now set the next layer protocol flag, regardless if
it was already set. This was not done in some protocols,
like EthernetII, and as a consequence if the network layer protocol
was replaced by other, the packet would be serialized incorrectly.
- Fixed invalid parsing of some unknown DNS records.
- Fixed unaligned memory accesses that were not supported under
ARMv4 and ARMv5.
- Added BaseSniffer::set_extract_raw_pdus.
- Reduced minimum automake version to 1.11.
- Added Utils::to_string(PDU::PDUType).
- Fixed error compilations on Windows.
- Fixed ICMPv6 checksum calculation.
- Added method in IP and TCP to emplace an option (C++11 only).
- Added small option optimization to PDUOption.
- Fixed error compilation on RSNInformation.
- Renamed ICMP::check to ICMP::checksum.
- Added Sniffer support to set interface to promiscuous mode.
- TCPStreamFollower now handles overlapping fragments correctly.
- Fixed bugs in TCPStreamFollower which didn't allow it to follow
stream correctly.
- TCPStreamFollower now doesn't clear its state after every call to
TCPStreamFollower::follow_streams.
- Added IPv6 flag check to pdu_flag_to_ip_type.
- Added DHCP::hostname to extract the hostname options.
- Removed extra qualifier on SessionKeys::decrypt_unicast which
produced compilation errors on some platforms.
- PacketSender::send now uses PDU::matches_flag to match specific
PDU types.
- Removed 'no newline at end of file' warnings.
- Fixed bug when calling BIOCIMMEDIATE on *BSD.
- Fixed bug on PacketSender::send_recv which didn't work under *BSD.
- 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
DNS::Resource.
- tins.h now includes ppi.h.
- Done significant improvements in the speed of DNS parsing.
- Added PDUOption<>::to<> which converts a PDUOption to a specific type.
- Layer 3 packets sent using PacketSender::send_recv for which the
answer is a different PDU type.
- ICMP::gateway now uses IPv4Address.
- Added support for ICMP address mask request/reply.
- Fixed bug in PacketSender when using send_recv and a layer 2 PDU. The
interface in which the packet was sent was not the default_interface
set when the sender was constructed.
- IP packets sent using PacketSender::send_recv now match ICMP
responses.
- Added support for ICMP timestamp request/reply packets.
ICMP::matches_response now works with these types of packets as well.
- Added support for reassembling of fragmented IP packets via the
IPv4Reassembler class.
- Fragmented IP packet's inner_pdu PDUs are not decoded now.
- Added 1000ms as the default read timeout used when calling
pcap_open_live. Added BaseSniffer::set_timeout to modify this parameter.
- Added the --disable-dot11 configure switch.
- Added support for IPSec.
- Fixed bug triggered when ifaddrs::ifa_addr was null in
NetworkInterface::addresses.
- Added another overload of Utils::route_entries which returns the
result either than storing it in a parameter.
- Added ARP monitor, WPS detector, DNS queries sniffer and DNS spoofer
examples.
- Added another Sniffer constructor which doesn't expect the maximum
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.
- BaseSniffer::next_packet uses pcap_loop instead of pcap_next, which
doesn't work well on some linux distributions.
- Added PPI PDU class.
- Fixed a bug in EthernetII triggered when the size of the whole frame
was lower than 60 bytes.
- Added AddressRange class and IPv4Address, IPv6Address and
HWAddress<>::operator/.
- Added is_broadcast, is_multicast and is_unicast to IPv4, IPv6
and HWAddress.
- Added is_private and is_loopback methods to IPv4 and IPv6 addresses.
- Done some optimizations on TCP's constructor from buffer.
- Added helper functions to Dot11Data to retrieve the source,
destination and BSSID addresses.
- Fixed bugs in DNS triggered when parsing MX and unknown records.
- BaseSniffer::next_packet now iterates until a valid packet is found.
- TCP::get_flag is now const.
- The --disable-wpa2 now works as expected.
v1.1 - Wed Jun 5 09:03:37 ART 2013
- Implemented std::hash specialization for IPv4, IPv6 and HWAddress<>
types.
- Added a RSNHandshakeCapturer class.
- Added WPA2Decrypter class.
- IEEE 802.11 frames are not parsed if the RadioTap FAILED_FCS flag
is on.
- RadioTap now calculates its size everytime it's serialized.
- Splitted the dot11.h and dot11.cpp files into several files to
speed up compilation times.
- Added HWAddress<>::is_broadcast and HWAddress::operator[].
- Fixed a bug triggered when parsing Dot11QoSData frames.
v1.0 - Tue Apr 23 20:40:57 ART 2013
- Link layer protocol PDUs now don't hold a NetworkInterface. This led
to changes in their constructors.
- Removed the obsolete PDU* parameter taken by several classes'
constructors.
- IP now sets the sender's address automatically when no link layer
PDU is used.
- IP, TCP and UDP now calculate the checksum everytime they're
serialized.
- Added PDU::rfind_pdu.
- Defined several exception types.
- Implemented matches_response on several protocols.
- PacketSender is now movable.
- Added an overload of add_option that takes an rvalue-reference in IP,
TCP, DHCP, ICMPv6 and Dot11.
- Added support for GNU/kFreeBSD.
- Removed several deprecated methods, such as PDU::clone_packet.
- Added PacketSender::send(PDU&, NetworkInterface).
- Normalized the TLV options naming conventions in all of the classes
that used them.
- Added support for Dot1Q, STP, PPPoE protocols.
- Made some important optimizations on PDUOption<>'s constructors.
- Added Utils::resolve_domain and Utils::resolve_domain6
v0.3 - Thu Jan 31 16:47:27 ART 2013
- Added IPv6, ICMPv6 and DHCPv6 classes.
- Added support for Loopback interfaces and the Linux Crooked Capture
pseudo protocol.
- Added support for IPv6 records in DNS.
- Added Packet/RefPacket class.
- Added support for FreeBSD, OSX and Windows.
- Added C++11 move semantics to several classes.
- Done a complete rewrite of the build system; it now uses libtool.
- Fixed several bugs in DNS.
v0.2 - Sat Oct 20 11:26:40 2012
- Added support for big endian architectures.
- Simplified several interfaces.
- Added IPv4Address and HWAddress class to simplify handling IP and hardware addresses.
- Added NetworkInterface class to abstract network interfaces.
- Added TCPStreamFollower class to follow TCP streams on the fly.
- Added WEPDecrypter class to decrypt WEP-encrypted 802.11 data frames on the fly.
- Added several new PDUs: Loopback, IEEE802_3, LLC, DNS.
- Added support for reading and writing pcap files.
- Moved to BSD-2 license.

809
CHANGES.md Normal file
View File

@@ -0,0 +1,809 @@
##### v4.5 - Sun Aug 20 04:46:53 PM UTC 2023
- Add VXLAN support (#501)
- Add `FileSniffer` constructor taking a `FILE*` (#499).
- Remove use of deprecated `std::iterator` (#481).
- Add missing `algorithm` header include (#497).
- Validate high order two bits of first dns label octet (#494).
- Use `CMAKE_INSTALL_LIBDIR` in `CONF_CMAKE_INSTALL_DIR` (#472).
- Ignore IPv6 packets with payload after one with no Next Header (#500).
- Fix unqualified `std::move` call warnings on clang (#488).
- Fix incorrect IP address range calculation when using /0 prefix (#484) (#486).
- Fall back to system GTest if available (#473).
- Fix compilation issue on android (#471).
- Fix DNS parser reading garbage on misreported packet size (#468).
- Fix DNS parser misinterpreting bad label size (#466).
##### v4.4 - Thu Feb 17 14:41:59 UTC 2022
- Add RFC8335 extended echo types to `ICMP` and `ICMPv6` (#426)
- Handle loops in DNS name decompression (#444)
- Fix Windows' `interface` macro colliding with uses of that identifier in the code (#458)
- Sending IPv6 packets to a link-scope destination address now uses the right interface index (#448)
- Fix incorrect endian being used for ICMP's `gateway` and `address_mask` (#437)
- Socket in `PacketSender::open_l3_socket` is now closed if `setsockopt` fails (#433)
- Fix various incorrect doxygen documentation comments (#439).
- Fix infinite loop when querying the routing table in \*BSD (#427)
##### v4.3 - Fri Sep 18 03:08:33 UTC 2020
- Assign a PDUType to `Dot11ControlTA` (#420)
- Don't consider IPv6 ESP header a normal extension header (#374)
- Don't include non-existing headers when installed without libpcap (#382)
- Add `IPv6Address::is_local_unicast` (#369)
- Fix memory leak in `PacketWriter` (#343)
- Fix memory leaks in `OfflinePacketFilter` (#343)
- Fix detection of new TCP stream (#335)
- Introduce `TCP::has_flags` (#334)
- Fix padding calculations in RadioTapWriter (#333)
##### v4.2 - Fri Mar 8 04:15:13 UTC 2019
- Updated location of installed CMake files in unix systems (#331)
- Fix check to detect cross compilation (#330)
- Allow getting a PDU's advertised size and use it in `PacketWriter` (#324)
- Install DLLs in right directory (#326)
- Add missing Dot11 tagged option types (#305)
- Add support for DLT_RAW (#313)
- Fix potential invalid memory accesses when parsing RadioTap (#322)
##### v4.1 - Tue Dec 11 02:08:48 UTC 2018
- Fix serialization for QinQ (#316)
- Added base class access specifier for socket_close_error (#306)
- Rewrote hw_address_to_string to not require a stringstream (#299)
- Make RadioTapParser::skip_to_field check for end of buffer (#296)
- Ensure local include directory comes before system. (#293)
- Calculate IP option sizes properly (#288)
- Add parsing of well known IPv6 extension headers (#287)
- Add missing operators to address classes (#275)
- Add version macros in config.h
- Don't assume IPv6 uses ICMPv6 underneath
- Allow users to specify library install dir
- Use Sleep windows function passing milliseconds as parameter
- Implement IPv6::recv_response
- Don't use nullptr in non C++11 code
- Ignore (possibly malformed) options after EOL (#281)
- Don't include dot11.h in tins.h if it is not configured in the library (#277)
- Fix memory leak in PDU's move assignment operator
- Append padding to IPv6 options
##### v4.0 - Mon Dec 4 00:04:30 UTC 2017
- Add parent PDU to each PDU.
- Removed parent PDU parameter on `PDU::write_serialization`.
- Split `utils.h` into multiple files under the `utils` directory.
- Split `internals.h` into multiple files under the `detail` directory.
- Improve compilation times by removing useless include directives.
- Refactor `PDUOption` conversions so that heavy headers are not included in source file.
- Use `std::vector` instead of `std::list` in `TCP`, `IP`, `IPv6`, `DHCP`, `DHCPv6`, `DNS`, `LLC`, `Dot11` and `PPPoE`.
- Improve performance on `IP`, `IPv6` and `TCP` by compiting option sizes during serialization.
- Minor performance improvements in `DNS`.
- Fix `IPv6` next header handling. Now each one contains its own type and the next type is only set during serialization for ease of use.
- Refactor `RadioTap` parsing and serialization using a generic parser/writer.
- Add `BaseSniffer::set_pcap_sniffing_method` to specify whether `pcap_loop` or `pcap_dispatch` should be used when sniffing.
- Use `IFF_POINTOPOINT` on BSD when getting broadcast address for an interface.
- Added cipher and akm suites from 802.11-2016.
- Add IPv6 layer parsing on `Loopback` packets.
- Allow serializing `Loopback` on Windows.
- Use the right flag on `Loopback` for `IPv6`.
- Use the first fragment as a base when reassembling `IP` packets in `IPv4Reassembler`.
- Restructure CMake files removing useless `CMakeLists.txt` in `include` paths.
- Add getter/setter for "more data" field in `Dot11Base`.
- Implemented matching for ND protocol related ICMPv6 messages.
- Ensure TCP::OptionTypes has 8-bit range.
- Add header files into CMake sources so IDE can pick them up.
- Add MPLS "experimental" field.
- Fix dhcpv6::duid_type constructor from duid_ll.
##### v3.5 - Sat Apr 1 09:11:58 PDT 2017
- Added Utils::route6_entries
- Allow masking IPv4/6 and hardware addresses via `operator&`
- Add IPv4Address::from_prefix_length
- Move `stream_id` into a new file and rename it `StreamIdentifier`
- Allow disabling TCPIP classes
- Properly handle out of order SACKs on `AckTracker`
- Move TCP data tracking into a separate class
- Allow constructing `StreamIdentifier` from a `Stream`
- Allow configuring pcap timestamp precision
- Allow building libtins using MinGW
- Allow including libtins using `add_subdirectory` via CMake
- Allow setting customer user data to each TCP stream
- Allow skipping data forward in TCP streams
- Allow attaching to already existing TCP streams
- Fix: AddressRange masks first address as well
- Fix: Add TINS_API to `IPv4Address::operator<<`, `DataTracker` and `AckTracker`
- Fix: Don't always set `key_t` to 0 on `RSNEAPOL`
- Fix: Handle MLDv1 properly on ICMP
- Fix: Make Utils::resolve_hwaddress work on Windows
- Fix: Interface was sometimes considered down when it was up (BSD/Linux)
- Fix: Don't set `Dot1Q`'s payload type if next protocol type is unknown
- Fix: Use recvfrom on BSD/OSX when capturing layer 3 packets
- Fix: Make `Timestamp::current_time` work on Windows
- Fix: Forward `NetworkInterface` argument when calling `PacketSender::send_l2`
- Fix: `Timestamp` overflow issue
- Fix: boost's include directories variable incorrectly used on build system
- Fix: Configuring auto cleanup of `Stream`'s server data not working
- Fix: Set `EthernetII` payload type to `UNKNOWN` if there's no inner PDU
- Fix: Set payload type to 0 if there's no inner PDU in `IP`, `Dot1Q` and `IPv6`
- Fix: Buffer length check issues on `Dot11QosData`
- Fix: Use AF_INET6 flag when opening L3 IPv6 socket
- Fix: Check expecter size properly on `DNS::extract_metadata`
- Fix: several unused parameter warnings
- Fix: CCMP decryption issue when `Dot11QoSData` has a TID != 0
##### v3.4 - Wed Mar 9 20:24:54 PST 2016
- Check the secure bit on HandshakeCapturer to detect 2nd packet
- Add info members directly into NetworkInterface
- Add IPv6 addresses to NetworkInterface::Info
- Make *MemoryStream use size_t rather than uint32_t
- Add WPA2Decrypter callback interface
- Set MACOSX_RPATH to ON
- Don't fail configuration if openssl is missing
- Build layer 5 as RawPDU if IPv6 has fragment header
- Fix examples so they build on gcc 4.6
- Fix flag value for sniffer's immediate mode
- Fix IP fragment reassemble when packet has flags DF+MF
- Add extract_metadata to main PDU classes
- Fix examples to make them work on Windows
- Use timercmp/sub and std::chrono to subtract timevals on PacketSender
- Build examples against local libtins build
- Add uninstall target
- Prefix HAVE_ config.h macros with TINS_
- Use compiler intrinsics to swap bytes
- Use C++11 mode by default
- Add missing TINS_API to PDU classes.
- Extend/fix ICMPv6 enum values and unify naming
- Return an empty string for dot11 ssid, if ssid is present but empty
- Implement new TCP stream follower mechanism
- Use ExternalProject_Add rather than including the gtest directory
- Fix invalid endian on IP fragment offset on OSX
##### v3.3 - Sun Jan 31 21:06:04 PST 2016
- Add TCP connection close example
- 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.
- The functor used on BaseSniffer::sniff_loop can now take a Packet.
- Added mcs, tx_flags, ext and data_retries options to RadioTap.
- Fixed big endian representation of RadioTap header.
- RadioTap's dbm_signal and dbm_noise are now signed.
- RadioTap now throws if an option is not present when getting
its value.
- TKIP decryption now works correctly on packets from AP to STA.
- Added support for PKTAP header.
- Fixed endian issue on IPv4Address::ip_to_int on Windows.
- Fixed IP parsing when total length is 0 due to TCP segmentation offload.
- Re-added support for pkg-config.
- TCPStreamFollower now calls PDU::find_pdu instead of PDU::rfind_pdu.
- Fixed assertion throw caused by DNS parsing on Windows on debug mode.
- Added throw on BSD when trying to send_recv L3 packets.
- Added Loopback::matches_response.
- Removed obsolete autotools files.
- Fixed exception thrown when an interface didn't have an IP address
on NetworkInterface.
- Added NetworkInterface::is_loopback.
- Moved all headers to the directory include/tins.
- Fixed compilation warning on TCPStramFollower due to signed to unsigned
conversion on integral constant.
- BaseSniffer::get_pcap_handle is now public.
- PPPoE session packets are now parsed correctly.
- Fixed invalid Loopback protocol detection on FreeBSD/OSX.
- Fixed OSX IP packet sending issue.
- Added useful constructors to RawPDU.
- Fixed compilation errors on FreeBSD.
- Improved documentation on several classes.
- Fixed parsing bug when allocating IP over IP packets.
- Fixed Windows network interface naming.
- Utils::network_interface returns pcap compatible names on Windows.
- NetworkInterface::name now works on Windows.
- Added documentation generation through the build system.
- Added SnifferConfiguration class.
- Fixed bug on Dot3 serialization.
- Added OfflinePacketFilter class.
- Renamed NOEXCEPT macro to TINS_NOEXCEPT.
- Added DataLinkType class.
- 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.
- Fixed empty domain name encoding on DNS.
- 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.
- Packets can now be constructed from a PDU pointer and take ownership
of it.
- All protocols now set the next layer protocol flag, regardless if
it was already set. This was not done in some protocols,
like EthernetII, and as a consequence if the network layer protocol
was replaced by other, the packet would be serialized incorrectly.
- Fixed invalid parsing of some unknown DNS records.
- Fixed unaligned memory accesses that were not supported under
ARMv4 and ARMv5.
- Added BaseSniffer::set_extract_raw_pdus.
- Reduced minimum automake version to 1.11.
- Added Utils::to_string(PDU::PDUType).
- Fixed error compilations on Windows.
- Fixed ICMPv6 checksum calculation.
- Added method in IP and TCP to emplace an option (C++11 only).
- Added small option optimization to PDUOption.
- Fixed error compilation on RSNInformation.
- Renamed ICMP::check to ICMP::checksum.
- Added Sniffer support to set interface to promiscuous mode.
- TCPStreamFollower now handles overlapping fragments correctly.
- Fixed bugs in TCPStreamFollower which didn't allow it to follow
stream correctly.
- TCPStreamFollower now doesn't clear its state after every call to
TCPStreamFollower::follow_streams.
- Added IPv6 flag check to pdu_flag_to_ip_type.
- Added DHCP::hostname to extract the hostname options.
- Removed extra qualifier on SessionKeys::decrypt_unicast which
produced compilation errors on some platforms.
- PacketSender::send now uses PDU::matches_flag to match specific
PDU types.
- Removed 'no newline at end of file' warnings.
- Fixed bug when calling BIOCIMMEDIATE on *BSD.
- Fixed bug on PacketSender::send_recv which didn't work under *BSD.
- 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
DNS::Resource.
- tins.h now includes ppi.h.
- Done significant improvements in the speed of DNS parsing.
- Added PDUOption<>::to<> which converts a PDUOption to a specific type.
- Layer 3 packets sent using PacketSender::send_recv for which the
answer is a different PDU type.
- ICMP::gateway now uses IPv4Address.
- Added support for ICMP address mask request/reply.
- Fixed bug in PacketSender when using send_recv and a layer 2 PDU. The
interface in which the packet was sent was not the default_interface
set when the sender was constructed.
- IP packets sent using PacketSender::send_recv now match ICMP
responses.
- Added support for ICMP timestamp request/reply packets.
ICMP::matches_response now works with these types of packets as well.
- Added support for reassembling of fragmented IP packets via the
IPv4Reassembler class.
- Fragmented IP packet's inner_pdu PDUs are not decoded now.
- Added 1000ms as the default read timeout used when calling
pcap_open_live. Added BaseSniffer::set_timeout to modify this parameter.
- Added the --disable-dot11 configure switch.
- Added support for IPSec.
- Fixed bug triggered when ifaddrs::ifa_addr was null in
NetworkInterface::addresses.
- Added another overload of Utils::route_entries which returns the
result either than storing it in a parameter.
- Added ARP monitor, WPS detector, DNS queries sniffer and DNS spoofer
examples.
- Added another Sniffer constructor which doesn't expect the maximum
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.
- BaseSniffer::next_packet uses pcap_loop instead of pcap_next, which
doesn't work well on some linux distributions.
- Added PPI PDU class.
- Fixed a bug in EthernetII triggered when the size of the whole frame
was lower than 60 bytes.
- Added AddressRange class and IPv4Address, IPv6Address and
HWAddress<>::operator/.
- Added is_broadcast, is_multicast and is_unicast to IPv4, IPv6
and HWAddress.
- Added is_private and is_loopback methods to IPv4 and IPv6 addresses.
- Done some optimizations on TCP's constructor from buffer.
- Added helper functions to Dot11Data to retrieve the source,
destination and BSSID addresses.
- Fixed bugs in DNS triggered when parsing MX and unknown records.
- BaseSniffer::next_packet now iterates until a valid packet is found.
- TCP::get_flag is now const.
- The --disable-wpa2 now works as expected.
v1.1 - Wed Jun 5 09:03:37 ART 2013
- Implemented std::hash specialization for IPv4, IPv6 and HWAddress<>
types.
- Added a RSNHandshakeCapturer class.
- Added WPA2Decrypter class.
- IEEE 802.11 frames are not parsed if the RadioTap FAILED_FCS flag
is on.
- RadioTap now calculates its size everytime it's serialized.
- Splitted the dot11.h and dot11.cpp files into several files to
speed up compilation times.
- Added HWAddress<>::is_broadcast and HWAddress::operator[].
- Fixed a bug triggered when parsing Dot11QoSData frames.
v1.0 - Tue Apr 23 20:40:57 ART 2013
- Link layer protocol PDUs now don't hold a NetworkInterface. This led
to changes in their constructors.
- Removed the obsolete PDU* parameter taken by several classes'
constructors.
- IP now sets the sender's address automatically when no link layer
PDU is used.
- IP, TCP and UDP now calculate the checksum everytime they're
serialized.
- Added PDU::rfind_pdu.
- Defined several exception types.
- Implemented matches_response on several protocols.
- PacketSender is now movable.
- Added an overload of add_option that takes an rvalue-reference in IP,
TCP, DHCP, ICMPv6 and Dot11.
- Added support for GNU/kFreeBSD.
- Removed several deprecated methods, such as PDU::clone_packet.
- Added PacketSender::send(PDU&, NetworkInterface).
- Normalized the TLV options naming conventions in all of the classes
that used them.
- Added support for Dot1Q, STP, PPPoE protocols.
- Made some important optimizations on PDUOption<>'s constructors.
- Added Utils::resolve_domain and Utils::resolve_domain6
-------------------------------------------------------------------------------
##### v0.3 - Thu Jan 31 16:47:27 ART 2013
- Added IPv6, ICMPv6 and DHCPv6 classes.
- Added support for Loopback interfaces and the Linux Crooked Capture
pseudo protocol.
- Added support for IPv6 records in DNS.
- Added Packet/RefPacket class.
- Added support for FreeBSD, OSX and Windows.
- Added C++11 move semantics to several classes.
- Done a complete rewrite of the build system; it now uses libtool.
- Fixed several bugs in DNS.
-------------------------------------------------------------------------------
##### v0.2 - Sat Oct 20 11:26:40 2012
- Added support for big endian architectures.
- Simplified several interfaces.
- Added IPv4Address and HWAddress class to simplify handling IP and hardware addresses.
- Added NetworkInterface class to abstract network interfaces.
- Added TCPStreamFollower class to follow TCP streams on the fly.
- Added WEPDecrypter class to decrypt WEP-encrypted 802.11 data frames on the fly.
- Added several new PDUs: Loopback, IEEE802_3, LLC, DNS.
- Added support for reading and writing pcap files.
- Moved to BSD-2 license.

View File

@@ -1,22 +1,39 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.1)
PROJECT(libtins)
OPTION(LIBTINS_BUILD_EXAMPLES "Build examples" ON)
OPTION(LIBTINS_BUILD_TESTS "Build tests" ON)
# Compile in release mode by default
IF(NOT CMAKE_BUILD_TYPE)
MESSAGE(STATUS "Setting build type to 'RelWithDebInfo' as none was specified.")
SET(CMAKE_BUILD_TYPE RelWithDebInfo)
SET(CMAKE_BUILD_TYPE RelWithDebInfo)
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 -Wextra")
ENDIF()
IF(APPLE)
# This is set to ON as of policy CMP0042
SET(CMAKE_MACOSX_RPATH ON)
ENDIF()
# Build output checks
OPTION(LIBTINS_BUILD_SHARED "Build libtins as a shared library." ON)
IF(LIBTINS_BUILD_SHARED)
MESSAGE(
STATUS
STATUS
"Build will generate a shared library. "
"Use LIBTINS_BUILD_SHARED=0 to perform a static build"
)
@@ -24,18 +41,26 @@ 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 "${LIBTINS_VERSION_MAJOR}.${LIBTINS_VERSION_MINOR}")
SET(TINS_VERSION_MAJOR 4)
SET(TINS_VERSION_MINOR 5)
SET(TINS_VERSION_PATCH 0)
SET(LIBTINS_VERSION "${TINS_VERSION_MAJOR}.${TINS_VERSION_MINOR}")
# Required Packages
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/")
# Allow disabling packet capture mechanism
OPTION(LIBTINS_ENABLE_PCAP "Enable capturing packets via libpcap" ON)
# Look for libpcap
FIND_PACKAGE(PCAP REQUIRED)
IF(LIBTINS_ENABLE_PCAP)
FIND_PACKAGE(PCAP REQUIRED)
SET(TINS_HAVE_PCAP ON)
ENDIF()
# Set some Windows specific flags
IF(WIN32)
@@ -43,50 +68,153 @@ 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)
# MinWG need some extra definitions to compile properly (WIN32 for PCAP and WIN32_WINNT version for ws2tcpip.h)
IF(MINGW)
ADD_DEFINITIONS(-DWIN32)
MACRO(get_WIN32_WINNT version)
IF (WIN32 AND CMAKE_SYSTEM_VERSION)
SET(ver ${CMAKE_SYSTEM_VERSION})
STRING(REPLACE "." "" ver ${ver})
STRING(REGEX REPLACE "([0-9])" "0\\1" ver ${ver})
SET(${version} "0x${ver}")
ENDIF()
ENDMACRO()
get_WIN32_WINNT(ver)
ADD_DEFINITIONS(-D_WIN32_WINNT=${ver})
ENDIF(MINGW)
ENDIF(WIN32)
INCLUDE(ExternalProject)
# *******************
# Compilation options
OPTION(LIBTINS_ENABLE_CXX11 "Compile libtins with c++11 features" OFF)
# *******************
# Always check for C++ features
INCLUDE(CheckCXXFeatures)
IF(HAS_GCC_BUILTIN_SWAP)
SET(TINS_HAVE_GCC_BUILTIN_SWAP ON)
ENDIF()
# C++11 support
OPTION(LIBTINS_ENABLE_CXX11 "Compile libtins with c++11 features" ON)
IF(LIBTINS_ENABLE_CXX11)
SET(HAVE_CXX11 ON)
INCLUDE(CheckCXX11Features)
IF(HAS_CXX11_NULLPTR AND HAS_CXX11_RVALUE_REFERENCES)
# We only use declval and decltype on gcc/clang as VC fails to build that code,
# at least on VC2013
IF(HAS_CXX11_RVALUE_REFERENCES AND HAS_CXX11_FUNCTIONAL AND HAS_CXX11_CHRONO AND
HAS_CXX11_NOEXCEPT AND ((HAS_CXX11_DECLVAL AND HAS_CXX11_DECLTYPE) OR MSVC))
SET(TINS_HAVE_CXX11 ON)
MESSAGE(STATUS "Enabling C++11 features")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX11_COMPILER_FLAGS}")
ELSE(HAS_CXX11_NULLPTR AND HAS_CXX11_RVALUE_REFERENCES)
MESSAGE(FATAL_ERROR "C++11 features requested but the compiler does not support them.")
ENDIF(HAS_CXX11_NULLPTR AND HAS_CXX11_RVALUE_REFERENCES)
ELSE()
MESSAGE(WARNING "The compiler doesn't support the necessary C++11 features. "
"Disabling C++11 on this build")
ENDIF()
ELSE(LIBTINS_ENABLE_CXX11)
MESSAGE(
WARNING
WARNING
"Disabling C++11 features. Use LIBTINS_ENABLE_CXX11=1 to enable them. "
"Unless you are using an old compiler, you should enable this option, "
"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)
SET(HAVE_DOT11 ON)
SET(TINS_HAVE_DOT11 ON)
MESSAGE(STATUS "Enabling IEEE 802.11 support.")
IF(LIBTINS_ENABLE_WPA2)
FIND_PACKAGE(OpenSSL REQUIRED)
SET(HAVE_WPA2_DECRYPTION ON)
MESSAGE(STATUS "Enabling WPA2 decryption support.")
FIND_PACKAGE(OpenSSL)
IF(OPENSSL_FOUND)
SET(TINS_HAVE_WPA2_DECRYPTION ON)
MESSAGE(STATUS "Enabling WPA2 decryption support.")
ELSE()
MESSAGE(WARNING "Disabling WPA2 decryption support since OpenSSL was not found")
# Default this to empty strings
SET(OPENSSL_INCLUDE_DIR "")
SET(OPENSSL_LIBRARIES "")
ENDIF()
ELSE(LIBTINS_ENABLE_WPA2)
MESSAGE(STATUS "Disabling WPA2 decryption support.")
ENDIF(LIBTINS_ENABLE_WPA2)
ENDIF(LIBTINS_ENABLE_DOT11)
# Optionally enable TCPIP classes (on by default)
OPTION(LIBTINS_ENABLE_TCPIP "Enable TCPIP classes" ON)
IF(LIBTINS_ENABLE_TCPIP AND TINS_HAVE_CXX11)
SET(TINS_HAVE_TCPIP ON)
MESSAGE(STATUS "Enabling TCPIP classes")
ELSE()
SET(TINS_HAVE_TCPIP OFF)
MESSAGE(STATUS "Disabling TCPIP classes")
ENDIF()
# Search for libboost
FIND_PACKAGE(Boost)
# Optionally enable the ACK tracker (on by default)
OPTION(LIBTINS_ENABLE_ACK_TRACKER "Enable TCP ACK tracking support" ON)
IF(LIBTINS_ENABLE_ACK_TRACKER AND TINS_HAVE_CXX11)
IF (Boost_FOUND)
MESSAGE(STATUS "Enabling TCP ACK tracking support.")
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
SET(TINS_HAVE_ACK_TRACKER ON)
ELSE()
MESSAGE(WARNING "Disabling ACK tracking support as boost.icl was not found")
SET(TINS_HAVE_ACK_TRACKER OFF)
ENDIF()
ELSE()
SET(TINS_HAVE_ACK_TRACKER OFF)
MESSAGE(STATUS "Disabling ACK tracking support")
ENDIF()
# Optionally enable the TCP stream custom data (on by default)
OPTION(LIBTINS_ENABLE_TCP_STREAM_CUSTOM_DATA "Enable TCP stream custom data support" ON)
IF(LIBTINS_ENABLE_TCP_STREAM_CUSTOM_DATA AND TINS_HAVE_CXX11)
IF (Boost_FOUND)
MESSAGE(STATUS "Enabling TCP stream custom data support.")
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
SET(TINS_HAVE_TCP_STREAM_CUSTOM_DATA ON)
ELSE()
MESSAGE(WARNING "Disabling TCP stream custom data support as boost.any was not found")
SET(TINS_HAVE_TCP_STREAM_CUSTOM_DATA OFF)
ENDIF()
ELSE()
SET(TINS_HAVE_TCP_STREAM_CUSTOM_DATA OFF)
MESSAGE(STATUS "Disabling TCP stream custom data support")
ENDIF()
OPTION(LIBTINS_ENABLE_WPA2_CALLBACKS "Enable WPA2 callback interface" ON)
IF(LIBTINS_ENABLE_WPA2_CALLBACKS AND TINS_HAVE_WPA2_DECRYPTION AND TINS_HAVE_CXX11)
SET(STATUS "Enabling WPA2 callback interface")
SET(TINS_HAVE_WPA2_CALLBACKS ON)
ENDIF()
# Use pcap_sendpacket to send l2 packets rather than raw sockets
IF(WIN32)
SET(USE_PCAP_SENDPACKET_DEFAULT ON)
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_ENABLE_PCAP AND LIBTINS_USE_PCAP_SENDPACKET)
SET(TINS_HAVE_PACKET_SENDER_PCAP_SENDPACKET ON)
MESSAGE(STATUS "Using pcap_sendpacket to send l2 packets.")
ENDIF()
# Add a target to generate API documentation using Doxygen
FIND_PACKAGE(Doxygen QUIET)
IF(DOXYGEN_FOUND)
CONFIGURE_FILE(
${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile.in
${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile.in
${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
@ONLY
)
ADD_CUSTOM_TARGET(
@@ -97,35 +225,103 @@ IF(DOXYGEN_FOUND)
)
ENDIF(DOXYGEN_FOUND)
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
# Configuration file
CONFIGURE_FILE(
"${PROJECT_SOURCE_DIR}/include/tins/config.h.in"
"${PROJECT_SOURCE_DIR}/include/tins/config.h"
)
IF (NOT CMAKE_INSTALL_LIBDIR)
SET(CMAKE_INSTALL_LIBDIR lib)
ENDIF()
IF (NOT CMAKE_INSTALL_BINDIR)
SET(CMAKE_INSTALL_BINDIR bin)
ENDIF()
# The library output directory
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
# Support for pkg-config
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(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_SUBDIRECTORY(include)
# Confiugure the uninstall script
CONFIGURE_FILE(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY
)
# Add uninstall target
ADD_CUSTOM_TARGET(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
# ******************
# Add subdirectories
# ******************
ADD_SUBDIRECTORY(src)
ADD_SUBDIRECTORY(tests)
ADD_SUBDIRECTORY(examples)
IF(LIBTINS_BUILD_EXAMPLES)
IF(LIBTINS_ENABLE_PCAP)
ADD_SUBDIRECTORY(examples)
ELSE()
MESSAGE(STATUS "Not building examples as pcap support is disabled")
ENDIF()
ENDIF()
IF(LIBTINS_BUILD_TESTS)
# Only include googletest if the git submodule has been fetched
IF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/googletest/CMakeLists.txt")
# Enable tests and add the test directory
MESSAGE(STATUS "Tests have been enabled")
SET(GOOGLETEST_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/googletest)
SET(GOOGLETEST_INCLUDE ${GOOGLETEST_ROOT}/googletest/include)
SET(GOOGLETEST_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/googletest)
SET(GOOGLETEST_LIBRARY ${GOOGLETEST_BINARY_DIR}/googletest)
ExternalProject_Add(
googletest
DOWNLOAD_COMMAND ""
SOURCE_DIR ${GOOGLETEST_ROOT}
BINARY_DIR ${GOOGLETEST_BINARY_DIR}
CMAKE_CACHE_ARGS "-DBUILD_GTEST:bool=ON" "-DBUILD_GMOCK:bool=OFF"
"-Dgtest_force_shared_crt:bool=ON"
"-DCMAKE_CXX_COMPILER:path=${CMAKE_CXX_COMPILER}"
INSTALL_COMMAND ""
)
# Make sure we build googletest before anything else
ADD_DEPENDENCIES(tins googletest)
ENABLE_TESTING()
ADD_SUBDIRECTORY(tests)
ELSE()
FIND_PACKAGE(GTest QUIET)
IF(${GTest_FOUND})
ENABLE_TESTING()
ADD_SUBDIRECTORY(tests)
ELSE()
MESSAGE(STATUS "googletest git submodule is absent. Run `git submodule init && git submodule update` to get it")
ENDIF()
ENDIF()
ENDIF()
# **********************************
# CMake project configuration export
# **********************************
if(UNIX)
set(CONF_CMAKE_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/libtins")
else()
set(CONF_CMAKE_INSTALL_DIR CMake)
endif()
# Add all targets to the build-tree export set
EXPORT(
@@ -153,13 +349,13 @@ INSTALL(
FILES
"${PROJECT_BINARY_DIR}/libtinsConfig.cmake"
"${PROJECT_BINARY_DIR}/libtinsConfigVersion.cmake"
DESTINATION CMake
DESTINATION ${CONF_CMAKE_INSTALL_DIR}
COMPONENT dev
)
# Install the export set for use with the install-tree
INSTALL(
EXPORT libtinsTargets
DESTINATION CMake
DESTINATION ${CONF_CMAKE_INSTALL_DIR}
COMPONENT dev
)

27
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,27 @@
# Contributing
Bug reports and enhancements to the library are really valued and appreciated!
# Bug reports
If you find a bug, please report it! Bugs on the library are taken seriously
and a patch for them is usually pushed on the same day.
When reporting a bug, please make sure to indicate the platform (e.g. GNU/Linux, Windows, OSX)
in which you came across the issue, as this is essential to finding the cause.
## Packet parsing bugs
If you find a bug related to packet parsing (e.g. a field on a packet contains an
invalid value), please try to provide a pcap file that contains the packet that
was incorrectly parsed. Doing this will make it very simple to find the issue, plus
you will be asked to provide this file anyway, so this just makes things
easier.
# Pull requests
Pull requests are very welcomed. When doing a pull request please:
* Notice that your code will be compiled and tests will be run automatically by the travis and
appveyor CI tools. If your code has issues on any of the tested platforms (GNU/Linux, Windows
and OSX), please fix it or otherwise the PR won't be merged.

View File

@@ -1,4 +1,4 @@
Copyright (c) 2012-2014, Matias Fontanini
Copyright (c) 2012-2017, Matias Fontanini
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,7 @@
libtins
=======
# libtins
[![Build status](https://travis-ci.org/mfontanini/libtins.svg?branch=master)](https://travis-ci.org/mfontanini/libtins)
[![Build status](https://ci.appveyor.com/api/projects/status/33n8ib68nx3tptib/branch/master?svg=true)](https://ci.appveyor.com/project/mfontanini/libtins/branch/master)
libtins is a high-level, multiplatform C++ network packet sniffing and
crafting library.
@@ -34,6 +36,7 @@ cmake ../
make
```
### Static/shared build
Note that by default, only the shared object is compiled. If you would
like to generate a static library file, run:
@@ -44,7 +47,9 @@ cmake ../ -DLIBTINS_BUILD_SHARED=0
The generated static/shared library files will be located in the
_build/lib_ directory.
libtins is noticeable faster if you enable _C++11_ support. Therefore,
### C++11 support
libtins is noticeably faster if you enable _C++11_ support. Therefore,
if your compiler supports this standard, then you should enable it.
In order to do so, use the _LIBTINS_ENABLE_CXX11_ switch:
@@ -52,6 +57,22 @@ In order to do so, use the _LIBTINS_ENABLE_CXX11_ switch:
cmake ../ -DLIBTINS_ENABLE_CXX11=1
```
### TCP ACK tracker
The TCP ACK tracker feature requires the boost.icl library (header only).
This feature is enabled by default but will be disabled if the boost
headers are not found. You can disable this feature by using:
```Shell
cmake ../ -DLIBTINS_ENABLE_ACK_TRACKER=0
```
If your boost installation is on some non-standard path, use
the parameters shown on the
[CMake FindBoost help](https://cmake.org/cmake/help/v3.0/module/FindBoost.html)
### WPA2 decryption
If you want to disable _WPA2_ decryption support, which will remove
openssl as a dependency for compilation, use the
_LIBTINS_ENABLE_WPA2_ switch:
@@ -60,6 +81,8 @@ _LIBTINS_ENABLE_WPA2_ switch:
cmake ../ -DLIBTINS_ENABLE_WPA2=0
```
### IEEE 802.11 support
If you want to disable IEEE 802.11 support(this will also disable
RadioTap and WPA2 decryption), which will reduce the size of the
resulting library in around 20%, use the _LIBTINS_ENABLE_DOT11_ switch:
@@ -85,9 +108,40 @@ 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"
directory. The same samples can be found online at:
http://libtins.github.io/examples/
## Contributing ##
If you want to report a bug or make a pull request, please have a look at
the [contributing](CONTRIBUTING.md) file before doing so.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,7 @@
int foo() noexcept {
return 0;
}
int main() {
return foo();
}

View File

@@ -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,8 @@ 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)
check_function_exists(pcap_set_tstamp_precision HAVE_PCAP_TIMESTAMP_PRECISION)
set(CMAKE_REQUIRED_LIBRARIES)
mark_as_advanced(

53
cmake/appveyor.yml Normal file
View File

@@ -0,0 +1,53 @@
version: 1.0.{build}
configuration:
- debug
- release
platform:
- Win32
- x64
environment:
matrix:
- compiler: vs2013
- compiler: vs2015
BOOST_ROOT: C:/Libraries/boost
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 "%compiler%"=="vs2013" (set VS_VERSION=12) else (set VS_VERSION=14)
- set VS=Visual Studio %VS_VERSION%
- if "%platform%"=="Win32" (set GENERATOR="%VS%" & set ARCH_BITS=32)
- if "%platform%"=="x64" (set GENERATOR="%VS% Win64" & set ARCH_BITS=64)
- set BOOST_LIBRARYDIR=C:\Libraries\boost\lib%ARCH_BITS%-msvc-%VS_VERSION%.0
- cmake .. -G %GENERATOR% -DPCAP_ROOT_DIR=c:\WpdPack -DLIBTINS_BUILD_SHARED=0 -DLIBTINS_ENABLE_WPA2=0 -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_LIBRARYDIR%" -DBoost_USE_STATIC_LIBS="ON"
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-%compiler%-%platform%-%Configuration%.zip libtins
test_script:
- cd c:\projects\libtins\build
- ctest -C %Configuration% -V
deploy_script:
- ps: Push-AppveyorArtifact "install\libtins-$env:Compiler-$env:Platform-$env:Configuration.zip"
skip_commits:
message: /Update documentation.*/

View File

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

View File

@@ -1365,7 +1365,9 @@ INCLUDE_FILE_PATTERNS =
# undefined via #undef or recursively expanded use the := operator
# instead of the = operator.
PREDEFINED =
PREDEFINED = "TINS_IS_CXX11=1" \
"TINS_HAVE_WPA2_CALLBACKS=1" \
"TINS_HAVE_DOT11=1"
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, 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;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, 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(5000);
#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;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, 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);
}

118
examples/defragmenter.cpp Normal file
View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, 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,18 +45,18 @@ 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
// Sniff on the provided interface in promiscuous mode
SnifferConfiguration config;
config.set_promisc_mode(true);
// Only capture udp packets sent to port 53

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, 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,13 +50,13 @@ 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(
DNS::resource(
query.dname(),
"127.0.0.1",
DNS::A,
@@ -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,15 +85,16 @@ 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
// Sniff on the provided interface in promiscuous mode
SnifferConfiguration config;
config.set_promisc_mode(true);
// Use immediate mode so we get the packets as fast as we can
config.set_immediate_mode(true);
// Only capture udp packets sent to port 53
config.set_filter("udp and dst port 53");
Sniffer sniffer(argv[1], config);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,6 +27,13 @@
*
*/
#ifdef _WIN32
#define NOMINMAX
#endif // _WIN32
// Fix for gcc 4.6
#define _GLIBCXX_USE_NANOSLEEP
#include <iostream>
#include <mutex>
#include <chrono>
@@ -35,6 +42,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
@@ -42,8 +68,8 @@ using namespace Tins;
template<typename Duration>
class statistics {
public:
using duration_type = Duration;
using locker_type = std::lock_guard<std::mutex>;
typedef Duration duration_type;
typedef lock_guard<mutex> locker_type;
struct information {
duration_type average, worst;
@@ -51,65 +77,63 @@ 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;
typedef milliseconds duration_type;
// The statistics type used.
using statistics_type = statistics<duration_type>;
typedef statistics<duration_type> statistics_type;
void run(BaseSniffer& sniffer);
const statistics_type& stats() const {
return m_stats;
}
private:
using packet_info = std::tuple<IPv4Address, IPv4Address, uint16_t>;
using clock_type = std::chrono::steady_clock;
using time_point_type = std::chrono::time_point<clock_type>;
typedef tuple<IPv4Address, IPv4Address, uint16_t> packet_info;
typedef system_clock clock_type;
typedef clock_type::time_point time_point_type;
bool callback(const PDU& pdu);
static packet_info make_packet_info(const PDU& pdu, const DNS& dns);
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 +141,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 +154,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 +171,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;
}
}

147
examples/http_requests.cpp Normal file
View File

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

140
examples/icmp_responses.cpp Normal file
View 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;
}
}

View File

@@ -0,0 +1,87 @@
/*
* 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 <sstream>
#include <tins/network_interface.h>
using std::cout;
using std::wcout;
using std::endl;
using std::string;
using std::ostringstream;
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;
#ifdef _WIN32
// If this is running on Windows, also print the friendly name
wcout << " (" << iface.friendly_name() << ")";
#endif // _WIN32
cout << ": " << endl;
string ipv6_string;
if (info.ipv6_addrs.empty()) {
ipv6_string = "(none)";
}
else {
ostringstream oss;
for (size_t i = 0; i < info.ipv6_addrs.size(); ++i) {
const NetworkInterface::IPv6Prefix& prefix = info.ipv6_addrs[i];
if (i > 0) {
oss << ", ";
}
oss << prefix.address << "/" << prefix.prefix_length;
}
ipv6_string = oss.str();
}
cout << " HW address: " << info.hw_addr << endl
<< " IP address: " << info.ip_addr << endl
<< " IPv6 addresses: " << ipv6_string << endl
<< " Netmask: " << info.netmask << endl
<< " Broadcast: " << info.bcast_addr << endl
<< " Iface index: " << iface.id() << endl
<< " Status: " << "interface " << status << endl << endl;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, 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) {
@@ -110,15 +116,14 @@ bool Scanner::callback(PDU &pdu)
cout << "Port: " << setw(5) << tcp.sport() << " closed\n";
}
// Is SYN flag on? Then port is open!
else if(tcp.flags() == (TCP::SYN | TCP::ACK)) {
else if(tcp.has_flags(TCP::SYN | TCP::ACK)) {
cout << "Port: " << setw(5) << tcp.sport() << " open\n";
}
}
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;
}
}

69
examples/route_table.cpp Normal file
View File

@@ -0,0 +1,69 @@
/*
* 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> v4_entries = Utils::route_entries();
cout << "IPv4 route table entries: " << endl
<< "========================= " << endl;
for (size_t i = 0; i < v4_entries.size(); ++i) {
cout << "Entry " << setw(2) << i << ": " << endl
<< "Interface: " << v4_entries[i].interface << endl
<< "Destination: " << v4_entries[i].destination << endl
<< "Gateway: " << v4_entries[i].gateway << endl
<< "Genmask: " << v4_entries[i].mask << endl
<< "Metric: " << v4_entries[i].metric << endl << endl;
}
vector<Utils::Route6Entry> v6_entries = Utils::route6_entries();
if (!v6_entries.empty()) {
cout << endl
<< "IPv6 route table entries: " << endl
<< "========================= " << endl;
for (size_t i = 0; i < v6_entries.size(); ++i) {
cout << "Entry " << setw(2) << i << ": " << endl
<< "Interface: " << v6_entries[i].interface << endl
<< "Destination: " << v6_entries[i].destination << endl
<< "Gateway: " << v6_entries[i].gateway << endl
<< "Genmask: " << v6_entries[i].mask << endl
<< "Metric: " << v6_entries[i].metric << endl << endl;
}
}
}

192
examples/stream_dump.cpp Normal file
View File

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

View File

@@ -0,0 +1,107 @@
/*
* Copyright (c) 2017, 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 <functional>
#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.has_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;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,15 +27,45 @@
*
*/
#ifdef _WIN32
#define NOMINMAX
#endif // _WIN32
// Fix for gcc 4.6
#define _GLIBCXX_USE_NANOSLEEP
#include <iostream>
#include <iomanip>
#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 +73,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 +95,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));
// Give it a little time
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;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, 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

Submodule googletest added at 13206d6f53

View File

@@ -1 +0,0 @@
ADD_SUBDIRECTORY(tins)

View File

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

View File

@@ -1,18 +1,18 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, 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
@@ -30,19 +30,23 @@
#ifndef TINS_ADDRESS_RANGE
#define TINS_ADDRESS_RANGE
#include <stdexcept>
#include <iterator>
#include "endianness.h"
#include "internals.h"
#include <tins/endianness.h>
#include <tins/exceptions.h>
#include <tins/detail/address_helpers.h>
namespace Tins {
/**
* \brief AddressRange iterator class.
*/
template<typename Address>
class AddressRangeIterator : public std::iterator<std::forward_iterator_tag, const Address> {
class AddressRangeIterator {
public:
typedef typename std::iterator<std::forward_iterator_tag, const Address>::value_type value_type;
typedef std::forward_iterator_tag iterator_category;
typedef const Address value_type;
typedef std::ptrdiff_t difference_type;
typedef const Address* pointer;
typedef const Address& reference;
struct end_iterator {
@@ -53,9 +57,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 +67,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 +91,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 +100,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 +108,8 @@ public:
* Increments this iterator.
*/
AddressRangeIterator& operator++() {
reached_end = Internals::increment(addr);
return *this;
reached_end_ = Internals::increment(address_);
return* this;
}
/**
@@ -119,47 +121,47 @@ public:
return copy;
}
private:
Address addr;
bool reached_end;
Address address_;
bool reached_end_;
};
/**
* \brief Represents a range of addresses.
*
* This class provides a begin()/end() interface which allows
* iterating through every address stored in it.
* iterating through every address stored in it.
*
* Note that when iterating a range that was created using
* operator/(IPv4Address, int) and the analog for IPv6, the
* operator/(IPv4Address, int) and the analog for IPv6, the
* network and broadcast addresses are discarded:
*
* \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);
* }
*
* // That's only valid for iteration, not for AddressRange<>::contains
*
*
* assert(range.contains("192.168.5.0")); // works
* assert(range.contains("192.168.5.255")); // works
* \endcode
*
* Ranges created using AddressRange(address_type, address_type)
* Ranges created using AddressRange(address_type, address_type)
* will allow the iteration over the entire range:
*
* \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);
* }
*
*
* assert(range.contains("192.168.5.0")); // still valid
* assert(range.contains("192.168.5.255")); // still valid
* \endcode
*
*
*/
template<typename Address>
class AddressRange {
@@ -188,20 +190,20 @@ public:
* The range will consist of the addresses [first, last].
*
* If only_hosts is true, then the network and broadcast addresses
* will not be available when iterating the range.
* will not be available when iterating the range.
*
* If last < first, an std::runtime_error exception is thrown.
*
*
* \param first The first address in the range.
* \param last The last address(inclusive) in the range.
* \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)
throw std::runtime_error("Invalid address range");
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 exception_base("Invalid address range");
}
}
/**
@@ -211,10 +213,10 @@ 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),
first & mask,
Internals::last_address_from_mask(first, mask),
true
);
}
@@ -224,8 +226,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 +235,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,43 +247,46 @@ 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());
}
/**
* \brief Indicates whether this range is iterable.
*
* Iterable ranges are those for which there is at least one
* Iterable ranges are those for which there is at least one
* address that could represent a host. For IPv4 ranges, a /31 or
* /32 ranges does not contain any, therefore it's not iterable.
* The same is true for /127 and /128 IPv6 ranges.
*
* If is_iterable returns false for a range, then iterating it
* through the iterators returned by begin() and end() is
* undefined.
*
* through the iterators returned by begin() and end() is
* undefined.
*
* \return bool indicating whether this range is iterable.
*/
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 +305,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 +325,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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,287 +31,314 @@
#ifndef TINS_ARP_H
#define TINS_ARP_H
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
#include "hw_address.h"
#include "ip_address.h"
#include <tins/macros.h>
#include <tins/pdu.h>
#include <tins/endianness.h>
#include <tins/hw_address.h>
#include <tins/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 Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Constructs an ARP object using the provided addresses.
*
* 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 EthernetII object containing the ARP Reply.
*/
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);
arp_header header_;
};
} // Tins
#endif // TINS_ARP_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,333 +31,333 @@
#define TINS_BOOTP_H
#include <stdint.h>
#include <algorithm>
#include <vector>
#include "pdu.h"
#include "macros.h"
#include "endianness.h"
#include "ip_address.h"
#include "hw_address.h"
#include <tins/pdu.h>
#include <tins/macros.h>
#include <tins/endianness.h>
#include <tins/ip_address.h>
#include <tins/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) {
size_t copy_threshold = std::min(n, sizeof(bootp_.chaddr));
for (size_t i = 0; i < copy_threshold; ++i) {
if (i < copy_threshold) {
bootp_.chaddr[i] = new_chaddr[i];
}
else {
bootp_.chaddr[i] = 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);
/**
* 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;
private:
bootp_header bootp_;
vend_type vend_;
};
} // Tins
#endif // TINS_BOOTP_H

View File

@@ -2,12 +2,38 @@
#define TINS_CONFIG_H
/* Define if the compiler supports basic C++11 syntax */
#cmakedefine HAVE_CXX11
#cmakedefine TINS_HAVE_CXX11
/* Have IEEE 802.11 support */
#cmakedefine HAVE_DOT11
#cmakedefine TINS_HAVE_DOT11
/* Have WPA2 decryption library */
#cmakedefine HAVE_WPA2_DECRYPTION
#cmakedefine TINS_HAVE_WPA2_DECRYPTION
/* Use pcap_sendpacket to send l2 packets */
#cmakedefine TINS_HAVE_PACKET_SENDER_PCAP_SENDPACKET
/* Have TCPIP classes */
#cmakedefine TINS_HAVE_TCPIP
/* Have TCP ACK tracking */
#cmakedefine TINS_HAVE_ACK_TRACKER
/* Have TCP stream custom data */
#cmakedefine TINS_HAVE_TCP_STREAM_CUSTOM_DATA
/* Have GCC builtin swap */
#cmakedefine TINS_HAVE_GCC_BUILTIN_SWAP
/* Have WPA2Decrypter callbacks */
#cmakedefine TINS_HAVE_WPA2_CALLBACKS
/* Have libpcap */
#cmakedefine TINS_HAVE_PCAP
/* Version macros */
#define TINS_VERSION_MAJOR ${TINS_VERSION_MAJOR}
#define TINS_VERSION_MINOR ${TINS_VERSION_MINOR}
#define TINS_VERSION_PATCH ${TINS_VERSION_PATCH}
#endif // TINS_CONFIG_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, 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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,389 +27,510 @@
*
*/
#include "config.h"
#include <tins/config.h>
#if !defined(TINS_CRYPTO_H) && defined(HAVE_DOT11)
#if !defined(TINS_CRYPTO_H) && defined(TINS_HAVE_DOT11)
#define TINS_CRYPTO_H
#include <map>
#include <string>
#include <algorithm>
#include <vector>
#include "utils.h"
#include "snap.h"
#include "rawpdu.h"
#include "handshake_capturer.h"
#ifdef TINS_HAVE_WPA2_CALLBACKS
#include <functional>
#endif // TINS_HAVE_WPA2_CALLBACKS
#include <tins/macros.h>
#include <tins/handshake_capturer.h>
namespace Tins {
class PDU;
class Dot11;
class Dot11Data;
class SNAP;
class RawPDU;
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
#ifdef TINS_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;
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;
template<typename Functor, typename Decrypter>
typename DecrypterProxy<Functor, Decrypter>::decrypter_type &
DecrypterProxy<Functor, Decrypter>::decrypter()
{
return decrypter_;
}
/**
* \brief Getter for the SSID
* \return The access point's SSID
*/
const std::string& ssid() const;
private:
pmk_type pmk_;
std::string ssid_;
};
template<typename Functor, typename Decrypter>
const typename DecrypterProxy<Functor, Decrypter>::decrypter_type &
DecrypterProxy<Functor, Decrypter>::decrypter() const
{
return decrypter_;
}
} // WPA2
#endif // TINS_HAVE_WPA2_DECRYPTION
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);
}
/**
* \brief Decrypts WEP-encrypted traffic.
*/
class TINS_API WEPDecrypter {
public:
typedef HWAddress<6> address_type;
// RC4 stuff
/**
* \brief Constructs a WEPDecrypter object.
*/
WEPDecrypter();
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]);
}
}
/**
* \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);
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 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 TINS_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;
#ifdef TINS_HAVE_WPA2_CALLBACKS
/**
* \brief The type used to store the callback type used when a new access
* point is found.
*
* The first argument to the function will be the access point's SSID and
* the second one its BSSID.
*/
typedef std::function<void(const std::string&,
const address_type&)> ap_found_callback_type;
/**
* The type used to store the callback type used when a new handshake
* is captured.
*
* The first argument to the function will be the access point's SSID and
* the second one its BSSID. The third argument will be the client's hardware
* address.
*/
typedef std::function<void(const std::string&,
const address_type&,
const address_type&)> handshake_captured_callback_type;
#endif // TINS_HAVE_WPA2_CALLBACKS
/**
* \brief Adds an access points's information.
*
* 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);
#ifdef TINS_HAVE_WPA2_CALLBACKS
/**
* \brief Sets the handshake captured callback
*
* This callback will be executed every time a new handshake is captured.
*
* \sa handshake_captured_callback_type
* \param callback The new callback to be set
*/
void handshake_captured_callback(const handshake_captured_callback_type& callback);
/**
* \brief Sets the access point found callback
*
* This callback will be executed every time a new access point is found, that's
* advertising an SSID added when calling add_ap_data.
*
* \sa ap_found_callback_type
* \param callback The new callback to be set
*/
void ap_found_callback(const ap_found_callback_type& callback);
#endif // TINS_HAVE_WPA2_CALLBACKS
/**
* \brief Getter for the keys on this decrypter
*
* 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_;
#ifdef TINS_HAVE_WPA2_CALLBACKS
handshake_captured_callback_type handshake_captured_callback_;
ap_found_callback_type ap_found_callback_;
#endif // TINS_HAVE_WPA2_CALLBACKS
};
#endif // TINS_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 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 TINS_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 // TINS_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);
}
} // Crypto
} // Tins
#endif // TINS_CRYPTO_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,7 +30,7 @@
#ifndef TINS_CXXSTD_H
#define TINS_CXXSTD_H
#include <memory>
#include <tins/config.h>
#ifdef __GXX_EXPERIMENTAL_CXX0X__
#define TINS_CXXSTD_GCC_FIX 1
@@ -38,20 +38,15 @@
#define TINS_CXXSTD_GCC_FIX 0
#endif // __GXX_EXPERIMENTAL_CXX0X__
#ifndef TINS_IS_CXX11
#if !defined(TINS_IS_CXX11) && defined(TINS_HAVE_CXX11)
#define TINS_IS_CXX11 (__cplusplus > 199711L || TINS_CXXSTD_GCC_FIX == 1 || _MSC_VER >= 1800)
#elif !defined(TINS_IS_CXX11)
#define TINS_IS_CXX11 0
#endif // TINS_IS_CXX11
namespace Tins{
namespace Internals {
template<typename T>
struct smart_ptr {
#if TINS_IS_CXX11
typedef std::unique_ptr<T> type;
#else
typedef std::auto_ptr<T> type;
#endif
};
template<class T> void unused(const T&) { }
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -41,6 +41,7 @@ class Dot3;
class SLL;
class Loopback;
class PPI;
class IP;
/**
* \struct DataLinkType
@@ -73,6 +74,7 @@ TINS_MAKE_DATA_LINK_TYPE(Loopback, DLT_LOOP)
TINS_MAKE_DATA_LINK_TYPE(PPI, DLT_PPI)
TINS_MAKE_DATA_LINK_TYPE(Dot11, DLT_IEEE802_11)
TINS_MAKE_DATA_LINK_TYPE(RadioTap, DLT_IEEE802_11_RADIO)
TINS_MAKE_DATA_LINK_TYPE(IP, DLT_RAW)
#undef TINS_MAKE_DATA_LINK_TYPE

View File

@@ -0,0 +1,106 @@
/*
* Copyright (c) 2017, 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_ADDRESS_HELPERS_H
#define TINS_ADDRESS_HELPERS_H
#include <tins/hw_address.h>
/**
* \cond
*/
namespace Tins {
class IPv4Address;
class IPv6Address;
namespace Internals {
template<typename T>
bool increment_buffer(T& addr) {
typename T::iterator it = addr.end() - 1;
while (it >= addr.begin() && *it == 0xff) {
*it = 0;
--it;
}
// reached end
if (it < addr.begin()) {
return true;
}
(*it)++;
return false;
}
template<typename T>
bool decrement_buffer(T& addr) {
typename T::iterator it = addr.end() - 1;
while (it >= addr.begin() && *it == 0) {
*it = 0xff;
--it;
}
// reached end
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);
template<size_t n>
bool increment(HWAddress<n>& addr) {
return increment_buffer(addr);
}
template<size_t n>
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);
template<size_t n>
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) {
*addr_iter = *addr_iter | ~*it;
}
return addr;
}
} // Internals
} // Tins
/**
* \endcond
*/
#endif // TINS_ADDRESS_HELPERS_H

View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) 2017, 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_HELPERS_H
#define TINS_ICMP_EXTENSION_HELPERS_H
#include <stdint.h>
/**
* \cond
*/
namespace Tins {
class PDU;
class ICMPExtensionsStructure;
namespace Memory {
class InputMemoryStream;
} // Memory
namespace Internals {
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);
} // Internals
} // Tins
/**
* \endcond
*/
#endif // TINS_ICMP_EXTENSION_HELPERS_H

View File

@@ -0,0 +1,70 @@
/*
* Copyright (c) 2017, 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_PDU_HELPERS_H
#define TINS_PDU_HELPERS_H
#include <tins/constants.h>
#include <tins/config.h>
#include <tins/pdu.h>
/**
* \cond
*/
namespace Tins {
namespace Internals {
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,
uint32_t size, bool rawpdu_on_no_match = true);
#ifdef TINS_HAVE_PCAP
PDU* pdu_from_dlt_flag(int flag, const uint8_t* buffer,
uint32_t size, bool rawpdu_on_no_match = true);
#endif // TINS_HAVE_PCAP
PDU* pdu_from_flag(PDU::PDUType type, const uint8_t* buffer, uint32_t size);
Constants::Ethernet::e pdu_flag_to_ether_type(PDU::PDUType flag);
PDU::PDUType ether_type_to_pdu_flag(Constants::Ethernet::e flag);
Constants::IP::e pdu_flag_to_ip_type(PDU::PDUType flag);
PDU::PDUType ip_type_to_pdu_flag(Constants::IP::e flag);
inline bool is_dot3(const uint8_t* ptr, size_t sz) {
return (sz >= 13 && ptr[12] < 8);
}
} // Internals
} // Tins
/**
* \endcond
*/
#endif // TINS_PDU_HELPERS_H

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 2017, 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_SEQUENCE_NUMBER_HELPERS_H
#define TINS_SEQUENCE_NUMBER_HELPERS_H
#include <stdint.h>
/**
* \cond
*/
namespace Tins {
namespace Internals {
// Compares sequence numbers as defined by RFC 1982.
int seq_compare(uint32_t seq1, uint32_t seq2);
} // namespace Internals
} // namespace Tins
/**
* \endcond
*/
#endif // TINS_SEQUENCE_NUMBER_HELPERS_H

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2017, 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_SMART_PTR_H
#define TINS_SMART_PTR_H
#include <memory>
#include <tins/cxxstd.h>
namespace Tins {
namespace Internals {
template<typename T>
struct smart_ptr {
#if TINS_IS_CXX11
typedef std::unique_ptr<T> type;
#else
typedef std::auto_ptr<T> type;
#endif
};
} // Internals
} // Tins
#endif // TINS_SMART_PTR_H

View File

@@ -0,0 +1,127 @@
/*
* Copyright (c) 2017, 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_TYPE_TRAITS_H
#define TINS_TYPE_TRAITS_H
#include <stdint.h>
#include <tins/cxxstd.h>
#if TINS_IS_CXX11
#include <type_traits>
#include <utility>
#endif
namespace Tins {
namespace Internals {
/**
* \cond
*/
template<bool, typename T = void>
struct enable_if {
typedef T type;
};
template<typename T>
struct enable_if<false, T> {
};
template <typename T>
struct type_to_type {
typedef T type;
};
template<typename T>
struct is_unsigned_integral {
static const bool value = false;
};
template<>
struct is_unsigned_integral<uint8_t> {
static const bool value = true;
};
template<>
struct is_unsigned_integral<uint16_t> {
static const bool value = true;
};
template<>
struct is_unsigned_integral<uint32_t> {
static const bool value = true;
};
template<>
struct is_unsigned_integral<uint64_t> {
static const bool value = true;
};
#if TINS_IS_CXX11 && !defined(_MSC_VER)
// Template metaprogramming trait to determine if a functor can accept another parameter as an argument
template <typename T, typename P, typename=void>
struct accepts_type : std::false_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 <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));
}
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);
}
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());
}
#endif
/**
* \endcond
*/
} // Internals
} // Tins
#endif // TINS_TYPE_TRAITS_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,481 +30,503 @@
#ifndef TINS_DHCP_H
#define TINS_DHCP_H
#include <list>
#include <vector>
#include <string>
#include "bootp.h"
#include "pdu_option.h"
#include "cxxstd.h"
#include <tins/bootp.h>
#include <tins/macros.h>
#include <tins/pdu_option.h>
#include <tins/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::vector<option> options_type;
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Creates an instance of DHCP.
*
* 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 The list of 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);
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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,19 +31,25 @@
#define TINS_DHCPV6_H
#include <cstring>
#include <list>
#include "pdu.h"
#include "endianness.h"
#include "small_uint.h"
#include "ipv6_address.h"
#include "pdu_option.h"
#include <tins/pdu.h>
#include <tins/macros.h>
#include <tins/endianness.h>
#include <tins/small_uint.h>
#include <tins/ipv6_address.h>
#include <tins/pdu_option.h>
namespace Tins {
namespace Memory {
class OutputMemoryStream;
} // Memory
namespace Tins {
/**
* \class DHCPv6
* \brief Represents a DHCPv6 PDU.
*/
class DHCPv6 : public PDU {
class TINS_API DHCPv6 : public PDU {
public:
/**
* Represents a DHCPv6 option.
@@ -156,7 +162,7 @@ public:
/**
* The type used to store the DHCPv6 options.
*/
typedef std::list<option> options_type;
typedef std::vector<option> options_type;
/**
* The type used to store IP addresses.
@@ -182,7 +188,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 +205,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 +224,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 +239,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 +253,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 +269,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 +289,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 +305,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 +325,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 +344,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 +363,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 +381,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)
: id(duid_en::duid_id), data(identifier.serialize()) {}
duid_type(const duid_ll& identifier)
: id(duid_ll::duid_id), data(identifier.serialize()) {}
static duid_type from_option(const option &opt);
static duid_type from_option(const option& opt);
};
/**
@@ -408,6 +411,14 @@ public:
*/
typedef std::vector<uint8_t> interface_id_type;
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/**
* Default constructor.
*/
@@ -423,7 +434,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 +444,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 +452,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 +462,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 +470,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 +519,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 +692,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 +700,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 +735,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 +768,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 +808,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,117 +832,92 @@ 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
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
* This method overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \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);
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)
{
size_t index = start_index;
uint16_t uint16_t_buffer;
while(start != end) {
buffer.resize(buffer.size() + sizeof(uint16_t) + start->size());
uint16_t_buffer = Endian::host_to_be<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);
index += start->size();
start++;
}
}
template<typename OutputType>
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) {
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)
throw option_not_found();
output.push_back(
value_type(ptr + index, ptr + index + size)
);
index += size;
}
if(index != total_sz)
throw malformed_option();
return output;
}
}
}
} // Tins
#endif // TINS_DHCPV6_H

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,18 +27,18 @@
*
*/
#include "config.h"
#include <tins/config.h>
#if !defined(TINS_DOT_11) && defined(HAVE_DOT11)
#if !defined(TINS_DOT_11) && defined(TINS_HAVE_DOT11)
#define TINS_DOT_11
#include "dot11/dot11_base.h"
#include "dot11/dot11_data.h"
#include "dot11/dot11_mgmt.h"
#include "dot11/dot11_beacon.h"
#include "dot11/dot11_assoc.h"
#include "dot11/dot11_auth.h"
#include "dot11/dot11_probe.h"
#include "dot11/dot11_control.h"
#include <tins/dot11/dot11_base.h>
#include <tins/dot11/dot11_data.h>
#include <tins/dot11/dot11_mgmt.h>
#include <tins/dot11/dot11_beacon.h>
#include <tins/dot11/dot11_assoc.h>
#include <tins/dot11/dot11_auth.h>
#include <tins/dot11/dot11_probe.h>
#include <tins/dot11/dot11_control.h>
#endif // TINS_DOT_11

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,19 +27,20 @@
*
*/
#include "../config.h"
#include <tins/config.h>
#if !defined(TINS_DOT11_DOT11_ASSOC_H) && defined(HAVE_DOT11)
#if !defined(TINS_DOT11_DOT11_ASSOC_H) && defined(TINS_HAVE_DOT11)
#define TINS_DOT11_DOT11_ASSOC_H
#include "../dot11/dot11_mgmt.h"
#include <tins/dot11/dot11_mgmt.h>
#include <tins/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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,18 +27,19 @@
*
*/
#include "../config.h"
#include <tins/config.h>
#if !defined(TINS_DOT11_DOT11_AUTH_H) && defined(HAVE_DOT11)
#if !defined(TINS_DOT11_DOT11_AUTH_H) && defined(TINS_HAVE_DOT11)
#define TINS_DOT11_DOT11_AUTH_H
#include "../dot11/dot11_mgmt.h"
#include <tins/dot11/dot11_mgmt.h>
#include <tins/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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,27 +27,31 @@
*
*/
#include "../config.h"
#include <tins/config.h>
#if !defined(TINS_DOT11_DOT11_H) && defined(HAVE_DOT11)
#if !defined(TINS_DOT11_DOT11_H) && defined(TINS_HAVE_DOT11)
#define TINS_DOT11_DOT11_H
#include <list>
#include "../pdu.h"
#include "../pdu_option.h"
#include "../small_uint.h"
#include "../hw_address.h"
#include "../endianness.h"
#include "../cxxstd.h"
#include "../macros.h"
#include <tins/pdu.h>
#include <tins/pdu_option.h>
#include <tins/small_uint.h>
#include <tins/hw_address.h>
#include <tins/endianness.h>
#include <tins/cxxstd.h>
#include <tins/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.
@@ -62,7 +66,7 @@ public:
/**
* The type used to store tagged options.
*/
typedef std::list<option> options_type;
typedef std::vector<option> options_type;
/**
* \brief This PDU's flag.
@@ -123,9 +127,148 @@ public:
ERP_INFORMATION,
TS_DELAY,
TCLAS_PROCESSING,
QOS_CAPABILITY = 46,
HT_CAPABILITY,
QOS_CAPABILITY,
RSN = 48,
EXT_SUPPORTED_RATES = 50,
AP_CHANNEL_REPORT,
NEIGHBOR_REPORT,
RCPI,
MOBILITY_DOMAIN_MDE,
FAST_BSS_TRANSITION_FTE,
TIMEOUT_INTERVAL,
RIC_DATA_RDE,
DSE_REG_LOC,
SUPPORTED_OP_CLASSES,
EXT_CH_SWITCH_ANNOUNCEMENT,
HT_OPERATION,
SEC_CH_OFFSET,
BSS_AVG_ACCESS_DELAY,
ANTENNA,
RSNI,
MEASUREMENT_PILOT_TRANSMISSION,
BSS_AVAIL_ADMISSION_CAPACITY,
BSS_AC_ACCESS_DELAY,
TIME_ADVERTISEMENT,
RM_ENABLED_CAP,
MULTIPLE_BSSID,
BSS_2040_COEX,
BSS_2040_INTOLERANT_CH_REPORT,
OVERLAPPING_BSS_SCAN_PARAM,
RIC_DESCRIPTOR,
MGMT_MIC,
EVENT_REQ = 78,
EVENT_REPORT,
DIAG_REQ,
DIAG_REPORT,
LOCATION_PARAMS,
NONTRANSMITTED_BSSID_CAP,
SSID_LIST,
MULTIPLE_BSSID_INDEX,
FMS_DESCRIPTOR,
FMS_REQ,
FMS_RESP,
QOS_TRAFFIC_CAP,
BSS_MAX_IDLE_PERIOD,
TFS_REQ,
TFS_RESP,
WNM_SLEEP_MODE,
TIM_BROADCAST_REQ,
TIM_BROADCAST_RESP,
COLLOCATED_INTERFERENCE_REPORT,
CH_USAGE,
TIME_ZONE,
DMS_REQ,
DMS_RESP,
LINK_ID,
WAKEUP_SCHEDULE,
CH_SWITCH_TIMING,
PTI_CONTROL,
TPU_BUFFER_STATUS,
INTERWORKING,
ADVERTISEMENT_PROTOCOL,
EXPEDITED_BANDWIDTH_REQ,
QOS_MAP,
ROAMING_CONSORTIUM,
EMERG_ALERT_ID,
MESH_CONFIG,
MESH_ID,
MESH_LINK_METRIC_REPORT,
CONGESTION_NOTIFICATION,
MESH_PEERING_MGMT,
MESH_CH_SWITCH_PARAMS,
MESH_AWAKE_WINDOW,
BEACON_TIMING,
MCCAOP_SETUP_REQ,
MCCAOP_SETUP_REPLY,
MCCAOP_ADVERTISEMENT,
MCCAOP_TEARDOWN,
GANN,
RANN,
EXT_CAP,
PREQ = 130,
PREP,
PERR,
PXU = 137,
PXUC,
AUTH_MESH_PEER_EX,
MIC,
DEST_URI,
UAPSD_COEX,
DMG_WAKEUP_SCHEDULE,
EXT_SCHEDULE,
STA_AVAIL,
DMG_TSPEC,
NEXT_DMG_ATI,
DMG_CAP,
DMG_OP = 151,
DMG_BSS_PARAM_CHG,
DMG_BEAM_REFINEMENT,
CH_MEASUREMENT_FEEDBACK,
AWAKE_WINDOW = 157,
MULTIBAND,
ADDBA_ESXT,
NEXTPCP_LIST,
PCP_HANDOVER,
DMG_LINK_MARGIN,
SWITCHING_STREAM,
SESSION_TRANSITION,
DYNAMIC_TONE_PAIRING_REPORT,
CLUSTER_REPORT,
RELAY_CAP,
RELAY_TRANSFER_PARAM_SET,
BEAMLINK_MAINTENANCE,
MULTIPLE_MAC_SUBLAYERS,
UPID,
DMG_LINK_ADAPTATION_ACK,
MCCAOP_ADV_OVERVIEW = 174,
QUIET_PERIOD_REQ,
QUIET_PERIOD_RESP = 177,
QMF_POLICY = 181,
ECAPC_POLICY = 182,
CLUSTER_TIME_OFFSET,
INTRA_ACCESS_CAT_PRIORITY,
SCS_DESCRIPTOR,
QLOAD_REPORT,
HCCA_TXOP_UPDATE_COUNT,
HIGHER_LAYER_STREAM_ID,
GCR_GROUP_ADDR,
ANTENNA_SECTOR_ID_PATTERN,
VHT_CAP,
VHT_OP,
EXT_BSS_LOAD,
WIDE_BANDWIDTH_CH_SWITCH,
TRANSMIT_POWER_ENVELOPE,
CH_SWITCH_WRAPPER,
AID,
QUIET_CHANNEL,
OP_MODE_NOTIFY,
UPSIM,
REDUCED_NEIGHBOR_REPORT,
TVHT_OP,
DEV_LOC = 204,
WHITE_SPACE_MAP,
FINE_TUNING_MEASUREMENT_PARAMS,
VENDOR_SPECIFIC = 221
};
@@ -187,7 +330,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 +344,124 @@ 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 More Data field.
*
* \return The stored More Data field.
*/
small_uint<1> more_data() const {
return header_.control.more_data;
}
/**
* \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
@@ -345,6 +521,13 @@ public:
*/
void power_mgmt(small_uint<1> new_value);
/**
* \brief Setter for the More Data field.
*
* \param new_value The new More Data field value.
*/
void more_data(small_uint<1> new_value);
/**
* \brief Setter for the WEP field.
*
@@ -371,7 +554,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 +565,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 +588,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 +642,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 +660,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 +705,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);
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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,140 +27,153 @@
*
*/
#include "../config.h"
#include <tins/config.h>
#if !defined(TINS_DOT11_DOT11_BEACON_H) && defined(HAVE_DOT11)
#if !defined(TINS_DOT11_DOT11_BEACON_H) && defined(TINS_HAVE_DOT11)
#define TINS_DOT11_DOT11_BEACON_H
#include "../dot11/dot11_mgmt.h"
#include <tins/dot11/dot11_mgmt.h>
#include <tins/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

View File

@@ -1,18 +1,18 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, 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
@@ -27,64 +27,67 @@
*
*/
#include "../config.h"
#include <tins/config.h>
#if !defined(TINS_DOT11_DOT11_CONTROL_H) && defined(HAVE_DOT11)
#if !defined(TINS_DOT11_DOT11_CONTROL_H) && defined(TINS_HAVE_DOT11)
#define TINS_DOT11_DOT11_CONTROL_H
#include "../dot11/dot11_base.h"
#include <tins/dot11/dot11_base.h>
#include <tins/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.
*/
static const PDU::PDUType pdu_flag = PDU::DOT11_CONTROL;
/**
* \brief Constructor for creating a 802.11 control frame PDU
*
* Constructs a 802.11 Control PDU taking the destination and
* Constructs a 802.11 Control PDU taking the destination and
* source hardware addresses.
*
* \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
* adds all identifiable PDUs found in the buffer as children
* 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
* 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.
*/
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,46 +95,62 @@ 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 This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::DOT11_CONTROL_TA;
/**
* \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);
/**
* \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11::matches_flag(flag);
}
protected:
/**
* \brief Constructor for creating a 802.11 control frame TA PDU
*
* Constructs a 802.11 PDU taking the destination and source
* Constructs a 802.11 PDU taking the destination and source
* hardware addresses.
*
* \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
* adds all identifiable PDUs found in the buffer as children
* 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
* 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.
*/
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 +163,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,30 +192,30 @@ 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
* \brief Constructs a Dot11RTS 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
* 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.
*/
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 +223,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 +237,7 @@ public:
}
};
class Dot11PSPoll : public Dot11ControlTA {
class TINS_API Dot11PSPoll : public Dot11ControlTA {
public:
/**
* \brief This PDU's flag.
@@ -224,37 +247,37 @@ public:
/**
* \brief Constructor for creating a 802.11 PS-Poll frame PDU
*
* Constructs a 802.11 PDU taking the destination and source
* Constructs a 802.11 PDU taking the destination and source
* hardware addresses.
*
* \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
* adds all identifiable PDUs found in the buffer as children of
* 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
* 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.
*/
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 +285,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 +299,7 @@ public:
}
};
class Dot11CFEnd : public Dot11ControlTA {
class TINS_API Dot11CFEnd : public Dot11ControlTA {
public:
/**
* \brief This PDU's flag.
@@ -284,37 +309,37 @@ public:
/**
* \brief Constructor for creating a 802.11 CF-End frame PDU
*
* Constructs a 802.11 PDU taking the destination and source
* Constructs a 802.11 PDU taking the destination and source
* hardware addresses.
*
* \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
* all identifiable PDUs found in the buffer as children of this
* \brief Constructs a Dot11CFEnd 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
* 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.
*/
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 +347,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.
@@ -344,37 +371,37 @@ public:
/**
* \brief Constructor for creating a 802.11 End-CF-Ack frame PDU
*
* Constructs a 802.11 PDU taking the destination and source
* Constructs a 802.11 PDU taking the destination and source
* hardware addresses.
*
*
* \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
* and adds all identifiable PDUs found in the buffer as children
* \brief Constructs a Dot11EndCFAck frame 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
* 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.
*/
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 +409,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.
@@ -404,35 +433,35 @@ public:
/**
* \brief Constructor for creating a 802.11 Ack frame PDU
*
* Constructs a 802.11 PDU taking the destination and source
* Constructs a 802.11 PDU taking the destination and source
* hardware addresses.
*
* \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
* adds all identifiable PDUs found in the buffer as children of
* 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
* 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.
*/
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 +469,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.
@@ -465,30 +496,30 @@ public:
/**
* \brief Constructor for creating a 802.11 Block Ack request frame PDU
*
* Constructs a 802.11 PDU taking the destination and source
* Constructs a 802.11 PDU taking the destination and source
* hardware addresses.
*
*
* \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
* and adds all identifiable PDUs found in the buffer as children
* \brief Constructs a Dot11BlockAckRequest 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
* 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.
*/
Dot11BlockAckRequest(const uint8_t *buffer, uint32_t total_sz);
Dot11BlockAckRequest(const uint8_t* buffer, uint32_t total_sz);
/* Getter */
@@ -496,11 +527,11 @@ public:
* \brief Getter for the bar control field.
* \return The stored bar control field.
*/
small_uint<4> bar_control() const {
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
}
@@ -508,26 +539,26 @@ public:
* \brief Getter for the start sequence field.
* \return The stored start sequence.
*/
small_uint<12> start_sequence() const {
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
}
/**
* \brief Getter for the fragment number field.
* \return The stored fragment number field.
*/
small_uint<4> fragment_number() const {
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
}
/**
* \brief Returns the 802.11 frame's header length.
*
@@ -549,7 +580,7 @@ public:
* \param bar The start sequence field to be set.
*/
void start_sequence(small_uint<12> seq);
/**
* \brief Setter for the fragment number field.
* \param frag The fragment number field to be set.
@@ -561,7 +592,7 @@ public:
*
* \sa PDU::clone
*/
Dot11BlockAckRequest *clone() const {
Dot11BlockAckRequest* clone() const {
return new Dot11BlockAckRequest(*this);
}
@@ -569,35 +600,35 @@ 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.
*/
static const PDU::PDUType pdu_flag = PDU::DOT11_BLOCK_ACK;
/**
* The size of the bitmap field.
*/
@@ -606,30 +637,30 @@ public:
/**
* \brief Constructor for creating a 802.11 Block Ack frame PDU
*
* Constructs a 802.11 PDU taking the destination and source
* Constructs a 802.11 PDU taking the destination and source
* hardware addresses.
*
*
* \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
* and adds all identifiable PDUs found in the buffer as children
* \brief Constructs a Dot11BlockAck frame 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
* 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.
*/
Dot11BlockAck(const uint8_t *buffer, uint32_t total_sz);
Dot11BlockAck(const uint8_t* buffer, uint32_t total_sz);
/* Getters */
@@ -637,11 +668,11 @@ public:
* \brief Getter for the bar control field.
* \return The stored bar control field.
*/
small_uint<4> bar_control() const {
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
}
@@ -649,26 +680,26 @@ public:
* \brief Getter for the start sequence field.
* \return The stored start sequence.
*/
small_uint<12> start_sequence() const {
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
}
/**
* \brief Getter for the fragment number field.
* \return The stored fragment number field.
*/
small_uint<4> fragment_number() const {
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
}
/**
* \brief Returns the 802.11 frame's header length.
*
@@ -690,7 +721,7 @@ public:
* \param bar The start sequence field to be set.
*/
void start_sequence(small_uint<12> seq);
/**
* \brief Setter for the fragment number field.
* \param frag The fragment number field to be set.
@@ -699,32 +730,36 @@ public:
/**
* \brief Getter for the bitmap field.
*
*
* The returned pointer <b>must not</b> be free'd.
*
*
* \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 +767,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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,15 +27,20 @@
*
*/
#include "../config.h"
#include <tins/config.h>
#if !defined(TINS_DOT11_DOT11_DATA_H) && defined(HAVE_DOT11)
#if !defined(TINS_DOT11_DOT11_DATA_H) && defined(TINS_HAVE_DOT11)
#define TINS_DOT11_DOT11_DATA_H
#include "../dot11/dot11_base.h"
#include <tins/dot11/dot11_base.h>
#include <tins/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_;
};
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,21 +27,22 @@
*
*/
#include "../config.h"
#include <tins/config.h>
#if !defined(TINS_DOT11_DOT11_MGMT_H) && defined(HAVE_DOT11)
#if !defined(TINS_DOT11_DOT11_MGMT_H) && defined(TINS_HAVE_DOT11)
#define TINS_DOT11_DOT11_MGMT_H
#include <vector>
#include <utility>
#include "../dot11/dot11_base.h"
#include <tins/dot11/dot11_base.h>
#include <tins/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;
/**
@@ -373,14 +463,17 @@ public:
uint16_t dwell_time;
uint8_t hop_set, hop_pattern, hop_index;
fh_params_set() {}
fh_params_set()
: dwell_time(0), hop_set(0), hop_pattern(0), hop_index(0) {}
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);
};
/**
@@ -390,15 +483,18 @@ public:
uint8_t cfp_count, cfp_period;
uint16_t cfp_max_duration, cfp_dur_remaining;
cf_params_set() {}
cf_params_set()
: cfp_count(0), cfp_period(0), cfp_max_duration(0), cfp_dur_remaining(0) {}
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 +505,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() : recovery_interval(0) {}
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 +530,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);
};
/**
@@ -450,14 +549,18 @@ public:
uint8_t flag, number_of_sets, modulus, offset;
byte_array random_table;
fh_pattern_type() {}
fh_pattern_type()
: flag(0), number_of_sets(0), modulus(0), offset(0) {}
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);
};
/**
@@ -466,12 +569,15 @@ public:
struct channel_switch_type {
uint8_t switch_mode, new_channel, switch_count;
channel_switch_type() {}
channel_switch_type()
: switch_mode(0), new_channel(0), switch_count(0) {}
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);
};
/**
@@ -481,14 +587,17 @@ public:
uint8_t quiet_count, quiet_period;
uint16_t quiet_duration, quiet_offset;
quiet_type() {}
quiet_type()
: quiet_count(0), quiet_period(0), quiet_duration(0), quiet_offset(0) {}
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);
};
/**
@@ -499,14 +608,14 @@ public:
uint16_t available_capacity;
uint8_t channel_utilization;
bss_load_type() {}
bss_load_type()
: station_count(0), available_capacity(0), channel_utilization(0) {}
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);
};
/**
@@ -516,14 +625,17 @@ public:
uint8_t dtim_count, dtim_period, bitmap_control;
byte_array partial_virtual_bitmap;
tim_type() {}
tim_type()
: dtim_count(0), dtim_period(0), bitmap_control(0) {}
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 +647,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 +664,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 +684,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 +697,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 +708,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 +745,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 +754,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 +768,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 +801,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 +825,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 +839,7 @@ public:
*
* \param params The new CF parameter set value.
*/
void cf_parameter_set(const cf_params_set &params);
void cf_parameter_set(const cf_params_set& params);
/**
* \brief Helper method to set the IBSS parameter set tagged option.
@@ -735,14 +853,14 @@ public:
*
* \param params The IBSS DFS data to be set.
*/
void ibss_dfs(const ibss_dfs_params &params);
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 &params);
void country(const country_params& params);
/**
* \brief Helper method to set the FH parameters set tagged option.
@@ -757,7 +875,7 @@ public:
*
* \param params The data to be used for this FH pattern table option.
*/
void fh_pattern_table(const fh_pattern_type &params);
void fh_pattern_table(const fh_pattern_type& params);
/**
* \brief Helper method to set the Power Constraint tagged option.
@@ -771,14 +889,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 +918,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 +952,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 +1214,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 +1228,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 +1252,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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,20 +27,21 @@
*
*/
#include "../config.h"
#include <tins/config.h>
#if !defined(TINS_DOT11_DOT11_PROBE_H) && defined(HAVE_DOT11)
#if !defined(TINS_DOT11_DOT11_PROBE_H) && defined(TINS_HAVE_DOT11)
#define TINS_DOT11_DOT11_PROBE_H
#include "../dot11/dot11_mgmt.h"
#include <tins/dot11/dot11_mgmt.h>
#include <tins/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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,22 +30,32 @@
#ifndef TINS_DOT1Q_H
#define TINS_DOT1Q_H
#include "pdu.h"
#include "endianness.h"
#include "small_uint.h"
#include <tins/pdu.h>
#include <tins/macros.h>
#include <tins/endianness.h>
#include <tins/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.
*/
static const PDU::PDUType pdu_flag = PDU::DOT1Q;
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/**
* Default constructor
*/
@@ -64,14 +74,14 @@ 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
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
* This method overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;
@@ -86,7 +96,7 @@ public:
* \return The stored priority field value.
*/
small_uint<3> priority() const {
return _header.priority;
return header_.priority;
}
/**
@@ -94,7 +104,7 @@ public:
* \return The stored CFI field value.
*/
small_uint<1> cfi() const {
return _header.cfi;
return header_.cfi;
}
/**
@@ -103,9 +113,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 +124,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 +147,7 @@ public:
* appended at the end of this packet.
*/
bool append_padding() const {
return _append_padding;
return append_padding_;
}
// Setters
@@ -177,18 +189,18 @@ 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);
TINS_BEGIN_PACK
struct dot1q_hdr {
struct dot1q_header {
#if TINS_IS_BIG_ENDIAN
uint16_t priority:3,
cfi:1,
@@ -203,10 +215,10 @@ private:
#endif
} TINS_END_PACK;
static uint16_t get_id(const dot1q_hdr *hdr);
static uint16_t get_id(const dot1q_header* hdr);
dot1q_hdr _header;
bool _append_padding;
dot1q_header header_;
bool append_padding_;
};
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,164 +31,179 @@
#define TINS_DOT3_H
#include <stdint.h>
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
#include "hw_address.h"
#include <tins/macros.h>
#include <tins/pdu.h>
#include <tins/config.h>
#include <tins/endianness.h>
#include <tins/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 Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Constructs 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 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());
/* Getters */
/**
* \brief Getter for the destination hardware address.
*
* \return The destination hardware address.
*/
address_type dst_addr() const { return _eth.dst_mac; }
/**
* \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 Getter for the source hardware address.
*
* \return The source hardware address.
*/
address_type src_addr() const { return _eth.src_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 length field.
* \return The length field value.
*/
uint16_t length() const { return Endian::be_to_host(_eth.length); };
/**
* \brief Getter for the source hardware address.
*
* \return The source hardware address.
*/
address_type src_addr() const {
return header_.src_mac;
}
/* Setters */
/**
* \brief Getter for the length field.
* \return The length field value.
*/
uint16_t length() const {
return Endian::be_to_host(header_.length);
}
/**
* \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);
/* Setters */
/**
* \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 destination hardware address.
*
* \param address The new destination hardware address.
*/
void dst_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 source hardware address.
*
* \param address The new source hardware address.
*/
void src_addr(const address_type& address);
/* 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
/**
* \brief Setter for the length field.
*
* \param value The new value for the length field
*/
void length(uint16_t value);
/**
* \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;
// Virtual methods
#ifndef WIN32
/**
* \sa PDU::recv_response
*/
PDU *recv_response(PacketSender &sender, const NetworkInterface &iface);
#endif // WIN32
/**
* \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(TINS_HAVE_PACKET_SENDER_PCAP_SENDPACKET)
/**
* \sa PDU::send()
*/
void send(PacketSender& sender, const NetworkInterface& iface);
#endif // !_WIN32 || TINS_HAVE_PACKET_SENDER_PCAP_SENDPACKET
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \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
*/
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;
#ifndef _WIN32
/**
* \sa PDU::recv_response
*/
PDU* recv_response(PacketSender& sender, const NetworkInterface& iface);
#endif // _WIN32
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \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;
ethhdr _eth;
};
}
void write_serialization(uint8_t* buffer, uint32_t total_sz);
dot3_header header_;
};
} // Tins
#endif // TINS_DOT3_H

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,7 @@
#define TINS_ENDIANNESS_H
#include <stdint.h>
#include "macros.h"
#include <tins/macros.h>
#if defined(__APPLE__)
#include <sys/types.h>
@@ -41,7 +41,8 @@
#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)
#include <cstdlib>
// Assume windows == little endian. fixme later
#define TINS_IS_LITTLE_ENDIAN 1
#define TINS_IS_BIG_ENDIAN 0
@@ -51,187 +52,208 @@
#define TINS_IS_BIG_ENDIAN (__BYTE_ORDER == __BIG_ENDIAN)
#endif
// Define macros to swap bytes using compiler intrinsics when possible
#if defined(_MSC_VER)
#define TINS_BYTE_SWAP_16(data) _byteswap_ushort(data)
#define TINS_BYTE_SWAP_32(data) _byteswap_ulong(data)
#define TINS_BYTE_SWAP_64(data) _byteswap_uint64(data)
#elif defined(TINS_HAVE_GCC_BUILTIN_SWAP)
#define TINS_BYTE_SWAP_16(data) __builtin_bswap16(data)
#define TINS_BYTE_SWAP_32(data) __builtin_bswap32(data)
#define TINS_BYTE_SWAP_64(data) __builtin_bswap64(data)
#else
#define TINS_NO_BYTE_SWAP_INTRINSICS
#endif
namespace Tins {
namespace Endian {
/**
* \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) {
/**
* \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) {
#ifdef TINS_NO_BYTE_SWAP_INTRINSICS
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) {
#else
return TINS_BYTE_SWAP_16(data);
#endif
}
/**
* \brief Changes a 32-bit integral value's endianess.
*
* \param data The data to convert.
*/
inline uint32_t do_change_endian(uint32_t data) {
#ifdef TINS_NO_BYTE_SWAP_INTRINSICS
return (((data & 0xff000000) >> 24) | ((data & 0x00ff0000) >> 8) |
((data & 0x0000ff00) << 8) | ((data & 0x000000ff) << 24));
((data & 0x0000ff00) << 8) | ((data & 0x000000ff) << 24));
#else
return TINS_BYTE_SWAP_32(data);
#endif
}
/**
* \brief Changes a 64-bit integral value's endianess.
*
* \param data The data to convert.
*/
inline uint64_t do_change_endian(uint64_t data) {
#ifdef TINS_NO_BYTE_SWAP_INTRINSICS
return (((uint64_t)(do_change_endian((uint32_t)(data & 0xffffffff))) << 32) |
(do_change_endian(((uint32_t)(data >> 32)))));
#else
return TINS_BYTE_SWAP_64(data);
#endif
}
/**
* \cond
*/
// Helpers to convert
template<typename T>
struct conversion_dispatch_helper {
static T dispatch(T data) {
return do_change_endian(data);
}
/**
* \brief Changes a 64-bit integral value's endianess.
};
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 Convert any integral type to big endian.
*
* \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_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;
}
/**
* \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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,175 +31,188 @@
#define TINS_ETHERNET_II_H
#include <stdint.h>
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
#include "hw_address.h"
#include <tins/macros.h>
#include <tins/pdu.h>
#include <tins/config.h>
#include <tins/endianness.h>
#include <tins/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 Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Constructs 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 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());
/* 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; }
/**
* \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 Getter for the source's hardware address.
*
* \return address_type containing the source hardware address.
*/
address_type src_addr() const { return _eth.src_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 payload_type
* \return The payload type.
*/
uint16_t payload_type() const { return Endian::be_to_host(_eth.payload_type); };
/**
* \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;
}
/* Setters */
/**
* \brief Getter for the payload_type
* \return The payload type.
*/
uint16_t payload_type() const {
return Endian::be_to_host(header_.payload_type);
}
/**
* \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);
/* Setters */
/**
* \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 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 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 source hardware address.
*
* \param new_src_addr the source hardware address to be set.
*/
void src_addr(const address_type& new_src_addr);
/* 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;
/**
* \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);
// Windows does not support sending L2 PDUs.
#ifndef WIN32
/**
* \sa PDU::send()
*/
void send(PacketSender &sender, const NetworkInterface &iface);
#endif // WIN32
/* 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;
/**
* \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::send()
*/
void send(PacketSender& sender, const NetworkInterface& iface);
#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 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::ETHERNET_II; }
#ifndef _WIN32
/**
* \brief Receives a matching response for this packet.
*
* \sa PDU::recv_response
*/
PDU* recv_response(PacketSender& sender, const NetworkInterface& iface);
#endif // _WIN32
/**
* \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);
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const {
return pdu_flag;
}
ethhdr _eth;
};
/**
* \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);
}
ethernet_header header_;
};
} // Tins
#endif // TINS_ETHERNET_II_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,152 +34,297 @@
#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) { }
exception_base(const char* 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";
}
option_not_found() : exception_base("Option not found") { }
};
/**
* \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()) { }
malformed_packet() : exception_base("Malformed packet") { }
malformed_packet(const std::string& message) : exception_base(message) { }
};
const char* what() const throw() {
return "Malformed packet";
}
/**
* \brief Exception thrown when a DNS decompression pointer is out of bounds.
*/
class dns_decompression_pointer_out_of_bounds : public malformed_packet {
public:
dns_decompression_pointer_out_of_bounds() : malformed_packet("DNS decompression: pointer out of bounds") { }
};
/**
* \brief Exception thrown when a DNS decompression pointer loops.
*/
class dns_decompression_pointer_loops : public malformed_packet {
public:
dns_decompression_pointer_loops() : malformed_packet("DNS decompression: pointer loops") { }
};
/**
* \brief Exception thrown when serializing a packet fails.
*/
class serialization_error : public exception_base {
public:
serialization_error() : exception_base("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";
}
pdu_not_found() : exception_base("PDU not found") { }
};
/**
* \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()) { }
invalid_interface() : exception_base("Invalid interface") { }
};
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:
invalid_address() : exception_base("Invalid address") { }
};
/**
* \brief Exception thrown when a PDU option is set using an incorrect value
*/
class invalid_option_value : public exception_base {
public:
invalid_option_value() : exception_base("Invalid option value") { }
};
/**
* \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";
}
field_not_present() : exception_base("Field not present") { }
};
/**
* \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 : public 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() {
return "The provided socket type is invalid";
}
invalid_socket_type() : exception_base("The provided socket type is invalid") { }
};
/**
* \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() {
return "The sniffed link layer PDU type is unknown";
}
unknown_link_type() : exception_base("The sniffed link layer PDU type is unknown") { }
};
/**
* \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() {
return "Malformed option";
}
malformed_option() : exception_base("Malformed option") { }
};
/**
* \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() {
return "Bad Tins cast";
}
bad_tins_cast() : exception_base("Bad Tins cast") { }
};
/**
* \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() {
return "Protocol disabled";
protocol_disabled() : exception_base("Protocol disabled") { }
};
/**
* \brief Exception thrown when a feature has been disabled
* at compile time.
*/
class feature_disabled : public exception_base {
public:
feature_disabled() : exception_base("Feature disabled") { }
};
/**
* \brief Exception thrown when a payload is too large to fit
* into a PDUOption.
*/
class option_payload_too_large : public exception_base {
public:
option_payload_too_large() : exception_base("Option payload too large") { }
};
/**
* \brief Exception thrown when an IPv6 extension header is being
* created from invalid data
*/
class invalid_ipv6_extension_header : public exception_base {
public:
invalid_ipv6_extension_header() : exception_base("Invalid IPv6 extension header") { }
};
/**
* \brief Generic pcap error
*/
class pcap_error : public exception_base {
public:
pcap_error(const char* message) : exception_base(message) {
}
pcap_error(const std::string& 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:
pdu_not_serializable() : exception_base("PDU not serializable") { }
};
/**
* \brief Exception thrown when opening a pcap handle fails
*/
class pcap_open_failed : public exception_base {
public:
pcap_open_failed() : exception_base("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:
unsupported_function() : exception_base("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:
invalid_domain_name() : exception_base("Invalid domain name") { }
};
/**
* \brief Exception thrown when a stream is not found
*/
class stream_not_found : public exception_base {
public:
stream_not_found() : exception_base("Stream not found") { }
};
/**
* \brief Exception thrown when a required callback for an object is not set
*/
class callback_not_set : public exception_base {
public:
callback_not_set() : exception_base("Callback not set") { }
};
/**
* \brief Exception thrown when an invalid packet is provided to some function
*/
class invalid_packet : public exception_base {
public:
invalid_packet() : exception_base("Invalid packet") { }
};
namespace Crypto {
namespace WPA2 {
/**
* \brief Exception thrown when an invalid WPA2 handshake is found.
*/
class invalid_handshake : public exception_base {
public:
invalid_handshake() : exception_base("Invalid WPA2 handshake") { }
};
} // WPA2
} // Crypto
} // Tins
#endif // TINS_EXCEPTIONS_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,143 +27,144 @@
*
*/
#include "config.h"
#include <tins/config.h>
#if !defined(TINS_HANDSHAKE_CAPTURER_H) && defined(HAVE_DOT11)
#if !defined(TINS_HANDSHAKE_CAPTURER_H) && defined(TINS_HAVE_DOT11)
#define TINS_HANDSHAKE_CAPTURER_H
#include <vector>
#include <map>
#include <utility>
#include "hw_address.h"
#include "eapol.h"
#include <tins/hw_address.h>
#include <tins/macros.h>
#include <tins/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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,15 +31,42 @@
#define TINS_HWADDRESS_H
#include <stdint.h>
#include <stdexcept>
#include <iterator>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <sstream>
#include "cxxstd.h"
#include <iosfwd>
#include <string>
#include <cstring>
#include <tins/cxxstd.h>
#include <tins/macros.h>
#if TINS_IS_CXX11
// std::hash
#include <memory>
#endif // TINS_IS_CXX11
namespace Tins {
namespace Internals {
// Defined in hw_address.cpp
/**
* \cond
*/
TINS_API std::string hw_address_to_string(const uint8_t* ptr, size_t count);
TINS_API void string_to_hw_address(const std::string& hw_addr, uint8_t* output,
size_t output_size);
TINS_API bool hw_address_equal_compare(const uint8_t* start1, const uint8_t* end1,
const uint8_t* start2);
TINS_API bool hw_address_lt_compare(const uint8_t* start1, const uint8_t* end1,
const uint8_t* start2, const uint8_t* end2);
TINS_API bool hw_address_gt_compare(const uint8_t* start1, const uint8_t* end1,
const uint8_t* start2, const uint8_t* end2);
/**
* \endcond
*/
} // Internals
/**
* \class HWAddress
* \brief Represents a hardware address.
@@ -60,15 +87,13 @@ namespace Tins {
* }
* \endcode
*/
template<size_t n, typename Storage = uint8_t>
template<size_t n>
class HWAddress {
public:
/**
* \brief The type of the elements stored in the hardware address.
*
* This is the same as the template parameter Storage.
*/
typedef Storage storage_type;
typedef uint8_t storage_type;
/**
* \brief The random access iterator type.
@@ -89,7 +114,7 @@ public:
/**
* \brief The broadcast address.
*/
static const HWAddress<n, Storage> broadcast;
static const HWAddress<n> broadcast;
/**
* \brief Constructor from a const storage_type*.
@@ -107,10 +132,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
std::fill(begin(), end(), storage_type());
if (ptr) {
std::memcpy(buffer_, ptr, address_size);
}
else {
std::memset(buffer_, 0, address_size);
}
}
/**
@@ -124,15 +151,15 @@ public:
*
* \param address The hex-notation address to be parsed.
*/
HWAddress(const std::string &address) {
convert(address, buffer);
HWAddress(const std::string& address) {
Internals::string_to_hw_address(address, buffer_, n);
}
/**
* \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 +170,7 @@ public:
*/
template<size_t i>
HWAddress(const char (&address)[i]) {
convert(address, buffer);
Internals::string_to_hw_address(address, buffer_, n);
}
/**
@@ -159,19 +186,16 @@ public:
* \param rhs The HWAddress to be constructed from.
*/
template<size_t i>
HWAddress(const HWAddress<i> &rhs) {
// Fill extra bytes
std::fill(
// Copy as most as we can
std::copy(
rhs.begin(),
rhs.begin() + std::min(i, n),
begin()
),
end(),
0
);
HWAddress(const HWAddress<i>& rhs) {
size_t copy_threshold = i < n ? i : n;
for (size_t index = 0; index < n; ++index) {
if (index < copy_threshold) {
buffer_[index] = rhs[index];
}
else {
buffer_[index] = storage_type();
}
}
}
/**
@@ -181,7 +205,7 @@ public:
* \return iterator.
*/
iterator begin() {
return buffer;
return buffer_;
}
/**
@@ -191,7 +215,7 @@ public:
* \return const_iterator.
*/
const_iterator begin() const {
return buffer;
return buffer_;
}
/**
@@ -201,7 +225,7 @@ public:
* \return iterator.
*/
iterator end() {
return buffer + address_size;
return buffer_ + address_size;
}
/**
@@ -211,7 +235,7 @@ public:
* \return const_iterator.
*/
const_iterator end() const {
return buffer + address_size;
return buffer_ + address_size;
}
/**
@@ -221,8 +245,8 @@ public:
*
* \return bool indicating whether addresses are equal.
*/
bool operator==(const HWAddress &rhs) const {
return std::equal(begin(), end(), rhs.begin());
bool operator==(const HWAddress& rhs) const {
return Internals::hw_address_equal_compare(begin(), end(), rhs.begin());
}
/**
@@ -232,7 +256,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,16 +267,89 @@ public:
*
* \return bool indicating whether this address is less-than rhs.
*/
bool operator<(const HWAddress &rhs) const {
return std::lexicographical_compare(begin(), end(), rhs.begin(), rhs.end());
bool operator<(const HWAddress& rhs) const {
return Internals::hw_address_lt_compare(begin(), end(), rhs.begin(), rhs.end());
}
/**
* \brief Compares this HWAddress for less-than equality.
*
* \param rhs The HWAddress to be compared to.
*
* \return bool indicating whether this address is equal or less-than rhs.
*/
bool operator<=(const HWAddress& rhs) const {
return !operator>(rhs);
}
/**
* \brief Compares this HWAddress for greater-than inequality.
*
* \param rhs The HWAddress to be compared to.
*
* \return bool indicating whether this address is greater-than rhs.
*/
bool operator>(const HWAddress& rhs) const {
return Internals::hw_address_gt_compare(begin(), end(), rhs.begin(), rhs.end());
}
/**
* \brief Compares this HWAddress for greater-than equality.
*
* \param rhs The HWAddress to be compared to.
*
* \return bool indicating whether this address is equal or greater-than rhs.
*/
bool operator>=(const HWAddress& rhs) const {
return !operator<(rhs);
}
/**
* \brief Apply a mask to this address
*
* \param mask The mask to be applied
* \return The result of applying the mask to this address
*/
HWAddress operator&(const HWAddress& mask) const {
HWAddress<n> output = *this;
for (size_t i = 0; i < n; ++i) {
output[i] = output[i] & mask[i];
}
return output;
}
/**
* \brief Apply a mask to this address
*
* \param mask The mask to be applied
* \return The result of applying the mask to this address
*/
HWAddress operator|(const HWAddress& mask) const {
HWAddress<n> output = *this;
for (size_t i = 0; i < n; ++i) {
output[i] = output[i] | mask[i];
}
return output;
}
/**
* \brief not operator
* \return The result of applying the mask to this address
*/
HWAddress operator~() const {
HWAddress<n> output = *this;
for (size_t i = 0; i < n; ++i) {
output[i] = ~output[i];
}
return output;
}
/**
* \brief Retrieves the size of this address.
*
* This effectively returns the address_size constant.
*/
const size_t size() const {
size_t size() const {
return address_size;
}
@@ -260,14 +357,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);
}
/**
@@ -283,9 +380,7 @@ public:
* \return std::string containing the hex-notation address.
*/
std::string to_string() const {
std::ostringstream oss;
oss << *this;
return oss.str();
return Internals::hw_address_to_string(buffer_, size());
}
/**
@@ -294,7 +389,16 @@ public:
* \param i The element to retrieve.
*/
storage_type operator[](size_t i) const {
return buffer[i];
return begin()[i];
}
/**
* \brief Retrieves the i-th storage_type in this address.
*
* \param i The element to retrieve.
*/
storage_type& operator[](size_t i) {
return begin()[i];
}
/**
@@ -304,14 +408,8 @@ 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) {
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]);
friend std::ostream& operator<<(std::ostream& os, const HWAddress& addr) {
return os << addr.to_string();
}
/**
@@ -325,80 +423,47 @@ 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 std::string storage_to_string(storage_type element) {
std::ostringstream oss;
oss << std::hex;
if(element < 0x10)
oss << '0';
oss << (unsigned)element;
return oss.str();
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);
}
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)
{
unsigned i(0);
size_t count(0);
storage_type tmp;
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')
tmp = (tmp << 4) | (hw_addr[i] - 'a' + 10);
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')
tmp = (tmp << 4) | (hw_addr[i] - '0');
else if(hw_addr[i] == ':')
break;
else
throw std::runtime_error("Invalid byte found");
i++;
}
*(output++) = tmp;
count++;
if(i < hw_addr.size()) {
if(hw_addr[i] == ':')
i++;
else
throw std::runtime_error("Invalid separator");
}
}
while(count++ < n) {
*(output++) = storage_type();
}
}
template<size_t n>
const HWAddress<n> HWAddress<n>::broadcast = make_broadcast_address();
template<size_t n, typename Storage>
const HWAddress<n, Storage> HWAddress<n, Storage>::broadcast("ff:ff:ff:ff:ff:ff");
} // 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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, 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,474 @@
#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 <tins/macros.h>
#include <tins/pdu.h>
#include <tins/endianness.h>
#include <tins/ip_address.h>
#include <tins/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,
EXTENDED_ECHO_REQUEST = 42,
EXTENDED_ECHO_REPLY = 43
};
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Creates an instance of ICMP.
*
* 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(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(orig_timestamp_or_address_mask_);
}
/**
* \brief Returns the header size.
*
* This method 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 method 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);
void write_serialization(uint8_t* buffer, uint32_t total_sz);
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_;
uint32_t recv_timestamp_;
uint32_t trans_timestamp_;
ICMPExtensionsStructure extensions_;
};
} // Tins
#endif // TINS_ICMP_H

View File

@@ -0,0 +1,307 @@
/*
* Copyright (c) 2017, 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 <stdint.h>
#include <tins/macros.h>
#include <tins/small_uint.h>
#include <tins/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::vector<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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2017, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,7 +30,7 @@
#ifndef TINS_IEEE802_3_H
#define TINS_IEEE802_3_H
#include "dot3.h"
#include <tins/dot3.h>
namespace Tins {
typedef Dot3 IEEE802_3;

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