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

118 Commits
v4.0 ... 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
79 changed files with 1981 additions and 369 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

View File

@@ -1,3 +1,123 @@
##### v4.5 - Sun Aug 20 04:46:53 PM UTC 2023
- Add VXLAN support (#501)
- Add `FileSniffer` constructor taking a `FILE*` (#499).
- Remove use of deprecated `std::iterator` (#481).
- Add missing `algorithm` header include (#497).
- Validate high order two bits of first dns label octet (#494).
- Use `CMAKE_INSTALL_LIBDIR` in `CONF_CMAKE_INSTALL_DIR` (#472).
- Ignore IPv6 packets with payload after one with no Next Header (#500).
- Fix unqualified `std::move` call warnings on clang (#488).
- Fix incorrect IP address range calculation when using /0 prefix (#484) (#486).
- Fall back to system GTest if available (#473).
- Fix compilation issue on android (#471).
- Fix DNS parser reading garbage on misreported packet size (#468).
- Fix DNS parser misinterpreting bad label size (#466).
##### v4.4 - Thu Feb 17 14:41:59 UTC 2022
- Add RFC8335 extended echo types to `ICMP` and `ICMPv6` (#426)
- Handle loops in DNS name decompression (#444)
- Fix Windows' `interface` macro colliding with uses of that identifier in the code (#458)
- Sending IPv6 packets to a link-scope destination address now uses the right interface index (#448)
- Fix incorrect endian being used for ICMP's `gateway` and `address_mask` (#437)
- Socket in `PacketSender::open_l3_socket` is now closed if `setsockopt` fails (#433)
- Fix various incorrect doxygen documentation comments (#439).
- Fix infinite loop when querying the routing table in \*BSD (#427)
##### v4.3 - Fri Sep 18 03:08:33 UTC 2020
- Assign a PDUType to `Dot11ControlTA` (#420)
- Don't consider IPv6 ESP header a normal extension header (#374)
- Don't include non-existing headers when installed without libpcap (#382)
- Add `IPv6Address::is_local_unicast` (#369)
- Fix memory leak in `PacketWriter` (#343)
- Fix memory leaks in `OfflinePacketFilter` (#343)
- Fix detection of new TCP stream (#335)
- Introduce `TCP::has_flags` (#334)
- Fix padding calculations in RadioTapWriter (#333)
##### v4.2 - Fri Mar 8 04:15:13 UTC 2019
- Updated location of installed CMake files in unix systems (#331)
- Fix check to detect cross compilation (#330)
- Allow getting a PDU's advertised size and use it in `PacketWriter` (#324)
- Install DLLs in right directory (#326)
- Add missing Dot11 tagged option types (#305)
- Add support for DLT_RAW (#313)
- Fix potential invalid memory accesses when parsing RadioTap (#322)
##### v4.1 - Tue Dec 11 02:08:48 UTC 2018
- Fix serialization for QinQ (#316)
- Added base class access specifier for socket_close_error (#306)
- Rewrote hw_address_to_string to not require a stringstream (#299)
- Make RadioTapParser::skip_to_field check for end of buffer (#296)
- Ensure local include directory comes before system. (#293)
- Calculate IP option sizes properly (#288)
- Add parsing of well known IPv6 extension headers (#287)
- Add missing operators to address classes (#275)
- Add version macros in config.h
- Don't assume IPv6 uses ICMPv6 underneath
- Allow users to specify library install dir
- Use Sleep windows function passing milliseconds as parameter
- Implement IPv6::recv_response
- Don't use nullptr in non C++11 code
- Ignore (possibly malformed) options after EOL (#281)
- Don't include dot11.h in tins.h if it is not configured in the library (#277)
- Fix memory leak in PDU's move assignment operator
- Append padding to IPv6 options
##### v4.0 - Mon Dec 4 00:04:30 UTC 2017
- Add parent PDU to each PDU.
@@ -178,7 +298,7 @@
- Move implementations on utils.h to utils.cpp
- Add ICMPv6 Multicast Listener Query Messages support
- Add ICMPv6 Multicast Listener Query Messages support
- Add ICMPv6 Multicast Listener Report Message support
@@ -322,7 +442,7 @@
- Added RadioTap channel map type
- Made rsn_information() a const member function to make Dot11ManagementFrame
- Made rsn_information() a const member function to make Dot11ManagementFrame
immutable
- Ensure HAVE_CXX11 is checked when defining TINS_IS_CXX11
@@ -372,7 +492,7 @@ its value.
- Removed obsolete autotools files.
- Fixed exception thrown when an interface didn't have an IP address
- Fixed exception thrown when an interface didn't have an IP address
on NetworkInterface.
- Added NetworkInterface::is_loopback.
@@ -416,7 +536,7 @@ conversion on integral constant.
- Added DataLinkType class.
- IPv4Address now uses inet_pton when constructing from string.
- IPv4Address now uses inet_pton when constructing from string.
-------------------------------------------------------------------------------
@@ -437,8 +557,8 @@ conversion on integral constant.
- 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,
- 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.
@@ -479,7 +599,7 @@ TCPStreamFollower::follow_streams.
- Added DHCP::hostname to extract the hostname options.
- Removed extra qualifier on SessionKeys::decrypt_unicast which
- Removed extra qualifier on SessionKeys::decrypt_unicast which
produced compilation errors on some platforms.
- PacketSender::send now uses PDU::matches_flag to match specific
@@ -495,9 +615,9 @@ PDU types.
-------------------------------------------------------------------------------
##### v2.0 - Thu Jan 23 11:09:38 ART 2014
##### v2.0 - Thu Jan 23 11:09:38 ART 2014
- DNSResourceRecord was removed. Now DNS records are added using
- DNSResourceRecord was removed. Now DNS records are added using
DNS::Resource.
- tins.h now includes ppi.h.
@@ -506,21 +626,21 @@ DNS::Resource.
- Added PDUOption<>::to<> which converts a PDUOption to a specific type.
- Layer 3 packets sent using PacketSender::send_recv for which the
- 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
- 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
- IP packets sent using PacketSender::send_recv now match ICMP
responses.
- Added support for ICMP timestamp request/reply packets.
- 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
@@ -528,20 +648,20 @@ IPv4Reassembler class.
- Fragmented IP packet's inner_pdu PDUs are not decoded now.
- Added 1000ms as the default read timeout used when calling
- 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
- 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
- Added ARP monitor, WPS detector, DNS queries sniffer and DNS spoofer
examples.
- Added another Sniffer constructor which doesn't expect the maximum
@@ -560,10 +680,10 @@ 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
- 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
- Added AddressRange class and IPv4Address, IPv6Address and
HWAddress<>::operator/.
- Added is_broadcast, is_multicast and is_unicast to IPv4, IPv6
@@ -573,7 +693,7 @@ and HWAddress.
- Done some optimizations on TCP's constructor from buffer.
- Added helper functions to Dot11Data to retrieve the source,
- Added helper functions to Dot11Data to retrieve the source,
destination and BSSID addresses.
- Fixed bugs in DNS triggered when parsing MX and unknown records.
@@ -593,7 +713,7 @@ types.
- Added WPA2Decrypter class.
- IEEE 802.11 frames are not parsed if the RadioTap FAILED_FCS flag
- IEEE 802.11 frames are not parsed if the RadioTap FAILED_FCS flag
is on.
- RadioTap now calculates its size everytime it's serialized.
@@ -610,13 +730,13 @@ 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'
- 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
- IP, TCP and UDP now calculate the checksum everytime they're
serialized.
- Added PDU::rfind_pdu.
@@ -627,7 +747,7 @@ serialized.
- PacketSender is now movable.
- Added an overload of add_option that takes an rvalue-reference in IP,
- Added an overload of add_option that takes an rvalue-reference in IP,
TCP, DHCP, ICMPv6 and Dot11.
- Added support for GNU/kFreeBSD.
@@ -670,7 +790,7 @@ pseudo protocol.
##### v0.2 - Sat Oct 20 11:26:40 2012
- Added support for big endian architectures.
- Added support for big endian architectures.
- Simplified several interfaces.

View File

@@ -45,9 +45,10 @@ ELSE(LIBTINS_BUILD_SHARED)
ENDIF(LIBTINS_BUILD_SHARED)
# The version number.
SET(LIBTINS_VERSION_MAJOR 4)
SET(LIBTINS_VERSION_MINOR 0)
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_CURRENT_SOURCE_DIR}/cmake/Modules/")
@@ -224,18 +225,22 @@ IF(DOXYGEN_FOUND)
)
ENDIF(DOXYGEN_FOUND)
# The library output directory
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
# 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})
@@ -298,7 +303,13 @@ IF(LIBTINS_BUILD_TESTS)
ENABLE_TESTING()
ADD_SUBDIRECTORY(tests)
ELSE()
MESSAGE(STATUS "googletest git submodule is absent. Run `git submodule init && git submodule update` to get it")
FIND_PACKAGE(GTest QUIET)
IF(${GTest_FOUND})
ENABLE_TESTING()
ADD_SUBDIRECTORY(tests)
ELSE()
MESSAGE(STATUS "googletest git submodule is absent. Run `git submodule init && git submodule update` to get it")
ENDIF()
ENDIF()
ENDIF()
@@ -306,6 +317,12 @@ 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(
TARGETS tins
@@ -332,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
)

View File

@@ -22,9 +22,6 @@ easier.
Pull requests are very welcomed. When doing a pull request please:
* Base your PR branch on the `develop` branch. This is **almost always** pointing to the
same commit as `master`, so you shouldn't have any issues changing the destination branch
to `develop` at the time you try to do the pull request if you based your code on `master`.
* Your code will be compiled and tests will be run automatically by the travis and
* 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

@@ -79,14 +79,14 @@ function(cxx11_check_feature FEATURE_NAME RESULT_VAR)
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}")
@@ -105,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}")

View File

@@ -1366,7 +1366,8 @@ INCLUDE_FILE_PATTERNS =
# instead of the = operator.
PREDEFINED = "TINS_IS_CXX11=1" \
"TINS_HAVE_WPA2_CALLBACKS=1"
"TINS_HAVE_WPA2_CALLBACKS=1" \
"TINS_HAVE_DOT11=1"
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.

View File

@@ -88,7 +88,7 @@ void do_arp_spoofing(NetworkInterface iface,
sender.send(to_gw, iface);
sender.send(to_victim, iface);
#ifdef _WIN32
Sleep(5);
Sleep(5000);
#else
sleep(5);
#endif

View File

@@ -116,7 +116,7 @@ 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";
}
}

View File

@@ -68,7 +68,7 @@ private:
const IP& ip = pdu.rfind_pdu<IP>();
const TCP& tcp = pdu.rfind_pdu<TCP>();
// We'll only close a connection when seeing a SYN|ACK
if (tcp.flags() == (TCP::SYN | TCP::ACK)) {
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

View File

@@ -40,9 +40,13 @@ 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 {

View File

@@ -31,4 +31,9 @@
/* 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

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

@@ -652,7 +652,7 @@ public:
// Getters
/**
* \brief Setter for the id field.
* \brief Getter for the id field.
*
* \return uint16_t containing the value of the id field.
*/
@@ -661,7 +661,7 @@ public:
}
/**
* \brief Setter for the query response field.
* \brief Getter for the query response field.
*
* \return QRType containing the value of the query response
* field.
@@ -671,7 +671,7 @@ public:
}
/**
* \brief Setter for the opcode field.
* \brief Getter for the opcode field.
*
* \return uint8_t containing the value of the opcode field.
*/
@@ -680,7 +680,7 @@ public:
}
/**
* \brief Setter for the authoritative answer field.
* \brief Getter for the authoritative answer field.
*
* \return uint8_t containing the value of the authoritative
* answer field.
@@ -690,7 +690,7 @@ public:
}
/**
* \brief Setter for the truncated field.
* \brief Getter for the truncated field.
*
* \return uint8_t containing the value of the truncated field.
*/
@@ -699,7 +699,7 @@ public:
}
/**
* \brief Setter for the recursion desired field.
* \brief Getter for the recursion desired field.
*
* \return uint8_t containing the value of the recursion
* desired field.
@@ -709,7 +709,7 @@ public:
}
/**
* \brief Setter for the recursion available field.
* \brief Getter for the recursion available field.
*
* \return uint8_t containing the value of the recursion
* available field.
@@ -719,7 +719,7 @@ public:
}
/**
* \brief Setter for the z desired field.
* \brief Getter for the z desired field.
*
* \return uint8_t containing the value of the z field.
*/
@@ -728,7 +728,7 @@ public:
}
/**
* \brief Setter for the authenticated data field.
* \brief Getter for the authenticated data field.
*
* \return uint8_t containing the value of the authenticated
* data field.
@@ -738,7 +738,7 @@ public:
}
/**
* \brief Setter for the checking disabled field.
* \brief Getter for the checking disabled field.
*
* \return uint8_t containing the value of the checking
* disabled field.
@@ -748,7 +748,7 @@ public:
}
/**
* \brief Setter for the rcode field.
* \brief Getter for the rcode field.
*
* \return uint8_t containing the value of the rcode field.
*/
@@ -757,7 +757,7 @@ public:
}
/**
* \brief Setter for the questions field.
* \brief Getter for the questions field.
*
* \return uint16_t containing the value of the questions field.
*/
@@ -766,7 +766,7 @@ public:
}
/**
* \brief Setter for the answers field.
* \brief Getter for the answers field.
*
* \return uint16_t containing the value of the answers field.
*/
@@ -775,7 +775,7 @@ public:
}
/**
* \brief Setter for the authority field.
* \brief Getter for the authority field.
*
* \return uint16_t containing the value of the authority field.
*/
@@ -784,7 +784,7 @@ public:
}
/**
* \brief Setter for the additional field.
* \brief Getter for the additional field.
*
* \return uint16_t containing the value of the additional field.
*/
@@ -1034,7 +1034,8 @@ private:
uint32_t compose_name(const uint8_t* ptr, char* out_ptr) const;
void convert_records(const uint8_t* ptr,
const uint8_t* end,
resources_type& res) const;
resources_type& res,
const uint16_t rr_count) const;
void skip_to_section_end(Memory::InputMemoryStream& stream,
const uint32_t num_records) const;
void skip_to_dname_end(Memory::InputMemoryStream& stream) const;

View File

@@ -127,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
};

View File

@@ -5,14 +5,14 @@
* 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
@@ -46,11 +46,11 @@ 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.
@@ -59,15 +59,15 @@ public:
/**
* \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.
*/
@@ -97,6 +97,11 @@ public:
*/
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.
*/
@@ -109,30 +114,39 @@ public:
* \param addr The new target address.
*/
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(),
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.
*/
@@ -149,8 +163,8 @@ protected:
/**
* \brief Getter for the control ta additional fields size.
*/
uint32_t controlta_size() const {
return static_cast<uint32_t>(taddr_.size() + sizeof(dot11_header));
uint32_t controlta_size() const {
return static_cast<uint32_t>(taddr_.size() + sizeof(dot11_header));
}
void write_ext_header(Memory::OutputMemoryStream& stream);
@@ -178,19 +192,19 @@ public:
* \param dst_addr The destination hardware address.
* \param target_addr The source hardware address.
*/
Dot11RTS(const address_type& dst_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.
*/
@@ -233,26 +247,26 @@ 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(),
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.
*/
@@ -295,26 +309,26 @@ 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(),
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.
*/
@@ -357,26 +371,26 @@ 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(),
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.
*/
@@ -419,7 +433,7 @@ 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.
@@ -428,15 +442,15 @@ public:
/**
* \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.
*/
@@ -482,26 +496,26 @@ 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(),
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.
*/
@@ -513,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
}
@@ -525,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.
*
@@ -566,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.
@@ -614,7 +628,7 @@ public:
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::DOT11_BLOCK_ACK;
/**
* The size of the bitmap field.
*/
@@ -623,26 +637,26 @@ 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(),
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.
*/
@@ -654,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
}
@@ -666,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.
*
@@ -707,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.
@@ -716,9 +730,9 @@ 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 {

View File

@@ -64,8 +64,26 @@ public:
class malformed_packet : public exception_base {
public:
malformed_packet() : exception_base("Malformed packet") { }
malformed_packet(const std::string& message) : exception_base(message) { }
};
/**
* \brief Exception thrown when a DNS decompression pointer is out of bounds.
*/
class dns_decompression_pointer_out_of_bounds : public malformed_packet {
public:
dns_decompression_pointer_out_of_bounds() : malformed_packet("DNS decompression: pointer out of bounds") { }
};
/**
* \brief Exception thrown when a DNS decompression pointer loops.
*/
class dns_decompression_pointer_loops : public malformed_packet {
public:
dns_decompression_pointer_loops() : malformed_packet("DNS decompression: pointer loops") { }
};
/**
* \brief Exception thrown when serializing a packet fails.
*/
@@ -128,7 +146,7 @@ public:
/**
* \brief Exception thrown when PacketSender fails to close a socket.
*/
class socket_close_error : exception_base {
class socket_close_error : public exception_base {
public:
socket_close_error(const std::string& msg)
: exception_base(msg) { }
@@ -204,6 +222,15 @@ 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
*/

View File

@@ -59,6 +59,9 @@ TINS_API bool hw_address_equal_compare(const uint8_t* start1, const uint8_t* end
TINS_API bool hw_address_lt_compare(const uint8_t* start1, const uint8_t* end1,
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
*/
@@ -268,6 +271,39 @@ public:
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
*
@@ -281,7 +317,33 @@ public:
}
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.
*

View File

@@ -89,7 +89,9 @@ public:
INFO_REQUEST = 15,
INFO_REPLY = 16,
ADDRESS_MASK_REQUEST = 17,
ADDRESS_MASK_REPLY = 18
ADDRESS_MASK_REPLY = 18,
EXTENDED_ECHO_REQUEST = 42,
EXTENDED_ECHO_REPLY = 43
};
/**
@@ -318,7 +320,7 @@ public:
* \return Returns the gateway field value.
*/
address_type gateway() const {
return address_type(Endian::be_to_host(header_.un.gateway));
return address_type(header_.un.gateway);
}
/**
@@ -381,7 +383,7 @@ public:
* \return Returns the address mask value.
*/
address_type address_mask() const {
return address_type(Endian::be_to_host(orig_timestamp_or_address_mask_));
return address_type(orig_timestamp_or_address_mask_);
}
/**

View File

@@ -30,6 +30,7 @@
#ifndef TINS_ICMPV6_H
#define TINS_ICMPV6_H
#include <algorithm>
#include <vector>
#include <tins/macros.h>
#include <tins/pdu.h>
@@ -92,7 +93,9 @@ public:
MULTICAST_ROUTER_ADVERT = 151,
MULTICAST_ROUTER_SOLICIT = 152,
MULTICAST_ROUTER_TERMINATE = 153,
RPL_CONTROL_MSG = 155
RPL_CONTROL_MSG = 155,
EXTENDED_ECHO_REQUEST = 160,
EXTENDED_ECHO_REPLY = 161
};
/**
@@ -173,7 +176,7 @@ public:
addr_list_type(const addresses_type& addresses = addresses_type())
: addresses(addresses) {
std::fill(reserved, reserved + sizeof(reserved), 0);
std::fill(reserved, reserved + sizeof(reserved), static_cast<uint8_t>(0));
}
static addr_list_type from_option(const option& opt);
@@ -199,7 +202,7 @@ public:
naack_type(uint8_t code = 0, uint8_t status = 0)
: code(code), status(status) {
std::fill(reserved, reserved + 4, 0);
std::fill(reserved, reserved + 4, static_cast<uint8_t>(0));
}
static naack_type from_option(const option& opt);
@@ -323,7 +326,7 @@ public:
* The key_hash member will be 0-initialized.
*/
rsa_sign_type() {
std::fill(key_hash, key_hash + sizeof(key_hash), 0);
std::fill(key_hash, key_hash + sizeof(key_hash), static_cast<uint8_t>(0));
}
static rsa_sign_type from_option(const option& opt);
@@ -489,7 +492,7 @@ public:
timestamp_type(uint64_t timestamp = 0)
: timestamp(timestamp) {
std::fill(reserved, reserved + sizeof(reserved), 0);
std::fill(reserved, reserved + sizeof(reserved), static_cast<uint8_t>(0));
}
static timestamp_type from_option(const option& opt);

View File

@@ -174,9 +174,9 @@ public:
option_identifier(OptionNumber number, OptionClass op_class,
small_uint<1> copied)
#if TINS_IS_LITTLE_ENDIAN
: number(number), op_class(op_class), copied(copied) {}
: number(static_cast<uint8_t>(number)), op_class(static_cast<uint8_t>(op_class)), copied(copied) {}
#else
: copied(copied), op_class(op_class), number(number) {}
: copied(copied), op_class(static_cast<uint8_t>(op_class)), number(static_cast<uint8_t>(number)) {}
#endif
/**
@@ -281,6 +281,10 @@ public:
/* Getters */
uint32_t advertised_size() const {
return static_cast<uint32_t>(tot_len());
}
/**
* \brief Getter for the header length field.
*

View File

@@ -33,7 +33,7 @@
#include <string>
#include <iosfwd>
#include <functional>
#include <stdint.h>
#include <cstdint>
#include <tins/cxxstd.h>
#include <tins/macros.h>
@@ -135,6 +135,38 @@ public:
return ip_addr_ < rhs.ip_addr_;
}
/**
* \brief Compares this address for less-than equality.
*
* \param rhs The address to be compared to.
*
* \return bool indicating whether this address is equal or less-than rhs.
*/
bool operator<=(const IPv4Address& rhs) const {
return !operator>(rhs);
}
/**
* \brief Compare this IPv4Address for greater-than inequality.
*
* \param rhs The address to be compared.
* \return bool indicating whether this address is greater-than rhs.
*/
bool operator>(const IPv4Address& rhs) const {
return ip_addr_ > rhs.ip_addr_;
}
/**
* \brief Compares this address for greater-than equality.
*
* \param rhs The address to be compared to.
*
* \return bool indicating whether this address is equal or greater-than rhs.
*/
bool operator>=(const IPv4Address& rhs) const {
return !operator<(rhs);
}
/**
* \brief Apply a mask to this address
*
@@ -142,6 +174,19 @@ public:
* \return The result of applying the mask to this address
*/
IPv4Address operator&(const IPv4Address& mask) const;
/**
* \brief Apply a mask to this address
*
* \param mask The mask to be applied
* \return The result of applying the mask to this address
*/
IPv4Address operator|(const IPv4Address& mask) const;
/**
* not operator (invert)
*/
IPv4Address operator~() const;
/**
* \brief Returns true if this is a private IPv4 address.

View File

@@ -73,6 +73,11 @@ public:
*/
typedef std::vector<ext_header> headers_type;
/**
* The type used to store an extension header option.
*/
typedef std::pair<uint8_t, std::vector<uint8_t> > header_option_type;
/**
* The values used to identify extension headers.
*/
@@ -105,6 +110,46 @@ public:
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/*
* \brief The type used to store Hop-By-Hop Extension Headers
*/
struct hop_by_hop_header {
std::vector<header_option_type> options;
static hop_by_hop_header from_extension_header(const ext_header& hdr);
};
/*
* \brief The type used to store Destination Routing Extension Headers
*/
struct destination_routing_header {
std::vector<header_option_type> options;
static destination_routing_header from_extension_header(const ext_header& hdr);
};
/**
* \brief The type used to store Routing Extension headers
*/
struct routing_header {
uint8_t routing_type;
uint8_t segments_left;
std::vector<uint8_t> data;
static routing_header from_extension_header(const ext_header& hdr);
};
/**
* \brief The type used to store Fragment Extension headers
*/
struct fragment_header {
uint16_t fragment_offset;
bool more_fragments;
uint32_t identification;
static fragment_header from_extension_header(const ext_header& hdr);
};
/**
* \brief Constructs an IPv6 object.
*
@@ -298,6 +343,14 @@ public:
* \sa PDU::send()
*/
void send(PacketSender& sender, const NetworkInterface &);
/**
* \brief Receives a matching response for this packet.
*
* \sa PDU::recv_response
* \param sender The packet sender which will receive the packet.
*/
PDU* recv_response(PacketSender& sender, const NetworkInterface &);
#endif
/**
@@ -356,6 +409,8 @@ private:
uint32_t calculate_headers_size() const;
static void write_header(const ext_header& header, Memory::OutputMemoryStream& stream);
static bool is_extension_header(uint8_t header_id);
static uint32_t get_padding_size(const ext_header& header);
static std::vector<header_option_type> parse_header_options(const uint8_t* data, size_t size);
TINS_BEGIN_PACK
struct ipv6_header {

View File

@@ -160,7 +160,40 @@ public:
bool operator<(const IPv6Address& rhs) const {
return std::lexicographical_compare(begin(), end(), rhs.begin(), rhs.end());
}
/**
* \brief Compares this address for less-than equality.
*
* \param rhs The address to be compared to.
*
* \return bool indicating whether this address is equal or less-than rhs.
*/
bool operator<=(const IPv6Address& rhs) const {
return !operator>(rhs);
}
/**
* \brief Compares this address for greater-than inequality.
*
* \param rhs The address to be compared to.
*
* \return bool indicating whether this address is greater-than rhs.
*/
bool operator>(const IPv6Address& rhs) const {
return std::lexicographical_compare(rhs.begin(), rhs.end(), begin(), end());
}
/**
* \brief Compares this address for greater-than equality.
*
* \param rhs The address to be compared to.
*
* \return bool indicating whether this address is equal or greater-than rhs.
*/
bool operator>=(const IPv6Address& rhs) const {
return !operator<(rhs);
}
/**
* \brief Helper function which copies the address into an output
* iterator.
@@ -197,6 +230,14 @@ public:
*/
bool is_multicast() const;
/**
* \brief Return true if this is a Link-Local unicast IPv6 address.
*
* This method returns true if this address is in the address range
* fe80::/10, false otherwise
*/
bool is_local_unicast() const;
/**
* \brief Returns the size of an IPv6 Address.
*
@@ -218,7 +259,17 @@ public:
/**
* Applies a mask to an address
*/
TINS_API friend IPv6Address operator&(const IPv6Address& lhs, const IPv6Address& rhs);
IPv6Address operator&(const IPv6Address& rhs) const;
/**
* or a mask to an address
*/
IPv6Address operator|(const IPv6Address& rhs) const;
/**
* not operator (invert)
*/
IPv6Address operator~() const ;
private:
void init(const char* addr);

View File

@@ -236,7 +236,7 @@ public:
* \return The LLC frame format.
*/
uint8_t type() {
return type_;
return static_cast<uint8_t>(type_);
}
/**
@@ -245,7 +245,7 @@ public:
* \return The sender send sequence number if format is INFORMATION else 0.
*/
uint8_t send_seq_number() {
return (type() == INFORMATION) ? (control_field.info.send_seq_num) : 0;
return static_cast<uint8_t>((type() == INFORMATION) ? (control_field.info.send_seq_num) : 0);
}
/**

View File

@@ -118,6 +118,17 @@ public:
* \param ip The ip address being looked up.
*/
NetworkInterface(IPv4Address ip);
/**
* \brief Constructs a NetworkInterface from an ipv6 address.
*
* This abstracted interface will be the one that would be the gateway
* when sending a packet to the given ip.
*
* \param ip The ipv6 address being looked up.
*/
NetworkInterface(IPv6Address ipv6);
/**
* \brief Getter for this interface's identifier.

View File

@@ -65,7 +65,9 @@ class PDU;
* - Those that don't contain a link layer PDU. In this case, the
* kernel will be responsible for picking the appropriate network interface
* based on the destination address.
*
* - Exception: <a href="https://datatracker.ietf.org/doc/html/rfc2553#section-3.3">RFC2553</a>
* requires IPv6 link-scope address have a interface defined.
* .
* \par Note for Windows users:
* Sending layer 3 PDUs (without a link layer protocol) is very restricted
* on Windows (<a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms740548(v=vs.85).aspx">link</a>).
@@ -131,6 +133,7 @@ public:
ARP_SOCKET,
ICMP_SOCKET,
IPV6_SOCKET,
ICMPV6_SOCKET,
SOCKETS_END
};

View File

@@ -5,14 +5,14 @@
* 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
@@ -26,7 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_PDU_H
#define TINS_PDU_H
@@ -49,22 +49,22 @@ class NetworkInterface;
*/
typedef std::vector<uint8_t> byte_array;
/**
/**
* \class PDU
* \brief Base class for protocol data units.
*
* Every PDU implementation inherits from this class.
* Every PDU implementation inherits from this class.
*
* PDUs can contain 0 or 1 inner PDU. By stacking several PDUs together,
* you can construct packets. These are created upwards: upper layers
* will be children of the lower ones.
* you can construct packets. These are created upwards: upper layers
* will be children of the lower ones.
*
* If you want to find a specific protocol within a PDU chain, you can use
* PDU::find_pdu and PDU::rfind_pdu. Both of them take a template parameter
* that indicates the PDU type you are looking for. The first one returns a
* pointer to the first object of that type, and the second one returns a
* reference (and throws if it is not found).
*
* that indicates the PDU type you are looking for. The first one returns a
* pointer to the first object of that type, and the second one returns a
* reference (and throws if it is not found).
*
* For example:
*
* \code
@@ -86,7 +86,7 @@ typedef std::vector<uint8_t> byte_array;
* stack into a vector of bytes. This process might modify some parameters
* on packets depending on which protocols are used in it. For example:
*
* - If the lowest protocol layer is IP (this means that there is no
* - If the lowest protocol layer is IP (this means that there is no
* link layer protocol in the packet), then it calculates the source address
* that should be used in that IP PDU. \sa IP
* - If a protocol contains a checksum field, its value will be calculated
@@ -170,6 +170,7 @@ public:
ICMPv6,
SLL,
DHCPv6,
DOT1AD,
DOT1Q,
PPPOE,
STP,
@@ -178,10 +179,12 @@ public:
IPSEC_ESP,
PKTAP,
MPLS,
DOT11_CONTROL_TA,
VXLAN,
UNKNOWN = 999,
USER_DEFINED_PDU = 1000
};
/**
* The endianness used by this PDU. This can be overriden
* by subclasses.
@@ -196,10 +199,10 @@ public:
* \brief Default constructor
*/
metadata();
/**
* \brief Constructs an instance of metadata using the given values
*/
metadata(uint32_t header_size, PDUType current_type, PDUType next_type);
@@ -219,33 +222,34 @@ public:
PDUType next_pdu_type;
};
/**
/**
* \brief Default constructor.
*/
PDU();
#if TINS_IS_CXX11
/**
* \brief Move constructor.
*
*
* \param rhs The PDU to be moved.
*/
PDU(PDU &&rhs) TINS_NOEXCEPT
PDU(PDU &&rhs) TINS_NOEXCEPT
: inner_pdu_(0), parent_pdu_(0) {
std::swap(inner_pdu_, rhs.inner_pdu_);
if (inner_pdu_) {
inner_pdu_->parent_pdu(this);
}
}
/**
* \brief Move assignment operator.
*
*
* \param rhs The PDU to be moved.
*/
PDU& operator=(PDU &&rhs) TINS_NOEXCEPT {
delete inner_pdu_;
inner_pdu_ = 0;
std::swap(inner_pdu_, rhs.inner_pdu_);
rhs.inner_pdu_ = 0;
if (inner_pdu_) {
inner_pdu_->parent_pdu(this);
}
@@ -253,7 +257,7 @@ public:
}
#endif
/**
/**
* \brief PDU destructor.
*
* Deletes the inner pdu, as a consequence every child pdu is
@@ -279,6 +283,12 @@ public:
*/
uint32_t size() const;
/** \brief The whole chain of PDU's advertised size, including this one.
*
* Returns the sum of this and all children PDU's advertised size.
*/
virtual uint32_t advertised_size() const;
/**
* \brief Getter for the inner PDU.
* \return The current inner PDU. Might be a null pointer.
@@ -294,18 +304,18 @@ public:
PDU* parent_pdu() const {
return parent_pdu_;
}
/**
* \brief Releases the inner PDU.
*
*
* This method makes this PDU to <b>no longer own</b> the inner
* PDU. The current inner PDU is returned, and is <b>not</b>
* destroyed. That means after calling this function, you are
* destroyed. That means after calling this function, you are
* responsible for using operator delete on the returned pointer.
*
*
* Use this method if you want to somehow re-use a PDU that
* is already owned by another PDU.
*
*
* \return The current inner PDU. Might be 0.
*/
PDU* release_inner_pdu();
@@ -315,26 +325,26 @@ public:
*
* When setting a new inner_pdu, the instance takesownership of
* the object, therefore deleting it when it's no longer required.
*
*
* \param next_pdu The new child PDU.
*/
void inner_pdu(PDU* next_pdu);
/**
* \brief Sets the child PDU.
*
* The PDU parameter is cloned using PDU::clone.
*
*
* \param next_pdu The new child PDU.
*/
void inner_pdu(const PDU& next_pdu);
/**
/**
* \brief Serializes the whole chain of PDU's, including this one.
*
* This allocates a std::vector of size size(), and fills it
* with the serialization this PDU, and all of the inner ones'.
*
*
* \return serialization_type containing the serialization
* of the whole stack of PDUs.
*/
@@ -348,7 +358,7 @@ public:
* If no PDU matches, 0 is returned.
* \param flag The flag which being searched.
*/
template<typename T>
template<typename T>
T* find_pdu(PDUType type = T::pdu_flag) {
PDU* pdu = this;
while (pdu) {
@@ -359,24 +369,24 @@ public:
}
return 0;
}
/**
* \brief Finds and returns the first PDU that matches the given flag.
*
* \param flag The flag which being searched.
*/
template<typename T>
template<typename T>
const T* find_pdu(PDUType type = T::pdu_flag) const {
return const_cast<PDU*>(this)->find_pdu<T>(type);
}
/**
* \brief Finds and returns the first PDU that matches the given flag.
*
*
* If the PDU is not found, a pdu_not_found exception is thrown.
*
*
* \sa PDU::find_pdu
*
*
* \param flag The flag which being searched.
*/
template<typename T>
@@ -393,7 +403,7 @@ public:
*
* \param flag The flag which being searched.
*/
template<typename T>
template<typename T>
const T& rfind_pdu(PDUType type = T::pdu_flag) const {
return const_cast<PDU*>(this)->rfind_pdu<T>(type);
}
@@ -408,36 +418,36 @@ public:
*/
virtual PDU* clone() const = 0;
/**
/**
* \brief Send the stack of PDUs through a PacketSender.
*
* This method will be called only for the PDU on the bottom of the stack,
* therefore it should only implement this method if it can be sent.
*
*
* PacketSender implements specific methods to send packets which start
* on every valid TCP/IP stack layer; this should only be a proxy for
* those methods.
*
*
* If this PDU does not represent a link layer protocol, then
* the interface argument will be ignored.
*
*
* \param sender The PacketSender which will send the packet.
* \param iface The network interface in which this packet will
* \param iface The network interface in which this packet will
* be sent.
*/
virtual void send(PacketSender& sender, const NetworkInterface& iface);
/**
/**
* \brief Receives a matching response for this packet.
*
* This method should act as a proxy for PacketSender::recv_lX methods.
*
*
* \param sender The packet sender which will receive the packet.
* \param iface The interface in which to expect the response.
*/
virtual PDU* recv_response(PacketSender& sender, const NetworkInterface& iface);
/**
/**
* \brief Check whether ptr points to a valid response for this PDU.
*
* This method must check whether the buffer pointed by ptr is a valid
@@ -486,18 +496,18 @@ protected:
/**
* \brief Prepares this PDU for serialization.
*
*
* This method is called before the inner PDUs are serialized.
* It's useful in situations such as when serializing IP PDUs,
* which don't contain any link layer encapsulation, and therefore
* require to set the source IP address before the TCP/UDP checksum
* is calculated.
*
*
* By default, this method does nothing
*/
virtual void prepare_for_serialize();
/**
/**
* \brief Serializes this PDU and propagates this action to child PDUs.
*
* \param buffer The buffer in which to store this PDU's serialization.
@@ -505,7 +515,7 @@ protected:
*/
void serialize(uint8_t* buffer, uint32_t total_sz);
/**
/**
* \brief Serializes this TCP PDU.
*
* Each PDU must override this method and implement it's own
@@ -523,18 +533,18 @@ private:
/**
* \brief Concatenation operator.
*
* This operator concatenates several PDUs. A copy of the right
*
* This operator concatenates several PDUs. A copy of the right
* operand is set at the end of the left one's inner PDU chain.
* This means that:
*
*
* IP some_ip = IP("127.0.0.1") / TCP(12, 13) / RawPDU("bleh");
*
* Works as expected, meaning the output PDU will look like the
*
* Works as expected, meaning the output PDU will look like the
* following:
*
*
* IP - TCP - RawPDU
*
*
* \param lop The left operand, which will be the one modified.
* \param rop The right operand, the one which will be appended
* to lop.
@@ -551,7 +561,7 @@ T& operator/= (T& lop, const PDU& rop) {
/**
* \brief Concatenation operator.
*
*
* \sa operator/=
*/
template<typename T>
@@ -562,7 +572,7 @@ T operator/ (T lop, const PDU& rop) {
/**
* \brief Concatenation operator on PDU pointers.
*
*
* \sa operator/=
*/
template<typename T>

View File

@@ -106,8 +106,8 @@ private:
*/
template <typename Concrete>
bool operator==(const PDUIteratorBase<Concrete>& lhs, const PDUIteratorBase<Concrete>& rhs) {
const PDU* lhs_pdu = &*static_cast<const Concrete&>(lhs);
const PDU* rhs_pdu = &*static_cast<const Concrete&>(rhs);
const PDU* lhs_pdu = static_cast<const Concrete&>(lhs).operator->();
const PDU* rhs_pdu = static_cast<const Concrete&>(rhs).operator->();
return lhs_pdu == rhs_pdu;
}
@@ -241,7 +241,7 @@ public:
template <typename OtherIterator>
PDUIteratorRange(const PDUIteratorRange<OtherIterator>& other)
: start_(&*other.begin()), end_(&*other.end()) {
: start_(other.begin().operator->()), end_(other.end().operator->()) {
}

View File

@@ -115,7 +115,7 @@ public:
* \param data The payload to use.
*/
RawPDU(payload_type&& data)
: payload_(move(data)) { }
: payload_(std::move(data)) { }
#endif // TINS_IS_CXX11
/**

View File

@@ -406,10 +406,17 @@ private:
*/
class TINS_API FileSniffer : public BaseSniffer {
public:
/**
* \brief Constructs an instance of FileSniffer.
* \param fp The pcap file which will be parsed.
* \param configuration A SnifferConfiguration to be used on the file.
*/
FileSniffer(FILE *fp, const SnifferConfiguration& configuration);
/**
* \brief Constructs an instance of FileSniffer.
* \param file_name The pcap file which will be parsed.
* \param filter A capture filter to be used on the file.(optional);
* \param configuration A SnifferConfiguration to be used on the file.
*/
FileSniffer(const std::string& file_name, const SnifferConfiguration& configuration);
@@ -418,9 +425,18 @@ public:
*
* \brief Constructs an instance of FileSniffer.
* \param file_name The pcap file which will be parsed.
* \param filter A capture filter to be used on the file.(optional);
* \param filter A capture filter to be used on the file. (optional)
*/
FileSniffer(const std::string& file_name, const std::string& filter = "");
/**
* \deprecated Use the constructor that takes a SnifferConfiguration instead.
*
* \brief Constructs an instance of FileSniffer.
* \param fp The pcap file which will be parsed.
* \param filter A capture filter to be used on the file. (optional)
*/
FileSniffer(FILE *fp, const std::string& filter = "");
};
template <typename T>
@@ -449,8 +465,14 @@ HandlerProxy<T> make_sniffer_handler(T* ptr,
/**
* \brief Iterates over packets sniffed by a BaseSniffer.
*/
class SnifferIterator : public std::iterator<std::forward_iterator_tag, Packet> {
class SnifferIterator {
public:
typedef std::forward_iterator_tag iterator_category;
typedef Packet value_type;
typedef std::ptrdiff_t difference_type;
typedef Packet* pointer;
typedef Packet& reference;
/**
* Constructs a SnifferIterator.
* \param sniffer The sniffer to iterate.

View File

@@ -288,13 +288,29 @@ public:
* \code
* TCP tcp = ...;
* if(tcp.flags() == (TCP::SYN | TCP::ACK)) {
* // It's a SYN+ACK!
* // It's a SYN+ACK, but not SYN+ACK+ECN!
* }
* \endcode
*
* \return The value of the flags field.
*/
small_uint<12> flags() const;
/**
* \brief Check if the given flags are set.
*
* \code
* TCP tcp = ...;
* if(tcp.has_flags(TCP::SYN | TCP::ACK)) {
* // It's a SYN+ACK, but it also possible that other flags are set!
* // it is equivalent to: (tpc.flags() & (TCP::SYN | TCP::ACK)) == (TCP::SYN | TCP::ACK)
* }
* \endcode
*
* \param check_flags
* \return true if all check_flags are set
*/
bool has_flags(small_uint<12> check_flags) const;
/* Setters */

View File

@@ -40,23 +40,28 @@
#include <tins/llc.h>
#include <tins/icmp.h>
#include <tins/icmpv6.h>
#if defined(TINS_HAVE_DOT11)
#include <tins/dot11.h>
#endif
#include <tins/dot1q.h>
#include <tins/dot3.h>
#include <tins/ip.h>
#include <tins/ipv6.h>
#include <tins/mpls.h>
#include <tins/packet_sender.h>
#include <tins/packet_writer.h>
#include <tins/pdu.h>
#include <tins/radiotap.h>
#include <tins/rawpdu.h>
#include <tins/snap.h>
#include <tins/sniffer.h>
#include <tins/tcp.h>
#include <tins/udp.h>
#include <tins/utils.h>
#if defined(TINS_HAVE_PCAP)
#include <tins/packet_writer.h>
#include <tins/sniffer.h>
#include <tins/ppi.h>
#include <tins/tcp_stream.h>
#endif
#include <tins/crypto.h>
#include <tins/pdu_cacher.h>
#include <tins/rsn_information.h>
@@ -73,7 +78,7 @@
#include <tins/pdu_allocator.h>
#include <tins/ipsec.h>
#include <tins/ip_reassembler.h>
#include <tins/ppi.h>
#include <tins/pdu_iterator.h>
#include <tins/vxlan.h>
#endif // TINS_TINS_H

View File

@@ -114,7 +114,11 @@ public:
RadioTap::option current_option();
/**
* Gets the pointer at which the current option is located
* \brief Gets the pointer at which the current option is located
*
* A past-the-end pointer may be returned in case of malformed input or
* end of data. Its validity must be checked (e.g. using
* \ref RadioTapParser.has_fields) before dereference.
*/
const uint8_t* current_option_ptr() const;

View File

@@ -110,6 +110,14 @@ struct Route6Entry {
template<typename ForwardIterator>
void route_entries(ForwardIterator output);
/**
* \brief Retrieves entries in the routing table.
*
* \brief output ForwardIterator in which entries will be stored.
*/
template<typename ForwardIterator>
void route6_entries(ForwardIterator output);
/**
* \brief Retrieves entries in the routing table.
*
@@ -117,6 +125,7 @@ void route_entries(ForwardIterator output);
*/
TINS_API std::vector<RouteEntry> route_entries();
/**
* \brief Retrieves entries in the routing table.
*
@@ -146,6 +155,19 @@ TINS_API std::set<std::string> network_interfaces();
*/
TINS_API bool gateway_from_ip(IPv4Address ip, IPv4Address& gw_addr);
/**
* \brief Finds the gateway's IP address for the given IP
* address.
*
* \param ip The IP address for which the default gateway will
* be searched.
* \param gw_addr This parameter will contain the gateway's IP
* address in case it is found.
*
* \return bool indicating whether the lookup was successfull.
*/
TINS_API bool gateway_from_ip(IPv6Address ip, IPv6Address& gw_addr);
} // Utils
} // Tins
@@ -158,4 +180,13 @@ void Tins::Utils::route_entries(ForwardIterator output) {
}
}
template<typename ForwardIterator>
void Tins::Utils::route6_entries(ForwardIterator output) {
std::vector<Route6Entry> entries = route6_entries();
for (size_t i = 0; i < entries.size(); ++i) {
*output = entries[i];
++output;
}
}
#endif // TINS_ROUTING_UTILS_H

98
include/tins/vxlan.h Normal file
View File

@@ -0,0 +1,98 @@
#ifndef TINS_VXLAN_H
#define TINS_VXLAN_H
#include <tins/pdu.h>
#include <tins/small_uint.h>
namespace Tins {
/**
* \class VXLAN
* \brief Represents a VXLAN PDU.
*
* This class represents a VXLAN PDU.
*
* \sa RawPDU
*/
class TINS_API VXLAN : public PDU {
public:
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::VXLAN;
/**
* \brief Constructs a VXLAN PDU.
*
* \param vni VXLAN Network Identifier.
*/
VXLAN(const small_uint<24> vni = 0);
/**
* \brief Constructs a VXLAN object from a buffer and adds
* the Ethernet II PDU.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
VXLAN(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Getter for the flags.
*/
uint8_t get_flags() const { return Endian::be_to_host(header_.flags) >> 24; }
/**
* \brief Getter for the VNI.
*/
small_uint<24> get_vni() const { return Endian::be_to_host(header_.vni) >> 8; }
/**
* \brief Setter for the flags.
* \param new_flags The new flags.
*/
void set_flags(uint8_t new_flags) { header_.flags = Endian::host_to_be(new_flags << 24); }
/**
* \brief Setter for the VNI.
* \param new_vni The new VNI.
*/
void set_vni(small_uint<24> new_vni) { header_.vni = Endian::host_to_be(new_vni << 8); }
/**
* \brief Returns the VXLAN frame's header length.
*
* This method overrides PDU::header_size. This size includes the
* payload and options size.
*
* \return An uint32_t with the header's size.
* \sa PDU::header_size
*/
uint32_t header_size() const { return sizeof(header_); }
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \sa PDU::clone
*/
VXLAN *clone() const { return new VXLAN(*this); }
private:
TINS_BEGIN_PACK
struct vxlan_header {
uint32_t flags;
uint32_t vni;
} TINS_END_PACK;
void write_serialization(uint8_t* buffer, uint32_t total_sz);
vxlan_header header_;
};
} // Tins
#endif // TINS_VXLAN_H

View File

@@ -8,10 +8,10 @@ IF(HAVE_PCAP_TIMESTAMP_PRECISION)
ADD_DEFINITIONS("-DHAVE_PCAP_TIMESTAMP_PRECISION=1")
ENDIF()
INCLUDE_DIRECTORIES(
${LIBTINS_INCLUDE_DIR}
INCLUDE_DIRECTORIES(BEFORE
${OPENSSL_INCLUDE_DIR}
${PCAP_INCLUDE_DIR}
${LIBTINS_INCLUDE_DIR}
)
set(SOURCES
@@ -73,6 +73,7 @@ set(SOURCES
utils/routing_utils.cpp
utils/resolve_utils.cpp
utils/pdu_utils.cpp
vxlan.cpp
)
set(HEADERS
@@ -151,6 +152,7 @@ set(HEADERS
${LIBTINS_INCLUDE_DIR}/tins/utils/routing_utils.h
${LIBTINS_INCLUDE_DIR}/tins/utils/resolve_utils.h
${LIBTINS_INCLUDE_DIR}/tins/utils/pdu_utils.h
${LIBTINS_INCLUDE_DIR}/tins/vxlan.h
)
SET(DOT11_DEPENDENT_SOURCES
@@ -219,8 +221,9 @@ SET_TARGET_PROPERTIES(tins PROPERTIES VERSION ${LIBTINS_VERSION} SOVERSION ${LIB
INSTALL(
TARGETS tins
EXPORT libtinsTargets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT dev
)
@@ -233,4 +236,4 @@ MACRO(INSTALL_HEADERS_WITH_DIRECTORY HEADER_LIST)
ENDFOREACH(HEADER)
ENDMACRO()
INSTALL_HEADERS_WITH_DIRECTORY(${HEADERS})
INSTALL_HEADERS_WITH_DIRECTORY(${HEADERS})

View File

@@ -211,6 +211,8 @@ Constants::Ethernet::e pdu_flag_to_ether_type(PDU::PDUType flag) {
return Constants::Ethernet::ARP;
case PDU::DOT1Q:
return Constants::Ethernet::VLAN;
case PDU::DOT1AD:
return Constants::Ethernet::QINQ;
case PDU::PPPOE:
return Constants::Ethernet::PPPOED;
case PDU::MPLS:
@@ -238,6 +240,9 @@ PDU::PDUType ether_type_to_pdu_flag(Constants::Ethernet::e flag) {
return PDU::ARP;
case Constants::Ethernet::VLAN:
return PDU::DOT1Q;
case Constants::Ethernet::QINQ:
case Constants::Ethernet::OLD_QINQ:
return PDU::DOT1AD;
case Constants::Ethernet::PPPOED:
return PDU::PPPOE;
//case PDU::RSNEAPOL
@@ -295,4 +300,4 @@ PDU::PDUType ip_type_to_pdu_flag(Constants::IP::e flag) {
}
} // Internals
} // Tins
} // Tins

View File

@@ -86,14 +86,18 @@ void DNS::skip_to_dname_end(InputMemoryStream& stream) const {
break;
}
else {
if ((value & 0xc0)) {
// This is an offset label, skip the second byte and we're done
const uint8_t offset_discriminator = value & 0xc0;
if (offset_discriminator == 0xc0) {
// This is an offset pointer, skip the second byte and we're done
stream.skip(1);
break;
}
else {
else if (offset_discriminator == 0) {
// This is an actual label, skip its contents
stream.skip(value);
} else {
// high order two bits of the first octet of a label must be either 11 or 00
throw malformed_packet();
}
}
}
@@ -336,9 +340,13 @@ uint32_t DNS::compose_name(const uint8_t* ptr, char* out_ptr) const {
const uint8_t* end = &records_data_[0] + records_data_.size();
const uint8_t* end_ptr = 0;
char* current_out_ptr = out_ptr;
uint8_t pointer_counter = 0;
while (*ptr) {
if (pointer_counter++ > 30){
throw dns_decompression_pointer_loops();
}
// It's an offset
if ((*ptr & 0xc0)) {
if (((*ptr & 0xc0) == 0xc0)) {
if (TINS_UNLIKELY(ptr + sizeof(uint16_t) > end)) {
throw malformed_packet();
}
@@ -347,7 +355,7 @@ uint32_t DNS::compose_name(const uint8_t* ptr, char* out_ptr) const {
index = Endian::be_to_host(index) & 0x3fff;
// Check that the offset is neither too low or too high
if (index < 0x0c || (&records_data_[0] + (index - 0x0c)) >= end) {
throw malformed_packet();
throw dns_decompression_pointer_out_of_bounds();
}
// We've probably found the end of the original domain name. Save it.
if (end_ptr == 0) {
@@ -410,10 +418,11 @@ void DNS::inline_convert_v4(uint32_t value, char* output) {
// Parses records in some section.
void DNS::convert_records(const uint8_t* ptr,
const uint8_t* end,
resources_type& res) const {
resources_type& res,
const uint16_t rr_count) const {
InputMemoryStream stream(ptr, end - ptr);
char dname[256], small_addr_buf[256];
while (stream) {
while (stream && (res.size() < rr_count)) {
string data;
bool used_small_buffer = false;
// Retrieve the record's domain name.
@@ -573,7 +582,8 @@ DNS::resources_type DNS::answers() const {
convert_records(
&records_data_[0] + answers_idx_,
&records_data_[0] + authority_idx_,
res
res,
answers_count()
);
}
return res;
@@ -585,7 +595,8 @@ DNS::resources_type DNS::authority() const {
convert_records(
&records_data_[0] + authority_idx_,
&records_data_[0] + additional_idx_,
res
res,
authority_count()
);
}
return res;
@@ -597,7 +608,8 @@ DNS::resources_type DNS::additional() const {
convert_records(
&records_data_[0] + additional_idx_,
&records_data_[0] + records_data_.size(),
res
res,
additional_count()
);
}
return res;

View File

@@ -107,15 +107,10 @@ uint32_t Dot1Q::trailer_size() const {
void Dot1Q::write_serialization(uint8_t* buffer, uint32_t total_sz) {
OutputMemoryStream stream(buffer, total_sz);
if (inner_pdu()) {
Constants::Ethernet::e flag;
Constants::Ethernet::e flag = Constants::Ethernet::UNKNOWN;
PDUType type = inner_pdu()->pdu_type();
if (type == PDU::DOT1Q) {
flag = Constants::Ethernet::QINQ;
}
else {
// Set the appropriate payload type flag
flag = Internals::pdu_flag_to_ether_type(type);
}
// Set the appropriate payload type flag
flag = Internals::pdu_flag_to_ether_type(type);
if (flag != Constants::Ethernet::UNKNOWN) {
payload_type(static_cast<uint16_t>(flag));
}

View File

@@ -156,7 +156,7 @@ bool EthernetII::matches_response(const uint8_t* ptr, uint32_t total_sz) const {
void EthernetII::write_serialization(uint8_t* buffer, uint32_t total_sz) {
OutputMemoryStream stream(buffer, total_sz);
if (inner_pdu()) {
Constants::Ethernet::e flag;
Constants::Ethernet::e flag = Constants::Ethernet::UNKNOWN;
const PDUType type = inner_pdu()->pdu_type();
// Dirty trick to successfully tag PPPoE session/discovery packets
if (type == PDU::PPPOE) {
@@ -164,6 +164,17 @@ void EthernetII::write_serialization(uint8_t* buffer, uint32_t total_sz) {
flag = (pppoe->code() == 0) ? Constants::Ethernet::PPPOES
: Constants::Ethernet::PPPOED;
}
// Dirty trick: Double Dot1Q is interpreted as Dot1AD
else if (type == PDU::DOT1Q) {
flag = Internals::pdu_flag_to_ether_type(type);
if (inner_pdu()->inner_pdu()) {
const PDUType inner_type = inner_pdu()->inner_pdu()->pdu_type();
if (inner_type == PDU::DOT1Q) {
flag = Constants::Ethernet::QINQ;
}
}
}
else {
flag = Internals::pdu_flag_to_ether_type(type);
}

View File

@@ -34,32 +34,35 @@
#include <tins/exceptions.h>
using std::string;
using std::ostream;
using std::hex;
using std::ostringstream;
using std::lexicographical_compare;
using std::equal;
namespace Tins {
namespace Internals {
void storage_to_string(ostream& output, uint8_t value) {
output << hex;
if (value < 0x10) {
output << '0';
}
output << (unsigned)value;
}
string hw_address_to_string(const uint8_t* ptr, size_t count) {
ostringstream output;
string output;
output.reserve(count*3);
for (size_t i = 0; i < count; ++i) {
if (i != 0) {
output << ":";
output += ":";
}
storage_to_string(output, ptr[i]);
char j = ptr[i];
char upper = (j >> 4) & 0x0F;
if (upper > 9)
upper += 'a'-10;
else
upper += '0';
char lower = j & 0x0F;
if (lower > 9)
lower += 'a'-10;
else
lower += '0';
output += upper;
output += lower;
}
return output.str();
return output;
}
void string_to_hw_address(const string& hw_addr, uint8_t* output, size_t output_size) {
@@ -113,5 +116,10 @@ bool hw_address_lt_compare(const uint8_t* start1, const uint8_t* end1,
return lexicographical_compare(start1, end1, start2, end2);
}
bool hw_address_gt_compare(const uint8_t* start1, const uint8_t* end1,
const uint8_t* start2, const uint8_t* end2) {
return lexicographical_compare(start2, end2, start1, end1);
}
} // Internals
} // Tins

View File

@@ -98,7 +98,7 @@ void ICMP::sequence(uint16_t new_seq) {
}
void ICMP::gateway(address_type new_gw) {
header_.un.gateway = Endian::host_to_be(static_cast<uint32_t>(new_gw));
header_.un.gateway = static_cast<uint32_t>(new_gw);
}
void ICMP::mtu(uint16_t new_mtu) {
@@ -122,7 +122,7 @@ void ICMP::transmit_timestamp(uint32_t new_timestamp) {
}
void ICMP::address_mask(address_type new_mask) {
orig_timestamp_or_address_mask_ = Endian::host_to_be(static_cast<uint32_t>(new_mask));
orig_timestamp_or_address_mask_ = static_cast<uint32_t>(new_mask);
}
uint32_t ICMP::header_size() const {

View File

@@ -321,7 +321,12 @@ void IP::add_option(const option& opt) {
uint32_t IP::calculate_options_size() const {
uint32_t options_size = 0;
for (options_type::const_iterator iter = options_.begin(); iter != options_.end(); ++iter) {
options_size += 1 + iter->data_size();
options_size += sizeof(uint8_t);
const option_identifier option_id = iter->option();
// Only add length field and data size for non [NOOP, EOL] options
if (option_id.op_class != CONTROL || option_id.number > NOOP) {
options_size += sizeof(uint8_t) + iter->data_size();
}
}
return options_size;
}

View File

@@ -62,7 +62,7 @@ const AddressRange<IPv4Address> loopback_range = IPv4Address("127.0.0.0") / 8;
const AddressRange<IPv4Address> multicast_range = IPv4Address("224.0.0.0") / 4;
IPv4Address IPv4Address::from_prefix_length(uint32_t prefix_length) {
return IPv4Address(Endian::host_to_be(0xffffffff << (32 - prefix_length)));
return IPv4Address(prefix_length ? Endian::host_to_be(0xffffffff << (32 - prefix_length)) : 0u);
}
IPv4Address::IPv4Address(uint32_t ip)
@@ -153,4 +153,12 @@ IPv4Address IPv4Address::operator&(const IPv4Address& mask) const {
return IPv4Address(Endian::be_to_host(ip_addr_ & mask.ip_addr_));
}
IPv4Address IPv4Address::operator|(const IPv4Address& mask) const {
return IPv4Address(Endian::be_to_host(ip_addr_ | mask.ip_addr_));
}
IPv4Address IPv4Address::operator~() const {
return IPv4Address(Endian::be_to_host(~ip_addr_));
}
} // Tins

View File

@@ -32,6 +32,9 @@
#include <netinet/in.h>
#include <sys/socket.h>
#else
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <ws2tcpip.h>
#endif
#include <tins/ipv6.h>
@@ -43,6 +46,7 @@
#include <tins/memory_helpers.h>
#include <tins/detail/pdu_helpers.h>
using std::make_pair;
using std::vector;
using Tins::Memory::InputMemoryStream;
@@ -69,6 +73,49 @@ PDU::metadata IPv6::extract_metadata(const uint8_t *buffer, uint32_t total_sz) {
return metadata(header_size, pdu_flag, PDU::UNKNOWN);
}
IPv6::hop_by_hop_header IPv6::hop_by_hop_header::from_extension_header(const ext_header& hdr) {
if (TINS_UNLIKELY(hdr.option() != HOP_BY_HOP)) {
throw invalid_ipv6_extension_header();
}
hop_by_hop_header header;
header.options = parse_header_options(hdr.data_ptr(), hdr.data_size());
return header;
}
IPv6::destination_routing_header IPv6::destination_routing_header::from_extension_header(const ext_header& hdr) {
if (TINS_UNLIKELY(hdr.option() != DESTINATION_ROUTING_OPTIONS)) {
throw invalid_ipv6_extension_header();
}
destination_routing_header header;
header.options = parse_header_options(hdr.data_ptr(), hdr.data_size());
return header;
}
IPv6::routing_header IPv6::routing_header::from_extension_header(const ext_header& hdr) {
if (TINS_UNLIKELY(hdr.option() != ROUTING)) {
throw invalid_ipv6_extension_header();
}
Memory::InputMemoryStream stream(hdr.data_ptr(), hdr.data_size());
routing_header header;
header.routing_type = stream.read<uint8_t>();
header.segments_left = stream.read<uint8_t>();
header.data.assign(stream.pointer(), stream.pointer() + stream.size());
return header;
}
IPv6::fragment_header IPv6::fragment_header::from_extension_header(const ext_header& hdr) {
if (TINS_UNLIKELY(hdr.option() != FRAGMENT)) {
throw invalid_ipv6_extension_header();
}
Memory::InputMemoryStream stream(hdr.data_ptr(), hdr.data_size());
fragment_header header;
uint16_t field = stream.read_be<uint16_t>();
header.fragment_offset = field >> 3;
header.more_fragments = field & 1;
header.identification = stream.read_be<uint32_t>();
return header;
}
IPv6::IPv6(address_type ip_dst, address_type ip_src, PDU* /*child*/)
: header_(), next_header_() {
version(6);
@@ -83,7 +130,7 @@ IPv6::IPv6(const uint8_t* buffer, uint32_t total_sz) {
uint32_t actual_payload_length = payload_length();
bool is_payload_fragmented = false;
while (stream) {
if (is_extension_header(current_header)) {
if (is_extension_header(current_header) && current_header != NO_NEXT_HEADER) {
if (current_header == FRAGMENT) {
is_payload_fragmented = true;
}
@@ -160,8 +207,40 @@ IPv6::IPv6(const uint8_t* buffer, uint32_t total_sz) {
bool IPv6::is_extension_header(uint8_t header_id) {
return header_id == HOP_BY_HOP || header_id == DESTINATION_ROUTING_OPTIONS
|| header_id == ROUTING || header_id == FRAGMENT || header_id == AUTHENTICATION
|| header_id == SECURITY_ENCAPSULATION || header_id == DESTINATION_OPTIONS
|| header_id == MOBILITY || header_id == NO_NEXT_HEADER;
|| header_id == DESTINATION_OPTIONS || header_id == MOBILITY
|| header_id == NO_NEXT_HEADER;
}
uint32_t IPv6::get_padding_size(const ext_header& header) {
const uint32_t padding = (header.data_size() + sizeof(uint8_t) * 2) % 8;
return padding == 0 ? 0 : (8 - padding);
}
vector<IPv6::header_option_type> IPv6::parse_header_options(const uint8_t* data, size_t size) {
Memory::InputMemoryStream stream(data, size);
vector<header_option_type> options;
while (stream.size() > 0) {
try {
uint8_t option = stream.read<uint8_t>();
if (option == PAD_1) {
continue;
}
uint8_t size = stream.read<uint8_t>();
if (size > stream.size()) {
throw invalid_ipv6_extension_header();
}
if (option != PAD_N) {
options.push_back(make_pair(option, vector<uint8_t>(stream.pointer(),
stream.pointer() +
size)));
}
stream.skip(size);
} catch (const malformed_packet&) {
throw invalid_ipv6_extension_header();
}
}
return options;
}
void IPv6::version(small_uint<4> new_version) {
@@ -290,18 +369,27 @@ void IPv6::write_serialization(uint8_t* buffer, uint32_t total_sz) {
}
#ifndef BSD
void IPv6::send(PacketSender& sender, const NetworkInterface &) {
struct sockaddr_in6 link_addr;
PacketSender::SocketType type = PacketSender::IPV6_SOCKET;
void IPv6::send(PacketSender& sender, const NetworkInterface& interface) {
sockaddr_in6 link_addr;
const PacketSender::SocketType type = PacketSender::IPV6_SOCKET;
link_addr.sin6_family = AF_INET6;
link_addr.sin6_port = 0;
memcpy((uint8_t*)&link_addr.sin6_addr, header_.dst_addr, address_type::address_size);
if (inner_pdu() && inner_pdu()->pdu_type() == PDU::ICMP) {
type = PacketSender::ICMP_SOCKET;
// Required to set sin6_scope_id to interface index as stated in RFC2553.
// https://datatracker.ietf.org/doc/html/rfc2553#section-3.3
if (IPv6Address(header_.dst_addr).is_local_unicast()) {
link_addr.sin6_scope_id = interface.id();
}
memcpy((uint8_t*)&link_addr.sin6_addr, header_.dst_addr, address_type::address_size);
sender.send_l3(*this, (struct sockaddr*)&link_addr, sizeof(link_addr), type);
}
PDU* IPv6::recv_response(PacketSender& sender, const NetworkInterface &) {
PacketSender::SocketType type = PacketSender::IPV6_SOCKET;
if (inner_pdu() && inner_pdu()->pdu_type() == PDU::ICMPv6) {
type = PacketSender::ICMPV6_SOCKET;
}
return sender.recv_l3(*this, 0, sizeof(sockaddr_in6), type);
}
#endif
void IPv6::add_ext_header(const ext_header& header) {
@@ -337,6 +425,8 @@ uint32_t IPv6::calculate_headers_size() const {
uint32_t output = 0;
for (const_iterator iter = ext_headers_.begin(); iter != ext_headers_.end(); ++iter) {
output += static_cast<uint32_t>(iter->data_size() + sizeof(uint8_t) * 2);
output += get_padding_size(*iter);
}
return output;
}
@@ -346,6 +436,8 @@ void IPv6::write_header(const ext_header& header, OutputMemoryStream& stream) {
stream.write(header.option());
stream.write(length);
stream.write(header.data_ptr(), header.data_size());
// Append padding
stream.fill(get_padding_size(header), 0);
}
} // Tins

View File

@@ -57,6 +57,7 @@ namespace Tins {
const IPv6Address loopback_address = "::1";
const AddressRange<IPv6Address> multicast_range = IPv6Address("ff00::") / 8;
const AddressRange<IPv6Address> local_unicast_range = IPv6Address("fe80::") / 10;
IPv6Address IPv6Address::from_prefix_length(uint32_t prefix_length) {
IPv6Address address;
@@ -138,17 +139,41 @@ bool IPv6Address::is_multicast() const {
return multicast_range.contains(*this);
}
bool IPv6Address::is_local_unicast() const {
return local_unicast_range.contains(*this);
}
ostream& operator<<(ostream& os, const IPv6Address& addr) {
return os << addr.to_string();
}
IPv6Address operator&(const IPv6Address& lhs, const IPv6Address& rhs) {
IPv6Address output = lhs;
IPv6Address::iterator addr_iter = output.begin();
IPv6Address IPv6Address::operator&(const IPv6Address& rhs) const {
IPv6Address result = *this;
IPv6Address::iterator addr_iter = result.begin();
for (IPv6Address::const_iterator it = rhs.begin(); it != rhs.end(); ++it, ++addr_iter) {
*addr_iter = *addr_iter & *it;
}
return output;
return result;
}
IPv6Address IPv6Address::operator|(const IPv6Address& rhs) const {
IPv6Address result = *this;
IPv6Address::iterator addr_iter = result.begin();
for (IPv6Address::const_iterator it = rhs.begin(); it != rhs.end(); ++it, ++addr_iter) {
*addr_iter = *addr_iter | *it;
}
return result;
}
IPv6Address IPv6Address::operator~() const {
IPv6Address result = *this;
for (IPv6Address::iterator addr_iter = result.begin(); addr_iter != result.end(); ++addr_iter) {
*addr_iter = ~*addr_iter;
}
return result;
}
} // Tins

View File

@@ -257,6 +257,35 @@ NetworkInterface::NetworkInterface(IPv4Address ip)
}
}
NetworkInterface::NetworkInterface(IPv6Address ipv6)
: iface_id_(0) {
typedef vector<Utils::Route6Entry> entries_type;
if (ipv6 == "::1") {
#if defined(BSD) || defined(__FreeBSD_kernel__)
iface_id_ = resolve_index("lo0");
#else
iface_id_ = resolve_index("lo");
#endif
}
else {
const Utils::Route6Entry* best_match = 0;
entries_type entries;
Utils::route6_entries(std::back_inserter(entries));
for (entries_type::const_iterator it(entries.begin()); it != entries.end(); ++it) {
if ((ipv6 & it->mask) == it->destination) {
if (!best_match || it->mask > best_match->mask || it->metric < best_match->metric) {
best_match = &*it;
}
}
}
if (!best_match) {
throw invalid_interface();
}
iface_id_ = resolve_index(best_match->interface.c_str());
}
}
string NetworkInterface::name() const {
#ifndef _WIN32
char iface_name[IF_NAMESIZE];
@@ -302,7 +331,7 @@ NetworkInterface::Info NetworkInterface::info() const {
}
#else // _WIN32
#ifndef ANDROID
struct ifaddrs* ifaddrs = 0;
struct ifaddrs* if_it = 0;
getifaddrs(&ifaddrs);
@@ -312,7 +341,9 @@ NetworkInterface::Info NetworkInterface::info() const {
if (ifaddrs) {
freeifaddrs(ifaddrs);
}
#else
throw new std::runtime_error("android ifaddr not supported");
#endif
#endif // _WIN32
// If we didn't even get the hw address or ip address, this went wrong

View File

@@ -37,11 +37,14 @@ using std::string;
namespace Tins {
OfflinePacketFilter::OfflinePacketFilter(const OfflinePacketFilter& other) {
*this = other;
string_filter_ = other.string_filter_;
init(string_filter_, pcap_datalink(other.handle_), pcap_snapshot(other.handle_));
}
OfflinePacketFilter& OfflinePacketFilter::operator=(const OfflinePacketFilter& other) {
string_filter_ = other.string_filter_;
pcap_freecode(&filter_);
pcap_close(handle_);
init(string_filter_, pcap_datalink(other.handle_), pcap_snapshot(other.handle_));
return* this;
}
@@ -58,8 +61,14 @@ void OfflinePacketFilter::init(const string& pcap_filter,
link_type,
snap_len
);
if (!handle_) {
throw pcap_open_failed();
}
if (pcap_compile(handle_, &filter_, pcap_filter.c_str(), 1, 0xffffffff) == -1) {
throw invalid_pcap_filter(pcap_geterr(handle_));
string error(pcap_geterr(handle_));
pcap_freecode(&filter_);
pcap_close(handle_);
throw invalid_pcap_filter(error.c_str());
}
}

View File

@@ -108,6 +108,7 @@ PacketSender::PacketSender(const NetworkInterface& iface,
types_[IP_RAW_SOCKET] = IPPROTO_RAW;
types_[IPV6_SOCKET] = IPPROTO_RAW;
types_[ICMP_SOCKET] = IPPROTO_ICMP;
types_[ICMPV6_SOCKET] = IPPROTO_ICMPV6;
}
PacketSender::~PacketSender() {
@@ -251,8 +252,9 @@ void PacketSender::open_l3_socket(SocketType type) {
throw invalid_socket_type();
}
if (sockets_[type] == INVALID_RAW_SOCKET) {
const bool is_v6 = (type == IPV6_SOCKET || type == ICMPV6_SOCKET);
socket_type sockfd;
sockfd = socket((type == IPV6_SOCKET) ? AF_INET6 : AF_INET, SOCK_RAW, socktype);
sockfd = socket(is_v6 ? AF_INET6 : AF_INET, SOCK_RAW, socktype);
if (sockfd < 0) {
throw socket_open_error(make_error_string());
}
@@ -263,8 +265,13 @@ void PacketSender::open_l3_socket(SocketType type) {
#else
typedef const char* option_ptr;
#endif
const int level = (type == IPV6_SOCKET) ? IPPROTO_IPV6 : IPPROTO_IP;
const int level = (is_v6) ? IPPROTO_IPV6 : IPPROTO_IP;
if (setsockopt(sockfd, level, IP_HDRINCL, (option_ptr)&on, sizeof(on)) != 0) {
#ifndef _WIN32
::close(sockfd);
#else
::closesocket(sockfd);
#endif
throw socket_open_error(make_error_string());
}

View File

@@ -70,12 +70,12 @@ void PacketWriter::write(Packet& packet) {
}
void PacketWriter::write(PDU& pdu, const struct timeval& tv) {
PDU::serialization_type buffer = pdu.serialize();
struct pcap_pkthdr header;
memset(&header, 0, sizeof(header));
header.ts = tv;
header.len = static_cast<bpf_u_int32>(pdu.advertised_size());
PDU::serialization_type buffer = pdu.serialize();
header.caplen = static_cast<bpf_u_int32>(buffer.size());
header.len = static_cast<bpf_u_int32>(buffer.size());
pcap_dump((u_char*)dumper_, &header, &buffer[0]);
}
@@ -86,8 +86,9 @@ void PacketWriter::init(const string& file_name, int link_type) {
}
dumper_ = pcap_dump_open(handle_, file_name.c_str());
if (!dumper_) {
string error(pcap_geterr(handle_));
pcap_close(handle_);
throw pcap_error(pcap_geterr(handle_));
throw pcap_error(error);
}
}

View File

@@ -85,6 +85,14 @@ uint32_t PDU::size() const {
return sz;
}
uint32_t PDU::advertised_size() const {
uint32_t result = header_size() + trailer_size();
if (inner_pdu_) {
result += inner_pdu()->advertised_size();
}
return result;
}
void PDU::send(PacketSender &, const NetworkInterface &) {
}

View File

@@ -224,7 +224,7 @@ void BaseSniffer::set_extract_raw_pdus(bool value) {
}
void BaseSniffer::set_pcap_sniffing_method(PcapSniffingMethod method) {
if (method == nullptr) {
if (method == 0) {
throw std::runtime_error("Sniffing method cannot be null");
}
pcap_sniffing_method_ = method;
@@ -391,6 +391,20 @@ void Sniffer::set_rfmon(bool rfmon_enabled) {
// **************************** FileSniffer ****************************
FileSniffer::FileSniffer(FILE *fp,
const SnifferConfiguration& configuration) {
char error[PCAP_ERRBUF_SIZE];
pcap_t* phandle = pcap_fopen_offline(fp, error);
if (!phandle) {
throw pcap_error(error);
}
set_pcap_handle(phandle);
// Configure the sniffer
configuration.configure_sniffer_pre_activation(*this);
}
FileSniffer::FileSniffer(const string& file_name,
const SnifferConfiguration& configuration) {
char error[PCAP_ERRBUF_SIZE];
@@ -420,6 +434,22 @@ FileSniffer::FileSniffer(const string& file_name, const string& filter) {
config.configure_sniffer_pre_activation(*this);
}
FileSniffer::FileSniffer(FILE *fp, const string& filter) {
SnifferConfiguration config;
config.set_filter(filter);
char error[PCAP_ERRBUF_SIZE];
pcap_t* phandle = pcap_fopen_offline(fp, error);
if (!phandle) {
throw pcap_error(error);
}
set_pcap_handle(phandle);
// Configure the sniffer
config.configure_sniffer_pre_activation(*this);
}
// ************************ SnifferConfiguration ************************
const unsigned SnifferConfiguration::DEFAULT_SNAP_LEN = 65535;

View File

@@ -81,7 +81,11 @@ TCP::TCP(const uint8_t* buffer, uint32_t total_sz) {
while (stream.pointer() < header_end) {
const OptionTypes option_type = (OptionTypes)stream.read<uint8_t>();
if (option_type <= NOP) {
if (option_type == EOL) {
stream.skip(header_end - stream.pointer());
break;
}
else if (option_type == NOP) {
#if TINS_IS_CXX11
add_option(option_type, 0);
#else
@@ -253,6 +257,10 @@ small_uint<12> TCP::flags() const {
return (header_.res1 << 8) | header_.flags_8;
}
bool TCP::has_flags(small_uint<12> check_flags) const {
return (flags() & check_flags) == check_flags;
}
void TCP::set_flag(Flags tcp_flag, small_uint<1> value) {
switch (tcp_flag) {
case FIN:
@@ -309,7 +317,7 @@ void TCP::write_serialization(uint8_t* buffer, uint32_t total_sz) {
if (options_size < total_options_size) {
const uint16_t padding = total_options_size - options_size;
stream.fill(padding, 1);
stream.fill(padding, 0);
}
uint32_t check = 0;

View File

@@ -33,8 +33,6 @@
#include <tins/detail/sequence_number_helpers.h>
using std::move;
using Tins::Internals::seq_compare;
namespace Tins {
@@ -67,7 +65,7 @@ bool DataTracker::process_payload(uint32_t seq, payload_type payload) {
}
bool added_some = false;
// Store this payload
store_payload(seq, move(payload));
store_payload(seq, std::move(payload));
// Keep looping while the fragments seq is lower or equal to our seq
buffered_payload_type::iterator iter = buffered_payload_.find(seq_number_);
while (iter != buffered_payload_.end() && seq_compare(iter->first, seq_number_) <= 0) {
@@ -85,7 +83,7 @@ bool DataTracker::process_payload(uint32_t seq, payload_type payload) {
payload.begin(),
payload.begin() + (seq_number_ - iter->first)
);
store_payload(seq_number_, move(iter->second));
store_payload(seq_number_, std::move(iter->second));
iter = erase_iterator(iter);
}
else {
@@ -158,14 +156,14 @@ void DataTracker::store_payload(uint32_t seq, payload_type payload) {
// New segment, store it
if (iter == buffered_payload_.end()) {
total_buffered_bytes_ += payload.size();
buffered_payload_.insert(make_pair(seq, move(payload)));
buffered_payload_.insert(make_pair(seq, std::move(payload)));
}
else if (iter->second.size() < payload.size()) {
// Increment by the diff between sizes
total_buffered_bytes_ += (payload.size() - iter->second.size());
// If we already have payload on this position but it's a shorter
// chunk than the new one, replace it
iter->second = move(payload);
iter->second = std::move(payload);
}
}

View File

@@ -115,7 +115,7 @@ void Flow::process_packet(PDU& pdu) {
}
// can process either way, since it will abort immediately if not needed
if (data_tracker_.process_payload(tcp->seq(), move(raw->payload()))) {
if (data_tracker_.process_payload(tcp->seq(), std::move(raw->payload()))) {
if (on_data_callback_) {
on_data_callback_(*this);
}
@@ -127,19 +127,19 @@ void Flow::advance_sequence(uint32_t seq) {
}
void Flow::update_state(const TCP& tcp) {
if ((tcp.flags() & TCP::FIN) != 0) {
if (tcp.has_flags(TCP::FIN)) {
state_ = FIN_SENT;
}
else if ((tcp.flags() & TCP::RST) != 0) {
else if (tcp.has_flags(TCP::RST)) {
state_ = RST_SENT;
}
else if (state_ == SYN_SENT && (tcp.flags() & TCP::ACK) != 0) {
else if (state_ == SYN_SENT && tcp.has_flags(TCP::ACK)) {
#ifdef TINS_HAVE_ACK_TRACKER
ack_tracker_ = AckTracker(tcp.ack_seq());
#endif // TINS_HAVE_ACK_TRACKER
state_ = ESTABLISHED;
}
else if (state_ == UNKNOWN && (tcp.flags() & TCP::SYN) != 0) {
else if (state_ == UNKNOWN && tcp.has_flags(TCP::SYN)) {
// This is the server's state, sending it's first SYN|ACK
#ifdef TINS_HAVE_ACK_TRACKER
ack_tracker_ = AckTracker(tcp.ack_seq());

View File

@@ -61,7 +61,7 @@ Stream::Stream(PDU& packet, const timestamp_type& ts)
}
const TCP& tcp = packet.rfind_pdu<TCP>();
// If this is not the first packet of a stream (SYN), then it's a partial stream
is_partial_stream_ = tcp.flags() != TCP::SYN;
is_partial_stream_ = !tcp.has_flags(TCP::SYN);
}
void Stream::process_packet(PDU& packet, const timestamp_type& ts) {

View File

@@ -84,7 +84,9 @@ void StreamFollower::process_packet(PDU& packet, const timestamp_type& ts) {
if (iter == streams_.end()) {
// Start tracking if they're either SYNs or they contain data (attach
// to an already running flow).
if (tcp->flags() == TCP::SYN || (attach_to_flows_ && tcp->find_pdu<RawPDU>() != 0)) {
// Start on client's SYN, not on server's SYN+ACK
const bool is_syn = tcp->has_flags(TCP::SYN) && !tcp->has_flags(TCP::ACK);
if (is_syn || (attach_to_flows_ && tcp->find_pdu<RawPDU>() != 0)) {
iter = streams_.insert(make_pair(identifier, Stream(packet, ts))).first;
iter->second.setup_flows_callbacks();
if (on_new_connection_) {
@@ -93,7 +95,7 @@ void StreamFollower::process_packet(PDU& packet, const timestamp_type& ts) {
else {
throw callback_not_set();
}
if (tcp->flags() != TCP::SYN) {
if (!is_syn) {
// assume the connection is established
iter->second.client_flow().state(Flow::ESTABLISHED);
iter->second.server_flow().state(Flow::ESTABLISHED);

View File

@@ -230,7 +230,7 @@ bool TCPStream::generic_process(uint32_t& my_seq,
bool TCPStream::update(IP* ip, TCP* tcp) {
if (!syn_ack_sent_) {
if (tcp->flags() == (TCP::SYN | TCP::ACK)) {
if (tcp->has_flags(TCP::SYN | TCP::ACK)) {
server_seq_ = tcp->seq() + 1;
client_seq_ = tcp->ack_seq();
syn_ack_sent_ = true;

View File

@@ -81,6 +81,7 @@ string to_string(PDU::PDUType pduType) {
ENUM_TEXT(ICMPv6);
ENUM_TEXT(SLL);
ENUM_TEXT(DHCPv6);
ENUM_TEXT(DOT1AD);
ENUM_TEXT(DOT1Q);
ENUM_TEXT(PPPOE);
ENUM_TEXT(STP);

View File

@@ -65,7 +65,7 @@ const RadioTapParser::FieldMetadata RadioTapParser::RADIOTAP_METADATA[] = {
};
const uint32_t RadioTapParser::MAX_RADIOTAP_FIELD = sizeof(RADIOTAP_METADATA) /
sizeof(FieldMetadata) + 1;
sizeof(FieldMetadata);
#if TINS_IS_LITTLE_ENDIAN
TINS_BEGIN_PACK
@@ -131,13 +131,10 @@ struct RadioTapFlags {
} TINS_END_PACK;
#endif
void align_buffer(const uint8_t* buffer_start, const uint8_t*& buffer, uint32_t size, size_t n) {
void align_buffer(const uint8_t* buffer_start, const uint8_t*& buffer, size_t n) {
uint32_t offset = (buffer - buffer_start) & (n - 1);
if (offset) {
offset = n - offset;
if (TINS_UNLIKELY(offset > size)) {
throw malformed_packet();
}
buffer += offset;
}
}
@@ -233,7 +230,7 @@ bool RadioTapParser::skip_to_field(RadioTap::PresentFlags flag) {
}
bool RadioTapParser::has_fields() const {
return current_bit_ != MAX_RADIOTAP_FIELD;
return current_bit_ != MAX_RADIOTAP_FIELD && current_ptr_ < end_;
}
bool RadioTapParser::has_field(RadioTap::PresentFlags flag) const {
@@ -281,7 +278,7 @@ bool RadioTapParser::advance_to_next_field() {
if (current_bit_ < MAX_RADIOTAP_FIELD) {
const uint8_t* radiotap_start = start_ - sizeof(uint32_t);
// Skip and align the buffer
align_buffer(radiotap_start, current_ptr_, end_ - radiotap_start,
align_buffer(radiotap_start, current_ptr_,
RADIOTAP_METADATA[current_bit_].alignment);
return true;
}

View File

@@ -41,11 +41,12 @@ namespace Tins {
namespace Utils {
uint32_t calculate_padding(uint32_t alignment, uint32_t offset) {
return offset % alignment;
uint32_t extra = offset % alignment;
return extra == 0 ? 0 : alignment - extra;
}
uint32_t get_bit(uint32_t value) {
return log(value) / log(2);
return round(log2(value));
}
RadioTapWriter::RadioTapWriter(vector<uint8_t>& buffer)
@@ -54,7 +55,7 @@ RadioTapWriter::RadioTapWriter(vector<uint8_t>& buffer)
void RadioTapWriter::write_option(const RadioTap::option& option) {
const uint32_t bit = get_bit(option.option());
if (bit > RadioTapParser::MAX_RADIOTAP_FIELD) {
if (bit >= RadioTapParser::MAX_RADIOTAP_FIELD) {
throw malformed_option();
}
const bool is_empty = buffer_.empty();

View File

@@ -154,6 +154,7 @@ vector<char> query_route_table(int family) {
throw exception_base("sysctl failed");
}
buf.resize(len);
return buf;
}
@@ -412,17 +413,21 @@ set<string> network_interfaces() {
}
#else
set<string> network_interfaces() {
set<string> output;
struct ifaddrs* ifaddrs = 0;
struct ifaddrs* if_it = 0;
getifaddrs(&ifaddrs);
for (if_it = ifaddrs; if_it; if_it = if_it->ifa_next) {
output.insert(if_it->ifa_name);
}
if (ifaddrs) {
freeifaddrs(ifaddrs);
}
#ifndef ANDROID
set<string> output;
struct ifaddrs* ifaddrs = 0;
struct ifaddrs* if_it = 0;
getifaddrs(&ifaddrs);
for (if_it = ifaddrs; if_it; if_it = if_it->ifa_next) {
output.insert(if_it->ifa_name);
}
if (ifaddrs) {
freeifaddrs(ifaddrs);
}
return output;
#else
throw std::runtime_error("android ifaddr not supported");
#endif
}
#endif // _WIN32
@@ -439,5 +444,17 @@ bool gateway_from_ip(IPv4Address ip, IPv4Address& gw_addr) {
return false;
}
bool gateway_from_ip(IPv6Address ip, IPv6Address& gw_addr) {
typedef vector<Route6Entry> entries_type;
entries_type entries =route6_entries();
for (entries_type::const_iterator it(entries.begin()); it != entries.end(); ++it) {
if ((ip & it->mask) == it->destination) {
gw_addr = it->gateway;
return true;
}
}
return false;
}
} // Utils
} // Tins

36
src/vxlan.cpp Normal file
View File

@@ -0,0 +1,36 @@
#include <tins/internals.h>
#include <tins/memory_helpers.h>
#include <tins/small_uint.h>
#include <tins/vxlan.h>
using Tins::Memory::InputMemoryStream;
using Tins::Memory::OutputMemoryStream;
namespace Tins {
VXLAN::VXLAN(const small_uint<24> vni) {
set_flags(8);
set_vni(vni);
}
VXLAN::VXLAN(const uint8_t* buffer, uint32_t total_sz) {
InputMemoryStream stream(buffer, total_sz);
stream.read(header_);
// If there is any size left
if (stream) {
inner_pdu(
Internals::pdu_from_flag(
PDU::ETHERNET_II,
stream.pointer(),
stream.size()
)
);
}
}
void VXLAN::write_serialization(uint8_t* buffer, uint32_t total_sz) {
OutputMemoryStream stream(buffer, total_sz);
stream.write(header_);
}
} // Tins

View File

@@ -62,7 +62,7 @@ private:
template <typename T>
void ActiveTestRunner::add_test() {
tests_.emplace_back(new T(packet_sender_, configuration_));
tests_.emplace_back(std::unique_ptr<T>(new T(packet_sender_, configuration_)));
}
#endif // TINS_ACTIVE_TEST_RUNNER_H

View File

@@ -70,6 +70,7 @@ CREATE_TEST(tcp)
CREATE_TEST(tcp_ip)
CREATE_TEST(udp)
CREATE_TEST(utils)
CREATE_TEST(vxlan)
IF(LIBTINS_ENABLE_PCAP)
CREATE_TEST(offline_packet_filter)

View File

@@ -12,11 +12,19 @@ using namespace Tins;
class AddressRangeTest : public testing::Test {
public:
void contain_tests0(const IPv4Range& range);
void contain_tests0(const IPv6Range& range);
void contain_tests24(const IPv4Range& range);
void contain_tests24(const IPv6Range& range);
void contain_tests26(const IPv4Range& range);
};
void AddressRangeTest::contain_tests0(const IPv4Range& range) {
EXPECT_TRUE(range.contains("0.0.0.0"));
EXPECT_TRUE(range.contains("192.168.1.1"));
EXPECT_TRUE(range.contains("255.255.255.255"));
}
void AddressRangeTest::contain_tests24(const IPv4Range& range) {
EXPECT_TRUE(range.contains("192.168.0.0"));
EXPECT_TRUE(range.contains("192.168.0.1"));
@@ -33,6 +41,12 @@ void AddressRangeTest::contain_tests26(const IPv4Range& range) {
EXPECT_FALSE(range.contains("192.168.254.191"));
}
void AddressRangeTest::contain_tests0(const IPv6Range& range) {
EXPECT_TRUE(range.contains("::"));
EXPECT_TRUE(range.contains("dead::1:1"));
EXPECT_TRUE(range.contains("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
}
void AddressRangeTest::contain_tests24(const IPv6Range& range) {
EXPECT_TRUE(range.contains("dead::1"));
EXPECT_TRUE(range.contains("dead::1fee"));
@@ -42,13 +56,22 @@ void AddressRangeTest::contain_tests24(const IPv6Range& range) {
}
TEST_F(AddressRangeTest, Contains) {
contain_tests0(IPv4Range("0.0.0.0", "255.255.255.255"));
contain_tests0(IPv4Range::from_mask("0.0.0.0", "0.0.0.0"));
contain_tests0(IPv4Range::from_mask("0.0.0.0", IPv4Address::from_prefix_length(0)));
contain_tests24(IPv4Range("192.168.0.0", "192.168.0.255"));
contain_tests24(IPv4Range::from_mask("192.168.0.0", "255.255.255.0"));
contain_tests24(IPv4Range::from_mask("192.168.0.0", IPv4Address::from_prefix_length(24)));
contain_tests26(IPv4Range("192.168.254.192", "192.168.254.255"));
contain_tests26(IPv4Range::from_mask("192.168.254.192", "255.255.255.192"));
contain_tests26(IPv4Range::from_mask("192.168.254.192", IPv4Address::from_prefix_length(26)));
contain_tests0(IPv6Range("::0", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
contain_tests0(IPv6Range::from_mask("::", "::"));
contain_tests0(IPv6Range::from_mask("::", IPv6Address::from_prefix_length(0)));
contain_tests24(IPv6Range("dead::0", "dead::ffff"));
contain_tests24(IPv6Range::from_mask("dead::0", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:0"));
contain_tests24(IPv6Range::from_mask("dead::0", IPv6Address::from_prefix_length(112)));
{
AddressRange<HWAddress<6> > range("00:00:00:00:00:00", "00:00:00:00:00:ff");

View File

@@ -58,7 +58,7 @@ const uint8_t DHCPTest::expected_packet[] = {
TEST_F(DHCPTest, DefaultConstructor) {
DHCP dhcp;
EXPECT_EQ(dhcp.htype(), 1);
EXPECT_EQ(dhcp.hlen(), (const size_t)EthernetII::address_type::address_size);
EXPECT_EQ(dhcp.hlen(), (size_t)EthernetII::address_type::address_size);
}
TEST_F(DHCPTest, CopyConstructor) {
@@ -280,7 +280,7 @@ TEST_F(DHCPTest, ConstructorFromBuffer) {
EXPECT_EQ(dhcp1.opcode(), DHCP::DISCOVER);
EXPECT_EQ(dhcp1.htype(), 1);
ASSERT_EQ(dhcp1.hlen(), (const size_t)EthernetII::address_type::address_size);
ASSERT_EQ(dhcp1.hlen(), (size_t)EthernetII::address_type::address_size);
EXPECT_EQ(dhcp1.hops(), 0x1f);
EXPECT_EQ(dhcp1.xid(), 0x3fab23deU);
EXPECT_EQ(dhcp1.secs(), 0x9f1a);

View File

@@ -551,3 +551,113 @@ TEST_F(DNSTest, SOARecordSerialize) {
EXPECT_EQ(0x8ad71928U, r2.expire());
EXPECT_EQ(0x1ad92871U, r2.minimum_ttl());
}
TEST_F(DNSTest, BadLabelSize) {
const uint8_t header[] = {
0x45, 0xbc, // ID
0x81, 0x80, // response, recursion desired, recursion available, no error
0x00, 0x01, // QDCOUNT
0x00, 0x00, // ANCOUNT
0x00, 0x00, // NSCOUNT
0x00, 0x00 // ARCOUNT
};
size_t payload_sz{sizeof(header)};
uint8_t payload[512];
// copy header
std::copy(header,
header + payload_sz,
payload);
// add bad length
const size_t bad_label_len{0x80};
const size_t label_offset = payload_sz;
payload[payload_sz++] = bad_label_len;
// fill label for incorrect length and terminate
std::fill(payload + payload_sz,
payload + payload_sz + bad_label_len,
'a');
payload_sz += bad_label_len;
payload[payload_sz++] = 0x0;
// add type and class
const uint8_t type_class[] = {
0x00, 0x01,
0x00, 0x01
};
std::copy(type_class,
type_class + sizeof(type_class),
payload + payload_sz);
payload_sz += sizeof(type_class);
// invalid high two bits of label first octest is detected early now
try {
const DNS packet(payload, payload_sz);
FAIL();
} catch (malformed_packet& mp) {
SUCCEED();
}
// check the other invalid value of high two bits in label size
payload[label_offset] = 0x10;
try {
const DNS packet(payload, payload_sz);
FAIL();
} catch (malformed_packet& mp) {
SUCCEED();
}
}
TEST_F(DNSTest, BadPacketLength) {
// valid response packet with RR's in all sections
const uint8_t payload[] = {
0x74,0xa9,0x85,0x80,0x00,0x01,0x00,0x02,0x00,0x01,0x00,0x04,0x08,0x5f,0x73,0x65,0x72,
0x76,0x69,0x63,0x65,0x04,0x5f,0x74,0x63,0x70,0x05,0x77,0x69,0x66,0x69,0x36,0x03,
0x6c,0x61,0x6e,0x00,0x00,0x21,0x00,0x01,0xc0,0x0c,0x00,0x21,0x00,0x01,0x00,0x01,
0x51,0x80,0x00,0x16,0x00,0x00,0x00,0x03,0x00,0x09,0x04,0x66,0x61,0x73,0x74,0x05,
0x77,0x69,0x66,0x69,0x36,0x03,0x6c,0x61,0x6e,0x00,0xc0,0x0c,0x00,0x21,0x00,0x01,
0x00,0x01,0x51,0x80,0x00,0x16,0x00,0x00,0x00,0x01,0x00,0x09,0x04,0x73,0x6c,0x6f,
0x77,0x05,0x77,0x69,0x66,0x69,0x36,0x03,0x6c,0x61,0x6e,0x00,0xc0,0x62,0x00,0x02,
0x00,0x01,0x00,0x01,0x51,0x80,0x00,0x05,0x02,0x70,0x69,0xc0,0x62,0xc0,0x5d,0x00,
0x01,0x00,0x01,0x00,0x01,0x51,0x80,0x00,0x04,0x0a,0x18,0x00,0x02,0xc0,0x3b,0x00,
0x01,0x00,0x01,0x00,0x01,0x51,0x80,0x00,0x04,0x0a,0x18,0x00,0x02,0xc0,0x79,0x00,
0x01,0x00,0x01,0x00,0x01,0x51,0x80,0x00,0x04,0x0a,0x18,0x00,0x02,0x00,0x00,0x29,
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x00,0x0a,0x00,0x18,0x86,0x1f,0x14,0x0f,
0x41,0xfa,0xf3,0x95,0x48,0x6e,0x79,0x61,0x61,0x78,0x32,0x0f,0x44,0x5d,0x21,0x47,
0x85,0x83,0x9a,0x95
};
// valid DNS message but misreport packet size;
// before fix, parser headed into uncharted waters on requesting additional section
// buffer with space for valid packet plus garbage bytes
const size_t bigsz{512};
uint8_t big_packet[bigsz];
// copy valid packet
std::copy(payload,
payload + sizeof(payload),
big_packet);
// fill additional bytes with junk
std::fill(big_packet + sizeof(payload),
big_packet + bigsz,
0x5A);
// initial packet parse ok
const DNS packet(big_packet, bigsz);
// RR's parse ok now
EXPECT_EQ(packet.questions_count(), 1);
EXPECT_EQ(packet.answers_count(), 2);
EXPECT_EQ(packet.authority_count(), 1);
EXPECT_EQ(packet.additional_count(), 4);
EXPECT_EQ(packet.queries().size(), 1U);
EXPECT_EQ(packet.answers().size(), 2U);
EXPECT_EQ(packet.authority().size(), 1U);
EXPECT_EQ(packet.additional().size(), 4U);
}

View File

@@ -58,6 +58,17 @@ TEST_F(Dot1QTest, Serialize) {
);
}
TEST_F(Dot1QTest, SerializeCraftedPacket)
{
EthernetII pkt = EthernetII() / Dot1Q(10) / IP("192.168.1.2") / TCP(23, 45) / RawPDU("asdasdasd");
PDU::serialization_type buffer = pkt.serialize();
EXPECT_EQ(buffer[12], 0x81);
EXPECT_EQ(buffer[13], 0x00);
EthernetII pkt2(&buffer[0], buffer.size());
const Dot1Q &q1 = pkt2.rfind_pdu<Dot1Q>();
EXPECT_EQ(10, q1.id());
}
TEST_F(Dot1QTest, PayloadType) {
Dot1Q dot1;
dot1.payload_type(0x9283);
@@ -86,6 +97,12 @@ TEST_F(Dot1QTest, QinQ) {
EthernetII pkt = EthernetII() / Dot1Q(10) / Dot1Q(42) / IP("192.168.1.2") /
TCP(23, 45) / RawPDU("asdasdasd");
PDU::serialization_type buffer = pkt.serialize();
// First PID of the serialized packet should be Dot1AD = 0x88a8
EXPECT_EQ(buffer[12], 0x88);
EXPECT_EQ(buffer[13], 0xa8);
// Second PID of the serialized packet chouls be Dot1Q = 0x8100
EXPECT_EQ(buffer[16], 0x81);
EXPECT_EQ(buffer[17], 0x00);
EthernetII pkt2(&buffer[0], buffer.size());
const Dot1Q& q1 = pkt2.rfind_pdu<Dot1Q>();
ASSERT_TRUE(q1.inner_pdu() != NULL);

View File

@@ -52,6 +52,7 @@ TEST_F(HWAddressTest, LessThanOperator) {
HWAddress<6> bcast = "ff:ff:ff:ff:ff:ff";
EXPECT_LT(addr2, addr1);
EXPECT_LT(addr2, bcast);
EXPECT_LE(addr1, addr1);
std::map<HWAddress<6>, int> dict;
dict[addr1] = 12;
dict[addr2] = 15;
@@ -59,6 +60,20 @@ TEST_F(HWAddressTest, LessThanOperator) {
EXPECT_EQ(dict[addr2], 15);
}
TEST_F(HWAddressTest, GreaterThanOperator) {
HWAddress<6> addr1(byte_address), addr2(empty_addr);
HWAddress<6> bcast = "ff:ff:ff:ff:ff:ff";
EXPECT_GT(addr1, addr2);
EXPECT_GT(bcast, addr2);
EXPECT_GE(addr1, addr1);
std::map<HWAddress<6>, int> dict;
dict[addr1] = 12;
dict[addr2] = 15;
EXPECT_EQ(dict[addr1], 12);
EXPECT_EQ(dict[addr2], 15);
}
TEST_F(HWAddressTest, CopyConstructor) {
HWAddress<6> addr1(byte_address), addr2(addr1);
@@ -115,3 +130,18 @@ TEST_F(HWAddressTest, Mask) {
address_type("de:ad:be:ef:00:00") & address_type("ff:ff:ff:f0:00:00")
);
}
TEST_F(HWAddressTest, OrMask) {
typedef HWAddress<6> address_type;
EXPECT_EQ(
address_type("ff:ff:ff:ff:fe:be"),
address_type("de:ad:be:ef:fe:be") | address_type("ff:ff:ff:f0:00:00")
);
}
TEST_F(HWAddressTest, NotMask) {
typedef HWAddress<6> address_type;
EXPECT_EQ(
address_type("00:00:00:0f:ff:ff"), ~address_type("ff:ff:ff:f0:00:00")
);
}

View File

@@ -47,8 +47,19 @@ TEST(IPAddressTest, LessThanOperator) {
EXPECT_LT(addr1, "192.168.1.2");
EXPECT_LT(addr1, "192.168.0.226");
EXPECT_LT(addr1, "193.0.0.0");
EXPECT_LE(addr1, addr2);
}
TEST(IPAddressTest, GreaterThanOperator) {
IPv4Address addr1(ip_string), addr2(ip_string);
EXPECT_FALSE(addr1 < addr2);
EXPECT_GT(addr1, "192.167.1.2");
EXPECT_GT(addr1, "192.167.0.226");
EXPECT_GT(addr1, "191.0.0.0");
EXPECT_GE(addr1, addr2);
}
TEST(IPAddressTest, IsPrivate) {
EXPECT_TRUE(IPv4Address("192.168.0.1").is_private());
EXPECT_TRUE(IPv4Address("192.168.133.7").is_private());
@@ -112,6 +123,26 @@ TEST(IPAddressTest, Mask) {
);
}
TEST(IPAddressTest, OrMask) {
EXPECT_EQ(
IPv4Address("255.255.255.1"),
IPv4Address("192.168.100.1") | IPv4Address("255.255.255.0")
);
EXPECT_EQ(
IPv4Address("255.255.1.2"),
IPv4Address("192.255.1.2") | IPv4Address("255.128.0.0")
);
}
TEST(IPAddressTest, NotMask) {
EXPECT_EQ(
IPv4Address("0.0.0.255"), ~IPv4Address("255.255.255.0")
);
EXPECT_EQ(
IPv4Address("0.127.255.255"),~IPv4Address("255.128.0.0")
);
}
TEST(IPv4AddressTest, Size) {
EXPECT_EQ(4UL, IPv4Address("127.0.0.1").size());
EXPECT_EQ(4UL, IPv4Address().size());

View File

@@ -23,7 +23,8 @@ using namespace Tins;
class IPTest : public testing::Test {
public:
static const uint8_t expected_packet[], fragmented_packet[],
fragmented_ether_ip_packet[], tot_len_zero_packet[];
fragmented_ether_ip_packet[], tot_len_zero_packet[],
options_packet[];
void test_equals(const IP& ip1, const IP& ip2);
void test_overwrite_source_address(IP& ip);
@@ -450,6 +451,26 @@ const uint8_t IPTest::tot_len_zero_packet[] = {
, 0, 0, 0, 0, 0
};
const uint8_t IPTest::options_packet[] = {
0, 160, 204, 59, 191, 250, 16, 54, 233, 241, 145, 224, 8, 0, 72, 0,
0, 242, 0, 1, 0, 0, 128, 17, 233, 177, 192, 168, 0, 4, 220, 113,
61, 150, 130, 11, 0, 16, 0, 0, 0, 0, 120, 120, 120, 0, 143, 243,
26, 48, 0, 210, 82, 251, 92, 3, 98, 243, 14, 149, 245, 46, 106,
244, 99, 187, 143, 32, 82, 21, 116, 83, 205, 114, 68, 236, 121, 23,
98, 220, 15, 75, 139, 145, 57, 154, 24, 92, 35, 84, 179, 123, 191,
141, 122, 43, 42, 172, 212, 85, 117, 54, 227, 157, 155, 192, 52,
206, 57, 242, 150, 236, 164, 202, 143, 4, 3, 200, 56, 106, 36, 202,
38, 4, 12, 29, 108, 72, 89, 23, 180, 94, 81, 238, 41, 84, 146, 126,
185, 84, 104, 249, 166, 43, 188, 14, 141, 89, 245, 254, 222, 236,
173, 140, 121, 146, 77, 14, 132, 36, 8, 113, 162, 92, 174, 188,
214, 148, 64, 227, 220, 34, 193, 139, 234, 144, 213, 89, 74, 95,
177, 180, 145, 26, 248, 29, 238, 146, 249, 247, 75, 26, 155, 36, 8,
188, 34, 176, 73, 92, 242, 194, 185, 67, 67, 214, 235, 137, 67,
158, 144, 27, 235, 221, 252, 44, 227, 25, 229, 172, 166, 214, 6, 6,
136, 21, 173, 84, 20, 109, 140, 182, 114, 179, 167, 196, 250, 56,
169, 152, 160, 18, 136, 245, 138, 101, 177, 107, 121, 74, 204, 180,
193, 228, 135, 37
};
TEST_F(IPTest, DefaultConstructor) {
IP ip;
@@ -854,3 +875,11 @@ TEST_F(IPTest, SerializeAfterInnerPduRemoved) {
EthernetII eth2(&buffer[0], buffer.size());
EXPECT_EQ(eth1.size(), eth2.size());
}
TEST_F(IPTest, ParseSerializeOptions) {
EthernetII packet(options_packet, sizeof(options_packet));
PDU::serialization_type serialized = packet.serialize();
const vector<uint8_t> buffer(options_packet, options_packet + sizeof(options_packet));
EXPECT_EQ(buffer, serialized);
}

View File

@@ -70,6 +70,14 @@ TEST(IPv6AddressTest, LessThanOperator) {
EXPECT_LT(IPv6Address("17f8::1"), IPv6Address("17f8:0::0:5"));
EXPECT_LT(IPv6Address("::1"), IPv6Address("::5"));
EXPECT_LT(IPv6Address("1::"), IPv6Address("2::"));
EXPECT_LE(IPv6Address("1::"), IPv6Address("1::"));
}
TEST(IPv6AddressTest, GreaterThanOperator) {
EXPECT_GT(IPv6Address("17f8:0::0:5"), IPv6Address("17f8::1"));
EXPECT_GT(IPv6Address("::5"), IPv6Address("::1"));
EXPECT_GT(IPv6Address("2::"), IPv6Address("1::"));
EXPECT_GE(IPv6Address("2::"), IPv6Address("2::"));
}
TEST(IPv6AddressTest, OutputOperator) {
@@ -124,6 +132,33 @@ TEST(IPv6AddressTest, MaskAddress) {
);
}
TEST(IPv6AddressTest, OrMaskAddress) {
EXPECT_EQ(
IPv6Address("ffff:ffff:adad:beef::"),
IPv6Address("deaf:beef:adad:beef::") | IPv6Address("ffff:ffff::")
);
EXPECT_EQ(
IPv6Address("ffff:ffef:adad:beef::"),
IPv6Address("deaf:beef:adad:beef::") | IPv6Address("ffff:ff00::")
);
EXPECT_EQ(
IPv6Address("ffff:feef:adad:beef::"),
IPv6Address("deaf:beef:adad:beef::") | IPv6Address("ffff:f000::")
);
EXPECT_EQ(
IPv6Address("ffff:feef:adad:beef::"),
IPv6Address("deaf:beef:adad:beef::") | IPv6Address("ffff:e000::")
);
}
TEST(IPv6AddressTest, NotMaskAddress) {
EXPECT_EQ(IPv6Address("::ffff:ffff:ffff:ffff:ffff:ffff"),~IPv6Address("ffff:ffff::"));
EXPECT_EQ(IPv6Address("::ff:ffff:ffff:ffff:ffff:ffff"),~IPv6Address("ffff:ffff:ff00::"));
EXPECT_EQ(IPv6Address("::fff:ffff:ffff:ffff:ffff:ffff"),~IPv6Address("ffff:ffff:f000::"));
EXPECT_EQ(IPv6Address("::1fff:ffff:ffff:ffff:ffff:ffff"),~IPv6Address("ffff:ffff:e000::"));
}
TEST(IPv6AddressTest, Size) {
EXPECT_EQ(16UL, IPv6Address("dead:beef::1").size());
EXPECT_EQ(16UL, IPv6Address().size());

View File

@@ -360,3 +360,63 @@ TEST_F(IPv6Test, OptionAddition) {
EXPECT_TRUE(ipv6.search_header(IPv6::ROUTING) != 0);
EXPECT_TRUE(ipv6.search_header(IPv6::AUTHENTICATION) != 0);
}
TEST_F(IPv6Test, HopByHopPadding) {
IPv6 ipv6_header;
ipv6_header.add_header(IPv6::ExtensionHeader::HOP_BY_HOP);
EXPECT_EQ(48UL, ipv6_header.serialize().size());
}
TEST_F(IPv6Test, HopByHopParsing) {
EthernetII pkt(hop_by_hop_options, sizeof(hop_by_hop_options));
IPv6& ipv6 = pkt.rfind_pdu<IPv6>();
const IPv6::headers_type& headers = ipv6.headers();
EXPECT_EQ(1UL, headers.size());
const IPv6::ext_header* ext_header = ipv6.search_header(IPv6::ExtensionHeader::HOP_BY_HOP);
EXPECT_TRUE(ext_header != NULL);
const IPv6::hop_by_hop_header hbh_header = IPv6::hop_by_hop_header::from_extension_header(*ext_header);
EXPECT_EQ(1UL, hbh_header.options.size());
EXPECT_EQ(5, hbh_header.options[0].first);
}
TEST_F(IPv6Test, HopByHopExtensionHeader) {
const uint8_t options[] = {42, 3, 0, 0, 0, 86, 0, 17, 2, 0, 0, 1, 2, 0, 0};
IPv6::ext_header hdr(IPv6::HOP_BY_HOP, options, options + sizeof(options));
IPv6::hop_by_hop_header header = IPv6::hop_by_hop_header::from_extension_header(hdr);
EXPECT_EQ(3UL, header.options.size());
EXPECT_EQ(42, header.options[0].first);
EXPECT_EQ(86, header.options[1].first);
EXPECT_EQ(17, header.options[2].first);
}
TEST_F(IPv6Test, DestinationRoutingExtensionHeader) {
EXPECT_THROW(IPv6::destination_routing_header::from_extension_header(IPv6::HOP_BY_HOP),
invalid_ipv6_extension_header);
IPv6::destination_routing_header header = IPv6::destination_routing_header::from_extension_header(IPv6::DESTINATION_ROUTING_OPTIONS);
EXPECT_EQ(0UL, header.options.size());
}
TEST_F(IPv6Test, RoutingExtensionHeader) {
const uint8_t header_data[] = {42, 17, 0, 0, 0, 0, 0};
IPv6::ext_header hdr(IPv6::ROUTING, header_data, header_data + sizeof(header_data));
IPv6::routing_header header = IPv6::routing_header::from_extension_header(hdr);
EXPECT_EQ(42, header.routing_type);
EXPECT_EQ(17, header.segments_left);
EXPECT_EQ(5UL, header.data.size());
}
TEST_F(IPv6Test, FragmentExtensionHeader) {
const uint8_t header_data[] = {128, 1, 0, 0, 0, 42};
IPv6::ext_header hdr(IPv6::FRAGMENT, header_data, header_data + sizeof(header_data));
IPv6::fragment_header header = IPv6::fragment_header::from_extension_header(hdr);
EXPECT_EQ(4096, header.fragment_offset);
EXPECT_TRUE(header.more_fragments);
EXPECT_EQ(42UL, header.identification);
}

View File

@@ -37,6 +37,8 @@ TEST_F(NetworkInterfaceTest, ConstructorFromString) {
TEST_F(NetworkInterfaceTest, ConstructorFromIp) {
NetworkInterface iface(IPv4Address("127.0.0.1"));
EXPECT_EQ(iface.name(), iface_name);
NetworkInterface i6face(IPv6Address("::1"));
EXPECT_EQ(i6face.name(), iface_name);
}
TEST_F(NetworkInterfaceTest, Id) {

View File

@@ -83,6 +83,14 @@ TEST_F(PDUTest, OperatorConcatOnPacket) {
EXPECT_TRUE(std::equal(raw->payload().begin(), raw->payload().end(), raw_payload.begin()));
}
#if TINS_IS_CXX11
TEST_F(PDUTest, MoveAssignment) {
IP packet = IP("192.168.0.1") / TCP(22, 52);
packet = IP("1.2.3.4");
EXPECT_TRUE(packet.inner_pdu() == 0);
}
#endif // TINS_IS_CXX11
TEST_F(PDUTest, TinsCast) {
PDU* null_pdu = 0;
TCP tcp;

View File

@@ -25,7 +25,7 @@ public:
static const uint8_t expected_packet[], expected_packet1[],
expected_packet2[], expected_packet3[],
expected_packet4[], expected_packet5[],
expected_packet6[];
expected_packet6[], expected_packet7[];
};
const uint8_t RadioTapTest::expected_packet[] = {
@@ -324,6 +324,57 @@ const uint8_t RadioTapTest::expected_packet6[] = {
164, 143, 87, 89, 97, 79, 145, 16, 48, 248, 198, 140, 48
};
const uint8_t RadioTapTest::expected_packet7[] = {
0, 255, 255, 0, 0, 240, 96, 235, 105, 143, 60, 180, 134, 221, 96,
0, 0, 0, 2, 164, 17, 64, 50, 73, 237, 197, 18, 75, 232, 197, 18,
72, 232, 197, 18, 72, 232, 71, 50, 73, 237, 125, 18, 75, 249, 195,
18, 72, 232, 197, 18, 239, 232, 197, 169, 236, 43, 206, 48, 166, 9,
84, 151, 88, 20, 229, 233, 39, 55, 108, 16, 104, 206, 107, 0, 53,
186, 70, 2, 164, 18, 0, 44, 150, 132, 3, 0, 1, 0, 0, 0, 6, 0, 1,
12, 67, 79, 56, 48, 49, 77, 49, 56, 48, 49, 57, 49, 13, 97, 122,
99, 111, 114, 114, 101, 99, 116, 105, 111, 110, 115, 5, 108, 111,
99, 97, 108, 0, 0, 6, 0, 1, 0, 0, 6, 0, 1, 0, 1, 81, 128, 0, 64, 1,
97, 12, 114, 111, 111, 116, 45, 115, 101, 114, 118, 101, 114, 115,
3, 110, 101, 116, 0, 5, 110, 115, 116, 108, 100, 12, 118, 101, 114,
105, 115, 105, 103, 110, 45, 103, 114, 115, 3, 99, 111, 109, 0,
120, 42, 86, 53, 0, 0, 7, 8, 0, 0, 3, 132, 0, 9, 58, 128, 0, 1, 81,
128, 5, 108, 111, 97, 110, 115, 0, 0, 47, 0, 1, 0, 1, 81, 128, 0,
15, 5, 108, 111, 99, 117, 115, 0, 0, 6, 32, 0, 0, 0, 0, 19, 0, 0,
47, 0, 1, 0, 1, 81, 128, 0, 14, 3, 97, 97, 97, 0, 0, 7, 26, 0, 0,
0, 0, 3, 128, 0, 0, 46, 0, 1, 0, 1, 81, 128, 0, 147, 0, 6, 8, 0, 0,
1, 81, 128, 87, 17, 30, 16, 87, 3, 225, 0, 236, 199, 0, 23, 89,
103, 40, 110, 160, 29, 93, 75, 23, 152, 78, 76, 255, 197, 241, 39,
189, 75, 31, 226, 166, 224, 55, 9, 100, 96, 27, 180, 130, 25, 199,
101, 176, 122, 115, 169, 75, 199, 174, 203, 181, 165, 16, 159, 111,
84, 166, 162, 242, 43, 255, 148, 16, 118, 212, 144, 118, 67, 113,
59, 31, 224, 181, 103, 41, 238, 3, 174, 153, 106, 80, 171, 124,
162, 186, 167, 108, 66, 140, 244, 97, 170, 127, 170, 252, 124, 139,
246, 150, 166, 208, 191, 15, 64, 250, 217, 195, 6, 39, 246, 71,
204, 248, 143, 71, 121, 44, 149, 98, 145, 203, 102, 74, 220, 240,
180, 8, 218, 171, 76, 194, 62, 241, 85, 94, 72, 28, 192, 125, 0,
46, 0, 30, 0, 1, 81, 128, 0, 147, 0, 47, 8, 1, 0, 1, 81, 128, 87,
17, 30, 16, 87, 3, 225, 0, 236, 199, 0, 159, 85, 2, 138, 56, 31,
91, 69, 9, 81, 254, 59, 65, 14, 76, 208, 107, 158, 159, 118, 92,
38, 52, 210, 139, 201, 40, 32, 135, 48, 252, 254, 64, 135, 97, 24,
253, 193, 114, 103, 214, 39, 14, 218, 50, 22, 60, 15, 208, 85, 152,
119, 21, 169, 236, 43, 206, 48, 166, 9, 84, 151, 88, 20, 229, 233,
39, 55, 108, 83, 104, 206, 107, 253, 252, 203, 24, 90, 216, 48,
191, 44, 38, 161, 228, 97, 84, 197, 138, 7, 206, 54, 244, 52, 153,
26, 232, 221, 182, 130, 29, 57, 193, 218, 124, 99, 68, 78, 161,
113, 120, 4, 155, 62, 94, 21, 89, 212, 33, 122, 42, 72, 5, 42, 172,
87, 70, 122, 0, 0, 46, 0, 1, 0, 1, 81, 128, 0, 147, 0, 47, 8, 0, 0,
1, 81, 128, 87, 17, 30, 16, 87, 3, 225, 0, 236, 199, 0, 131, 10,
126, 206, 35, 167, 184, 76, 112, 237, 170, 253, 123, 131, 162, 186,
243, 100, 237, 217, 17, 187, 90, 115, 28, 62, 89, 112, 69, 16, 227,
159, 162, 42, 212, 216, 246, 149, 118, 20, 105, 70, 196, 64, 48,
65, 216, 187, 25, 142, 138, 171, 229, 5, 251, 167, 181, 93, 62, 78,
204, 130, 147, 131, 168, 13, 120, 116, 115, 115, 107, 98, 53, 113,
111, 110, 56, 115, 110, 9, 95, 107, 101, 114, 98, 101, 114, 111,
115, 4, 95, 116, 99, 243, 21, 33, 14, 178, 86, 218, 241, 92, 120,
80, 120, 138, 155, 39, 74, 89, 32, 154, 143, 135, 103, 206, 121,
227, 234
};
TEST_F(RadioTapTest, DefaultConstructor) {
RadioTap radio;
EXPECT_TRUE((radio.flags() & RadioTap::FCS) != 0);
@@ -437,6 +488,10 @@ TEST_F(RadioTapTest, ConstructorFromBuffer5) {
EXPECT_EQ(0x05, radio.mcs().mcs);
}
TEST_F(RadioTapTest, ConstructorFromBuffer6) {
EXPECT_THROW(RadioTap(expected_packet7, sizeof(expected_packet7)), malformed_packet);
}
TEST_F(RadioTapTest, Serialize) {
RadioTap radio(expected_packet, sizeof(expected_packet));
RadioTap::serialization_type buffer = radio.serialize();
@@ -704,4 +759,27 @@ TEST_F(RadioTapTest, RadioTapWritingEmptyBuffer) {
}
TEST_F(RadioTapTest, RadioTapWritingInvalidOption) {
vector<uint8_t> buffer(4, 0);
RadioTapWriter writer(buffer);
uint8_t foo = 0;
RadioTap::option option((RadioTap::PresentFlags)(1 << RadioTapParser::MAX_RADIOTAP_FIELD), sizeof(foo), &foo);
EXPECT_THROW(writer.write_option(option), malformed_option);
}
TEST_F(RadioTapTest, RadioTapWriterAlignment) {
vector<uint8_t> buffer(4, 0);
RadioTapWriter writer(buffer);
uint8_t flags = 10;
uint8_t xchannel[sizeof(RadioTap::xchannel_type)] = {
1, 2, 3, 4, 5, 6, 7, 8
};
writer.write_option(RadioTap::option(RadioTap::FLAGS, sizeof(flags), &flags));
writer.write_option(RadioTap::option(RadioTap::XCHANNEL, sizeof(xchannel), xchannel));
vector<uint8_t> expected = {
2, 0, 4, 0, 10, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8
};
EXPECT_EQ(buffer, expected);
}
#endif // TINS_HAVE_DOT11

View File

@@ -13,7 +13,8 @@ using namespace Tins;
class TCPTest : public testing::Test {
public:
static const uint8_t expected_packet[], checksum_packet[],
partial_packet[];
partial_packet[],
malformed_option_after_eol_packet[];
void test_equals(const TCP& tcp1, const TCP& tcp2);
};
@@ -36,6 +37,11 @@ const uint8_t TCPTest::partial_packet[] = {
142, 210, 0, 80, 60, 158, 102, 111, 10, 2, 46, 161, 80, 24, 0, 229, 247, 192, 0, 0
};
const uint8_t TCPTest::malformed_option_after_eol_packet[] = {
127, 77, 79, 29, 241, 218, 229, 70, 95, 174, 209, 35, 96, 2, 113,
218, 0, 0, 31, 174, 0, 1, 2, 4
};
TEST_F(TCPTest, DefaultConstructor) {
TCP tcp;
@@ -271,6 +277,11 @@ TEST_F(TCPTest, SpoofedOptions) {
EXPECT_EQ(pdu.serialize().size(), pdu.size());
}
TEST_F(TCPTest, MalformedOptionAfterEOL) {
TCP tcp(malformed_option_after_eol_packet, sizeof(malformed_option_after_eol_packet));
EXPECT_EQ(0U, tcp.options().size());
}
TEST_F(TCPTest, RemoveOption) {
TCP tcp(22, 987);
uint8_t a[] = { 1,2,3,4,5,6 };

90
tests/src/vxlan_test.cpp Normal file
View File

@@ -0,0 +1,90 @@
#include <gtest/gtest.h>
#include <string>
#include <tins/ethernetII.h>
#include <tins/ip.h>
#include <tins/tcp.h>
#include <tins/udp.h>
#include <tins/pdu.h>
#include <tins/small_uint.h>
#include <tins/vxlan.h>
#define PACKET_SIZE 68ul
using namespace std;
using namespace Tins;
class VXLANTest : public testing::Test {
public:
static const uint8_t expected_packet[PACKET_SIZE];
static const uint8_t flags;
static const uint16_t dport, sport, p_type;
static const small_uint<24> vni;
static const IP::address_type dst_ip, src_ip;
static const EthernetII::address_type dst_addr, src_addr;
};
const uint8_t VXLANTest::expected_packet[PACKET_SIZE] = {
0x08, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0x00,
0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
const uint8_t VXLANTest::flags = 8;
const uint16_t VXLANTest::dport = 19627;
const uint16_t VXLANTest::sport = 4789;
const uint16_t VXLANTest::p_type = 0xd0ab;
const small_uint<24> VXLANTest::vni = 0xffffff;
const IP::address_type VXLANTest::dst_ip = IP::address_type{"2.2.2.2"};
const IP::address_type VXLANTest::src_ip = IP::address_type{"1.1.1.1"};
const EthernetII::address_type VXLANTest::dst_addr = EthernetII::address_type{"aa:bb:cc:dd:ee:ff"};
const EthernetII::address_type VXLANTest::src_addr = EthernetII::address_type{"8a:8b:8c:8d:8e:8f"};
TEST_F(VXLANTest, Flags) {
auto const vxlan = VXLAN{};
EXPECT_EQ(vxlan.get_flags(), flags);
}
TEST_F(VXLANTest, VNI) {
auto const vxlan = VXLAN{vni};
EXPECT_EQ(vxlan.get_vni(), vni);
}
TEST_F(VXLANTest, Find) {
auto const pdu = VXLAN{} / EthernetII{dst_addr, src_addr};
auto const eth = pdu.find_pdu<EthernetII>();
ASSERT_TRUE(eth != nullptr);
EXPECT_EQ(eth->dst_addr(), dst_addr);
EXPECT_EQ(eth->src_addr(), src_addr);
}
TEST_F(VXLANTest, Serialize) {
auto eth = EthernetII{dst_addr, src_addr};
eth.payload_type(p_type);
auto vxlan = VXLAN{vni};
vxlan.inner_pdu(eth);
auto serialized = vxlan.serialize();
ASSERT_EQ(serialized.size(), PACKET_SIZE);
EXPECT_TRUE(std::equal(serialized.begin(), serialized.end(), expected_packet));
}
TEST_F(VXLANTest, ConstructorFromBuffer) {
auto vxlan = VXLAN{expected_packet, PACKET_SIZE};
EXPECT_EQ(vxlan.get_vni(), vni);
EXPECT_EQ(vxlan.get_flags(), flags);
auto const eth = vxlan.find_pdu<EthernetII>();
ASSERT_TRUE(eth != nullptr);
EXPECT_EQ(eth->dst_addr(), dst_addr);
EXPECT_EQ(eth->src_addr(), src_addr);
}
TEST_F(VXLANTest, OuterUDP) {
auto pkt = IP{dst_ip, src_ip} / UDP{dport, sport} / VXLAN{expected_packet, PACKET_SIZE};
auto const vxlan = pkt.find_pdu<VXLAN>();
ASSERT_TRUE(vxlan != nullptr);
EXPECT_EQ(vxlan->get_flags(), flags);
EXPECT_EQ(vxlan->get_vni(), vni);
}