1
0
mirror of https://github.com/mfontanini/libtins synced 2026-01-23 10:45:57 +01:00

240 Commits
v3.1 ... v3.3

Author SHA1 Message Date
Matias Fontanini
4b0976571e Fix invalid FCS serialization offset on RadioTap 2016-02-02 22:43:28 -08:00
Matias Fontanini
8ab48106d6 Update changelog 2016-01-31 21:04:29 -08:00
Matias Fontanini
3036f9ce91 Merge branch 'master' of github.com:mfontanini/libtins into develop
Conflicts:
	examples/dns_stats.cpp
	include/tins/sniffer.h
	src/sniffer.cpp
2016-01-31 21:03:57 -08:00
Matias Fontanini
88d8f99676 Replace "wether" with "whether" on doc strings 2016-01-31 20:45:30 -08:00
Matias Fontanini
fb4e5086fd Update copyright notice 2016-01-31 20:03:49 -08:00
Matias Fontanini
58e3a7a687 Don't use pcap_setdirection on Windows 2016-01-25 12:50:29 -08:00
Matias Fontanini
f54399c45c Add TCP connection close example 2016-01-24 20:49:58 -08:00
Matias Fontanini
0cf3dd3342 Move utils.h implementations to utils.cpp 2016-01-24 14:13:34 -08:00
Matias Fontanini
d7df3a449e Move utils.h implementations to utils.cpp 2016-01-24 11:37:05 -08:00
Matias Fontanini
dc1a5a6982 Add ICMPv6 Multicast Listener Query Messages support 2016-01-20 20:27:37 -08:00
Matias Fontanini
3d21ad7bec Remove useless friend class declarations 2016-01-14 12:49:42 -08:00
Matias Fontanini
757e54dc08 Use lower case names for DNS query/record and change type to query_type 2016-01-14 12:40:00 -08:00
Matias Fontanini
ced645fb02 Add DNS SOA record parsing and serialization
Fixes #48
2016-01-14 12:18:43 -08:00
Matias Fontanini
c1e479f523 Merge pull request #114 from jllorente/master
Added pcap_setdirection to sniffer
2016-01-12 10:31:40 -03:00
Matias Fontanini
ca56cc10dd Parse and serialize MX preference field correctly 2016-01-11 15:48:03 -08:00
Matias Fontanini
75add84741 Add NetworkInterface::friendly_name to get Windows friendly names
Fixes #103
2016-01-10 17:44:32 -08:00
Matias Fontanini
3d3d7b8506 Mask 16 bits on random number generated on traceroute example
Fixes #121
2016-01-10 16:42:07 -08:00
Matias Fontanini
b21154a926 Fix sequence number addition/subtraction when wrapping around
Fixes #115
2016-01-10 16:31:48 -08:00
Matias Fontanini
2169b1f71f Use 802.1ad protocol flag when seralizing stacked Dot1Q
Fixes #68
2016-01-09 14:30:43 -08:00
Matias Fontanini
d84f10cf08 Code cleanup and use same syntax on the entire project
Initial code cleanup

More code cleanup

Cleanup more code

Cleanup Dot11 code

Fix OSX build issue

Cleanup examples

Fix ref and pointer declaration syntax

Fix braces
2016-01-09 10:01:58 -08:00
Matias Fontanini
f5a82b1a17 Correctly serialize PPPoE session packets 2016-01-01 14:49:32 -08:00
Matias Fontanini
2c16aaaecd Fix IPv6 extension headers parsing/serialization 2016-01-01 14:39:09 -08:00
Matias Fontanini
d7e0d17154 Add ICMPv6 multicast listener report message structure 2016-01-01 10:24:45 -08:00
Matias Fontanini
2b7714500c Include examples before src to avoid duplicate tins target issue 2015-12-31 14:43:30 -08:00
Matias Fontanini
03ad7f3ae7 Fix big endian issue on MPLS 2015-12-31 06:18:44 -08:00
Matias Fontanini
756dd97fc7 Add copyright to files that didn't have it 2015-12-31 06:05:42 -08:00
Matias Fontanini
7bffa7801d Add MPLS PDU and hook it up with ICMP extensions 2015-12-31 05:57:18 -08:00
Matias Fontanini
4ba9085eeb Set UDP checksum to 0xffff if it's 0 2015-12-29 09:00:46 -08:00
Matias Fontanini
c4a2fed112 Don't define TINS_STATIC in config.h 2015-12-29 07:43:46 -08:00
Matias Fontanini
df3bca099a Fix invalid RSNEAPOL parsing issue 2015-12-29 07:07:38 -08:00
Matias Fontanini
53e2c58f0b Remove special clang on OSX case when building gtest 2015-12-29 06:11:03 -08:00
Matias Fontanini
d7a9816246 Update pseudoheader_checksum signature 2015-12-29 05:58:58 -08:00
Matias Fontanini
67d31fd62c Fix overall checksum calculation 2015-12-29 09:57:42 -03:00
Matias Fontanini
afe778d03c Set ICMP payload length without padding if no extensions are present 2015-12-28 14:18:26 -03:00
Matias Fontanini
7a2ae6b7d5 Export classes on Windows shared lib builds
Fixes #120
2015-12-28 06:28:52 -08:00
Matias Fontanini
481c51b4c7 Use google/googletest submodule and update to HEAD 2015-12-27 16:17:05 -08:00
Matias Fontanini
38239be472 Remove unused cassert header inclusions 2015-12-27 04:38:31 -08:00
Matias Fontanini
31ca9a6cc8 Port Dot11 classes to use OutputMemoryStream 2015-12-26 16:54:35 -08:00
Matias Fontanini
49af3714e8 Add padding at the end of the line on dns_stats
Fixes #118
2015-12-26 07:31:53 -08:00
Matias Fontanini
36216107ec Catch exceptions on arpmonitor
Fixes #119
2015-12-26 07:30:29 -08:00
Matias Fontanini
02e2b278de Add OutputMemoryStream and port most classes to use it 2015-12-26 06:30:00 -08:00
Matias Fontanini
9750f46c6d Port all PDUs to use InputMemoryStream on constructors from buffer 2015-12-25 06:30:27 -08:00
Matias Fontanini
13c05fbdb1 Add input memory stream class and port some PDUs to use it 2015-12-24 15:21:07 -08:00
Matias Fontanini
6d90b0ce32 Add extensions for ICMPv6 2015-12-21 12:33:52 -08:00
Jesus Llorente
6b82e50c03 Modified set_direction to return a bool 2015-12-21 17:56:18 +02:00
Matias Fontanini
530cc56922 Set proper value for length field 2015-12-19 16:46:13 -08:00
Matias Fontanini
0a16d8f462 Add ICMP extensions to ICMP PDU
The length field is still not being set
2015-12-17 20:42:57 -08:00
Matias Fontanini
e3c382efa0 Fix sum_range issue on big endian 2015-12-16 20:03:27 -08:00
Matias Fontanini
fb43cb738b Add ICMP extensions to ICMP PDU 2015-12-14 21:18:42 -08:00
Matias Fontanini
6e026fcb66 Add missing member functions to ICMP extension classes 2015-12-14 20:22:50 -08:00
Matias Fontanini
187e7b1ca3 Add ICMP extensions structure class 2015-12-13 21:49:26 -08:00
Matias Fontanini
8aff1b4afe Add ICMPExtension class 2015-12-13 19:46:58 -08:00
Matias Fontanini
45546eee39 Fix RSNInformation issues on big endian architectures 2015-12-08 08:36:24 -08:00
Matias Fontanini
a35b086d12 Use endian independent way of setting IP fragment offset and flags 2015-12-07 22:11:28 -08:00
Matias Fontanini
3e23bcc73c Add IP::fragment_offset and IP::flags 2015-12-07 21:10:41 -08:00
Matias Fontanini
35d5045db4 Don't set Ethernet type if inner PDU type is unknown
Fixes #116
2015-11-27 20:31:12 -08:00
Matias Fontanini
65b7919ebf Don't run IP source address overwrite tests on OSX 2015-11-25 09:31:19 -08:00
Jesus Llorente
4b9f998784 Removed tins_direction_t typedef in favor of native pcap_direction_t 2015-11-24 20:09:41 +02:00
Jesus Llorente
b07deba105 Added pcap_setdirection to sniffer 2015-11-23 23:10:34 +02:00
Matias Fontanini
534bdaf30b Always calculate IP checksum
Fixes #105
2015-11-08 10:25:49 -08:00
Matias Fontanini
87c4963533 Fix invalid constant value on PPPoE
Fixes #109
2015-11-01 07:55:57 -08:00
Matias Fontanini
978041a9a2 Define default constructor for PKTAP
Fixes #106
2015-10-16 10:04:42 -07:00
Matias Fontanini
30445f1e97 Guard 802.11 parsing code on PPI around HAVE_DOT11 2015-09-21 21:06:57 -07:00
Matias Fontanini
693cef04df Fix parsing of Dot11 packets encapsulated on PPI having FCS-at-end 2015-09-21 20:49:17 -07:00
Matias Fontanini
9d0a2d4f3e Fix DataLinkType typo on doxygen docs
[ci skip]
2015-09-19 09:00:33 -07:00
Matias Fontanini
2cf61403e1 Update docs on sniff_loop handle persistency
[ci skip]
2015-08-25 20:15:04 -07:00
Matias Fontanini
69b26bd637 Migrate .travis to new container infrastructure 2015-08-22 11:05:06 -07:00
Matias Fontanini
cec69ee261 Fixes #99: Use uint32_t for DNS resource TTL setter 2015-08-22 10:59:33 -07:00
Matias Fontanini
891f4ac4d7 Fixes #98: Erase streams when they're reassembed on IPv4Reassembler 2015-08-22 10:57:45 -07:00
Matias Fontanini
af71a4eca7 Make all exceptions derive from exception_base 2015-08-17 21:46:07 -07:00
Matias Fontanini
dd0b9ecde4 Merge pull request #96 from mfontanini/remove_option
Add remove_option member to IP, TCP, Dot11, ICMPv6, DHCP and DHCPv6
2015-08-17 16:36:30 -07:00
Matias Fontanini
6dec68128d Add remove_option member to IP, TCP, Dot11, ICMPv6, DHCP and DHCPv6 2015-08-17 15:19:03 -07:00
Matias Fontanini
ab61907a06 Merge pull request #91 from rklabs/fix_tunnel_interface
Allow no HW address on interfaces when looking up their info (TUN ifaces)
2015-07-22 10:11:55 -07:00
rklabs
9c9994f129 Restoring deleted comment 2015-07-22 22:24:53 +05:30
rklabs
97e6a99c5e Add additional check for found_ip in case of tunnel interface and then raise exception 2015-07-22 22:06:21 +05:30
rklabs
d09450980a Incase of tunnel interface(VPN) mac address can be 0 2015-07-22 21:08:40 +05:30
Matias Fontanini
79c0023f75 Merge pull request #90 from bkambach/master
Increment option size when adding a new option
2015-07-13 16:37:56 -07:00
bkambach
3b23d68a10 Remove code, instead of commenting it out 2015-07-13 17:52:44 -04:00
bkambach
fe48586eef Remove update of options size in constructor 2015-07-13 17:49:29 -04:00
bkambach
848d8348ae Increment option size when adding a new option 2015-07-13 17:28:33 -04:00
Matias Fontanini
da3bf12671 Add NOMINMAX on examples. 2015-06-22 21:50:58 -07:00
Matias Fontanini
d447009779 Add metric to RouteEntry. 2015-06-21 14:32:23 -07:00
Matias Fontanini
2c2c92325d Fix traceroute example. 2015-06-20 10:58:36 -07:00
Matias Fontanini
b451a9eae0 Detect if pcap version defines pcap_set_immediate_mode. 2015-06-14 11:23:32 -07:00
Matias Fontanini
c42c18f5df Allow setting immediate mode on Sniffer. 2015-06-14 10:56:00 -07:00
Matias Fontanini
8bb837eda8 Use one flags field for all flags on SnifferConfiguration. 2015-06-14 10:41:07 -07:00
Matias Fontanini
6b6636b0bb Add ICMP responses example. 2015-06-13 11:34:59 -07:00
Matias Fontanini
316bb12946 Add interfaces_info example. 2015-06-13 10:31:31 -07:00
Matias Fontanini
cab0ba8b9a Fix bug on SessionKeys::SessionKeys. 2015-06-12 20:09:23 -07:00
Matias Fontanini
0a2fdfcd42 Fix compilation errors on android. 2015-06-07 15:25:57 -07:00
Matias Fontanini
43217549eb Fix example compilation on Windows.
Fixes #75.
2015-06-02 21:52:40 -07:00
Matias Fontanini
0f3441ccf6 Add PacketWriter::write overload that takes a Packet. 2015-05-26 21:33:13 -07:00
Matias Fontanini
9c25f635eb Add travis CI status image on README.md. 2015-05-23 13:19:47 -07:00
Matias Fontanini
3ec8ab868e Use different IP addresses on IP tests depending on OS. 2015-05-23 12:48:57 -07:00
Matias Fontanini
8d28bfe7a1 Fix compilation warnings shown on travis. 2015-05-23 11:56:31 -07:00
Matias Fontanini
46f5d7a0cd Fix tests failing on travis. 2015-05-23 11:17:20 -07:00
Matias Fontanini
8400079bce Add .travis.yml. 2015-05-23 10:53:20 -07:00
Matias Fontanini
68c750810f Update documentation for WPA2::SupplicantData. 2015-05-22 20:48:25 -07:00
Matias Fontanini
0dee5618f2 Allow retrieving keys on WPA2Decrypter. 2015-05-21 21:14:24 -07:00
Matias Fontanini
76c6511e0c Add NetworkInterface::is_up and NetworkInterface::info. 2015-05-19 18:52:42 -07:00
Matias Fontanini
2f2a705127 Add NetworkInterface::Info::is_up. 2015-05-19 18:44:24 -07:00
Matias Fontanini
b0faebd135 Include appveyor build status icon 2015-05-18 21:14:34 -07:00
Matias Fontanini
2bf2b222e0 Add appveyor.yml. 2015-05-17 17:35:45 -07:00
Matias Fontanini
c42cd0114f Fix compilation warnings on Windows x64. 2015-05-17 17:30:54 -07:00
Matias Fontanini
5cd0c8e41b Fix FindPCAP.cmake to find winpcap on x64. 2015-05-17 11:52:30 -07:00
Matias Fontanini
8276dca22e Fix more tests warnings triggered on Windows. 2015-05-16 11:18:54 -07:00
Matias Fontanini
d4e632f513 Fix tests compilation warnings on Windows. 2015-05-16 11:08:52 -07:00
Matias Fontanini
325de4abca Fix error on VC triggered by pcap redefining the "inline" keyword. 2015-05-12 19:03:52 -07:00
Matias Fontanini
e651770018 Fix warning on test added on last commit. 2015-05-10 13:36:29 -07:00
Matias Fontanini
d1ffecb132 Soften DNS parsing rules. Fixes #74. 2015-05-10 12:19:58 -07:00
Matias Fontanini
460e87cb43 Remove VC insecure warnings on header files. 2015-05-02 17:39:53 -07:00
Matias Fontanini
a607ab380c Replace WIN32 macro with _WIN32. 2015-05-02 16:25:59 -07:00
Matias Fontanini
a7a63483df Fix gtest compilation issues on OSX. 2015-04-25 19:39:22 -07:00
Matias Fontanini
9de57e1b23 Update README.md. 2015-04-25 19:01:40 -07:00
Matias Fontanini
f229f9a81e Merge pull request #72 from mfontanini/googletest-submodule
Googletest submodule
2015-04-25 18:57:57 -07:00
Matias Fontanini
62260ab93b Fix more compilation warnings on Windows. 2015-04-25 18:54:43 -07:00
Matias Fontanini
c108f6e4e6 Fix compilation warnings on Windows. 2015-04-25 18:44:38 -07:00
Matias Fontanini
5c8fdd2b6c Build googletest using /MD on Windows. 2015-04-25 17:44:56 -07:00
Matias Fontanini
34bf1f23f7 Improve tests CMake build files. 2015-04-25 17:26:02 -07:00
Matias Fontanini
ae503523e4 Fix tests that failed on Windows. 2015-04-25 17:05:36 -07:00
Matias Fontanini
e64e0ce27b Fix IPv6Address::to_string on Windows. 2015-04-25 12:20:47 -07:00
Matias Fontanini
93ed4f537e Fix TCP test on Windows. 2015-04-25 12:15:04 -07:00
Matias Fontanini
995abd4d00 Fix DNS issues triggered on VC. 2015-04-25 11:32:47 -07:00
Matias Fontanini
0dcbe6ffbe Prefix googletest directory with CMake source dir. 2015-04-23 19:45:32 -07:00
Matias Fontanini
745ebfb904 Only include googletest if the git submodule has been fetched. 2015-04-23 19:43:00 -07:00
Matias Fontanini
c5b9afaf83 Add google test as git submodule. 2015-04-23 19:39:58 -07:00
Matias Fontanini
f4ccba93e6 Merge branch 'master' of github.com:mfontanini/libtins 2015-04-23 19:12:25 -07:00
Matias Fontanini
308cbcdc40 Merge pull request #70 from benmcmorran/master
Perserve IP protocol when using RawPDU
2015-04-21 09:00:57 -07:00
Ben McMorran
eb5598be7c Perserve IP protocol when using RawPDU
Previously, the IP protocol field for non-fragmented packets was forcibly overwritten to the protocol of the inner PDU even if that PDU was a RawPDU. This behavior contradicts the documentation.
2015-04-20 02:45:27 -04:00
Matias Fontanini
830da2488b Update project version to 3.3. 2015-04-19 13:54:37 -07:00
Matias Fontanini
530ac79ba4 Improve documentation for PacketSender. 2015-04-19 10:54:18 -07:00
Matias Fontanini
213b812520 Use pcap_sendpacket by default on Windows. 2015-04-18 19:52:25 -07:00
Matias Fontanini
8c2b56e286 Allow sending Dot3 on Windows using pcap_sendpacket. 2015-04-18 19:37:57 -07:00
Matias Fontanini
147c1a4315 Don't allow receiving l2 packets on windows. 2015-04-18 18:56:16 -07:00
Matias Fontanini
2fa4c2ade3 Soften more precompiler conditionals on PacketSender. 2015-04-18 18:26:49 -07:00
Matias Fontanini
621af33a81 Fix more precompiler conditionals. 2015-04-18 18:19:56 -07:00
Matias Fontanini
0d9fe13166 Fix macro conditional. 2015-04-18 18:17:28 -07:00
Matias Fontanini
1a9cd63397 Remove more WIN32 guards. 2015-04-18 18:15:00 -07:00
Matias Fontanini
e2f96123a3 Remove some WIN32-guarded code. 2015-04-18 18:08:22 -07:00
Matias Fontanini
96fc1a3749 Use pcap_sendpacket to send packets if this mode is enabled. 2015-04-18 17:46:14 -07:00
Matias Fontanini
f2ed64293b Merge pull request #67 from UlfWetzker/channel_map
Added channel_map_type
2015-04-12 09:52:13 -07:00
Ulf Wetzker
bf807be7bd Fixed typo and copy&past nonsense 2015-04-09 20:26:01 +02:00
Ulf Wetzker
437911eacd Added Doxygen documentation and fixed arrangement 2015-04-09 19:51:05 +02:00
Ulf Wetzker
2d89f1548d Added channel map type 2015-04-09 19:39:55 +02:00
Matias Fontanini
c8b3b8d2b8 Merge pull request #66 from UlfWetzker/rsn_const
Made rsn_information() a const member function
2015-04-08 08:56:38 -07:00
Ulf Wetzker
7d7aae5929 Made rsn_information() a const member function to make Dot11ManagementFrame immutable 2015-04-08 14:45:56 +02:00
Matias Fontanini
fc950f643b Merge pull request #65 from blazeable/master
Ensure HAVE_CXX11 is checked when defining TINS_IS_CXX11
2015-04-06 14:53:08 -07:00
blazeable
4bfec7b358 Ensure HAVE_CXX11 is checked when defining TINS_IS_CXX11
Include config.h in cxxstd.h
2015-04-06 23:43:48 +02:00
Matias Fontanini
3478c7b09a Don't define Sniffer callback traits when using VS. 2015-04-06 09:33:30 -07:00
Matias Fontanini
a326463160 Add one integer field for all flags on TCP. 2015-04-05 11:53:12 -07:00
Matias Fontanini
ebad686987 Add test for partial TCP packet. 2015-04-05 09:43:50 -07:00
Matias Fontanini
3791fc0ee6 Fix ICMPv6 issue on big endian. 2015-04-02 23:02:28 -07:00
Matias Fontanini
40a8354125 Fix Dot11/RSNInformation big endian issues. 2015-04-02 22:59:47 -07:00
Matias Fontanini
bb683c9f79 Fix invalid DNS IPv4 address parsing on big endian arch. 2015-04-02 22:43:35 -07:00
Matias Fontanini
5edd5932ba Don't compile WPA2 test if LIBTINS_ENABLE_WPA2=0. 2015-04-02 21:58:52 -07:00
Matias Fontanini
021f596cf0 Remove enable_if_t. 2015-04-02 21:58:41 -07:00
Matias Fontanini
992d187b04 Merge pull request #63 from UlfWetzker/radio_measurement
Fixed field name corresponding to IEEE 802.11-2012
2015-04-02 09:15:39 -07:00
Ulf Wetzker
d6d2434482 Fixed field name corresponding to IEEE 802.11-2012 (8.4.1.4 Capability Information field) 2015-03-31 16:37:28 +02:00
Matias Fontanini
811270760a Don't define enable_if_t, since it's not really necessary. 2015-03-29 15:47:44 -07:00
Matias Fontanini
38ee449921 Update CHANGES file. 2015-03-20 22:12:23 -07:00
Matias Fontanini
9efd00956f Fix BaseSniffer::sniff_loop documentation. 2015-03-20 21:21:38 -07:00
Matias Fontanini
b56be87315 Remove include/tins/config.h. 2015-03-07 09:30:44 -08:00
Matias Fontanini
c67f7ba2e8 Merge pull request #57 from rioderelfte/include-guard
add an include guard to config.h
2015-03-07 09:24:34 -08:00
Matias Fontanini
aad0c511a8 Merge pull request #51 from EricMCornelius/master
Use type_traits to enable Packet& sniff_loop callback variant in C++11
2015-03-06 09:42:25 -08:00
Matias Fontanini
8bdce8e7b8 Merge pull request #60 from mfontanini/radiotap_fixes
Radiotap fixes
2015-03-06 09:04:17 -08:00
Matias Fontanini
64deb4fb39 Merge pull request #59 from haralduna/radiotap_fixes
Rearranged and updated RadioTap fields for big endian
2015-03-06 09:03:49 -08:00
Harald Unander
8c74bada85 Rearranged and updated RadioTap fields for big endian 2015-03-06 14:19:30 +01:00
Florian Sowade
8a51050f0b add an include guard to config.h 2015-03-05 12:41:34 +01:00
Eric Cornelius
4be9719195 Make sure we can still compile old loop signatures without c++11 enabled 2015-03-05 03:25:41 -05:00
Matias Fontanini
fa4a074e2f Add missing RadioTap fields. 2015-03-04 21:27:47 -08:00
Matias Fontanini
be51d67575 Remove Utils::resolve_domain6 test. 2015-03-04 18:19:00 -08:00
Matias Fontanini
695f191bb8 Fix invalid DNS record retrieval. 2015-03-04 18:11:33 -08:00
Eric Cornelius
c304dc08c4 Eliminate unnecessary explicit template parameter specification 2015-02-25 11:04:42 -05:00
Eric Cornelius
87207a8091 Support both move and reference overloads for the loop handler 2015-02-25 10:56:11 -05:00
Matias Fontanini
88c122ffcb Merge pull request #52 from UlfWetzker/master
Add Exception for fields that are not present in RadioTap frames.
2015-02-10 07:49:41 -08:00
Ulf Wetzker
c05f93a16f Fixed RadioTap test case 2015-02-10 15:28:36 +01:00
Ulf Wetzker
93a46366a0 Fixed type for _dbm_signal and _dbm_noise 2015-02-09 14:30:34 +01:00
Ulf Wetzker
179e0722f5 Fixed name in RadioTap present bitmap for field dbm_TX_power 2015-02-09 14:13:07 +01:00
Ulf Wetzker
d640eebb99 Add Exception for fields that are not present in RadioTap frames. 2015-02-09 13:23:03 +01:00
Eric Cornelius
184328ea95 Move packet into callback to avoid unnecessary clone, fix forward_iterator value type, and update comments 2015-02-06 10:24:43 -05:00
Eric Cornelius
eb0b7c9091 Generalize the accepts_type trait a bit, and move to internals.h, rename the _invoke_functor function, and templatize it to avoid need to depend on Packet defintion 2015-02-05 00:45:13 -05:00
Eric Cornelius
2587dd6cb0 Use type_traits to enable Packet& sniff_loop callback variant in C++11 builds 2015-02-04 21:44:50 -05:00
Matias Fontanini
fb97b2b8f0 Merge pull request #49 from joerango/master
Fixed TKIP decryption. Now packets from AP to STA are also decrypted.
2015-01-22 21:27:31 -08:00
Joseph Beshay
7382cc65de Fixed TKIP decryption. Now packets from AP to STA are also decrypted. 2015-01-22 19:51:05 -06:00
Matias Fontanini
1ca4f8166b Fix bug on EAPOL over snap serialization. 2015-01-17 09:49:47 -08:00
Matias Fontanini
65607b0eb5 Fixed PKTAP next layer interpretation. 2014-12-21 10:51:18 -08:00
Matias Fontanini
a4c67e5acd Added PKTAP header. 2014-12-21 10:18:59 -08:00
Matias Fontanini
ccbeca269a Merge pull request #47 from zhiweicai/ipaddress-win-fix
Ipaddress win fix
2014-12-17 10:26:08 -08:00
zhiweicai
ab972565d6 recover config.h 2014-12-16 21:42:20 -05:00
zhiweicai
c3a81f76d5 recover config.h 2014-12-16 21:40:35 -05:00
zhiweicai
8bf3b1af45 fix ip_to_int function on windows 2014-12-16 21:32:59 -05:00
Matias Fontanini
ae135bb035 Fixed IP total length zero bug. 2014-11-25 22:49:05 -08:00
Matias Fontanini
bcd8cc58f7 Merge pull request #45 from carlos-jenkins/master
Re-added support for pkg-config.
2014-11-19 21:20:41 -08:00
Carlos Miguel Jenkins Perez
8415f41722 Re-added support for pkg-config. 2014-11-19 20:35:30 -06:00
Matias Fontanini
3d832cc48e Replaced calls to PDU::rfind_pdu to find_pdu on TCPStreamFollower. 2014-11-13 22:07:31 -08:00
Matias Fontanini
3b126ca02b Removed access to potentially invalid positions on vector. 2014-11-12 21:11:01 -08:00
Matias Fontanini
0ba05f9d1a Fixed assertion throw on DNS on Visual Studio. 2014-11-11 22:01:23 -08:00
Matias Fontanini
3a38d36a60 Fixed invalid parsing of RadioTap ext flag field. 2014-11-06 21:44:59 -08:00
Matias Fontanini
d55a03ca0c Added L3 packet receive exception on BSD. 2014-10-25 17:42:46 -05:00
Matias Fontanini
c4609fedd6 Added Loopback::matches_response. 2014-10-25 00:23:52 -05:00
Matias Fontanini
23a5cfb0c4 Removed obsolete autotools files. 2014-10-23 22:37:15 -05:00
Matias Fontanini
69440fbc75 Fixed exception thrown when an interface didn't have IP address. 2014-10-23 00:04:20 -05:00
Matias Fontanini
64fac4f255 Added NetworkInterface::is_loopback. 2014-10-19 09:13:28 -03:00
Matias Fontanini
9ee90755d1 Moved headers to include/tins. 2014-10-17 12:14:00 -03:00
Matias Fontanini
a1636896aa Fixed compilation warning on unsigned integral constant. 2014-10-17 12:03:37 -03:00
Matias Fontanini
e7435d3974 BaseSniffer::get_pcap_handle is now public. 2014-10-17 12:03:18 -03:00
Matias Fontanini
3ad96422b9 Added correct parsing of PPPoE session packets. 2014-09-24 09:15:20 -03:00
Matias Fontanini
1bc9bd1504 Fixed compiler warning on SnifferIterator. 2014-09-21 10:58:38 -03:00
Matias Fontanini
8fcfd57125 Fixed portscan example. 2014-09-20 15:11:39 -03:00
Matias Fontanini
ff74f3103c Fixed invalid Loopback protocol detection on FreeBSD/OSX. 2014-09-20 09:52:42 -03:00
Matias Fontanini
addf0b3d98 Fixed OSX IP packet sending. 2014-09-19 10:07:31 -03:00
Matias Fontanini
ad5e0614d4 Added constructors to RawPDU. 2014-09-19 08:55:23 -03:00
Matias Fontanini
1ba203d742 Fixed compilation errors on FreeBSD. 2014-09-19 08:50:35 -03:00
Matias Fontanini
74cca6a483 Improved documentation on several classes. 2014-09-14 14:13:25 -03:00
Matias Fontanini
977231cf46 Fixed bug when allocating IP over IP packets. 2014-09-09 08:37:17 -03:00
Matias Fontanini
b532753a16 Fixed network naming on Windows. 2014-09-07 23:48:37 -03:00
Matias Fontanini
e0b9e38587 Utils::network_interface returns pcap compatible names on Windows. 2014-09-07 17:54:11 -03:00
Matias Fontanini
9d4bdce7a9 NetworkInterface::name now works on Windows. 2014-09-07 16:40:50 -03:00
Matias Fontanini
e00d6aaa7e Removed obsolete README file. 2014-09-07 11:22:44 -03:00
Matias Fontanini
9bda470f9d Completely removed autotools build system.
Also cleaned up the project's root, moving some files
into subdirectories.
2014-09-07 00:47:27 -03:00
Matias Fontanini
8b2f6a7fb2 Updated version to 3.2. 2014-09-04 23:04:36 -03:00
Matias Fontanini
57be666de1 Added documentation generation through the build system. 2014-09-04 22:44:10 -03:00
Matias Fontanini
050214a5dc Updated documentation on several classes. 2014-09-02 23:46:27 -03:00
Matias Fontanini
8bd3313010 Removed print statement. 2014-08-31 18:46:13 -03:00
Matias Fontanini
4d8658ca54 Merge pull request #33 from mfontanini/sniffer-config-object
Sniffer config object
2014-08-31 18:44:02 -03:00
Matias Fontanini
b6fdba0077 The timeout Sniffer option is set to 1000 by default. 2014-08-31 18:34:52 -03:00
Matias Fontanini
83ced826d0 Fixed using pcap_compile on a not-yet activated pcap handle. 2014-08-30 23:54:18 -03:00
Matias Fontanini
d820b0d19d Added documentation for SnifferConfiguration. 2014-08-30 23:35:05 -03:00
Matias Fontanini
7135473d19 Fixed bug triggered on Dot3 serialization.
In addition, Dot3 now always sets the packet length on
serialization.
2014-08-30 23:02:41 -03:00
Matias Fontanini
a7a4105cf8 Added OfflinePacketFilter class. 2014-08-30 23:01:46 -03:00
Santiago Alessandri
2b6a079980 Added back the original constructors of the Sniffer and FileSniffer to keep compatibility. Tagged them as deprecated, though.
Changed the default if_mask to 0 as PCAP_NETMASK_UNKNOWN is still not present in all versions of pcap.

Snap length is always set and it's default value is of 65535 not 0.
2014-08-30 17:29:30 -07:00
Matias Fontanini
07be8e244c Renamed NOEXCEPT macro to TINS_NOEXCEPT. 2014-08-30 14:30:47 -03:00
Matias Fontanini
9d2a60ef43 Added DataLinkType class. 2014-08-30 14:28:29 -03:00
Matias Fontanini
88fc1e7a87 Merge pull request #32 from mfontanini/BUG-31
BUG #31 (Closed): Fixed CMake files.
2014-08-29 23:56:30 -03:00
Santiago Alessandri
b063687621 BUG #31 (Closed): Fixed CMake files. 2014-08-29 18:43:40 -07:00
Santiago Alessandri
039b41cb76 Updated the examples to work with the new Sniffer constructor using the SnifferConfiguration object. 2014-08-29 18:20:15 -07:00
Santiago Alessandri
49f451ecd1 Changed the name to SnifferConfiguration, it sounds better. 2014-08-29 16:35:13 -07:00
Santiago Alessandri
10c5013305 Created gitignore file to exclude build directory and config.h automatically generated file. 2014-08-29 16:31:01 -07:00
Santiago Alessandri
5b2934e102 Refactored sniffer class to take a SnifferConfigurator to do the setup.
This way it is easier to extend the different configuration capabilities.
2014-08-29 16:30:13 -07:00
Matias Fontanini
74c85085fb IPv4Address now uses inet_pton when constructing from string. 2014-08-28 22:53:47 -03:00
267 changed files with 24092 additions and 73411 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
build/**
include/tins/config.h

4
.gitmodules vendored Normal file
View File

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

26
.travis.yml Normal file
View File

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

257
CHANGES
View File

@@ -1,3 +1,251 @@
v3.3 - Sun Jan 31 21:06:04 PST 2016
- Add TCP connection close example
- Move implementations on utils.h to utils.cpp
- Add ICMPv6 Multicast Listener Query Messages support
- Add ICMPv6 Multicast Listener Report Message support
- Make DNS::Query and DNS::Resource lowercase and deprecate the old names
- Change DNS::query/resource::type to query_type and deprecate old name
- Add DNS Start Of Authority parsing and serialization
- Parse and serialize MX preference field correctly
- Add NetworkInterface::friendly_name to get Windows friendly names
- Mask 16 bits on random number generated on traceroute example
- Fix TCP sequence number addition/subtraction when wrapping around
- Use 802.1ad protocol flag when seralizing stacked Dot1Q
- Code cleanup and use same syntax on the entire project
- Correctly serialize PPPoE session packets
- Fix IPv6 extension headers parsing/serialization
- Include examples before src to avoid duplicate tins target issue
- Add MPLS PDU and hook it up with ICMP extensions
- Set UDP checksum to 0xffff if it's 0
- Don't define TINS_STATIC in config.h
- Fix invalid RSNEAPOL parsing issue
- Remove special clang on OSX case when building gtest
- Update pseudoheader_checksum signature
- Fix overall checksum calculation
- Set ICMP payload length without padding if no extensions are present
- Export classes on Windows shared lib builds
- Use google/googletest submodule and update to HEAD
- Remove unused cassert header inclusions
- Add input/output memory stream classes port PDU classes to use them
- Add extensions for ICMP/ICMPv6
- Fix RSNInformation issues on big endian architectures
- Add IP::fragment_offset and IP::flags
- Don't set Ethernet type if inner PDU type is unknown
- Don't run IP source address overwrite tests on OSX
- Always calculate IP/IPv6 checksum
- Fix invalid constant value on PPPoE
- Define default constructor for PKTAP
- Guard 802.11 parsing code on PPI around HAVE_DOT11
- Fix parsing of Dot11 packets encapsulated on PPI having FCS-at-end
- Fix DataLinkType typo on doxygen docs
- Update docs on sniff_loop handle persistency
- Use uint32_t for DNS resource TTL setter
- Erase streams when they're reassembed on IPv4Reassembler
- Make all exceptions derive from exception_base
- Add remove_option member to IP, TCP, Dot11, ICMPv6, DHCP and DHCPv6
- Allow HW addresses to be 00:00:00:00:00 on NetworkInterface::info
- Increment option size when adding a new DHCPv6 option
- Use NOMINMAX on examples
- Add metric field to RouteEntry
- Allow setting immediate mode on Sniffer
- Use one flags field for all flags on SnifferConfiguration
- Add ICMP responses example
- Add interfaces_info example
- Fix bug on SessionKeys::SessionKeys
- Fix compilation errors on android platform
- Fix example compilation on Windows
- Add PacketWriter::write overload that takes a Packet
- Use different IP addresses on IP tests depending on OS
- Allow retrieving keys on WPA2Decrypter
- Add NetworkInterface::is_up and NetworkInterface::info
- Add NetworkInterface::Info::is_up
- Fix compilation warnings on Windows x64
- Fix FindPCAP.cmake to find winpcap on x64
- Fix more tests warnings triggered on Windows
- Fix tests compilation warnings on Windows
- Fix error on VC triggered by pcap redefining the "inline" keyword
- Soften DNS parsing rules
- Replace WIN32 macro with _WIN32
- Fix IPv6Address::to_string on Windows
- Fix DNS issues triggered on VC
- Add google test as git submodule
- Perserve IP protocol when using RawPDU
- Use pcap_sendpacket by default to send packets on Windows
- Don't allow receiving l2 packets on windows
- Added RadioTap channel map type
- Made rsn_information() a const member function to make Dot11ManagementFrame
immutable
- Ensure HAVE_CXX11 is checked when defining TINS_IS_CXX11
- Use one integer field for all flags on TCP
- Fix invalid DNS IPv4 address parsing on big endian arch
- Don't compile WPA2 test if LIBTINS_ENABLE_WPA2=0
- Add Dot11 radio measurement name corresponding to IEEE 802.11-2012
-------------------------------------------------------------------------------
v3.2 - Fri Mar 20 22:12:23 PST 2015
- Added include guard for config.h.
- The functor used on BaseSniffer::sniff_loop can now take a Packet.
- Added mcs, tx_flags, ext and data_retries options to RadioTap.
- Fixed big endian representation of RadioTap header.
- RadioTap's dbm_signal and dbm_noise are now signed.
- RadioTap now throws if an option is not present when getting
its value.
- TKIP decryption now works correctly on packets from AP to STA.
- Added support for PKTAP header.
- Fixed endian issue on IPv4Address::ip_to_int on Windows.
- Fixed IP parsing when total length is 0 due to TCP segmentation offload.
- Re-added support for pkg-config.
- TCPStreamFollower now calls PDU::find_pdu instead of PDU::rfind_pdu.
- Fixed assertion throw caused by DNS parsing on Windows on debug mode.
- Added throw on BSD when trying to send_recv L3 packets.
- Added Loopback::matches_response.
- Removed obsolete autotools files.
- Fixed exception thrown when an interface didn't have an IP address
on NetworkInterface.
- Added NetworkInterface::is_loopback.
- Moved all headers to the directory include/tins.
- Fixed compilation warning on TCPStramFollower due to signed to unsigned
conversion on integral constant.
- BaseSniffer::get_pcap_handle is now public.
- PPPoE session packets are now parsed correctly.
- Fixed invalid Loopback protocol detection on FreeBSD/OSX.
- Fixed OSX IP packet sending issue.
- Added useful constructors to RawPDU.
- Fixed compilation errors on FreeBSD.
- Improved documentation on several classes.
- Fixed parsing bug when allocating IP over IP packets.
- Fixed Windows network interface naming.
- Utils::network_interface returns pcap compatible names on Windows.
- NetworkInterface::name now works on Windows.
- Added documentation generation through the build system.
- Added SnifferConfiguration class.
- Fixed bug on Dot3 serialization.
- Added OfflinePacketFilter class.
- Renamed NOEXCEPT macro to TINS_NOEXCEPT.
- Added DataLinkType class.
- IPv4Address now uses inet_pton when constructing from string.
-------------------------------------------------------------------------------
v3.1 - Sun Aug 24 21:39:43 ART 2014
- Fixed ICMPv6 checksum error on serialization.
@@ -6,6 +254,8 @@ v3.1 - Sun Aug 24 21:39:43 ART 2014
- Changed the build system to CMake.
-------------------------------------------------------------------------------
v3.0 - Thu Aug 7 21:39:09 ART 2014
- Timestamps can now be constructed from std::chrono::duration.
@@ -69,6 +319,8 @@ PDU types.
- Fixed bug triggered by not including the string header.
-------------------------------------------------------------------------------
v2.0 - Thu Jan 23 11:09:38 ART 2014
- DNSResourceRecord was removed. Now DNS records are added using
@@ -123,6 +375,8 @@ capture size.
- Added tins_cast as a replacement for dynamic_cast on PDUs.
-------------------------------------------------------------------------------
v1.2 - Mon oct 7 23:33:49 ART 2013
- Added BaseSniffer::begin and BaseSniffer::end.
@@ -217,6 +471,8 @@ that used them.
- Added Utils::resolve_domain and Utils::resolve_domain6
-------------------------------------------------------------------------------
v0.3 - Thu Jan 31 16:47:27 ART 2013
- Added IPv6, ICMPv6 and DHCPv6 classes.
@@ -236,6 +492,7 @@ pseudo protocol.
- Fixed several bugs in DNS.
-------------------------------------------------------------------------------
v0.2 - Sat Oct 20 11:26:40 2012

View File

@@ -9,8 +9,17 @@ ELSE(NOT CMAKE_BUILD_TYPE)
MESSAGE(STATUS "Using specified '${CMAKE_BUILD_TYPE}' build type.")
ENDIF(NOT CMAKE_BUILD_TYPE)
# Default compilation settings
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
# Compilation flags.
IF(MSVC)
# Don't always use Wall, since VC's /Wall is ridiculously verbose.
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3")
# Disable VC secure checks, since these are not really issues.
ADD_DEFINITIONS("-D_CRT_SECURE_NO_WARNINGS=1")
ADD_DEFINITIONS("-D_SCL_SECURE_NO_WARNINGS=1")
ADD_DEFINITIONS("-DNOGDI=1")
ELSE()
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
ENDIF()
# Build output checks
OPTION(LIBTINS_BUILD_SHARED "Build libtins as a shared library." ON)
@@ -24,12 +33,13 @@ IF(LIBTINS_BUILD_SHARED)
ELSE(LIBTINS_BUILD_SHARED)
MESSAGE(STATUS "Build will generate a static library.")
SET(LIBTINS_TYPE STATIC)
ADD_DEFINITIONS("-DTINS_STATIC=1")
ENDIF(LIBTINS_BUILD_SHARED)
# The version number.
SET(LIBTINS_VERSION_MAJOR 3)
SET(LIBTINS_VERSION_MINOR 1)
SET(LIBTINS_CPP_VERSION "${LIBTINS_VERSION_MAJOR}.${LIBTINS_VERSION_MINOR}")
SET(LIBTINS_VERSION_MINOR 3)
SET(LIBTINS_VERSION "${LIBTINS_VERSION_MAJOR}.${LIBTINS_VERSION_MINOR}")
# Required Packages
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
@@ -43,12 +53,14 @@ IF(WIN32)
SET(LIBTINS_OS_LIBS Ws2_32.lib Iphlpapi.lib)
# Add the NOMINMAX macro to avoid Windows' min and max macros.
# While compiling on windows, for some reason, WIN32 is not defined,
# maybe we could fix this later, but it's OK for now.
ADD_DEFINITIONS(-DNOMINMAX -DWIN32)
ADD_DEFINITIONS(-DNOMINMAX)
ENDIF(WIN32)
# *******************
# Compilation options
# *******************
# C++11 support
OPTION(LIBTINS_ENABLE_CXX11 "Compile libtins with c++11 features" OFF)
IF(LIBTINS_ENABLE_CXX11)
SET(HAVE_CXX11 ON)
@@ -67,6 +79,7 @@ ELSE(LIBTINS_ENABLE_CXX11)
"as it increases the library's performance")
ENDIF(LIBTINS_ENABLE_CXX11)
# IEEE 802.11 and WPA2 decryption support
OPTION(LIBTINS_ENABLE_DOT11 "Compile libtins with IEEE 802.11 support" ON)
OPTION(LIBTINS_ENABLE_WPA2 "Compile libtins with WPA2 decryption features (requires OpenSSL)" ON)
IF(LIBTINS_ENABLE_DOT11)
@@ -81,20 +94,85 @@ IF(LIBTINS_ENABLE_DOT11)
ENDIF(LIBTINS_ENABLE_WPA2)
ENDIF(LIBTINS_ENABLE_DOT11)
# Use pcap_sendpacket to send l2 packets rather than raw sockets
IF(WIN32)
SET(USE_PCAP_SENDPACKET_DEFAULT ON)
ELSE(WIN32)
SET(USE_PCAP_SENDPACKET_DEFAULT OFF)
ENDIF(WIN32)
OPTION(LIBTINS_USE_PCAP_SENDPACKET "Use pcap_sendpacket to send l2 packets"
${USE_PCAP_SENDPACKET_DEFAULT})
IF(LIBTINS_USE_PCAP_SENDPACKET)
SET(HAVE_PACKET_SENDER_PCAP_SENDPACKET ON)
MESSAGE(STATUS "Using pcap_sendpacket to send l2 packets.")
ENDIF(LIBTINS_USE_PCAP_SENDPACKET)
# Add a target to generate API documentation using Doxygen
FIND_PACKAGE(Doxygen QUIET)
IF(DOXYGEN_FOUND)
CONFIGURE_FILE(
${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile.in
${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
@ONLY
)
ADD_CUSTOM_TARGET(
docs
${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen" VERBATIM
)
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)
# Congiguration file
# Configuration file
CONFIGURE_FILE(
"${PROJECT_SOURCE_DIR}/include/config.h.in"
"${PROJECT_SOURCE_DIR}/include/config.h"
"${PROJECT_SOURCE_DIR}/include/tins/config.h.in"
"${PROJECT_SOURCE_DIR}/include/tins/config.h"
)
ENABLE_TESTING()
# Support for pkg-config
SET(CMAKE_INSTALL_LIBDIR lib)
SET(pkgconfig_prefix ${CMAKE_INSTALL_PREFIX})
SET(pkgconfig_exec_prefix ${CMAKE_INSTALL_PREFIX})
SET(pkgconfig_libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
SET(pkgconfig_version ${LIBTINS_VERSION})
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libtins.pc.in
${CMAKE_CURRENT_BINARY_DIR}/libtins.pc @ONLY)
INSTALL(
FILES
${CMAKE_CURRENT_BINARY_DIR}/libtins.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
)
# ******************
# Add subdirectories
# ******************
ADD_SUBDIRECTORY(include)
ADD_SUBDIRECTORY(src)
ADD_SUBDIRECTORY(tests)
ADD_SUBDIRECTORY(examples)
ADD_SUBDIRECTORY(src)
# Only include googletest if the git submodule has been fetched
IF(EXISTS "${CMAKE_SOURCE_DIR}/googletest/CMakeLists.txt")
# Enable tests and add the test directory
MESSAGE(STATUS "Tests have been enabled")
SET(gtest_force_shared_crt ON CACHE BOOL "Always use /MD")
SET(BUILD_GMOCK OFF)
SET(BUILD_GTEST ON)
ENABLE_TESTING()
ADD_SUBDIRECTORY(googletest)
ADD_SUBDIRECTORY(tests)
ELSE()
MESSAGE(STATUS "googletest git submodule is absent. Run `git submodule init && git submodule update` to get it")
ENDIF()
# **********************************
# CMake project configuration export
# **********************************
# Add all targets to the build-tree export set
EXPORT(
@@ -110,20 +188,20 @@ EXPORT(PACKAGE libtins)
# for the build tree
SET(CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/include")
CONFIGURE_FILE(
libtinsConfig.cmake.in
cmake/libtinsConfig.cmake.in
"${PROJECT_BINARY_DIR}/libtinsConfig.cmake" @ONLY
)
CONFIGURE_FILE(
libtinsConfigVersion.cmake.in
cmake/libtinsConfigVersion.cmake.in
"${PROJECT_BINARY_DIR}/libtinsConfigVersion.cmake" @ONLY
)
# Install the libtinsConfig.cmake and libtinsConfigVersion.cmake
INSTALL(
FILES
"${PROJECT_BINARY_DIR}/libtinsConfig.cmake"
"${PROJECT_BINARY_DIR}/libtinsConfigVersion.cmake"
DESTINATION CMake
COMPONENT dev
"${PROJECT_BINARY_DIR}/libtinsConfigVersion.cmake"
DESTINATION CMake
COMPONENT dev
)
# Install the export set for use with the install-tree

View File

@@ -1,131 +0,0 @@
AUTOMAKE_OPTIONS=subdir-objects 1.11
ACLOCAL_AMFLAGS=${ACLOCAL_FLAGS} -I m4
# pkg-config stuff
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libtins.pc
lib_LTLIBRARIES=libtins.la
libtins_la_LDFLAGS = -version-info @LIBTINS_VERSION@
AM_CXXFLAGS = -Wall -pedantic -I@LIBTINS_INCLUDE_DIR@
libtins_la_SOURCES=src/arp.cpp \
src/bootp.cpp \
src/handshake_capturer.cpp \
src/stp.cpp \
src/pppoe.cpp \
src/crypto.cpp \
src/dhcp.cpp \
src/dhcpv6.cpp \
src/dns.cpp \
src/dot3.cpp \
src/dot1q.cpp \
src/eapol.cpp \
src/ethernetII.cpp \
src/icmp.cpp \
src/icmpv6.cpp \
src/internals.cpp \
src/ip_reassembler.cpp \
src/ip.cpp \
src/ip_address.cpp \
src/ipv6.cpp \
src/ipv6_address.cpp \
src/ipsec.cpp \
src/llc.cpp \
src/loopback.cpp \
src/network_interface.cpp \
src/packet_sender.cpp \
src/packet_writer.cpp \
src/ppi.cpp \
src/pdu.cpp \
src/radiotap.cpp \
src/address_range.cpp \
src/rawpdu.cpp \
src/rsn_information.cpp \
src/sll.cpp \
src/snap.cpp \
src/sniffer.cpp \
src/tcp.cpp \
src/tcp_stream.cpp \
src/udp.cpp \
src/utils.cpp \
src/dot11/dot11_base.cpp \
src/dot11/dot11_data.cpp \
src/dot11/dot11_mgmt.cpp \
src/dot11/dot11_beacon.cpp \
src/dot11/dot11_assoc.cpp \
src/dot11/dot11_auth.cpp \
src/dot11/dot11_probe.cpp \
src/dot11/dot11_control.cpp
libtinsdir = $(includedir)/tins
libtins_HEADERS = include/internals.h \
include/dhcpv6.h \
include/dot11.h \
include/dot1q.h \
include/dot3.h \
include/small_uint.h \
include/ip.h \
include/ipsec.h \
include/eapol.h \
include/tcp_stream.h \
include/pppoe.h \
include/handshake_capturer.h \
include/ipv6.h \
include/icmpv6.h \
include/ieee802_3.h \
include/endianness.h \
include/rsn_information.h \
include/loopback.h \
include/ethernetII.h \
include/crypto.h \
include/packet.h \
include/llc.h \
include/ip_reassembler.h \
include/icmp.h \
include/hw_address.h \
include/packet_writer.h \
include/macros.h \
include/arp.h \
include/ip_address.h \
include/pdu.h \
include/packet_sender.h \
include/bootp.h \
include/network_interface.h \
include/sll.h \
include/ppi.h \
include/radiotap.h \
include/dns.h \
include/rawpdu.h \
include/sniffer.h \
include/snap.h \
include/pdu_cacher.h \
include/dhcp.h \
include/timestamp.h \
include/tcp.h \
include/pdu_option.h \
include/tins.h \
include/udp.h \
include/ipv6_address.h \
include/constants.h \
include/utils.h \
include/cxxstd.h \
include/stp.h \
include/exceptions.h \
include/config.h \
include/address_range.h \
include/pdu_allocator.h
libtins_dot11_HEADERS = include/dot11/dot11_base.h \
include/dot11/dot11_beacon.h \
include/dot11/dot11_data.h \
include/dot11/dot11_mgmt.h \
include/dot11/dot11_assoc.h \
include/dot11/dot11_auth.h \
include/dot11/dot11_probe.h \
include/dot11/dot11_control.h
libtins_dot11dir = $(includedir)/tins/dot11/

File diff suppressed because it is too large Load Diff

73
README
View File

@@ -1,73 +0,0 @@
------------------------------------------------------------------------
libtins v3.0
------------------------------------------------------------------------
-------------------------------- About ---------------------------------
libtins is a high-level, multiplatform C++ network packet sniffing and
crafting library.
Its main purpose is to provide the C++ developer an easy, efficient,
platform and endianess-independent way to create tools which need to
send, receive and manipulate specially crafted packets.
In order to read tutorials, examples and checkout some benchmarks of the
library, please visit:
http://libtins.github.io/
------------------------------- Compiling ------------------------------
libtins depends on libpcap and openssl, although the latter is not
necessary if some features of the library are disabled.
In order to compile, execute:
./configure
make
Note that by default, only the shared object is compiled. If you would
like to generate a static library file as well, run:
./configure --enable-static
The generated static/shared library files will be located in the .libs
directory.
libtins is noticeable faster if you enable C++11 support. Therefore, if
your compiler supports this standard, then you should enable it. In
order to do so, use the --enable-c++11 switch:
./configure --enable-c++11
If you want to disable WPA2 decryption support, which will remove
openssl as a dependency for compilation, use the --disable-wpa2 switch:
./configure --disable-wpa2
If you want to disable IEEE 802.11 support(this will also disable
RadioTap and WPA2 decryption), which will reduce the size of the
resulting library in around 20%, use the --disable-dot11 switch:
./configure --disable-dot11
------------------------------ Installing-------------------------------
Once you're done, if you want to install the header files and the
shared object, execute as root:
make install
This will install the shared object typically in /usr/local/lib. Note
that you might have to update ldconfig's cache before using it, so
in order to invalidate it, you should run(as root):
ldconfig
------------------------------ Examples --------------------------------
You might want to have a look at the examples located in the "examples"
directory. The same samples can be found online at:
http://libtins.github.io/examples/

View File

@@ -1,5 +1,7 @@
libtins
=======
# libtins
[![Build status](https://travis-ci.org/mfontanini/libtins.svg?branch=master)](https://travis-ci.org/mfontanini/libtins)
[![Build status](https://ci.appveyor.com/api/projects/status/33n8ib68nx3tptib/branch/master?svg=true)](https://ci.appveyor.com/project/mfontanini/libtins/branch/master)
libtins is a high-level, multiplatform C++ network packet sniffing and
crafting library.
@@ -85,6 +87,32 @@ in order to invalidate it, you should run(as root):
ldconfig
```
## Running tests ##
You may want to run the unit tests on your system so you make sure
everything works. In order to do so, you need to follow these steps:
```Shell
# This will fetch the googletest submodule, needed for tests
git submodule init
git submodule update
mkdir build
cd build
# Use any options you want
cmake ..
# Compile tests
make tests
# Run them
make test
```
If you find that any tests fail, please create an ticket in the
issue tracker indicating the platform and architecture you're using.
## Examples ##
You might want to have a look at the examples located in the "examples"

1191
aclocal.m4 vendored

File diff suppressed because it is too large Load Diff

View File

@@ -18,6 +18,7 @@
# PCAP_LIBRARY The libpcap library (possibly includes a thread
# library e.g. required by pf_ring's libpcap)
# HAVE_PF_RING If a found version of libpcap supports PF_RING
# HAVE_PCAP_IMMEDIATE_MODE If the version of libpcap found supports immediate mode
find_path(PCAP_ROOT_DIR
NAMES include/pcap.h
@@ -28,9 +29,17 @@ find_path(PCAP_INCLUDE_DIR
HINTS ${PCAP_ROOT_DIR}/include
)
set (HINT_DIR ${PCAP_ROOT_DIR}/lib)
# On x64 windows, we should look also for the .lib at /lib/x64/
# as this is the default path for the WinPcap developer's pack
if (${CMAKE_SIZEOF_VOID_P} EQUAL 8 AND WIN32)
set (HINT_DIR ${PCAP_ROOT_DIR}/lib/x64/ ${HINT_DIR})
endif ()
find_library(PCAP_LIBRARY
NAMES pcap wpcap
HINTS ${PCAP_ROOT_DIR}/lib
HINTS ${HINT_DIR}
)
include(FindPackageHandleStandardArgs)
@@ -65,6 +74,7 @@ endif (NOT PCAP_LINKS_SOLO)
include(CheckFunctionExists)
set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY})
check_function_exists(pcap_get_pfring_id HAVE_PF_RING)
check_function_exists(pcap_set_immediate_mode HAVE_PCAP_IMMEDIATE_MODE)
set(CMAKE_REQUIRED_LIBRARIES)
mark_as_advanced(

44
cmake/appveyor.yml Normal file
View File

@@ -0,0 +1,44 @@
version: 1.0.{build}
configuration:
- debug
- release
platform:
- Win32
- x64
clone_depth: 1
install:
- git clone https://github.com/mfontanini/winpcap-installer.git
- cd winpcap-installer
- winpcap-boundary-meter-4.1.3.exe /S
- cd ..
- appveyor DownloadFile http://www.winpcap.org/install/bin/WpdPack_4_1_2.zip
- 7z x .\WpdPack_4_1_2.zip -oc:\
- git submodule init
- git submodule update
before_build:
- mkdir build
- cd build
- if "%platform%"=="x64" ( set GENERATOR="Visual Studio 12 Win64" ) else ( set GENERATOR="Visual Studio 12" )
- cmake .. -G %GENERATOR% -DPCAP_ROOT_DIR=c:\WpdPack -DLIBTINS_BUILD_SHARED=0 -DLIBTINS_ENABLE_WPA2=0 -DLIBTINS_ENABLE_CXX11=1
build:
project: C:/projects/libtins/build/libtins.sln
verbosity: minimal
after_build:
- mkdir install\libtins\include
- mkdir install\libtins\lib
- cd install\libtins
- copy C:\projects\libtins\build\lib\%Configuration%\tins.lib lib
- xcopy C:\projects\libtins\include include /s /e
- del include\CMakeLists.txt
- del include\tins\CMakeLists.txt
- del include\tins\config.h.in
- del include\tins\dot11\CMakeLists.txt
- cd ..\
- 7z a libtins-%platform%-%Configuration%.zip libtins
test_script:
- cd c:\projects\libtins\build
- ctest -C %Configuration%
deploy_script:
- ps: Push-AppveyorArtifact "install\libtins-$env:Platform-$env:Configuration.zip"
skip_commits:
message: /Update documentation.*/

View File

@@ -1 +0,0 @@
/usr/share/automake-1.14/compile

1530
config.guess vendored

File diff suppressed because it is too large Load Diff

1782
config.sub vendored

File diff suppressed because it is too large Load Diff

18244
configure vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,85 +0,0 @@
AC_INIT([libtins], [3.0], [matias.fontanini@gmail.com], [libtins], [http://libtins.sourceforge.net])
AC_CANONICAL_SYSTEM
AC_CONFIG_HEADER(include/config.h)
AM_INIT_AUTOMAKE([-Wall -Werror -Wno-extra-portability foreign])
LT_INIT([disable-static])
AC_CONFIG_MACRO_DIR([m4])
AM_MAINTAINER_MODE([disable])
AC_PROG_CXX
AC_LANG(C++)
AC_PROG_LIBTOOL
# Check that libpcap exists
AC_ARG_WITH([pcap-include-path],
[AS_HELP_STRING([--with-pcap-include-path],
[location of the libpcap headers, defaults to /usr/include/pcap])],
[CXXFLAGS="$CXXFLAGS -I$withval"; CPPFLAGS="-I$withval"])
AC_ARG_WITH([pcap-lib-path],
[AS_HELP_STRING([--with-pcap-lib-path], [location of the libpcap libraries])],
[LIBS="$LIBS -L$withval"])
AC_CHECK_LIB(pcap, pcap_loop, [], [AC_MSG_ERROR([pcap library is missing!])])
old_cppflags=$CPPFLAGS
CPPFLAGS=""
# Headers
LIBTINS_INCLUDE_DIR="include"
AC_CHECK_HEADERS([pcap.h], [], [AC_MSG_ERROR([libpcap headers are missing!])])
CPPFLAGS=$old_cppflags
# Options
wpa2_msg="WPA2 decryption(which requires openssl) can be disabled using the --disable-wpa2 flag."
AC_ARG_ENABLE(
c++11,
[ --enable-c++11 enable C++11 features],
[AX_CXX_COMPILE_STDCXX_11(noext)]
)
AC_ARG_ENABLE(
dot11,
[ --disable-dot11 disable IEEE 802.11 support],
[],
[
AC_DEFINE([HAVE_DOT11], 1, Have IEEE 802.11 support)
# Only allow enabling WPA2 if Dot11 is enabled.
AC_ARG_ENABLE(
wpa2,
[ --disable-wpa2 disable WPA2 decryption features],
[],
[
AC_CHECK_HEADERS(
[openssl/evp.h openssl/hmac.h openssl/aes.h],
[],
[AC_MSG_ERROR([openssl headers are missing! $wpa2_msg ])]
AC_DEFINE([HAVE_WPA2_DECRYPTION], 0, Have WPA2 decryption library)
)
AC_CHECK_LIB(
crypto,
PKCS5_PBKDF2_HMAC_SHA1,
[],
[AC_MSG_ERROR([openssl library is missing! $wpa2_msg ])]
)
AC_DEFINE([HAVE_WPA2_DECRYPTION], 1, Have WPA2 decryption library)
]
)
]
)
# Substitute options
AC_SUBST(CXXFLAGS)
AC_SUBST(LIBS)
AC_SUBST(LIBTINS_INCLUDE_DIR)
AC_SUBST([LIBTINS_VERSION], [3:0:0])
AC_CONFIG_FILES([Makefile libtins.pc])
AC_OUTPUT

708
depcomp
View File

@@ -1,708 +0,0 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2012-03-27.16; # UTC
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010,
# 2011, 2012 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
Run PROGRAMS ARGS to compile a file, generating dependencies
as side-effects.
Environment variables:
depmode Dependency tracking mode.
source Source file read by 'PROGRAMS ARGS'.
object Object file output by 'PROGRAMS ARGS'.
DEPDIR directory where to store dependencies.
depfile Dependency file to output.
tmpdepfile Temporary file to use when outputting dependencies.
libtool Whether libtool is used (yes/no).
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "depcomp $scriptversion"
exit $?
;;
esac
# A tabulation character.
tab=' '
# A newline character.
nl='
'
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
fi
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
depfile=${depfile-`echo "$object" |
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
# here, because this file can only contain one case statement.
if test "$depmode" = hp; then
# HP compiler uses -M and no extra arg.
gccflag=-M
depmode=gcc
fi
if test "$depmode" = dashXmstdout; then
# This is just like dashmstdout with a different argument.
dashmflag=-xM
depmode=dashmstdout
fi
cygpath_u="cygpath -u -f -"
if test "$depmode" = msvcmsys; then
# This is just like msvisualcpp but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvisualcpp
fi
if test "$depmode" = msvc7msys; then
# This is just like msvc7 but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvc7
fi
if test "$depmode" = xlc; then
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency informations.
gccflag=-qmakedep=gcc,-MF
depmode=gcc
fi
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
## it if -MD -MP comes after the -MF stuff. Hmm.
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
## the command line argument order; so add the flags where they
## appear in depend2.am. Note that the slowdown incurred here
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
for arg
do
case $arg in
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
*) set fnord "$@" "$arg" ;;
esac
shift # fnord
shift # $arg
done
"$@"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
mv "$tmpdepfile" "$depfile"
;;
gcc)
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
## -MM, not -M (despite what the docs say).
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
gccflag=-MD,
fi
"$@" -Wp,"$gccflag$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
## The second -e expression handles DOS-style file names with drive letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
## This next piece of magic avoids the "deleted header file" problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
tr ' ' "$nl" < "$tmpdepfile" |
## Some versions of gcc put a space before the ':'. On the theory
## that the space means something, we add a space to the output as
## well. hp depmode also adds that space, but also prefixes the VPATH
## to the object. Take care to not repeat it in the output.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
sgi)
if test "$libtool" = yes; then
"$@" "-Wp,-MDupdate,$tmpdepfile"
else
"$@" -MDupdate "$tmpdepfile"
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
echo "$object : \\" > "$depfile"
# Clip off the initial element (the dependent). Don't try to be
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
# the IRIX cc adds comments like '#:fec' to the end of the
# dependency line.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
tr "$nl" ' ' >> "$depfile"
echo >> "$depfile"
# The second pass generates a dummy entry for each header file.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> "$depfile"
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
# "include basename.Plo" scheme.
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
xlc)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
# current directory. Also, the AIX compiler puts '$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.u
tmpdepfile2=$base.u
tmpdepfile3=$dir.libs/$base.u
"$@" -Wc,-M
else
tmpdepfile1=$dir$base.u
tmpdepfile2=$dir$base.u
tmpdepfile3=$dir$base.u
"$@" -M
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
# Each line is of the form 'foo.o: dependent.h'.
# Do two passes, one to just change these to
# '$object: dependent.h' and one to simply 'dependent.h:'.
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
# "include basename.Plo" scheme.
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
icc)
# Intel's C compiler anf tcc (Tiny C Compiler) understand '-MD -MF file'.
# However on
# $CC -MD -MF foo.d -c -o sub/foo.o sub/foo.c
# ICC 7.0 will fill foo.d with something like
# foo.o: sub/foo.c
# foo.o: sub/foo.h
# which is wrong. We want
# sub/foo.o: sub/foo.c
# sub/foo.o: sub/foo.h
# sub/foo.c:
# sub/foo.h:
# ICC 7.1 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using '\':
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
# tcc 0.9.26 (FIXME still under development at the moment of writing)
# will emit a similar output, but also prepend the continuation lines
# with horizontal tabulation characters.
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each line is of the form 'foo.o: dependent.h',
# or 'foo.o: dep1.h dep2.h \', or ' dep3.h dep4.h \'.
# Do two passes, one to just change these to
# '$object: dependent.h' and one to simply 'dependent.h:'.
sed -e "s/^[ $tab][ $tab]*/ /" -e "s,^[^:]*:,$object :," \
< "$tmpdepfile" > "$depfile"
sed '
s/[ '"$tab"'][ '"$tab"']*/ /g
s/^ *//
s/ *\\*$//
s/^[^:]*: *//
/^$/d
/:$/d
s/$/ :/
' < "$tmpdepfile" >> "$depfile"
rm -f "$tmpdepfile"
;;
hp2)
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
# compilers, which have integrated preprocessors. The correct option
# to use with these is +Maked; it writes dependencies to a file named
# 'foo.d', which lands next to the object file, wherever that
# happens to be.
# Much of this is similar to the tru64 case; see comments there.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir.libs/$base.d
"$@" -Wc,+Maked
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
"$@" +Maked
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
# Add 'dependent.h:' lines.
sed -ne '2,${
s/^ *//
s/ \\*$//
s/$/:/
p
}' "$tmpdepfile" >> "$depfile"
else
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile" "$tmpdepfile2"
;;
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in 'foo.d' instead, so we check for that too.
# Subdirectories are respected.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
if test "$libtool" = yes; then
# With Tru64 cc, shared objects can also be used to make a
# static library. This mechanism is used in libtool 1.4 series to
# handle both shared and static libraries in a single compilation.
# With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
#
# With libtool 1.5 this exception was removed, and libtool now
# generates 2 separate objects for the 2 libraries. These two
# compilations output dependencies in $dir.libs/$base.o.d and
# in $dir$base.o.d. We have to check for both files, because
# one of the two compilations can be disabled. We should prefer
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
# automatically cleaned when .libs/ is deleted, while ignoring
# the former would cause a distcleancheck panic.
tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
tmpdepfile2=$dir$base.o.d # libtool 1.5
tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
"$@" -Wc,-MD
else
tmpdepfile1=$dir$base.o.d
tmpdepfile2=$dir$base.d
tmpdepfile3=$dir$base.d
tmpdepfile4=$dir$base.d
"$@" -MD
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
msvc7)
if test "$libtool" = yes; then
showIncludes=-Wc,-showIncludes
else
showIncludes=-showIncludes
fi
"$@" $showIncludes > "$tmpdepfile"
stat=$?
grep -v '^Note: including file: ' "$tmpdepfile"
if test "$stat" = 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The first sed program below extracts the file names and escapes
# backslashes for cygpath. The second sed program outputs the file
# name when reading, but also accumulates all include files in the
# hold buffer in order to output them again at the end. This only
# works with sed implementations that can handle large buffers.
sed < "$tmpdepfile" -n '
/^Note: including file: *\(.*\)/ {
s//\1/
s/\\/\\\\/g
p
}' | $cygpath_u | sort -u | sed -n '
s/ /\\ /g
s/\(.*\)/'"$tab"'\1 \\/p
s/.\(.*\) \\/\1:/
H
$ {
s/.*/'"$tab"'/
G
p
}' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvc7msys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
#nosideeffect)
# This comment above is used by automake to tell side-effect
# dependency tracking mechanisms from slower ones.
dashmstdout)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
test -z "$dashmflag" && dashmflag=-M
# Require at least two characters before searching for ':'
# in the target name. This is to cope with DOS-style filenames:
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
"$@" $dashmflag |
sed 's:^['"$tab"' ]*[^:'"$tab"' ][^:][^:]*\:['"$tab"' ]*:'"$object"'\: :' > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
tr ' ' "$nl" < "$tmpdepfile" | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
dashXmstdout)
# This case only exists to satisfy depend.m4. It is never actually
# run, as this mode is specially recognized in the preamble.
exit 1
;;
makedepend)
"$@" || exit $?
# Remove any Libtool call
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
cleared=no eat=no
for arg
do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
if test $eat = yes; then
eat=no
continue
fi
case "$arg" in
-D*|-I*)
set fnord "$@" "$arg"; shift ;;
# Strip any option that makedepend may not understand. Remove
# the object too, otherwise makedepend will parse it as a source file.
-arch)
eat=yes ;;
-*|$object)
;;
*)
set fnord "$@" "$arg"; shift ;;
esac
done
obj_suffix=`echo "$object" | sed 's/^.*\././'`
touch "$tmpdepfile"
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
rm -f "$depfile"
# makedepend may prepend the VPATH from the source file name to the object.
# No need to regex-escape $object, excess matching of '.' is harmless.
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
sed '1,2d' "$tmpdepfile" | tr ' ' "$nl" | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile" "$tmpdepfile".bak
;;
cpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
"$@" -E |
sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
sed '$ s: \\$::' > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
cat < "$tmpdepfile" >> "$depfile"
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvisualcpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
IFS=" "
for arg
do
case "$arg" in
-o)
shift
;;
$object)
shift
;;
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E 2>/dev/null |
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
echo "$tab" >> "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvcmsys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
none)
exec "$@"
;;
*)
echo "Unknown depmode $depmode" 1>&2
exit 1
;;
esac
exit 0
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

View File

@@ -31,14 +31,14 @@ PROJECT_NAME = libtins
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER = 1.2
PROJECT_NUMBER = @LIBTINS_VERSION@
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
OUTPUT_DIRECTORY = ../docs/
OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@/docs/
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
# 4096 sub-directories (in 2 levels) under the output directory of each output
@@ -581,7 +581,7 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = include src
INPUT = @CMAKE_CURRENT_SOURCE_DIR@/include @CMAKE_CURRENT_SOURCE_DIR@/src @CMAKE_CURRENT_SOURCE_DIR@/docs/mainpage.dox
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is

29
docs/mainpage.dox Normal file
View File

@@ -0,0 +1,29 @@
/**
* \mainpage Documentation
*
* \section intro_sec Introduction
*
* <i>libtins</i> is a high-level, multiplatform <i>C++</i> network packet
* sniffing and crafting library.
*
* Its main purpose is to provide the <i>C++</i> developer an easy, efficient,
* platform and endianess-independent way to create tools which need to
* send, receive and manipulate network packets.
*
* \section install_sec Installation
*
* Please visit the <a href="http://libtins.github.io/download/">downloads
* section</a> in order to see the installation instructions.
*
* \section tutorials_sec Tutorials
*
* If you want to learn about how the library works, please visit the
* <a href="http://libtins.github.io/tutorial/">tutorials</a> section.
*
* \section examples_sec Examples
*
* Make sure to visit the <a href="http://libtins.github.io/examples/">
* examples</a> section to see some short but illustrative examples on how
* to send and sniff packets using <i>libtins</i>.
*
*/

View File

@@ -3,7 +3,10 @@ FIND_PACKAGE(Threads QUIET)
IF(libtins_FOUND)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/examples)
INCLUDE_DIRECTORIES(${LIBTINS_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(
${LIBTINS_INCLUDE_DIRS}
${PCAP_INCLUDE_DIR}
)
LINK_LIBRARIES(${LIBTINS_LIBRARIES})
IF(HAVE_CXX11)
@@ -12,6 +15,10 @@ IF(libtins_FOUND)
dns_queries
dns_spoof
dns_stats
icmp_responses
interfaces_info
tcp_connection_close
traceroute
wps_detect
)
ELSE(HAVE_CXX11)
@@ -24,29 +31,39 @@ IF(libtins_FOUND)
${LIBTINS_CXX11_EXAMPLES}
beacon_display
portscan
traceroute
route_table
)
ADD_EXECUTABLE(arpspoofing EXCLUDE_FROM_ALL arpspoofing.cpp)
ADD_EXECUTABLE(route_table EXCLUDE_FROM_ALL route_table.cpp)
IF(HAVE_CXX11)
ADD_EXECUTABLE(arpmonitor EXCLUDE_FROM_ALL arpmonitor.cpp)
ADD_EXECUTABLE(dns_queries EXCLUDE_FROM_ALL dns_queries.cpp)
ADD_EXECUTABLE(dns_spoof EXCLUDE_FROM_ALL dns_spoof.cpp)
ADD_EXECUTABLE(dns_stats EXCLUDE_FROM_ALL dns_stats.cpp)
ADD_EXECUTABLE(icmp_responses EXCLUDE_FROM_ALL icmp_responses.cpp)
ADD_EXECUTABLE(interfaces_info EXCLUDE_FROM_ALL interfaces_info.cpp)
ADD_EXECUTABLE(tcp_connection_close EXCLUDE_FROM_ALL tcp_connection_close.cpp)
ADD_EXECUTABLE(wps_detect EXCLUDE_FROM_ALL wps_detect.cpp)
ENDIF(HAVE_CXX11)
ADD_EXECUTABLE(beacon_display EXCLUDE_FROM_ALL beacon_display.cpp)
if(THREADS_FOUND)
ADD_EXECUTABLE(portscan EXCLUDE_FROM_ALL portscan.cpp)
ADD_EXECUTABLE(traceroute EXCLUDE_FROM_ALL traceroute.cpp)
TARGET_LINK_LIBRARIES(portscan ${CMAKE_THREAD_LIBS_INIT})
TARGET_LINK_LIBRARIES(traceroute ${CMAKE_THREAD_LIBS_INIT})
ELSE(THREADS_FOUND)
IF(HAVE_CXX11)
ADD_EXECUTABLE(traceroute EXCLUDE_FROM_ALL traceroute.cpp)
ADD_EXECUTABLE(dns_stats EXCLUDE_FROM_ALL dns_stats.cpp)
TARGET_LINK_LIBRARIES(traceroute ${CMAKE_THREAD_LIBS_INIT})
TARGET_LINK_LIBRARIES(dns_stats ${CMAKE_THREAD_LIBS_INIT})
ENDIF(HAVE_CXX11)
IF(WIN32)
MESSAGE(WARNING "Disabling portscan example since it doesn't compile on Windows.")
ELSE()
ADD_EXECUTABLE(portscan EXCLUDE_FROM_ALL portscan.cpp)
TARGET_LINK_LIBRARIES(portscan ${CMAKE_THREAD_LIBS_INIT})
ENDIF()
ELSE()
MESSAGE(WARNING "Disabling portscan and traceroute examples since pthreads library was not found.")
ENDIF(THREADS_FOUND)
ENDIF()
ELSE(libtins_FOUND)
MESSAGE(
WARNING

View File

@@ -1,43 +0,0 @@
CXX=@CXX@
CXXFLAGS=-Wall @CXXFLAGS@
LDFLAGS=-ltins
EXECUTABLES=arpspoofing arpmonitor portscan traceroute beacon_display dns_queries dns_spoof dns_stats wps_detect
all: $(EXECUTABLES)
compile: $(OBJECTS)
recompile: clean all
arpspoofing:
$(CXX) arpspoofing.cpp -o arpspoofing $(CXXFLAGS) $(LDFLAGS)
arpmonitor:
$(CXX) arpmonitor.cpp -o arpmonitor -std=c++0x $(CXXFLAGS) $(LDFLAGS)
dns_queries:
$(CXX) dns_queries.cpp -o dns_queries -std=c++0x $(CXXFLAGS) $(LDFLAGS)
dns_spoof:
$(CXX) dns_spoof.cpp -o dns_spoof -std=c++0x $(CXXFLAGS) $(LDFLAGS)
dns_stats:
$(CXX) dns_stats.cpp -o dns_stats -std=c++0x $(CXXFLAGS) $(LDFLAGS) -lpthread
beacon_display:
$(CXX) beacon_display.cpp -o beacon_display $(CXXFLAGS) $(LDFLAGS)
wps_detect:
$(CXX) wps_detect.cpp -o wps_detect -std=c++0x $(CXXFLAGS) $(LDFLAGS)
portscan:
$(CXX) portscan.cpp -o portscan $(CXXFLAGS) $(LDFLAGS) -lpthread
traceroute:
$(CXX) traceroute.cpp -o traceroute -std=c++0x $(CXXFLAGS) $(LDFLAGS) -lpthread
.cpp.o:
$(CXX) $(CXXFLAGS) $(INCLUDE) $< -o $@
clean:
rm $(OBJECTS) $(EXECUTABLES)

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,21 +32,25 @@
#include <iostream>
#include <functional>
using std::cout;
using std::endl;
using std::map;
using std::bind;
using namespace Tins;
class arp_monitor {
public:
void run(Sniffer &sniffer);
void run(Sniffer& sniffer);
private:
bool callback(const PDU &pdu);
bool callback(const PDU& pdu);
std::map<IPv4Address, HWAddress<6>> addresses;
map<IPv4Address, HWAddress<6>> addresses;
};
void arp_monitor::run(Sniffer &sniffer)
{
void arp_monitor::run(Sniffer& sniffer) {
sniffer.sniff_loop(
std::bind(
bind(
&arp_monitor::callback,
this,
std::placeholders::_1
@@ -54,43 +58,50 @@ void arp_monitor::run(Sniffer &sniffer)
);
}
bool arp_monitor::callback(const PDU &pdu)
{
bool arp_monitor::callback(const PDU& pdu) {
// Retrieve the ARP layer
const ARP &arp = pdu.rfind_pdu<ARP>();
const ARP& arp = pdu.rfind_pdu<ARP>();
// Is it an ARP reply?
if(arp.opcode() == ARP::REPLY) {
if (arp.opcode() == ARP::REPLY) {
// Let's check if there's already an entry for this address
auto iter = addresses.find(arp.sender_ip_addr());
if(iter == addresses.end()) {
if (iter == addresses.end()) {
// We haven't seen this address. Save it.
addresses.insert({ arp.sender_ip_addr(), arp.sender_hw_addr()});
std::cout << "[INFO] " << arp.sender_ip_addr() << " is at "
<< arp.sender_hw_addr() << std::endl;
cout << "[INFO] " << arp.sender_ip_addr() << " is at "
<< arp.sender_hw_addr() << std::endl;
}
else {
// We've seen this address. If it's not the same HW address, inform it
if(arp.sender_hw_addr() != iter->second) {
std::cout << "[WARNING] " << arp.sender_ip_addr() << " is at "
<< iter->second << " but also at " << arp.sender_hw_addr()
<< std::endl;
if (arp.sender_hw_addr() != iter->second) {
cout << "[WARNING] " << arp.sender_ip_addr() << " is at "
<< iter->second << " but also at " << arp.sender_hw_addr()
<< endl;
}
}
}
return true;
}
int main(int argc, char *argv[])
{
int main(int argc, char* argv[]) {
if(argc != 2) {
std::cout << "Usage: " << *argv << " <interface>\n";
cout << "Usage: " <<* argv << " <interface>" << endl;
return 1;
}
arp_monitor monitor;
// Sniff on the provided interface in promiscuous mode
Sniffer sniffer(argv[1], Sniffer::PROMISC);
// Only capture arp packets
sniffer.set_filter("arp");
monitor.run(sniffer);
// Sniffer configuration
SnifferConfiguration config;
config.set_promisc_mode(true);
config.set_filter("arp");
try {
// Sniff on the provided interface in promiscuous mode
Sniffer sniffer(argv[1], config);
// Only capture arp packets
monitor.run(sniffer);
}
catch (std::exception& ex) {
std::cerr << "Error: " << ex.what() << std::endl;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,20 +32,29 @@
#include <string>
#include <stdexcept>
#include <cstdlib>
#include <unistd.h>
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
#include <unistd.h>
#endif // _WIN32
#include <tins/arp.h>
#include <tins/network_interface.h>
#include <tins/utils.h>
#include <tins/ethernetII.h>
#include <tins/packet_sender.h>
using namespace std;
using std::cout;
using std::runtime_error;
using std::endl;
using namespace Tins;
void do_arp_spoofing(NetworkInterface iface, IPv4Address gw, IPv4Address victim,
const NetworkInterface::Info &info)
{
void do_arp_spoofing(NetworkInterface iface,
IPv4Address gw,
IPv4Address victim,
const NetworkInterface::Info& info) {
PacketSender sender;
EthernetII::address_type gw_hw, victim_hw;
@@ -74,17 +83,23 @@ void do_arp_spoofing(NetworkInterface iface, IPv4Address gw, IPv4Address victim,
* performed by any routers. */
EthernetII to_gw = EthernetII(gw_hw, info.hw_addr) / gw_arp;
EthernetII to_victim = EthernetII(victim_hw, info.hw_addr) / victim_arp;
while(true) {
while (true) {
// Just send them once every 5 seconds.
sender.send(to_gw, iface);
sender.send(to_victim, iface);
sleep(5);
#ifdef _WIN32
Sleep(5);
#else
sleep(5);
#endif
}
}
int main(int argc, char *argv[]) {
if(argc != 3 && cout << "Usage: " << *argv << " <Gateway> <Victim>\n")
int main(int argc, char* argv[]) {
if (argc != 3) {
cout << "Usage: " <<* argv << " <Gateway> <Victim>" << endl;
return 1;
}
IPv4Address gw, victim;
EthernetII::address_type own_hw;
try {
@@ -92,7 +107,7 @@ int main(int argc, char *argv[]) {
gw = argv[1];
victim = argv[2];
}
catch(...) {
catch (...) {
cout << "Invalid ip found...\n";
return 2;
}
@@ -106,15 +121,15 @@ int main(int argc, char *argv[]) {
// Find the interface hardware and ip address.
info = iface.addresses();
}
catch(std::runtime_error &ex) {
catch (runtime_error& ex) {
cout << ex.what() << endl;
return 3;
}
try {
do_arp_spoofing(iface, gw, victim, info);
}
catch(std::runtime_error &ex) {
std::cout << "Runtime error: " << ex.what() << std::endl;
catch (runtime_error& ex) {
cout << "Runtime error: " << ex.what() << endl;
return 7;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,47 +32,57 @@
#include <string>
#include <tins/tins.h>
using std::set;
using std::cout;
using std::endl;
using std::string;
using std::runtime_error;
using namespace Tins;
class BeaconSniffer {
public:
void run(const std::string &iface);
void run(const string& iface);
private:
typedef Dot11::address_type address_type;
typedef std::set<address_type> ssids_type;
typedef set<address_type> ssids_type;
bool callback(PDU &pdu);
bool callback(PDU& pdu);
ssids_type ssids;
};
void BeaconSniffer::run(const std::string &iface) {
Sniffer sniffer(iface, Sniffer::PROMISC, "type mgt subtype beacon", true);
void BeaconSniffer::run(const std::string& iface) {
SnifferConfiguration config;
config.set_promisc_mode(true);
config.set_filter("type mgt subtype beacon");
config.set_rfmon(true);
Sniffer sniffer(iface, config);
sniffer.sniff_loop(make_sniffer_handler(this, &BeaconSniffer::callback));
}
bool BeaconSniffer::callback(PDU &pdu) {
bool BeaconSniffer::callback(PDU& pdu) {
// Get the Dot11 layer
const Dot11Beacon &beacon = pdu.rfind_pdu<Dot11Beacon>();
const Dot11Beacon& beacon = pdu.rfind_pdu<Dot11Beacon>();
// All beacons must have from_ds == to_ds == 0
if(!beacon.from_ds() && !beacon.to_ds()) {
if (!beacon.from_ds() && !beacon.to_ds()) {
// Get the AP address
address_type addr = beacon.addr2();
// Look it up in our set
ssids_type::iterator it = ssids.find(addr);
if(it == ssids.end()) {
if (it == ssids.end()) {
// First time we encounter this BSSID.
try {
/* If no ssid option is set, then Dot11::ssid will throw
* a std::runtime_error.
*/
std::string ssid = beacon.ssid();
string ssid = beacon.ssid();
// Save it so we don't show it again.
ssids.insert(addr);
// Display the tuple "address - ssid".
std::cout << addr << " - " << ssid << std::endl;
cout << addr << " - " << ssid << endl;
}
catch(std::runtime_error&) {
catch (runtime_error&) {
// No ssid, just ignore it.
}
}
@@ -81,10 +91,11 @@ bool BeaconSniffer::callback(PDU &pdu) {
}
int main(int argc, char* argv[]) {
// By default, sniff wlan0
std::string interface = "wlan0";
if(argc == 2)
interface = argv[1];
if (argc != 2) {
cout << "Usage: " <<* argv << " <interface>" << endl;
return 1;
}
string interface = argv[1];
BeaconSniffer sniffer;
sniffer.run(interface);
}

4116
examples/configure vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +0,0 @@
AC_INIT(myconfig, 0.1)
AC_PROG_CXX()
AC_LANG(C++)
saved_libs="${LIBS}"
LIBS="${LIBS} -ltins"
AC_MSG_CHECKING(libtins)
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <tins/dns.h>],
[Tins::DNS dummy])],
[echo done],
[echo error; echo *** libtins is not installed. Aborting... ***; exit 1])
LIBS="${saved_libs}"
AC_CHECK_HEADERS([tins/tins.h], , [echo "*** Error: libtins' headers are absent ***"; exit 1;])
AC_OUTPUT(Makefile)

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,10 +30,12 @@
#include <tins/tins.h>
#include <iostream>
using std::cout;
using std::endl;
using namespace Tins;
bool callback(const PDU &pdu)
{
bool callback(const PDU& pdu) {
// The packet probably looks like this:
//
// EthernetII / IP / UDP / RawPDU
@@ -43,22 +45,23 @@ bool callback(const PDU &pdu)
DNS dns = pdu.rfind_pdu<RawPDU>().to<DNS>();
// Retrieve the queries and print the domain name:
for(const auto &query : dns.queries())
std::cout << query.dname() << std::endl;
for (const auto& query : dns.queries()) {
cout << query.dname() << std::endl;
}
return true;
}
int main(int argc, char *argv[])
{
int main(int argc, char* argv[]) {
if(argc != 2) {
std::cout << "Usage: " << *argv << " <interface>" << std::endl;
cout << "Usage: " <<* argv << " <interface>" << endl;
return 1;
}
// Sniff on the provided interface in promiscuos mode
Sniffer sniffer(argv[1], Sniffer::PROMISC);
SnifferConfiguration config;
config.set_promisc_mode(true);
// Only capture udp packets sent to port 53
sniffer.set_filter("udp and dst port 53");
config.set_filter("udp and dst port 53");
Sniffer sniffer(argv[1], config);
// Start the capture
sniffer.sniff_loop(callback);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,12 +30,14 @@
#include <tins/tins.h>
#include <iostream>
using std::cout;
using std::endl;
using namespace Tins;
PacketSender sender;
bool callback(const PDU &pdu)
{
bool callback(const PDU& pdu) {
// The packet probably looks like this:
//
// EthernetII / IP / UDP / RawPDU
@@ -48,10 +50,10 @@ bool callback(const PDU &pdu)
DNS dns = udp.rfind_pdu<RawPDU>().to<DNS>();
// Is it a DNS query?
if(dns.type() == DNS::QUERY) {
if (dns.type() == DNS::QUERY) {
// Let's see if there's any query for an "A" record.
for(const auto &query : dns.queries()) {
if(query.type() == DNS::A) {
for (const auto& query : dns.queries()) {
if (query.query_type() == DNS::A) {
// Here's one! Let's add an answer.
dns.add_answer(
DNS::Resource(
@@ -66,16 +68,16 @@ bool callback(const PDU &pdu)
}
}
// Have we added some answers?
if(dns.answers_count() > 0) {
if (dns.answers_count() > 0) {
// It's a response now
dns.type(DNS::RESPONSE);
// Recursion is available(just in case)
dns.recursion_available(1);
// Build our packet
auto pkt = EthernetII(eth.src_addr(), eth.dst_addr()) /
IP(ip.src_addr(), ip.dst_addr()) /
UDP(udp.sport(), udp.dport()) /
dns;
IP(ip.src_addr(), ip.dst_addr()) /
UDP(udp.sport(), udp.dport()) /
dns;
// Send it!
sender.send(pkt);
}
@@ -83,17 +85,17 @@ bool callback(const PDU &pdu)
return true;
}
int main(int argc, char *argv[])
{
int main(int argc, char* argv[]) {
if(argc != 2) {
std::cout << "Usage: " << *argv << " <interface>" << std::endl;
cout << "Usage: " <<* argv << " <interface>" << endl;
return 1;
}
// Sniff on the provided interface in promiscuos mode
Sniffer sniffer(argv[1], Sniffer::PROMISC);
SnifferConfiguration config;
config.set_promisc_mode(true);
// Only capture udp packets sent to port 53
sniffer.set_filter("udp and dst port 53");
config.set_filter("udp and dst port 53");
Sniffer sniffer(argv[1], config);
// All packets will be sent through the provided interface
sender.default_interface(argv[1]);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,6 +27,10 @@
*
*/
#ifdef _WIN32
#define NOMINMAX
#endif // _WIN32
#include <iostream>
#include <mutex>
#include <chrono>
@@ -35,6 +39,25 @@
#include <algorithm>
#include <tins/tins.h>
using std::cout;
using std::endl;
using std::thread;
using std::string;
using std::bind;
using std::map;
using std::mutex;
using std::max;
using std::min;
using std::exception;
using std::lock_guard;
using std::tuple;
using std::make_tuple;
using std::this_thread::sleep_for;
using std::chrono::seconds;
using std::chrono::milliseconds;
using std::chrono::duration_cast;
using std::chrono::system_clock;
using namespace Tins;
// Holds the DNS response time statistics. The response time is
@@ -43,7 +66,7 @@ template<typename Duration>
class statistics {
public:
using duration_type = Duration;
using locker_type = std::lock_guard<std::mutex>;
using locker_type = lock_guard<mutex>;
struct information {
duration_type average, worst;
@@ -51,42 +74,41 @@ public:
};
statistics()
: m_duration(), m_worst(duration_type::min()), m_count()
{
: m_duration(), m_worst(duration_type::min()), m_count() {
}
void add_response_time(const duration_type& duration)
{
void add_response_time(const duration_type& duration) {
locker_type _(m_lock);
m_duration += duration;
m_count++;
m_worst = std::max(m_worst, duration);
m_worst = max(m_worst, duration);
}
information get_information() const
{
information get_information() const {
locker_type _(m_lock);
if(m_count == 0)
if(m_count == 0) {
return { };
else
}
else {
return { m_duration / m_count, m_worst, m_count };
}
};
private:
duration_type m_duration, m_worst;
size_t m_count;
mutable std::mutex m_lock;
mutable mutex m_lock;
};
// Sniffs and tracks DNS queries. When a matching DNS response is found,
// the response time is added to a statistics object.
//
// This class performs *no cleanup* on data associated with queries that
// This class performs* no cleanup* on data associated with queries that
// weren't answered.
class dns_monitor {
public:
// The response times are measured in milliseconds
using duration_type = std::chrono::milliseconds;
using duration_type = milliseconds;
// The statistics type used.
using statistics_type = statistics<duration_type>;
@@ -95,21 +117,20 @@ public:
return m_stats;
}
private:
using packet_info = std::tuple<IPv4Address, IPv4Address, uint16_t>;
using clock_type = std::chrono::steady_clock;
using time_point_type = std::chrono::time_point<clock_type>;
using packet_info = tuple<IPv4Address, IPv4Address, uint16_t>;
using clock_type = system_clock;
using time_point_type = clock_type::time_point;
bool callback(const PDU& pdu);
static packet_info make_packet_info(const PDU& pdu, const DNS& dns);
statistics_type m_stats;
std::map<packet_info, time_point_type> m_packet_info;
map<packet_info, time_point_type> m_packet_info;
};
void dns_monitor::run(BaseSniffer& sniffer)
{
void dns_monitor::run(BaseSniffer& sniffer) {
sniffer.sniff_loop(
std::bind(
bind(
&dns_monitor::callback,
this,
std::placeholders::_1
@@ -117,13 +138,12 @@ void dns_monitor::run(BaseSniffer& sniffer)
);
}
bool dns_monitor::callback(const PDU& pdu)
{
bool dns_monitor::callback(const PDU& pdu) {
auto now = clock_type::now();
auto dns = pdu.rfind_pdu<RawPDU>().to<DNS>();
auto info = make_packet_info(pdu, dns);
// If it's a query, add the sniff time to our map.
if(dns.type() == DNS::QUERY) {
if (dns.type() == DNS::QUERY) {
m_packet_info.insert(
std::make_pair(info, now)
);
@@ -131,11 +151,11 @@ bool dns_monitor::callback(const PDU& pdu)
else {
// It's a response, we need to find the query in our map.
auto iter = m_packet_info.find(info);
if(iter != m_packet_info.end()) {
if (iter != m_packet_info.end()) {
// We found the query, let's add the response time to the
// statistics object.
m_stats.add_response_time(
std::chrono::duration_cast<duration_type>(now - iter->second)
duration_cast<duration_type>(now - iter->second)
);
// Forget about the query.
m_packet_info.erase(iter);
@@ -148,42 +168,48 @@ bool dns_monitor::callback(const PDU& pdu)
// hold the same DNS id as belonging to the same query.
//
// This function retrieves a tuple (addr, addr, id) that will achieve it.
auto dns_monitor::make_packet_info(const PDU& pdu, const DNS& dns) -> packet_info
{
auto dns_monitor::make_packet_info(const PDU& pdu, const DNS& dns) -> packet_info {
const auto& ip = pdu.rfind_pdu<IP>();
return std::make_tuple(
return make_tuple(
// smallest address first
std::min(ip.src_addr(), ip.dst_addr()),
min(ip.src_addr(), ip.dst_addr()),
// largest address second
std::max(ip.src_addr(), ip.dst_addr()),
max(ip.src_addr(), ip.dst_addr()),
dns.id()
);
}
int main(int argc, char *argv[]) {
if(argc != 2) {
std::cout << "Usage: " << *argv << " <interface>\n";
return 1;
int main(int argc, char* argv[]) {
string iface;
if (argc == 2) {
// Use the provided interface
iface = argv[1];
}
else {
// Use the default interface
iface = NetworkInterface::default_interface().name();
}
try {
Sniffer sniffer(argv[1], Sniffer::PROMISC);
sniffer.set_filter("udp and port 53");
SnifferConfiguration config;
config.set_promisc_mode(true);
config.set_filter("udp and port 53");
Sniffer sniffer(iface, config);
dns_monitor monitor;
std::thread thread(
thread thread(
[&]() {
monitor.run(sniffer);
}
);
while(true) {
while (true) {
auto info = monitor.stats().get_information();
std::cout << "\rAverage " << info.average.count()
<< "ms. Worst: " << info.worst.count() << "ms. Count: "
<< info.count;
std::cout.flush();
std::this_thread::sleep_for(std::chrono::seconds(1));
cout << "\rAverage " << info.average.count()
<< "ms. Worst: " << info.worst.count() << "ms. Count: "
<< info.count << " ";
cout.flush();
sleep_for(seconds(1));
}
}
catch(std::exception& ex) {
std::cout << "[-] Error: " << ex.what() << std::endl;
catch (exception& ex) {
cout << "[-] Error: " << ex.what() << endl;
}
}

140
examples/icmp_responses.cpp Normal file
View File

@@ -0,0 +1,140 @@
/*
* Copyright (c) 2015, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <iostream>
#include <stdexcept>
#include <string>
#include <functional>
#include <tins/tins.h>
using std::cout;
using std::endl;
using std::bind;
using std::string;
using std::runtime_error;
using std::exception;
using namespace Tins;
// This class captured packets on an interface, using the specified filter
// and will respond with ICMP error packets whenever a packet is captured.
// The response mechanism is pretty naive as it generates a packet which
// has swapped HW and IP addresses (dst as src, src as dst).
class ICMPResponder {
public:
// Use the given interface and ICMP type/code on responses
ICMPResponder(string iface, int type, int code)
: m_iface(iface), m_sender(iface), m_type(type), m_code(code) {
}
// Run using the given filter
void run(const string& filter) {
// Initialize the configuration
SnifferConfiguration config;
// Use promiscuous mode
config.set_promisc_mode(true);
// Use this packet filter
config.set_filter(filter);
// Use immediate mode (we don't want to buffer packets, we want the mright away).
config.set_immediate_mode(true);
// Now create the Sniffer
Sniffer sniffer(m_iface, config);
if (sniffer.link_type() != DLT_EN10MB) {
throw runtime_error("Ethernet interfaces only supported");
}
// Start the sniffing! For each packet, ICMPReponder::callback will be called
sniffer.sniff_loop(bind(&ICMPResponder::callback, this, std::placeholders::_1));
}
private:
// Extracts the payload to be used over the ICMP layer in the response.
// This will be the entire IP header + 8 bytes of the next header.
RawPDU extract_icmp_payload(IP& pdu) {
PDU::serialization_type buffer = pdu.serialize();
// Use whole IP + 8 bytes of next header.
size_t end_index = pdu.header_size() + 8;
return RawPDU(buffer.begin(), buffer.begin() + end_index);
}
// Generates an ICMP response given a packet.
EthernetII generate_response(PDU& pdu) {
// Find Ethernet and IP headers.
EthernetII& received_eth = pdu.rfind_pdu<EthernetII>();
IP& received_ip = pdu.rfind_pdu<IP>();
// Create an Ethernet response, flipping the addresses
EthernetII output(received_eth.src_addr(), received_eth.dst_addr());
// Append an IP PDU, again flipping addresses.
//output /= IP(received_ip.src_addr(), received_ip.dst_addr());
output /= IP(received_ip.src_addr(), "8.8.8.8");
// Now generate the ICMP layer using the type and code provided.
ICMP icmp;
icmp.type(static_cast<ICMP::Flags>(m_type));
icmp.code(m_code);
// Append the ICMP layer to our packet
output /= icmp;
// Extract the payload to be used over ICMP.
output /= extract_icmp_payload(received_ip);
return output;
}
// Packet capture callback
bool callback(PDU& pdu) {
// Generate a response for this packet
EthernetII response = generate_response(pdu);
// Send this packet!
m_sender.send(response);
return true;
}
string m_iface;
PacketSender m_sender;
int m_type;
int m_code;
};
int main(int argc, char* argv[]) {
const int type = 3;
const int code = 0;
if (argc < 3) {
cout << "Usage: " << argv[0] << " <interface> <pcap_filter>" << endl;
return 1;
}
string iface = argv[1];
string filter = argv[2];
try {
ICMPResponder responder(iface, type, code);
responder.run(filter);
}
catch (exception& ex) {
cout << "Error: " << ex.what() << endl;
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) 2015, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <string>
#include <iostream>
#include <tins/network_interface.h>
using std::cout;
using std::endl;
using std::string;
using namespace Tins;
int main() {
// Get all interfaces and iterate over them.
for (const NetworkInterface& iface : NetworkInterface::all()) {
// Get the name of this interface
string name = iface.name();
// "stringify" the status of the interface
string status = iface.is_up() ? "up" : "down";
// Get this interface's information (addresses).
NetworkInterface::Info info = iface.info();
// Now print all of this info.
cout << name << ": " << endl;
cout << " HW address: " << info.hw_addr << endl
<< " IP address: " << info.ip_addr << endl
<< " Netmask: " << info.netmask << endl
<< " Broadcast: " << info.bcast_addr << endl
<< " Iface index: " << iface.id() << endl
<< " Status: " << "interface " << status << endl << endl;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,6 +30,7 @@
#include <iostream>
#include <iomanip>
#include <vector>
#include <set>
#include <string>
#include <cstdlib>
#include <pthread.h>
@@ -43,48 +44,114 @@
#include <tins/utils.h>
#include <tins/packet_sender.h>
using std::cout;
using std::endl;
using std::vector;
using std::pair;
using std::setw;
using std::string;
using std::set;
using std::runtime_error;
using namespace std;
using namespace Tins;
typedef std::pair<Sniffer*, std::string> sniffer_data;
typedef pair<Sniffer*, string> sniffer_data;
class Scanner {
public:
Scanner(const NetworkInterface& interface,
const IPv4Address& address,
const vector<string>& ports);
void run();
private:
void send_syns(const NetworkInterface& iface, IPv4Address dest_ip);
bool callback(PDU& pdu);
static void* thread_proc(void* param);
void launch_sniffer();
NetworkInterface iface;
IPv4Address host_to_scan;
set<uint16_t> ports_to_scan;
Sniffer sniffer;
};
Scanner::Scanner(const NetworkInterface& interface,
const IPv4Address& address,
const vector<string>& ports)
: iface(interface), host_to_scan(address), sniffer(interface.name()) {
sniffer.set_filter(
"tcp and ip src " + address.to_string() + " and tcp[tcpflags] & (tcp-rst|tcp-syn) != 0"
);
for (size_t i = 0; i < ports.size(); ++i) {
ports_to_scan.insert(atoi(ports[i].c_str()));
}
}
void* Scanner::thread_proc(void* param) {
Scanner* data = (Scanner*)param;
data->launch_sniffer();
return 0;
}
void Scanner::launch_sniffer() {
sniffer.sniff_loop(make_sniffer_handler(this, &Scanner::callback));
}
/* Our scan handler. This will receive SYNs and RSTs and inform us
* the scanned port's status.
*/
bool handler(PDU &pdu) {
const TCP &tcp = pdu.rfind_pdu<TCP>();
// Ok, it's a TCP PDU. Is RST flag on? Then port is closed.
if(tcp.get_flag(TCP::RST)) {
// This indicates we should stop sniffing.
if(tcp.get_flag(TCP::SYN))
return false;
cout << "Port: " << setw(5) << tcp.sport() << " closed\n";
bool Scanner::callback(PDU& pdu) {
// Find the layers we want.
const IP& ip = pdu.rfind_pdu<IP>();
const TCP& tcp = pdu.rfind_pdu<TCP>();
// Check if the host that we're scanning sent this packet and
// the source port is one of those that we scanned.
if(ip.src_addr() == host_to_scan && ports_to_scan.count(tcp.sport()) == 1) {
// Ok, it's a TCP PDU. Is RST flag on? Then port is closed.
if(tcp.get_flag(TCP::RST)) {
// This indicates we should stop sniffing.
if(tcp.get_flag(TCP::SYN))
return false;
cout << "Port: " << setw(5) << tcp.sport() << " closed\n";
}
// Is SYN flag on? Then port is open!
else if(tcp.flags() == (TCP::SYN | TCP::ACK)) {
cout << "Port: " << setw(5) << tcp.sport() << " open\n";
}
}
// Is SYN flag on? Then port is open!
else if(tcp.flags() == (TCP::SYN | TCP::ACK))
cout << "Port: " << setw(5) << tcp.sport() << " open\n";
return true;
}
void Scanner::run() {
pthread_t thread;
// Launch our sniff thread.
pthread_create(&thread, 0, &Scanner::thread_proc, this);
// Start sending SYNs to port.
send_syns(iface, host_to_scan);
// Wait for our sniffer.
void* dummy;
pthread_join(thread, &dummy);
}
// Send syns to the given ip address, using the destination ports provided.
void send_syns(const NetworkInterface &iface, IPv4Address dest_ip, const vector<string> &ips) {
void Scanner::send_syns(const NetworkInterface& iface, IPv4Address dest_ip) {
// Retrieve the addresses.
NetworkInterface::Info info = iface.addresses();
PacketSender sender;
// Allocate the IP PDU
IP ip = IP(dest_ip, info.ip_addr) / TCP();
// Get the reference to the TCP PDU
TCP &tcp = ip.rfind_pdu<TCP>();
TCP& tcp = ip.rfind_pdu<TCP>();
// Set the SYN flag on.
tcp.set_flag(TCP::SYN, 1);
// Just some random port.
tcp.sport(1337);
cout << "Sending SYNs..." << endl;
for(vector<string>::const_iterator it = ips.begin(); it != ips.end(); ++it) {
for (set<uint16_t>::const_iterator it = ports_to_scan.begin(); it != ports_to_scan.end(); ++it) {
// Set the new port and send the packet!
tcp.dport(atoi(it->c_str()));
tcp.dport(*it);
sender.send(ip);
}
// Wait 1 second.
@@ -93,6 +160,7 @@ void send_syns(const NetworkInterface &iface, IPv4Address dest_ip, const vector<
* by our function, which will in turn return false.
*/
tcp.set_flag(TCP::RST, 1);
tcp.sport(*ports_to_scan.begin());
// Pretend we're the scanned host...
ip.src_addr(dest_ip);
// We use an ethernet pdu, otherwise the kernel will drop it.
@@ -100,47 +168,28 @@ void send_syns(const NetworkInterface &iface, IPv4Address dest_ip, const vector<
sender.send(eth, iface);
}
void *thread_proc(void *param) {
// IP address is our parameter.
sniffer_data *data = (sniffer_data*)param;
Sniffer *sniffer = data->first;
sniffer->set_filter("tcp and ip src " + data->second + " and tcp[tcpflags] & (tcp-rst|tcp-syn) != 0");
// Sniff loop. Only sniff TCP PDUs comming from the given IP and have either RST or SYN flag on.
sniffer->sniff_loop(handler);
return 0;
}
void scan(int argc, char *argv[]) {
void scan(int argc, char* argv[]) {
IPv4Address ip(argv[1]);
// Resolve the interface which will be our gateway
NetworkInterface iface(ip);
cout << "Sniffing on interface: " << iface.name() << endl;
// 300 bytes are enough to receive SYNs and RSTs.
Sniffer sniffer(iface.name(), 300);
sniffer_data data(&sniffer, argv[1]);
pthread_t thread;
// Launch our sniff thread.
pthread_create(&thread, 0, thread_proc, &data);
// Consume arguments
argv += 2;
argc -= 2;
// Start sending SYNs to port.
send_syns(iface, ip, vector<string>(argv, argv + (argc)));
// Wait for our sniffer.
void *dummy;
pthread_join(thread, &dummy);
Scanner scanner(iface, ip, vector<string>(argv, argv + (argc)));
scanner.run();
}
int main(int argc, char *argv[]) {
if(argc < 3 && cout << "Usage: " << *argv << " <IPADDR> <port1> [port2] [port3]\n")
int main(int argc, char* argv[]) {
if (argc < 3) {
cout << "Usage: " <<* argv << " <IPADDR> <port1> [port2] [port3]" << endl;
return 1;
}
try {
scan(argc, argv);
}
catch(std::runtime_error &ex) {
catch(runtime_error& ex) {
cout << "Error - " << ex.what() << endl;
}
}

52
examples/route_table.cpp Normal file
View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 2015, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <iostream>
#include <iomanip>
#include <vector>
#include <tins/tins.h>
using std::cout;
using std::endl;
using std::setw;
using std::vector;
using namespace Tins;
int main() {
vector<Utils::RouteEntry> entries = Utils::route_entries();
for (size_t i = 0; i < entries.size(); ++i) {
cout << "Entry " << setw(2) << i << ": " << endl
<< "Interface: " << entries[i].interface << endl
<< "Destination: " << entries[i].destination << endl
<< "Gateway: " << entries[i].gateway << endl
<< "Genmask: " << entries[i].mask << endl
<< "Metric: " << entries[i].metric << endl << endl;
}
}

View File

@@ -0,0 +1,106 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <iostream>
#include <string>
#include <tins/tins.h>
using std::string;
using std::bind;
using std::cout;
using std::endl;
using std::exception;
using namespace Tins;
// This example will capture TCP packets and send packet that will reset
// the connection when it captures a packet with the SYN and ACK flags on.
class tcp_connection_closer {
public:
tcp_connection_closer() {
}
void run(const string& interface) {
using std::placeholders::_1;
// Make the PacketSender use this interface by default
sender_.default_interface(interface);
// Create the sniffer configuration
SnifferConfiguration config;
config.set_filter("tcp");
// We want to get the packets as fast as possible
config.set_immediate_mode(true);
// Create the sniffer and start the capture
Sniffer sniffer(interface, config);
sniffer.sniff_loop(bind(&tcp_connection_closer::callback, this, _1));
}
private:
bool callback(const PDU& pdu) {
const EthernetII& eth = pdu.rfind_pdu<EthernetII>();
const IP& ip = pdu.rfind_pdu<IP>();
const TCP& tcp = pdu.rfind_pdu<TCP>();
// We'll only close a connection when seeing a SYN|ACK
if (tcp.flags() == (TCP::SYN | TCP::ACK)) {
// Create an ethernet header flipping the addresses
EthernetII packet(eth.src_addr(), eth.dst_addr());
// Do the same for IP
packet /= IP(ip.src_addr(), ip.dst_addr());
// Flip TCP ports
TCP response_tcp(tcp.sport(), tcp.dport());
// Set RST|ACK flags
response_tcp.flags(TCP::RST | TCP::ACK);
// Use the right sequence and ack numbers
response_tcp.seq(tcp.ack_seq());
response_tcp.ack_seq(tcp.seq());
// Add this PDU to the packet we'll send
packet /= response_tcp;
// Send it!
sender_.send(packet);
}
return true;
}
PacketSender sender_;
};
int main(int argc, char* argv[]) {
if (argc != 2) {
cout << "Usage: " << *argv << " <interface>" << endl;
return 1;
}
try {
tcp_connection_closer closer;
closer.run(argv[1]);
}
catch (exception& ex) {
cout << "[-] Error: " << ex.what() << endl;
return 1;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,15 +27,41 @@
*
*/
#ifdef _WIN32
#define NOMINMAX
#endif // _WIN32
#include <iostream>
#include <chrono>
#include <thread>
#include <cstdint>
#include <random>
#include <map>
#include <algorithm>
#include <atomic>
#include <limits>
#include <mutex>
#include <tins/tins.h>
using std::cout;
using std::endl;
using std::move;
using std::map;
using std::min;
using std::setw;
using std::atomic;
using std::runtime_error;
using std::string;
using std::to_string;
using std::thread;
using std::this_thread::sleep_for;
using std::lock_guard;
using std::mutex;
using std::random_device;
using std::numeric_limits;
using std::bind;
using std::chrono::milliseconds;
using namespace Tins;
class Traceroute {
@@ -43,18 +69,21 @@ public:
typedef std::map<uint16_t, IPv4Address> result_type;
Traceroute(NetworkInterface interface, IPv4Address address)
: iface(interface), addr(address) { }
: iface(interface), addr(address), lowest_dest_ttl(numeric_limits<int>::max()) {
sequence = random_device()() & 0xffff;
}
result_type trace() {
SnifferConfiguration config;
config.set_promisc_mode(false);
// ICMPs that aren't sent from us.
Sniffer sniffer(
iface.name(), 500, false,
"ip proto \\icmp and not src host " + iface.addresses().ip_addr.to_string()
);
config.set_filter(
"ip proto \\icmp and not src host " + iface.addresses().ip_addr.to_string());
Sniffer sniffer(iface.name(), config);
PacketSender sender;
// Create our handler
auto handler = std::bind(
auto handler = bind(
&Traceroute::sniff_callback,
this,
std::placeholders::_1
@@ -62,90 +91,117 @@ public:
// We're running
running = true;
// Start the sniff thread
std::thread sniff_thread(
&Sniffer::sniff_loop<decltype(handler)>,
&sniffer,
handler,
0
thread sniff_thread(
[&]() {
sniffer.sniff_loop(handler);
}
);
send_packets(sender);
sniff_thread.join();
// If the final hop responded, add its address at the appropriate ttl
if (lowest_dest_ttl != numeric_limits<int>::max()) {
results[lowest_dest_ttl] = addr;
}
// Clear our results and return what we've found
return std::move(results);
return move(results);
}
private:
typedef std::map<uint16_t, size_t> ttl_map;
typedef map<uint16_t, size_t> ttl_map;
void send_packets(PacketSender &sender) {
void send_packets(PacketSender& sender) {
// ICMPs are icmp-requests by default
IP ip = IP(addr, iface.addresses().ip_addr) / ICMP();
// We'll find at most 10 hops.
ICMP& icmp = ip.rfind_pdu<ICMP>();
icmp.sequence(sequence);
// We'll find at most 20 hops.
for(auto i = 1; i <= 10; ++i) {
// Set this "unique" id
ip.id(i);
for (auto i = 1; i <= 20; ++i) {
// Set this ICMP id
icmp.id(i);
// Set the time-to-live option
ip.ttl(i);
// Critical section
{
std::lock_guard<std::mutex> _(lock);
lock_guard<mutex> _(lock);
ttls[i] = i;
}
sender.send(ip);
// Give him a little time
std::this_thread::sleep_for(std::chrono::milliseconds(100));
sleep_for(milliseconds(100));
}
running = false;
sender.send(ip);
}
bool sniff_callback(PDU &pdu) {
const IP &ip = pdu.rfind_pdu<IP>();
ttl_map::const_iterator iter;
// Fetch the IP PDU attached to the ICMP response
const IP inner_ip = pdu.rfind_pdu<RawPDU>().to<IP>();
// Critical section
{
std::lock_guard<std::mutex> _(lock);
iter = ttls.find(inner_ip.id());
}
bool sniff_callback(PDU& pdu) {
// Find IP and ICMP PDUs
const IP& ip = pdu.rfind_pdu<IP>();
const ICMP& icmp = pdu.rfind_pdu<ICMP>();
// Check if this is an ICMP TTL exceeded error response
if (icmp.type() == ICMP::TIME_EXCEEDED) {
// Fetch the IP PDU attached to the ICMP response
const IP inner_ip = pdu.rfind_pdu<RawPDU>().to<IP>();
// Now get the ICMP layer
const ICMP& inner_icmp = inner_ip.rfind_pdu<ICMP>();
// Make sure this is one of our packets.
if (inner_icmp.sequence() == sequence) {
ttl_map::const_iterator iter;
// It's an actual response
if(iter != ttls.end()) {
// Store it
results[inner_ip.id()] = ip.src_addr();
// Critical section
{
std::lock_guard<std::mutex> _(lock);
iter = ttls.find(inner_icmp.id());
}
// It's an actual response
if(iter != ttls.end()) {
// Store it
results[inner_icmp.id()] = ip.src_addr();
}
}
}
// Otherwise, this could be the final hop making an echo response
else if (icmp.type() == ICMP::ECHO_REPLY && icmp.sequence() == sequence &&
ip.src_addr() == addr) {
// Keep the lowest ttl seen for the destination.
lowest_dest_ttl = min(lowest_dest_ttl, static_cast<int>(icmp.id()));
}
return running;
}
NetworkInterface iface;
IPv4Address addr;
std::atomic<bool> running;
atomic<bool> running;
ttl_map ttls;
result_type results;
std::mutex lock;
mutex lock;
uint16_t sequence;
int lowest_dest_ttl;
};
int main(int argc, char* argv[]) {
if(argc <= 1 && std::cout << "Usage: " << *argv << " <IP_ADDRESS>\n")
if (argc <= 1) {
cout << "Usage: " <<* argv << " <ip_address>" << endl;
return 1;
}
try {
IPv4Address addr((std::string(argv[1])));
IPv4Address addr = string(argv[1]);
Traceroute tracer(addr, addr);
auto results = tracer.trace();
if(results.empty())
std::cout << "No hops found" << std::endl;
if (results.empty()) {
cout << "No hops found" << endl;
}
else {
std::cout << "Results: " << std::endl;
for(const auto &entry : results) {
std::cout << entry.first << " - " << entry.second << std::endl;
cout << "Results: " << endl;
for(const auto& entry : results) {
cout << setw(2) << entry.first << " - " << entry.second << endl;
}
}
}
catch(std::runtime_error &ex) {
std::cout << "Error - " << ex.what() << std::endl;
catch (runtime_error& ex) {
cout << "Error - " << ex.what() << endl;
return 2;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -41,11 +41,11 @@ std::set<HWAddress<6>> addrs;
const HWAddress<3> expected_oui("00:50:F2");
bool handler(const PDU& pdu) {
const Dot11Beacon &beacon = pdu.rfind_pdu<Dot11Beacon>();
const Dot11Beacon& beacon = pdu.rfind_pdu<Dot11Beacon>();
// Only process it once
if(addrs.insert(beacon.addr3()).second) {
// Iterate the tagged options
for(const auto &opt : beacon.options()) {
for(const auto& opt : beacon.options()) {
// Is this a vendor-specific tag?
if(opt.option() == Dot11::VENDOR_SPECIFIC) {
// Make sure there's enough size for the OUI + identifier
@@ -63,12 +63,16 @@ bool handler(const PDU& pdu) {
return true;
}
int main(int argc, char *argv[]) {
int main(int argc, char* argv[]) {
if(argc != 2) {
std::cout << "Usage: " << *argv << " <DEVICE>\n";
std::cout << "Usage: " <<* argv << " <DEVICE>\n";
return 1;
}
// Only sniff beacons
Sniffer sniffer(argv[1], 2000, true, "wlan type mgt subtype beacon");
SnifferConfiguration config;
config.set_snap_len(2000);
config.set_promisc_mode(true);
config.set_filter("wlan type mgt subtype beacon");
Sniffer sniffer(argv[1], config);
sniffer.sniff_loop(handler);
}

1
googletest Submodule

Submodule googletest added at 13206d6f53

View File

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

View File

@@ -1,316 +0,0 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_ARP_H
#define TINS_ARP_H
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
#include "hw_address.h"
#include "ip_address.h"
namespace Tins {
class NetworkInterface;
class EthernetII;
/**
* \brief Class that represents an ARP PDU.
*
*/
class ARP : public PDU {
public:
/**
* The type of the hardware address.
*/
typedef HWAddress<6> hwaddress_type;
/**
* The type of the IP address.
*/
typedef IPv4Address ipaddress_type;
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::ARP;
/**
* \brief Enum which indicates the type of ARP packet.
*/
enum Flags {
REQUEST = 0x0001,
REPLY = 0x0002
};
/**
* \brief Constructs an ARP object using the provided addresses.
*
* ARP requests and replies can be constructed easily using
* ARP::make_arp_request/reply static member functions.
*
* \sa ARP::make_arp_request
* \sa ARP::make_arp_reply
*
* \param target_ip The target IP address.
* \param sender_ip The sender IP address.
* \param target_hw The target hardware address.
* \param sender_hw The sender hardware address.
*/
ARP(ipaddress_type target_ip = ipaddress_type(),
ipaddress_type sender_ip = ipaddress_type(),
const hwaddress_type &target_hw = hwaddress_type(),
const hwaddress_type &sender_hw = hwaddress_type());
/**
* \brief Constructs an ARP object from a buffer.
*
* If there is not enough size for an ARP header in the buffer,
* a malformed_packet exception is thrown.
*
* If the buffer is bigger than the size of the ARP header,
* then the extra data is stored in a RawPDU.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
ARP(const uint8_t *buffer, uint32_t total_sz);
/* Getters */
/**
* \brief Getter for the sender's hardware address.
*
* \return The sender hardware address.
*/
hwaddress_type sender_hw_addr() const { return _arp.ar_sha; }
/**
* \brief Getter for the sender's IP address.
*
* \return The sender IP address.
*/
ipaddress_type sender_ip_addr() const { return ipaddress_type(_arp.ar_sip); }
/**
* \brief Getter for the target's hardware address.
*
* \return The target hardware address.
*/
hwaddress_type target_hw_addr() const { return _arp.ar_tha; }
/**
* \brief Getter for the target's IP address.
*
* \return The target IP address.
*/
ipaddress_type target_ip_addr() const { return ipaddress_type(_arp.ar_tip); }
/**
* \brief Getter for the hardware address format field.
*
* \return The hardware address format.
*/
uint16_t hw_addr_format() const { return Endian::be_to_host(_arp.ar_hrd); }
/**
* \brief Getter for the protocol address format field.
*
* \return The protocol address format.
*/
uint16_t prot_addr_format() const { return Endian::be_to_host(_arp.ar_pro); }
/**
* \brief Getter for the hardware address length field.
*
* \return The hardware address length.
*/
uint8_t hw_addr_length() const { return _arp.ar_hln; }
/**
* \brief Getter for the protocol address length field.
*
* \return The protocol address length.
*/
uint8_t prot_addr_length() const { return _arp.ar_pln; }
/**
* \brief Getter for the ARP opcode field.
*
* \return The ARP opcode.
*/
uint16_t opcode() const { return Endian::be_to_host(_arp.ar_op); }
/**
* \brief Getter for the header size.
* \return Returns the ARP header size.
* \sa PDU::header_size
*/
uint32_t header_size() const;
/* Setters */
/**
* \brief Setter for the sender's hardware address.
*
* \param new_snd_hw_addr The new sender hardware address.
*/
void sender_hw_addr(const hwaddress_type &new_snd_hw_addr);
/**
* \brief Setter for the sender's IP address.
*
* \param new_snd_ip_addr The new sender IP address.
*/
void sender_ip_addr(ipaddress_type new_snd_ip_addr);
/**
* \brief Setter for the target's hardware address.
*
* \param new_tgt_hw_addr The new target hardware address.
*/
void target_hw_addr(const hwaddress_type &new_tgt_hw_addr);
/**
* \brief Setter for the target's IP address.
*
* \param new_tgt_ip_addr The new target IP address.
*/
void target_ip_addr(ipaddress_type new_tgt_ip_addr);
/**
* \brief Setter for the hardware address format field.
*
* \param new_hw_addr_fmt The new hardware address format.
*/
void hw_addr_format(uint16_t new_hw_addr_fmt);
/**
* \brief Setter for the protocol address format field.
*
* \param new_prot_addr_fmt The new protocol address format.
*/
void prot_addr_format(uint16_t new_prot_addr_fmt);
/**
* \brief Setter for the hardware address length field.
*
* \param new_hw_addr_len The new hardware address length.
*/
void hw_addr_length(uint8_t new_hw_addr_len);
/**
* \brief Setter for the protocol address length field.
*
* \param new_prot_addr_len The new protocol address length.
*/
void prot_addr_length(uint8_t new_prot_addr_len);
/**
* \brief Setter for the ARP opcode field.
*
* \param new_opcode Flag enum value of the ARP opcode to set.
*/
void opcode(Flags new_opcode);
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \brief Creates an ARP Request within an EthernetII PDU.
*
* Creates an ARP Request PDU and embeds it inside an EthernetII
* PDU.
*
* \param target The target's IP address.
* \param sender The sender's IP address.
* \param hw_snd The sender's hardware address.
* \return EthernetII object containing the ARP Request.
*/
static EthernetII make_arp_request(ipaddress_type target,
ipaddress_type sender, const hwaddress_type &hw_snd = hwaddress_type());
/**
* \brief Creates an ARP Reply within an EthernetII PDU.
*
* Creates an ARP Reply PDU and embeds it inside an EthernetII
* PDU.
*
* \param target The target's IP address.
* \param sender The sender's IP address.
* \param hw_tgt The target's hardware address.
* \param hw_snd The sender's hardware address.
* \return EthetnetII containing the ARP Replay.
*/
static EthernetII make_arp_reply(ipaddress_type target,
ipaddress_type sender, const hwaddress_type &hw_tgt = hwaddress_type(),
const hwaddress_type &hw_snd = hwaddress_type());
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \sa PDU::clone
*/
ARP *clone() const {
return new ARP(*this);
}
private:
TINS_BEGIN_PACK
struct arphdr {
uint16_t ar_hrd; /* format of hardware address */
uint16_t ar_pro; /* format of protocol address */
uint8_t ar_hln; /* length of hardware address */
uint8_t ar_pln; /* length of protocol address */
uint16_t ar_op; /* ARP opcode (command) */
/* sender hardware address */
uint8_t ar_sha[hwaddress_type::address_size];
/* sender IP address */
uint32_t ar_sip;
/* target hardware address */
uint8_t ar_tha[hwaddress_type::address_size];
/* target IP address */
uint32_t ar_tip;
} TINS_END_PACK;
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
arphdr _arp;
};
}
#endif //TINS_ARP_H

View File

@@ -1,362 +0,0 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_BOOTP_H
#define TINS_BOOTP_H
#include <stdint.h>
#include <algorithm>
#include <vector>
#include "pdu.h"
#include "macros.h"
#include "endianness.h"
#include "ip_address.h"
#include "hw_address.h"
namespace Tins {
/**
* \brief Class representing a BootP packet.
*/
class BootP : public PDU {
public:
/**
* The type of the IP addresses.
*/
typedef IPv4Address ipaddress_type;
/**
* The type of the chaddr field.
*/
typedef HWAddress<16> chaddr_type;
/**
* The type of the vend field.
*/
typedef std::vector<uint8_t> vend_type;
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::BOOTP;
/**
* \brief Enum which contains the different opcodes BootP messages.
*/
enum OpCodes {
BOOTREQUEST = 1,
BOOTREPLY = 2
};
/**
* \brief Creates an instance of BootP.
*
* This sets the size of the vend field to 64, as the BootP RFC
* states.
*/
BootP();
/**
* \brief Constructs a BootP object from a buffer .
*
* If there's not enough size for a BootP header, then a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
* \param vend_field_size The vend field size to allocate.
* Subclasses might use 0 to provide their own interpretation of this field.
*/
BootP(const uint8_t *buffer, uint32_t total_sz, uint32_t vend_field_size = 64);
/* Getters */
/**
* \brief Getter for the opcode field.
* \return The opcode field for this BootP PDU.
*/
uint8_t opcode() const { return _bootp.opcode; }
/**
* \brief Getter for the htype field.
* \return The htype field for this BootP PDU.
*/
uint8_t htype() const { return _bootp.htype; }
/**
* \brief Getter for the hlen field.
* \return The hlen field for this BootP PDU.
*/
uint8_t hlen() const { return _bootp.hlen; }
/**
* \brief Getter for the hops field.
* \return The hops field for this BootP PDU.
*/
uint8_t hops() const { return _bootp.hops; }
/**
* \brief Getter for the xid field.
* \return The xid field for this BootP PDU.
*/
uint32_t xid() const { return Endian::be_to_host(_bootp.xid); }
/**
* \brief Getter for the secs field.
* \return The secs field for this BootP PDU.
*/
uint16_t secs() const { return Endian::be_to_host(_bootp.secs); }
/** \brief Getter for the padding field.
* \return The padding field for this BootP PDU.
*/
uint16_t padding() const { return Endian::be_to_host(_bootp.padding); }
/**
* \brief Getter for the ciaddr field.
* \return The ciaddr field for this BootP PDU.
*/
ipaddress_type ciaddr() const { return ipaddress_type(_bootp.ciaddr); }
/**
* \brief Getter for the yiaddr field.
* \return The yiaddr field for this BootP PDU.
*/
ipaddress_type yiaddr() const { return ipaddress_type(_bootp.yiaddr); }
/**
* \brief Getter for the siaddr field.
* \return The siaddr field for this BootP PDU.
*/
ipaddress_type siaddr() const { return ipaddress_type(_bootp.siaddr); }
/**
* \brief Getter for the giaddr field.
* \return The giaddr field for this BootP PDU.
*/
ipaddress_type giaddr() const { return ipaddress_type(_bootp.giaddr); }
/**
* \brief Getter for the chaddr field.
* \return The chddr field for this BootP PDU.
*/
chaddr_type chaddr() const { return _bootp.chaddr; }
/**
* \brief Getter for the sname field.
* \return The sname field for this BootP PDU.
*/
const uint8_t *sname() const { return _bootp.sname; }
/**
* \brief Getter for the file field.
* \return The file field for this BootP PDU.
*/
const uint8_t *file() const { return _bootp.file; }
/**
* \brief Getter for the vend field.
* \return The vend field for this BootP PDU.
*/
const vend_type &vend() const { return _vend; }
/**
* \brief Getter for the header size.
* \return Returns the BOOTP header size.
* \sa PDU::header_size
*/
uint32_t header_size() const;
/* Setters */
/**
* \brief Setter for the opcode field.
* \param new_opcode The opcode to be set.
*/
void opcode(uint8_t new_opcode);
/**
* \brief Setter for the htype field.
* \param new_htype The htype to be set.
*/
void htype(uint8_t new_htype);
/**
* \brief Setter for the hlen field.
* \param new_hlen The hlen to be set.
*/
void hlen(uint8_t new_hlen);
/**
* \brief Setter for the hops field.
* \param new_hops The hops to be set.
*/
void hops(uint8_t new_hops);
/**
* \brief Setter for the xid field.
* \param new_xid The xid to be set.
*/
void xid(uint32_t new_xid);
/**
* \brief Setter for the secs field.
* \param new_secs The secs to be set.
*/
void secs(uint16_t new_secs);
/**
* \brief Setter for the padding field.
* \param new_padding The padding to be set.
*/
void padding(uint16_t new_padding);
/**
* \brief Setter for the ciaddr field.
* \param new_ciaddr The ciaddr to be set.
*/
void ciaddr(ipaddress_type new_ciaddr);
/**
* \brief Setter for the yiaddr field.
* \param new_yiaddr The yiaddr to be set.
*/
void yiaddr(ipaddress_type new_yiaddr);
/**
* \brief Setter for the siaddr field.
* \param new_siaddr The siaddr to be set.
*/
void siaddr(ipaddress_type new_siaddr);
/**
* \brief Setter for the giaddr field.
* \param new_giaddr The giaddr to be set.
*/
void giaddr(ipaddress_type new_giaddr);
/**
* \brief Setter for the chaddr field.
* The new_chaddr pointer must be at least BOOTP::hlen() bytes long.
* \param new_chaddr The chaddr to be set.
*/
template<size_t n>
void chaddr(const HWAddress<n> &new_chaddr) {
// Copy the new addr
uint8_t *end = std::copy(
new_chaddr.begin(),
new_chaddr.begin() + std::min(n, sizeof(_bootp.chaddr)),
_bootp.chaddr
);
// Fill what's left with zeros
if(end < _bootp.chaddr + chaddr_type::address_size)
std::fill(end, _bootp.chaddr + chaddr_type::address_size, 0);
}
/**
* \brief Setter for the sname field.
* \param new_sname The sname to be set.
*/
void sname(const uint8_t *new_sname);
/**
* \brief Setter for the file field.
* \param new_file The file to be set.
*/
void file(const uint8_t *new_file);
/**
* \brief Setter for the vend field.
* \param new_vend The vend to be set.
*/
void vend(const vend_type &new_vend);
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* This returns true if the xid field is equal.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \sa PDU::clone
*/
BootP *clone() const {
return new BootP(*this);
}
protected:
/**
* \brief Getter for the vend field.
*
* This getter can be used by subclasses to avoid copying the
* vend field around.
*
* \return The vend field for this BootP PDU.
*/
vend_type &vend() { return _vend; }
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
private:
/**
* Struct that represents the Bootp datagram.
*/
TINS_BEGIN_PACK
struct bootphdr {
uint8_t opcode;
uint8_t htype;
uint8_t hlen;
uint8_t hops;
uint32_t xid;
uint16_t secs;
uint16_t padding;
uint32_t ciaddr;
uint32_t yiaddr;
uint32_t siaddr;
uint32_t giaddr;
uint8_t chaddr[16];
uint8_t sname[64];
uint8_t file[128];
} TINS_END_PACK;
bootphdr _bootp;
vend_type _vend;
};
}
#endif // TINS_BOOTP_H

View File

@@ -1,159 +0,0 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_CONSTANTS_H
#define TINS_CONSTANTS_H
namespace Tins {
/**
* \brief Constants used in protocols.
*/
namespace Constants {
/** \cond */
struct IP {
/** \endcond */
enum e {
PROTO_IP = 0, /* Dummy protocol for TCP. */
PROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */
PROTO_ICMP = 1, /* Internet Control Message Protocol. */
PROTO_IGMP = 2, /* Internet Group Management Protocol. */
PROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94). */
PROTO_TCP = 6, /* Transmission Control Protocol. */
PROTO_EGP = 8, /* Exterior Gateway Protocol. */
PROTO_PUP = 12, /* PUP protocol. */
PROTO_UDP = 17, /* User Datagram Protocol. */
PROTO_IDP = 22, /* XNS IDP protocol. */
PROTO_TP = 29, /* SO Transport Protocol Class 4. */
PROTO_DCCP = 33, /* Datagram Congestion Control Protocol. */
PROTO_IPV6 = 41, /* IPv6 header. */
PROTO_ROUTING = 43, /* IPv6 routing header. */
PROTO_FRAGMENT = 44, /* IPv6 fragmentation header. */
PROTO_RSVP = 46, /* Reservation Protocol. */
PROTO_GRE = 47, /* General Routing Encapsulation. */
PROTO_ESP = 50, /* encapsulating security payload. */
PROTO_AH = 51, /* authentication header. */
PROTO_ICMPV6 = 58, /* ICMPv6. */
PROTO_NONE = 59, /* IPv6 no next header. */
PROTO_DSTOPTS = 60, /* IPv6 destination options. */
PROTO_MTP = 92, /* Multicast Transport Protocol. */
PROTO_ENCAP = 98, /* Encapsulation Header. */
PROTO_PIM = 103, /* Protocol Independent Multicast. */
PROTO_COMP = 108, /* Compression Header Protocol. */
PROTO_SCTP = 132, /* Stream Control Transmission Protocol. */
PROTO_UDPLITE = 136, /* UDP-Lite protocol. */
PROTO_RAW = 255 /* Raw IP packets. */
};
};
struct Ethernet {
enum e {
UNKNOWN = 0,
//~ PUP = 0x0200, /* Xerox PUP */
SPRITE = 0x0500, /* Sprite */
IP = 0x0800, /* IP */
ARP = 0x0806, /* Address resolution */
REVARP = 0x8035, /* Reverse ARP */
AT = 0x809B, /* AppleTalk protocol */
AARP = 0x80F3, /* AppleTalk ARP */
VLAN = 0x8100, /* IEEE 802.1Q VLAN tagging */
IPX = 0x8137, /* IPX */
IPV6 = 0x86dd, /* IP protocol version 6 */
PPPOED = 0x8863, /* PPPoE Discovery */
EAPOL = 0x888e, /* EAPOL */
LOOPBACK = 0x9000 /* used to test interfaces */
};
};
struct ARP {
enum e {
NETROM = 0, /* From KA9Q: NET/ROM pseudo. */
ETHER = 1, /* Ethernet 10/100Mbps. */
EETHER = 2, /* Experimental Ethernet. */
AX25 = 3, /* AX.25 Level 2. */
PRONET = 4, /* PROnet token ring. */
CHAOS = 5, /* Chaosnet. */
IEEE802 = 6, /* IEEE 802.2 Ethernet/TR/TB. */
ARCNET = 7, /* ARCnet. */
APPLETLK = 8, /* APPLEtalk. */
DLCI = 15, /* Frame Relay DLCI. */
ATM = 19, /* ATM. */
METRICOM = 23, /* Metricom STRIP (new IANA id). */
IEEE1394 = 24, /* IEEE 1394 IPv4 - RFC 2734. */
EUI64 = 27, /* EUI-64. */
INFINIBAND = 32, /* InfiniBand. */
SLIP = 256,
CSLIP = 257,
SLIP6 = 258,
CSLIP6 = 259,
RSRVD = 260, /* Notional KISS type. */
ADAPT = 264,
ROSE = 270,
X25 = 271, /* CCITT X.25. */
HWX25 = 272, /* Boards with X.25 in firmware. */
PPP = 512,
CISCO = 513, /* Cisco HDLC. */
HDLC = CISCO,
LAPB = 516, /* LAPB. */
DDCMP = 517, /* Digital's DDCMP. */
RAWHDLC = 518, /* Raw HDLC. */
TUNNEL = 768, /* IPIP tunnel. */
TUNNEL6 = 769, /* IPIP6 tunnel. */
FRAD = 770, /* Frame Relay Access Device. */
SKIP = 771, /* SKIP vif. */
LOOPBACK = 772, /* Loopback device. */
LOCALTLK = 773, /* Localtalk device. */
FDDI = 774, /* Fiber Distributed Data Interface. */
BIF = 775, /* AP1000 BIF. */
SIT = 776, /* sit0 device - IPv6-in-IPv4. */
IPDDP = 777, /* IP-in-DDP tunnel. */
IPGRE = 778, /* GRE over IP. */
PIMREG = 779, /* PIMSM register interface. */
HIPPI = 780, /* High Performance Parallel I'face. */
ASH = 781, /* (Nexus Electronics) Ash. */
ECONET = 782, /* Acorn Econet. */
IRDA = 783, /* Linux-IrDA. */
FCPP = 784, /* Point to point fibrechanel. */
FCAL = 785, /* Fibrechanel arbitrated loop. */
FCPL = 786, /* Fibrechanel public loop. */
FCFABRIC = 787, /* Fibrechanel fabric. */
IEEE802_TR = 800, /* Magic type ident for TR. */
IEEE80211 = 801, /* IEEE 802.11. */
IEEE80211_PRISM = 802, /* IEEE 802.11 + Prism2 header. */
IEEE80211_RADIOTAP = 803, /* IEEE 802.11 + radiotap header. */
IEEE802154 = 804, /* IEEE 802.15.4 header. */
IEEE802154_PHY = 805, /* IEEE 802.15.4 PHY header. */
VOID_TYPE = 0xFFFF, /* Void type, nothing is known. */
NONE = 0xFFFE /* Zero header length. */
};
};
}
}
#endif // TINS_CONSTANTS_H

View File

@@ -1,415 +0,0 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "config.h"
#if !defined(TINS_CRYPTO_H) && defined(HAVE_DOT11)
#define TINS_CRYPTO_H
#include <map>
#include <string>
#include <algorithm>
#include <vector>
#include "utils.h"
#include "snap.h"
#include "rawpdu.h"
#include "handshake_capturer.h"
namespace Tins {
class PDU;
class Dot11;
class Dot11Data;
namespace Crypto {
/**
* \cond
*/
struct RC4Key;
#ifdef HAVE_WPA2_DECRYPTION
namespace WPA2 {
class invalid_handshake : public std::exception {
public:
const char *what() const throw() {
return "invalid handshake";
}
};
class SessionKeys {
public:
typedef Internals::byte_array<80> ptk_type;
typedef Internals::byte_array<32> pmk_type;
SessionKeys();
SessionKeys(const RSNHandshake &hs, const pmk_type &pmk);
SNAP *decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const;
private:
SNAP *ccmp_decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const;
SNAP *tkip_decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const;
RC4Key generate_rc4_key(const Dot11Data &dot11, const RawPDU &raw) const;
ptk_type ptk;
bool is_ccmp;
};
class SupplicantData {
public:
typedef HWAddress<6> address_type;
typedef SessionKeys::pmk_type pmk_type;
SupplicantData(const std::string &psk, const std::string &ssid);
const pmk_type &pmk() const;
private:
pmk_type pmk_;
};
}
#endif // HAVE_WPA2_DECRYPTION
/**
* \endcond
*/
/**
* \brief RC4 Key abstraction.
*/
struct RC4Key {
static const size_t data_size = 256;
/**
* \brief Initializes the key using the provided iterator range.
*
* \param start The start of the range.
* \param end The end of the range.
*/
template<typename ForwardIterator>
RC4Key(ForwardIterator start, ForwardIterator end);
/**
* The actual key data.
*/
uint8_t data[data_size];
};
/**
* \brief Decrypts WEP-encrypted traffic.
*/
class WEPDecrypter {
public:
typedef HWAddress<6> address_type;
/**
* \brief Constructs a WEPDecrypter object.
*/
WEPDecrypter();
/**
* \brief Adds a decryption password.
*
* \param addr The access point's BSSID.
* \param password The password which will be used to decrypt
* packets sent from and to the AP identifier by the BSSID addr.
*/
void add_password(const address_type &addr, const std::string &password);
/**
* \brief Removes a decryption password
*
* \param addr The BSSID of the access point.
*/
void remove_password(const address_type &addr);
/**
* \brief Decrypts the provided PDU.
*
* A Dot11Data PDU is looked up inside the provided PDU chain.
* If no such PDU exists or there is no password associated
* with the Dot11 packet's BSSID, then the PDU is left intact.
*
* Otherwise, the packet is decrypted using the given password.
* If the CRC found after decrypting is invalid, false is
* returned.
*
* \return false if no decryption was performed or decryption
* failed, true otherwise.
*/
bool decrypt(PDU &pdu);
private:
typedef std::map<address_type, std::string> passwords_type;
PDU *decrypt(RawPDU &raw, const std::string &password);
passwords_type passwords;
std::vector<uint8_t> key_buffer;
};
#ifdef HAVE_WPA2_DECRYPTION
/**
* \brief Decrypts WPA2-encrypted traffic.
*
* This class takes valid PSK and SSID tuples, captures client handshakes,
* and decrypts their traffic afterwards.
*/
class WPA2Decrypter {
public:
/*
* \brief The type used to store Dot11 addresses.
*/
typedef HWAddress<6> address_type;
/**
* \brief Adds an access points's information.
*
* This associates an SSID with a PSK, and allows the decryption of
* any BSSIDs that broadcast the same SSID.
*
* The decrypter will inspect beacon frames, looking for SSID tags
* that contain the given SSID.
*
* Note that using this overload, the decryption of data frames and
* handshake capturing will be disabled until any access point
* broadcasts the provided SSID(this shouldn't take long at all).
* If this is not the desired behaviour, then you should check out
* the ovther add_ap_data overload.
*
* \param psk The PSK associated with the SSID.
* \param ssid The network's SSID.
*/
void add_ap_data(const std::string &psk, const std::string &ssid);
/**
* \brief Adds a access points's information, including its BSSID.
*
* This overload can be used if the BSSID associated with this SSID is
* known beforehand. The addr parameter indicates which specific BSSID
* is associated to the SSID.
*
* Note that if any other access point broadcasts the provided SSID,
* it will be taken into account as well.
*
* \param psk The PSK associated with this SSID.
* \param ssid The network's SSID.
* \param addr The access point's BSSID.
*/
void add_ap_data(const std::string &psk, const std::string &ssid, const address_type &addr);
/**
* \brief Decrypts the provided PDU.
*
* A Dot11Data PDU is looked up inside the provided PDU chain.
* If no such PDU exists or no PSK was associated with the SSID
* broadcasted by the Dot11 packet's BSSID, or no EAPOL handshake
* was captured for the client involved in the communication,
* then the PDU is left intact.
*
* Otherwise, the packet is decrypted using the generated PTK.
* If the resulting MIC is invalid, then the packet is left intact.
*
* \return false if no decryption was performed, or the decryption
* failed, true otherwise.
*/
bool decrypt(PDU &pdu);
private:
typedef std::map<std::string, WPA2::SupplicantData> pmks_map;
typedef std::map<address_type, WPA2::SupplicantData> bssids_map;
typedef std::pair<address_type, address_type> addr_pair;
typedef std::map<addr_pair, WPA2::SessionKeys> keys_map;
void try_add_keys(const Dot11Data &dot11, const RSNHandshake &hs);
addr_pair make_addr_pair(const address_type &addr1, const address_type &addr2) {
return (addr1 < addr2) ?
std::make_pair(addr1, addr2) :
std::make_pair(addr2, addr1);
}
addr_pair extract_addr_pair(const Dot11Data &dot11);
addr_pair extract_addr_pair_dst(const Dot11Data &dot11);
bssids_map::const_iterator find_ap(const Dot11Data &dot11);
void add_access_point(const std::string &ssid, const address_type &addr);
RSNHandshakeCapturer capturer;
pmks_map pmks;
bssids_map aps;
keys_map keys;
};
#endif // HAVE_WPA2_DECRYPTION
/**
* \brief Pluggable decrypter object which can be used to decrypt
* data on sniffing sessions.
*
* This class holds a decrypter object and a functor, and implements
* a suitable operator() to be used on BaseSniffer::sniff_loop, which
* decrypts packets and forwards them to the given functor.
*/
template<typename Functor, typename Decrypter>
class DecrypterProxy {
public:
/**
* The type of the functor object.
*/
typedef Functor functor_type;
/**
* The type of the decrypter object.
*/
typedef Decrypter decrypter_type;
/**
* \brief Constructs an object from a functor and a decrypter.
* \param func The functor to be used to forward decrypted
* packets.
* \param decrypter The decrypter which will be used to decrypt
* packets
*/
DecrypterProxy(const functor_type &func,
const decrypter_type &decr = decrypter_type());
/**
* \brief Retrieves a reference to the decrypter object.
*/
decrypter_type &decrypter();
/**
* \brief Retrieves a const reference to the decrypter object.
*/
const decrypter_type &decrypter() const;
/**
* \brief The operator() which decrypts packets and forwards
* them to the functor.
*/
bool operator() (PDU &pdu);
private:
Functor functor_;
decrypter_type decrypter_;
};
/**
* \brief Performs RC4 encription/decryption of the given byte range,
* using the provided key.
*
* The decrypted range will be copied to the OutputIterator provided.
*
* \param start The beginning of the range.
* \param start The end of the range.
* \param key The key to be used.
* \param output The iterator in which to write the output.
*/
template<typename ForwardIterator, typename OutputIterator>
void rc4(ForwardIterator start, ForwardIterator end, RC4Key &key, OutputIterator output);
/**
* \brief Wrapper function to create a DecrypterProxy using a
* WEPDecrypter as the Decrypter template parameter.
*
* \param functor The functor to be forwarded to the DecrypterProxy
* constructor.
*/
template<typename Functor>
DecrypterProxy<Functor, WEPDecrypter> make_wep_decrypter_proxy(const Functor &functor);
#ifdef HAVE_WPA2_DECRYPTION
/**
* \brief Wrapper function to create a DecrypterProxy using a
* WPA2Decrypter as the Decrypter template parameter.
*
* \param functor The functor to be forwarded to the DecrypterProxy
* constructor.
*/
template<typename Functor>
DecrypterProxy<Functor, WPA2Decrypter> make_wpa2_decrypter_proxy(const Functor &functor) {
return DecrypterProxy<Functor, WPA2Decrypter>(functor);
}
#endif // HAVE_WPA2_DECRYPTION
// Implementation section
// DecrypterProxy
template<typename Functor, typename Decrypter>
DecrypterProxy<Functor, Decrypter>::DecrypterProxy(
const functor_type &func, const decrypter_type& decr)
: functor_(func), decrypter_(decr)
{
}
template<typename Functor, typename Decrypter>
typename DecrypterProxy<Functor, Decrypter>::decrypter_type &
DecrypterProxy<Functor, Decrypter>::decrypter()
{
return decrypter_;
}
template<typename Functor, typename Decrypter>
const typename DecrypterProxy<Functor, Decrypter>::decrypter_type &
DecrypterProxy<Functor, Decrypter>::decrypter() const
{
return decrypter_;
}
template<typename Functor, typename Decrypter>
bool DecrypterProxy<Functor, Decrypter>::operator() (PDU &pdu)
{
return decrypter_.decrypt(pdu) ? functor_(pdu) : true;
}
template<typename Functor>
DecrypterProxy<Functor, WEPDecrypter> make_wep_decrypter_proxy(const Functor &functor)
{
return DecrypterProxy<Functor, WEPDecrypter>(functor);
}
// RC4 stuff
template<typename ForwardIterator>
RC4Key::RC4Key(ForwardIterator start, ForwardIterator end) {
for(size_t i = 0; i < data_size; ++i)
data[i] = i;
size_t j = 0;
ForwardIterator iter = start;
for(size_t i = 0; i < data_size; ++i) {
j = (j + data[i] + *iter++) % 256;
if(iter == end)
iter = start;
std::swap(data[i], data[j]);
}
}
template<typename ForwardIterator, typename OutputIterator>
void rc4(ForwardIterator start, ForwardIterator end, RC4Key &key, OutputIterator output) {
size_t i = 0, j = 0;
while(start != end) {
i = (i + 1) % RC4Key::data_size;
j = (j + key.data[i]) % RC4Key::data_size;
std::swap(key.data[i], key.data[j]);
*output++ = *start++ ^ key.data[(key.data[i] + key.data[j]) % RC4Key::data_size];
}
}
}
}
#endif // TINS_CRYPTO_H

View File

@@ -1,492 +0,0 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_DHCP_H
#define TINS_DHCP_H
#include <list>
#include <vector>
#include <string>
#include "bootp.h"
#include "pdu_option.h"
#include "cxxstd.h"
namespace Tins {
/**
* \brief Class that represents the DHCP PDU.
*
* When adding options, the "End" option is not added automatically.
*
* \sa DHCP::end
*/
class DHCP : public BootP {
public:
/**
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::DHCP;
/**
* DHCP flags.
*/
enum Flags {
DISCOVER = 1,
OFFER = 2,
REQUEST = 3,
DECLINE = 4,
ACK = 5,
NAK = 6,
RELEASE = 7,
INFORM = 8
};
/**
* \brief DHCP options enum.
*/
enum OptionTypes {
PAD,
SUBNET_MASK,
TIME_OFFSET,
ROUTERS,
TIME_SERVERS,
NAME_SERVERS,
DOMAIN_NAME_SERVERS,
LOG_SERVERS,
COOKIE_SERVERS,
LPR_SERVERS,
IMPRESS_SERVERS,
RESOURCE_LOCATION_SERVERS,
HOST_NAME,
BOOT_SIZE,
MERIT_DUMP,
DOMAIN_NAME,
SWAP_SERVER,
ROOT_PATH,
EXTENSIONS_PATH,
IP_FORWARDING,
NON_LOCAL_SOURCE_ROUTING,
POLICY_FILTER,
MAX_DGRAM_REASSEMBLY,
DEFAULT_IP_TTL,
PATH_MTU_AGING_TIMEOUT,
PATH_MTU_PLATEAU_TABLE,
INTERFACE_MTU,
ALL_SUBNETS_LOCAL,
BROADCAST_ADDRESS,
PERFORM_MASK_DISCOVERY,
MASK_SUPPLIER,
ROUTER_DISCOVERY,
ROUTER_SOLICITATION_ADDRESS,
STATIC_ROUTES,
TRAILER_ENCAPSULATION,
ARP_CACHE_TIMEOUT,
IEEE802_3_ENCAPSULATION,
DEFAULT_TCP_TTL,
TCP_KEEPALIVE_INTERVAL,
TCP_KEEPALIVE_GARBAGE,
NIS_DOMAIN,
NIS_SERVERS,
NTP_SERVERS,
VENDOR_ENCAPSULATED_OPTIONS,
NETBIOS_NAME_SERVERS,
NETBIOS_DD_SERVER,
NETBIOS_NODE_TYPE,
NETBIOS_SCOPE,
FONT_SERVERS,
X_DISPLAY_MANAGER,
DHCP_REQUESTED_ADDRESS,
DHCP_LEASE_TIME,
DHCP_OPTION_OVERLOAD,
DHCP_MESSAGE_TYPE,
DHCP_SERVER_IDENTIFIER,
DHCP_PARAMETER_REQUEST_LIST,
DHCP_MESSAGE,
DHCP_MAX_MESSAGE_SIZE,
DHCP_RENEWAL_TIME,
DHCP_REBINDING_TIME,
VENDOR_CLASS_IDENTIFIER,
DHCP_CLIENT_IDENTIFIER,
NWIP_DOMAIN_NAME,
NWIP_SUBOPTIONS,
USER_CLASS = 77,
FQDN = 81,
DHCP_AGENT_OPTIONS = 82,
SUBNET_SELECTION = 118,
AUTHENTICATE = 210,
END = 255
};
/**
* The DHCP option type.
*/
typedef PDUOption<uint8_t, DHCP> option;
/**
* The type used to store the DHCP options.
*/
typedef std::list<option> options_type;
/**
* \brief Creates an instance of DHCP.
*
* This sets the hwtype and hlen fields to match the ethernet
* type and length.
*/
DHCP();
/**
* \brief Constructs a DHCP object from a buffer.
*
* If there is not enough size for a BootP header, or any of
* the TLV options contains an invalid size field, then a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
DHCP(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Adds a new option to this DHCP PDU.
* \param opt The option to be added.
*/
void add_option(const option &opt);
#if TINS_IS_CXX11
/**
* \brief Adds a new option to this DHCP PDU.
*
* The option is move-constructed.
*
* \param opt The option to be added.
*/
void add_option(option &&opt) {
internal_add_option(opt);
_options.push_back(std::move(opt));
}
#endif
/**
* \brief Searchs for an option that matchs the given flag.
* \param opt_flag The flag to be searched.
* \return A pointer to the option, or 0 if it was not found.
*/
const option *search_option(OptionTypes opt) const;
/**
* \brief Adds a type option to the option list.
*
* The new option is appended at the end of the list.
*
* \param type The type of this DHCP PDU.
*/
void type(Flags type);
/**
* \brief Adds an end option to the option list.
*
* The new option is appended at the end of the list.
*
* The END option is not added automatically. You should explicitly
* add it at the end of the DHCP options for the PDU to be
* standard-compliant.
*/
void end();
/**
* \brief Adds a server identifier option.
*
* The new option is appended at the end of the list.
*
* \param ip The server's IP address.
*/
void server_identifier(ipaddress_type ip);
/**
* \brief Adds an IP address lease time option.
*
* The new option is appended at the end of the list.
*
* \param time The lease time.
*/
void lease_time(uint32_t time);
/**
* \brief Adds a lease renewal time option.
*
* The new option is appended at the end of the list.
*
* \param time The lease renew time.
*/
void renewal_time(uint32_t time);
/**
* \brief Adds a rebind time option.
*
* The new option is appended at the end of the list.
*
* \param time The lease rebind time.
*/
void rebind_time(uint32_t time);
/**
* \brief Adds a subnet mask option.
*
* The new option is appended at the end of the list.
*
* \param mask The subnet mask.
*/
void subnet_mask(ipaddress_type mask);
/**
* \brief Adds a routers option.
*
* The new option is appended at the end of the list.
*
* \param routers A list of ip addresses.
*/
void routers(const std::vector<ipaddress_type> &routers);
/**
* \brief Adds a domain name servers option.
*
* The new option is appended at the end of the list.
*
* \param dns A list of ip addresses.
*/
void domain_name_servers(const std::vector<ipaddress_type> &dns);
/**
* \brief Adds a broadcast address option.
*
* The new option is appended at the end of the list.
*
* \param addr The broadcast address.
*/
void broadcast(ipaddress_type addr);
/**
* \brief Adds a requested address option.
*
* The new option is appended at the end of the list.
*
* \param addr The requested address.
*/
void requested_ip(ipaddress_type addr);
/**
* \brief Adds a domain name option.
*
* The new option is appended at the end of the list.
*
* \param name The domain name.
*/
void domain_name(const std::string &name);
/**
* \brief Adds a hostname option.
*
* The new option is appended at the end of the list.
*
* \param name The hostname.
*/
void hostname(const std::string &name);
// Option getters
/**
* \brief Searchs for a type option.
*
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return uint8_t containing the type option.
*/
uint8_t type() const;
/**
* \brief Searchs for a server identifier option.
*
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return ipaddress_type Containing the server identifier.
*/
ipaddress_type server_identifier() const;
/**
* \brief Searchs for a lease time option.
*
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return uint32_t Containing the lease time.
*/
uint32_t lease_time() const;
/**
* \brief Searchs for a lease renewal time option.
*
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return uint32_t Containing the renewal time.
*/
uint32_t renewal_time() const;
/**
* \brief Searchs for a rebind time option.
*
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return uint32_t Containing the rebind time.
*/
uint32_t rebind_time() const;
/**
* \brief Searchs for a subnet mask option.
*
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return ipaddress_type Containing the subnet mask.
*/
ipaddress_type subnet_mask() const;
/**
* \brief Searchs for a routers option.
*
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return std::vector<ipaddress_type> Containing the routers
* option data.
*/
std::vector<ipaddress_type> routers() const;
/**
* \brief Searchs for a dns option.
*
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return std::list<ipaddress_type> Contanining the DNS servers
* provided.
*/
std::vector<ipaddress_type> domain_name_servers() const;
/**
* \brief Searchs for a broadcast option.
*
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return ipaddress_type Containing the broadcast address.
*/
ipaddress_type broadcast() const;
/**
* \brief Searchs for a requested option.
*
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return ipaddress_type Containing the requested IP address.
*/
ipaddress_type requested_ip() const;
/**
* \brief Searchs for a domain name option.
*
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return std::string Containing the domain name.
*/
std::string domain_name() const;
/**
* \brief Searchs for a hostname option.
*
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return std::string Containing the hostname.
*/
std::string hostname() const;
/**
* \brief Getter for the options list.
* \return The option list.
*/
const options_type options() const { return _options; }
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \brief Getter for the header size.
* \return Returns the BOOTP header size.
* \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \sa PDU::clone
*/
DHCP *clone() const {
return new DHCP(*this);
}
private:
static const uint32_t MAX_DHCP_SIZE;
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
template<class T>
T search_and_convert(OptionTypes opt) const {
const option *option = search_option(opt);
if(!option)
throw option_not_found();
return option->to<T>();
}
void internal_add_option(const option &opt);
serialization_type serialize_list(const std::vector<ipaddress_type> &ip_list);
options_type _options;
uint32_t _size;
};
}
#endif // TINS_DHCP_H

View File

@@ -1,672 +0,0 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_DNS_H
#define TINS_DNS_H
#include <stdint.h>
#include <list>
#include <vector>
#include <cstring>
#include <string>
#include <map>
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
namespace Tins {
class IPv4Address;
class IPv6Address;
/**
* \class DNS
* \brief Represents a DNS PDU.
*/
class DNS : public PDU {
public:
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::DNS;
/**
* The DNS type.
*/
enum QRType {
QUERY = 0,
RESPONSE = 1
};
/**
* \brief Query types enum.
*/
enum QueryType {
A = 1,
NS,
MD,
MF,
CNAME,
SOA,
MB,
MG,
MR,
NULL_R,
WKS,
PTR,
HINFO,
MINFO,
MX,
TXT,
RP,
AFSDB,
X25,
ISDN,
RT,
NSAP,
NSAP_PTR,
SIG,
KEY,
PX,
GPOS,
AAAA,
LOC,
NXT,
EID,
NIMLOC,
SRV,
ATMA,
NAPTR,
KX,
CERT,
A6,
DNAM,
SINK,
OPT,
APL,
DS,
SSHFP,
IPSECKEY,
RRSIG,
NSEC,
DNSKEY,
DHCID,
NSEC3,
NSEC3PARAM
};
enum QueryClass {
IN = 1,
CH = 3,
HS = 4,
ANY = 255
};
/**
* \brief Struct that represent DNS queries.
*/
class Query {
public:
/**
* \brief Constructs a DNS query.
*
* \param nm The name of the domain being resolved.
* \param tp The query type.
* \param cl The query class.
*/
Query(const std::string &nm, QueryType tp, QueryClass cl)
: name_(nm), type_(tp), qclass_(cl) {}
/**
* \brief Default constructs this Query.
*/
Query() : type_(), qclass_() {}
/**
* \brief Setter for the name field.
*
* \param nm The name to be set.
*/
void dname(const std::string &nm) {
name_ = nm;
}
/**
* \brief Setter for the query type field.
*
* \param tp The query type to be set.
*/
void type(QueryType tp) {
type_ = tp;
}
/**
* \brief Setter for the query class field.
*
* \param cl The query class to be set.
*/
void query_class(QueryClass cl) {
qclass_ = cl;
}
/**
* \brief Getter for the name field.
*/
const std::string &dname() const { return name_; }
/**
* \brief Getter for the query type field.
*/
QueryType type() const { return type_; }
/**
* \brief Getter for the query class field.
*/
QueryClass query_class() const { return qclass_; }
private:
std::string name_;
QueryType type_;
QueryClass qclass_;
};
/**
* \brief Struct that represent DNS resource records.
*/
class Resource {
public:
/**
* Constructs a Resource object.
*
* \param dname The domain name for which this records
* provides an answer.
* \param data The resource's payload.
* \param type The type of this record.
* \param rclass The class of this record.
* \param ttl The time-to-live of this record.
*/
Resource(const std::string &dname, const std::string &data,
uint16_t type, uint16_t rclass, uint32_t ttl)
: dname_(dname), data_(data), type_(type), qclass_(rclass), ttl_(ttl) {}
Resource() : type_(), qclass_(), ttl_() {}
/**
* \brief Getter for the domain name field.
*
* This returns the domain name for which this record
* provides an answer.
*/
const std::string &dname() const { return dname_; }
/**
* Getter for the data field.
*/
const std::string &data() const { return data_; }
/**
* Getter for the query type field.
*/
uint16_t type() const { return type_; }
/**
* Getter for the query class field.
*/
uint16_t query_class() const { return qclass_; }
/**
* Getter for the type field.
*/
uint32_t ttl() const { return ttl_; }
/**
* Setter for the domain name field.
*/
void dname(const std::string &data) {
dname_ = data;
}
/**
* \brief Setter for the data field.
*
* The data will be encoded properly by the DNS class before
* being added to this packet. That means that if the type is
* A or AAAA, it will be properly encoded as an IPv4 or
* IPv6 address.
*
* The same happens for records that contain domain names,
* such as NS or CNAME. This data will be encoded using
* DNS domain name encoding.
*/
void data(const std::string &data) {
data_ = data;
}
/**
* Setter for the type field.
*/
void type(uint16_t data) {
type_ = data;
}
/**
* Setter for the class field.
*/
void query_class(uint16_t data) {
qclass_ = data;
}
/**
* Setter for the time-to-live field.
*/
void ttl(uint16_t data) {
ttl_ = data;
}
private:
std::string dname_, data_;
uint16_t type_, qclass_;
uint32_t ttl_;
};
typedef std::list<Query> queries_type;
typedef std::list<Resource> resources_type;
typedef IPv4Address address_type;
typedef IPv6Address address_v6_type;
/**
* \brief Default constructor.
*
* This constructor initializes every field to 0.
*/
DNS();
/**
* \brief Constructs a DNS object from a buffer.
*
* If there's not enough size for the DNS header, or any of the
* records are malformed, a malformed_packet is be thrown.
*
* \param buffer The buffer from which this PDU will be
* constructed.
* \param total_sz The total size of the buffer.
*/
DNS(const uint8_t *buffer, uint32_t total_sz);
// Getters
/**
* \brief Setter for the id field.
*
* \return uint16_t containing the value of the id field.
*/
uint16_t id() const { return Endian::be_to_host(dns.id); }
/**
* \brief Setter for the query response field.
*
* \return QRType containing the value of the query response
* field.
*/
QRType type() const { return static_cast<QRType>(dns.qr); }
/**
* \brief Setter for the opcode field.
*
* \return uint8_t containing the value of the opcode field.
*/
uint8_t opcode() const { return dns.opcode; }
/**
* \brief Setter for the authoritative answer field.
*
* \return uint8_t containing the value of the authoritative
* answer field.
*/
uint8_t authoritative_answer() const { return dns.aa; }
/**
* \brief Setter for the truncated field.
*
* \return uint8_t containing the value of the truncated field.
*/
uint8_t truncated() const { return dns.tc; }
/**
* \brief Setter for the recursion desired field.
*
* \return uint8_t containing the value of the recursion
* desired field.
*/
uint8_t recursion_desired() const { return dns.rd; }
/**
* \brief Setter for the recursion available field.
*
* \return uint8_t containing the value of the recursion
* available field.
*/
uint8_t recursion_available() const { return dns.ra; }
/**
* \brief Setter for the z desired field.
*
* \return uint8_t containing the value of the z field.
*/
uint8_t z() const { return dns.z; }
/**
* \brief Setter for the authenticated data field.
*
* \return uint8_t containing the value of the authenticated
* data field.
*/
uint8_t authenticated_data() const { return dns.ad; }
/**
* \brief Setter for the checking disabled field.
*
* \return uint8_t containing the value of the checking
* disabled field.
*/
uint8_t checking_disabled() const { return dns.cd; }
/**
* \brief Setter for the rcode field.
*
* \return uint8_t containing the value of the rcode field.
*/
uint8_t rcode() const { return dns.rcode; }
/**
* \brief Setter for the questions field.
*
* \return uint16_t containing the value of the questions field.
*/
uint16_t questions_count() const { return Endian::be_to_host(dns.questions); }
/**
* \brief Setter for the answers field.
*
* \return uint16_t containing the value of the answers field.
*/
uint16_t answers_count() const { return Endian::be_to_host(dns.answers); }
/**
* \brief Setter for the authority field.
*
* \return uint16_t containing the value of the authority field.
*/
uint16_t authority_count() const { return Endian::be_to_host(dns.authority); }
/**
* \brief Setter for the additional field.
*
* \return uint16_t containing the value of the additional field.
*/
uint16_t additional_count() const { return Endian::be_to_host(dns.additional); }
/**
* \brief Getter for the PDU's type.
*
* \return Returns the PDUType corresponding to the PDU.
*/
PDUType pdu_type() const { return PDU::DNS; }
/**
* \brief The header's size
*/
uint32_t header_size() const;
// Setters
/**
* \brief Setter for the id field.
*
* \param new_id The new id to be set.
*/
void id(uint16_t new_id);
/**
* \brief Setter for the query response field.
*
* \param new_qr The new qr to be set.
*/
void type(QRType new_qr);
/**
* \brief Setter for the opcode field.
*
* \param new_opcode The new opcode to be set.
*/
void opcode(uint8_t new_opcode);
/**
* \brief Setter for the authoritative answer field.
*
* \param new_aa The new authoritative answer field value to
* be set.
*/
void authoritative_answer(uint8_t new_aa);
/**
* \brief Setter for the truncated field.
*
* \param new_tc The new truncated field value to
* be set.
*/
void truncated(uint8_t new_tc);
/**
* \brief Setter for the recursion desired field.
*
* \param new_rd The new recursion desired value to
* be set.
*/
void recursion_desired(uint8_t new_rd);
/**
* \brief Setter for the recursion available field.
*
* \param new_ra The new recursion available value to
* be set.
*/
void recursion_available(uint8_t new_ra);
/**
* \brief Setter for the z(reserved) field.
*
* \param new_z The new z value to be set.
*/
void z(uint8_t new_z);
/**
* \brief Setter for the authenticated data field.
*
* \param new_ad The new authenticated data value to
* be set.
*/
void authenticated_data(uint8_t new_ad);
/**
* \brief Setter for the checking disabled field.
*
* \param new_z The new checking disabled value to be set.
*/
void checking_disabled(uint8_t new_cd);
/**
* \brief Setter for the rcode field.
*
* \param new_rcode The new rcode value to be set.
*/
void rcode(uint8_t new_rcode);
// Methods
/**
* \brief Add a query to perform.
*
* \param query The query to be added.
*/
void add_query(const Query &query);
/**
* \brief Add an answer resource record.
*
* \param resource The resource to be added.
*/
void add_answer(const Resource &resource);
/**
* \brief Add an authority resource record.
*
* \param resource The resource to be added.
*/
void add_authority(const Resource &resource);
/**
* \brief Add an additional resource record.
*
* \param resource The resource to be added.
*/
void add_additional(const Resource &resource);
/**
* \brief Getter for this PDU's DNS queries.
*
* \return The query records in this PDU.
*/
queries_type queries() const;
/**
* \brief Getter for this PDU's DNS answers
*
* \return The answer records in this PDU.
*/
resources_type answers() const;
/**
* \brief Getter for this PDU's DNS authority records.
*
* \return The authority records in this PDU.
*/
resources_type authority() const;
/**
* \brief Getter for this PDU's DNS additional records.
*
* \return The additional records in this PDU.
*/
resources_type additional() const;
/**
* \brief Encodes a domain name.
*
* This processes the input domain name and returns the encoded
* version. Each label in the original domain name will be
* prefixed with a byte that indicates the label's length.
* The null-terminator byte <b>will</b> be included in the encoded
* string. No compression is performed.
*
* For example, given the input "www.example.com", the output would
* be "\x03www\x07example\x03com\x00".
*
* \param domain_name The domain name to encode.
* \return The encoded domain name.
*/
static std::string encode_domain_name(const std::string &domain_name);
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \sa PDU::clone
*/
DNS *clone() const {
return new DNS(*this);
}
private:
TINS_BEGIN_PACK
struct dnshdr {
uint16_t id;
#if TINS_IS_LITTLE_ENDIAN
uint16_t
rd:1,
tc:1,
aa:1,
opcode:4,
qr:1,
rcode:4,
cd:1,
ad:1,
z:1,
ra:1;
#elif TINS_IS_BIG_ENDIAN
uint16_t
qr:1,
opcode:4,
aa:1,
tc:1,
rd:1,
ra:1,
z:1,
ad:1,
cd:1,
rcode:4;
#endif
uint16_t questions, answers,
authority, additional;
} TINS_END_PACK;
typedef std::list<Query> QueriesType;
typedef std::vector<std::pair<uint32_t*, uint32_t> > sections_type;
const uint8_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;
const uint8_t* find_section_end(const uint8_t *ptr, const uint32_t num_records) const;
const uint8_t* find_dname_end(const uint8_t *ptr) const;
void update_records(uint32_t &section_start, uint32_t num_records, uint32_t threshold, uint32_t offset);
uint8_t *update_dname(uint8_t *ptr, uint32_t threshold, uint32_t offset);
static void inline_convert_v4(uint32_t value, char *output);
static bool contains_dname(uint16_t type);
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
void add_record(const Resource &resource, const sections_type &sections);
dnshdr dns;
byte_array records_data;
uint32_t answers_idx, authority_idx, additional_idx;
};
}
#endif // TINS_DNS_H

View File

@@ -1,166 +0,0 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "../config.h"
#if !defined(TINS_DOT11_DOT11_BEACON_H) && defined(HAVE_DOT11)
#define TINS_DOT11_DOT11_BEACON_H
#include "../dot11/dot11_mgmt.h"
namespace Tins {
/**
* \brief Class representing an 802.11 Beacon.
*
*/
class Dot11Beacon : public Dot11ManagementFrame {
public:
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::DOT11_BEACON;
/**
* \brief Constructor for creating a 802.11 Beacon.
*
* Constructs a 802.11 Beacon taking destination and source
* hardware address.
*
* \param dst_hw_addr The destination hardware address.
* \param src_hw_addr The source hardware address.
*/
Dot11Beacon(const address_type &dst_hw_addr = address_type(),
const address_type &src_hw_addr = address_type());
/**
* \brief Constructs a Dot11Beacon object from a buffer and adds
* all identifiable PDUs found in the buffer as children of this
* one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for the header in the buffer
* or the input data is malformed, a malformed_packet exception
* is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11Beacon(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Getter for the timestamp field.
*
* \return The stored timestamp value.
*/
uint64_t timestamp() const { return Endian::le_to_host(_body.timestamp); }
/**
* \brief Getter for the interval field.
*
* \return The stored interval value.
*/
uint16_t interval() const { return Endian::le_to_host(_body.interval); }
/**
* \brief Getter for the Capabilities Information structure.
*
* \return A constant refereence to the stored Capabilities
* Information field.
*/
const capability_information& capabilities() const { return _body.capability; }
/**
* \brief Getter for the Capabilities Information.
*
* \return A refereence to the stored Capabilities Information
* field.
*/
capability_information& capabilities() { return _body.capability; }
/**
* \brief Setter for the timestamp field.
*
* \param new_timestamp The timestamp to be set.
*/
void timestamp(uint64_t new_timestamp);
/**
* \brief Setter for the interval field.
*
* \param new_interval The interval to be set.
*/
void interval(uint16_t new_interval);
/**
* \brief Returns the frame's header length.
*
* \return An uint32_t with the header's size.
* \sa PDU::header_size()
*/
uint32_t header_size() const;
/**
* \brief Check wether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
}
/**
* \brief Clones this PDU.
*
* \sa PDU::clone
*/
Dot11Beacon *clone() const {
return new Dot11Beacon(*this);
}
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
private:
TINS_BEGIN_PACK
struct BeaconBody {
uint64_t timestamp;
uint16_t interval;
capability_information capability;
} TINS_END_PACK;
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
BeaconBody _body;
};
} // namespace Tins
#endif // TINS_DOT11_DOT11_BEACON_H

View File

@@ -1,193 +0,0 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_DOT3_H
#define TINS_DOT3_H
#include <stdint.h>
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
#include "hw_address.h"
namespace Tins {
/**
* \brief Class representing an Ethernet II PDU.
*/
class Dot3 : public PDU {
public:
/**
* \brief The address type.
*/
typedef HWAddress<6> address_type;
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::IEEE802_3;
/**
* \brief Represents the Dot3 broadcast address.
*/
static const address_type BROADCAST;
/**
* \brief Constructor for creating an Dot3 PDU
*
* Constructor that builds an Dot3 PDU taking the interface name,
* destination's and source's MAC.
*
* \param dst_hw_addr The destination hardware address.
* \param src_hw_addr The source hardware address.
* \param child The PDU which will be set as the inner PDU.
*/
Dot3(const address_type &dst_hw_addr = address_type(),
const address_type &src_hw_addr = address_type());
/**
* \brief Constructs a Dot3 object from a buffer and adds a
* LLC object with the remaining data as the inner PDU.
*
* If there is not enough size for a Dot3 header, a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot3(const uint8_t *buffer, uint32_t total_sz);
/* Getters */
/**
* \brief Getter for the destination hardware address.
*
* \return The destination hardware address.
*/
address_type dst_addr() const { return _eth.dst_mac; }
/**
* \brief Getter for the source hardware address.
*
* \return The source hardware address.
*/
address_type src_addr() const { return _eth.src_mac; }
/**
* \brief Getter for the length field.
* \return The length field value.
*/
uint16_t length() const { return Endian::be_to_host(_eth.length); };
/* Setters */
/**
* \brief Setter for the destination hardware address.
*
* \param new_dst_mac The new destination hardware address.
*/
void dst_addr(const address_type &new_dst_mac);
/**
* \brief Setter for the source hardware address.
*
* \param new_src_mac The new source hardware address.
*/
void src_addr(const address_type &new_src_mac);
/**
* \brief Setter for the length field.
*
* \param new_length uint16_t with the new value of the length field.
*/
void length(uint16_t new_length);
/* Virtual methods */
/**
* \brief Returns the Dot3 frame's header length.
*
* \return An uint32_t with the header's size.
* \sa PDU::header_size()
*/
uint32_t header_size() const;
#ifndef WIN32
/**
* \sa PDU::send()
*/
void send(PacketSender &sender, const NetworkInterface &iface);
#endif // WIN32
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
#ifndef WIN32
/**
* \sa PDU::recv_response
*/
PDU *recv_response(PacketSender &sender, const NetworkInterface &iface);
#endif // WIN32
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \sa PDU::clone
*/
Dot3 *clone() const {
return new Dot3(*this);
}
private:
/**
* Struct that represents the Ethernet II header
*/
TINS_BEGIN_PACK
struct ethhdr {
uint8_t dst_mac[address_type::address_size];
uint8_t src_mac[address_type::address_size];
uint16_t length;
} TINS_END_PACK;
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
ethhdr _eth;
};
}
#endif // TINS_DOT3_H

View File

@@ -1,741 +0,0 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_EAPOL_H
#define TINS_EAPOL_H
#include <stdint.h>
#include "pdu.h"
#include "macros.h"
#include "small_uint.h"
#include "endianness.h"
namespace Tins {
/** \cond
* Forward declaration. Avoid header inclusion.
*/
class RSNInformation;
/** \endcond */
/**
* \brief Class that represents the EAP encapsulation over LAN.
*/
class EAPOL : public PDU {
public:
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::EAPOL;
/**
* The EAPOL type enum.
*/
enum EAPOLTYPE {
RC4 = 1,
RSN,
EAPOL_WPA = 254
};
/**
* \brief Static method to instantiate the correct EAPOL subclass
* based on a raw buffer.
*
* If no valid EAPOL type is detected, a null pointer is returned.
*
* \sa RC4EAPOL
* \sa RSNEAPOL
*
* \param buffer The buffer from which the data will be taken.
* \param total_sz The total size of the buffer.
*/
static EAPOL *from_bytes(const uint8_t *buffer, uint32_t total_sz);
/* Getters */
/**
* \brief Getter for the version field.
* \return The version field.
*/
uint8_t version() const { return _header.version; }
/**
* \brief Getter for the packet type field.
* \return The packet type field.
*/
uint8_t packet_type() const { return _header.packet_type; }
/**
* \brief Getter for the length field.
* \return The length field.
*/
uint16_t length() const { return Endian::be_to_host(_header.length); }
/**
* \brief Getter for the type field.
* \return The type field.
*/
uint8_t type() const { return _header.type; }
/* Setters */
/**
* \brief Sets the version field.
* \param new_version The new version to be set.
*/
void version(uint8_t new_version);
/**
* \brief Sets the packet type field.
* \param new_ptype The new packet type to be set.
*/
void packet_type(uint8_t new_ptype);
/**
* \brief Sets the length field.
* \param new_length The new length to be set.
*/
void length(uint16_t new_length);
/**
* \brief Sets the type field.
* \param new_type The new type to be set.
*/
void type(uint8_t new_type);
/**
* \brief Getter for the PDU's type.
* \return Returns the PDUType corresponding to the PDU.
*/
PDUType pdu_type() const { return PDU::EAPOL; }
protected:
/**
* \brief Protected constructor that sets the packet_type and type fields.
*/
EAPOL(uint8_t packet_type, EAPOLTYPE type);
/**
* \brief Constructor which creates an EAPOL object from a buffer.
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
EAPOL(const uint8_t *buffer, uint32_t total_sz);
TINS_BEGIN_PACK
struct eapolhdr {
uint8_t version, packet_type;
uint16_t length;
uint8_t type;
} TINS_END_PACK;
/**
* \brief Virtual method which should serialize the subclass specific
* body and save it in a byte array.
*
* \param buffer The pointer in which to save the serialization.
* \param total_sz The total size of the buffer.
*/
virtual void write_body(uint8_t *buffer, uint32_t total_sz) = 0;
private:
/**
* \brief Serialices this EAPOL PDU.
* \param buffer The buffer in which the PDU will be serialized.
* \param total_sz The size available in the buffer.
* \param parent The PDU that's one level below this one on the stack.
*/
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
eapolhdr _header;
};
/**
* \brief Class that represents the RC4 EAPOL PDU.
*/
class RC4EAPOL : public EAPOL {
public:
/**
* The type used to store the key.
*/
typedef std::vector<uint8_t> key_type;
/**
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::RC4EAPOL;
/**
* The length of the key IV field
*/
static const size_t key_iv_size = 16;
/**
* The length of the key sign field
*/
static const size_t key_sign_size = 16;
/**
* \brief Default constructor.
*/
RC4EAPOL();
/**
* \brief Constructs a RC4EAPOL object from a buffer.
*
* If there is not enough size for a RC4EAPOL header in the
* buffer, a malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
RC4EAPOL(const uint8_t *buffer, uint32_t total_sz);
/* Getters */
/**
* \brief Getter for the key length field.
* \return The key length field.
*/
uint16_t key_length() const { return Endian::be_to_host(_header.key_length); }
/**
* \brief Getter for the replay counter field.
* \return The replay counter field.
*/
uint64_t replay_counter() const { return Endian::be_to_host(_header.replay_counter); }
/**
* \brief Getter for the key IV field.
* \return The key IV field.
*/
const uint8_t *key_iv() const { return _header.key_iv; }
/**
* \brief Getter for the key flag field.
* \return The key flag field.
*/
small_uint<1> key_flag() const { return _header.key_flag; }
/**
* \brief Getter for the key index field.
* \return The key index field.
*/
small_uint<7> key_index() const { return _header.key_index; }
/**
* \brief Getter for the key signature field.
* \return The key signature field.
*/
const uint8_t *key_sign() const { return _header.key_sign; }
/**
* \brief Getter for the key field.
* \return The key field.
*/
const key_type &key() const { return _key; }
/* Setters */
/**
* \brief Sets the key length field.
* \param new_key_length The new key length to be set.
*/
void key_length(uint16_t new_key_length);
/**
* \brief Sets the replay counter field.
* \param new_replay_counter The new replay counter to be set.
*/
void replay_counter(uint64_t new_replay_counter);
/**
* \brief Sets the key IV field.
* \param new_key_iv The new key IV to be set.
*/
void key_iv(const uint8_t *new_key_iv);
/**
* \brief Sets the key flag field.
* \param new_key_flag The new key flag to be set.
*/
void key_flag(small_uint<1> new_key_flag);
/**
* \brief Sets the key index field.
* \param new_key_index The new key index to be set.
*/
void key_index(small_uint<7> new_key_index);
/**
* \brief Sets the key signature field.
* \param new_key_sign The new key signature to be set.
*/
void key_sign(const uint8_t *new_key_sign);
/**
* \brief Sets the key field.
* \param new_key The new key to be set.
*/
void key(const key_type &new_key);
/* Virtual method override. */
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. This size includes the
* payload and options size.
*
* \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \brief Getter for the PDU's type.
* \return Returns the PDUType corresponding to the PDU.
*/
PDUType pdu_type() const { return PDU::RC4EAPOL; }
/**
* \brief Check wether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) const {
return flag == PDU::RC4EAPOL || EAPOL::matches_flag(flag);
}
/**
* \brief Clones this PDU.
*
* \sa PDU::clone
*/
RC4EAPOL *clone() const {
return new RC4EAPOL(*this);
}
private:
TINS_BEGIN_PACK
struct rc4hdr {
uint16_t key_length;
uint64_t replay_counter;
uint8_t key_iv[key_iv_size];
uint8_t key_index:7,
key_flag:1;
uint8_t key_sign[16];
} TINS_END_PACK;
void write_body(uint8_t *buffer, uint32_t total_sz);
key_type _key;
rc4hdr _header;
};
/**
* \brief Class that represents the RSN EAPOL PDU.
*/
class RSNEAPOL : public EAPOL {
public:
/**
* The type used to store the key.
*/
typedef std::vector<uint8_t> key_type;
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::RSNEAPOL;
/**
* The length of the key IV field
*/
static const size_t key_iv_size = 16;
/**
* The length of the nonce field
*/
static const size_t nonce_size = 32;
/**
* The length of the mic field
*/
static const size_t mic_size = 16;
/**
* The length of the rsc field
*/
static const size_t rsc_size = 8;
/**
* The length of the id field
*/
static const size_t id_size = 8;
/**
* \brief Creates an instance of RSNEAPOL.
*/
RSNEAPOL();
/**
* \brief Constructs a RSNEAPOL object from a buffer.
*
* If there is not enough size for the RSNEAPOL header, a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
RSNEAPOL(const uint8_t *buffer, uint32_t total_sz);
/* Getters */
/**
* \brief Getter for the key length field.
* \return The key length field.
*/
uint16_t key_length() const { return Endian::be_to_host(_header.key_length); }
/**
* \brief Getter for the replay counter field.
* \return The replay counter field.
*/
uint64_t replay_counter() const { return Endian::be_to_host(_header.replay_counter); }
/**
* \brief Getter for the key IV field.
* \return The key IV field.
*/
const uint8_t *key_iv() const { return _header.key_iv; }
/**
* \brief Getter for the nonce field.
* \return The nonce field.
*/
const uint8_t *nonce() const { return _header.nonce; }
/**
* \brief Getter for the rsc field.
* \return The rsc field.
*/
const uint8_t *rsc() const { return _header.rsc; }
/**
* \brief Getter for the id field.
* \return The id field.
*/
const uint8_t *id() const { return _header.id; }
/**
* \brief Getter for the mic field.
* \return The mic field.
*/
const uint8_t *mic() const { return _header.mic; }
/**
* \brief Getter for the wpa length field.
* \return The wpa length field.
*/
uint16_t wpa_length() const { return Endian::be_to_host(_header.wpa_length); }
/**
* \brief Getter for the key field.
* \return The key field.
*/
const key_type &key() const { return _key; }
/**
* \brief Getter for the key mic field.
* \return 1 if this EAPOL PDU contains a valid MIC, 0 otherwise.
*/
small_uint<1> key_mic() const { return _header.key_mic; };
/**
* \brief Getter for the secure field.
* \return The secure field.
*/
small_uint<1> secure() const { return _header.secure; };
/**
* \brief Getter for the error field.
* \return The error field.
*/
small_uint<1> error() const { return _header.error; };
/**
* \brief Getter for the request field.
* \return The request field.
*/
small_uint<1> request() const { return _header.request; };
/**
* \brief Getter for the encrypted field.
* \return The encrypted field.
*/
small_uint<1> encrypted() const { return _header.encrypted; };
/**
* \brief Getter for the key descriptor field.
* \return The key descriptor field.
*/
small_uint<3> key_descriptor() const { return _header.key_descriptor; };
/**
* \brief Getter for the key type field.
*
* \return 1 if this is a pairwise key, 0 otherwise.
*/
small_uint<1> key_t() const { return _header.key_t; };
/**
* \brief Getter for the key_index field.
* \return The key_index field.
*/
small_uint<2> key_index() const { return _header.key_index; };
/**
* \brief Getter for the install field.
* \return The install field.
*/
small_uint<1> install() const { return _header.install; };
/**
* \brief Getter for the key_ack field.
* \return The key_ack field.
*/
small_uint<1> key_ack() const { return _header.key_ack; };
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. This size includes the
* payload and options size.
*
* \sa PDU::header_size
*/
uint32_t header_size() const;
/* Setters */
/**
* \brief Sets the key length field.
* \param new_key_length The new key length to be set.
*/
void key_length(uint16_t new_key_length);
/**
* \brief Sets the replay counter field.
* \param new_replay_counter The new replay counter to be set.
*/
void replay_counter(uint64_t new_replay_counter);
/**
* \brief Sets the key IV field.
* \param new_key_iv The new key IV to be set.
*/
void key_iv(const uint8_t *new_key_iv);
/**
* \brief Sets the nonce field.
*
* This method sets the nonce field. This field is 32 bytes long,
* therefore the input buffer should be at least that length.
* \param new_nonce The new nonce to be set.
*/
void nonce(const uint8_t *new_nonce);
/**
* \brief Sets the rsc field.
* \param new_rsc The new rsc to be set.
*/
void rsc(const uint8_t *new_rsc);
/**
* \brief Sets the id field.
* \param new_id The new id to be set.
*/
void id(const uint8_t *new_id);
/**
* \brief Sets the mic field.
*
* This method sets the mic field. This field is 16 bytes long,
* therefore the input buffer should be at least that length.
* \param new_mic The new mic to be set.
*/
void mic(const uint8_t *new_mic);
/**
* \brief Sets the wpa length field.
* \param new_wpa_length The new wpa length to be set.
*/
void wpa_length(uint16_t new_wpa_length);
/**
* \brief Sets the key field.
* \param new_key The new key to be set.
*/
void key(const key_type &new_key);
/**
* \brief Setter for the key_mic field.
* \param new_key_mic The new to be set.
*/
void key_mic(small_uint<1> new_key_mic);
/**
* \brief Setter for the secure field.
* \param new_secure The new to be set.
*/
void secure(small_uint<1> new_secure);
/**
* \brief Setter for the error field.
* \param new_error The new to be set.
*/
void error(small_uint<1> new_error);
/**
* \brief Setter for the request field.
* \param new_request The new to be set.
*/
void request(small_uint<1> new_request);
/**
* \brief Setter for the encrypted field.
* \param new_encrypted The new to be set.
*/
void encrypted(small_uint<1 > new_encrypted);
/**
* \brief Setter for the key_descriptor field.
* \param new_key_descriptor The new to be set.
*/
void key_descriptor(small_uint<3> new_key_descriptor);
/**
* \brief Setter for the key_t field.
* \param new_key_t The new to be set.
*/
void key_t(small_uint<1> new_key_t);
/**
* \brief Setter for the key_index field.
* \param new_key_index The new to be set.
*/
void key_index(small_uint<2> new_key_index);
/**
* \brief Setter for the install field.
* \param new_install The new to be set.
*/
void install(small_uint<1> new_install);
/**
* \brief Setter for the key_ack field.
* \param new_key_ack The new to be set.
*/
void key_ack(small_uint<1> new_key_ack);
/**
* \brief Getter for the PDU's type.
* \return Returns the PDUType corresponding to the PDU.
*/
PDUType pdu_type() const { return PDU::RSNEAPOL; }
/**
* \brief Check wether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) const {
return flag == PDU::RSNEAPOL || EAPOL::matches_flag(flag);
}
/**
* \brief Clones this PDU.
*
* \sa PDU::clone
*/
RSNEAPOL *clone() const {
return new RSNEAPOL(*this);
}
private:
TINS_BEGIN_PACK
struct rsnhdr {
#if TINS_IS_LITTLE_ENDIAN
uint16_t key_mic:1,
secure:1,
error:1,
request:1,
encrypted:1,
reserved:3,
key_descriptor:3,
key_t:1,
key_index:2,
install:1,
key_ack:1;
uint16_t key_length;
uint64_t replay_counter;
uint8_t nonce[nonce_size], key_iv[key_iv_size];
uint8_t rsc[rsc_size], id[id_size];
uint8_t mic[mic_size];
uint16_t wpa_length;
#else
uint16_t reserved:3,
encrypted:1,
request:1,
error:1,
secure:1,
key_mic:1,
key_ack:1,
install:1,
key_index:2,
key_t:1,
key_descriptor:3;
uint16_t key_length;
uint64_t replay_counter;
uint8_t nonce[nonce_size], key_iv[key_iv_size];
uint8_t rsc[rsc_size], id[id_size];
uint8_t mic[mic_size];
uint16_t wpa_length;
#endif
} TINS_END_PACK;
void write_body(uint8_t *buffer, uint32_t total_sz);
rsnhdr _header;
key_type _key;
};
}
#endif // TINS_EAPOL_H

View File

@@ -1,237 +0,0 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_ENDIANNESS_H
#define TINS_ENDIANNESS_H
#include <stdint.h>
#include "macros.h"
#if defined(__APPLE__)
#include <sys/types.h>
#define TINS_IS_LITTLE_ENDIAN (BYTE_ORDER == LITTLE_ENDIAN)
#define TINS_IS_BIG_ENDIAN (BYTE_ORDER == BIG_ENDIAN)
#elif defined(BSD)
#include <sys/endian.h>
#define TINS_IS_LITTLE_ENDIAN (_BYTE_ORDER == _LITTLE_ENDIAN)
#define TINS_IS_BIG_ENDIAN (_BYTE_ORDER == _BIG_ENDIAN)
#elif defined(WIN32)
// Assume windows == little endian. fixme later
#define TINS_IS_LITTLE_ENDIAN 1
#define TINS_IS_BIG_ENDIAN 0
#else
#include <endian.h>
#define TINS_IS_LITTLE_ENDIAN (__BYTE_ORDER == __LITTLE_ENDIAN)
#define TINS_IS_BIG_ENDIAN (__BYTE_ORDER == __BIG_ENDIAN)
#endif
namespace Tins {
namespace Endian {
/**
* \brief "Changes" a 8-bit integral value's endianess. This is an
* identity function.
*
* \param data The data to convert.
*/
inline uint8_t do_change_endian(uint8_t data) {
return data;
}
/**
* \brief Changes a 16-bit integral value's endianess.
*
* \param data The data to convert.
*/
inline uint16_t do_change_endian(uint16_t data) {
return ((data & 0xff00) >> 8) | ((data & 0x00ff) << 8);
}
/**
* \brief Changes a 32-bit integral value's endianess.
*
* \param data The data to convert.
*/
inline uint32_t do_change_endian(uint32_t data) {
return (((data & 0xff000000) >> 24) | ((data & 0x00ff0000) >> 8) |
((data & 0x0000ff00) << 8) | ((data & 0x000000ff) << 24));
}
/**
* \brief Changes a 64-bit integral value's endianess.
*
* \param data The data to convert.
*/
inline uint64_t do_change_endian(uint64_t data) {
return (((uint64_t)(do_change_endian((uint32_t)(data & 0xffffffff))) << 32) |
(do_change_endian(((uint32_t)(data >> 32)))));
}
/**
* \cond
*/
// Helpers to convert
template<typename T>
struct conversion_dispatch_helper {
static T dispatch(T data) {
return do_change_endian(data);
}
};
template<size_t>
struct conversion_dispatcher;
template<>
struct conversion_dispatcher<sizeof(uint8_t)>
: public conversion_dispatch_helper<uint8_t>
{ };
template<>
struct conversion_dispatcher<sizeof(uint16_t)>
: public conversion_dispatch_helper<uint16_t>
{ };
template<>
struct conversion_dispatcher<sizeof(uint32_t)>
: public conversion_dispatch_helper<uint32_t>
{ };
template<>
struct conversion_dispatcher<sizeof(uint64_t)>
: public conversion_dispatch_helper<uint64_t>
{ };
/**
* \endcond
*/
/**
* \brief Changes an integral value's endianess.
*
* This dispatchs to the corresponding function.
*
* \param data The data to convert.
*/
template<typename T>
inline T change_endian(T data) {
return conversion_dispatcher<sizeof(T)>::dispatch(data);
}
#if TINS_IS_LITTLE_ENDIAN
/**
* \brief Convert any integral type to big endian.
*
* \param data The data to convert.
*/
template<typename T>
inline T host_to_be(T data) {
return change_endian(data);
}
/**
* \brief Convert any integral type to little endian.
*
* On little endian platforms, the parameter is simply returned.
*
* \param data The data to convert.
*/
template<typename T>
inline T host_to_le(T data) {
return data;
}
/**
* \brief Convert any big endian value to the host's endianess.
*
* \param data The data to convert.
*/
template<typename T>
inline T be_to_host(T data) {
return change_endian(data);
}
/**
* \brief Convert any little endian value to the host's endianess.
*
* \param data The data to convert.
*/
template<typename T>
inline T le_to_host(T data) {
return data;
}
#elif TINS_IS_BIG_ENDIAN
/**
* \brief Convert any integral type to big endian.
*
* \param data The data to convert.
*/
template<typename T>
inline T host_to_be(T data) {
return data;
}
/**
* \brief Convert any integral type to little endian.
*
* On little endian platforms, the parameter is simply returned.
*
* \param data The data to convert.
*/
template<typename T>
inline T host_to_le(T data) {
return change_endian(data);
}
/**
* \brief Convert any big endian value to the host's endianess.
*
* \param data The data to convert.
*/
template<typename T>
inline T be_to_host(T data) {
return data;
}
/**
* \brief Convert any little endian value to the host's endianess.
*
* \param data The data to convert.
*/
template<typename T>
inline T le_to_host(T data) {
return change_endian(data);
}
#endif
}
}
#endif // TINS_ENDIANNESS_H

View File

@@ -1,204 +0,0 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_ETHERNET_II_H
#define TINS_ETHERNET_II_H
#include <stdint.h>
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
#include "hw_address.h"
namespace Tins {
/**
* \brief Class representing an Ethernet II PDU.
*/
class EthernetII : public PDU {
public:
/**
* \brief The hardware address type.
*/
typedef HWAddress<6> address_type;
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::ETHERNET_II;
/**
* \brief Represents the ethernetII broadcast address.
*/
static const address_type BROADCAST;
/**
* \brief Constructs an ethernet II PDU.
*
* \param dst_hw_addr address_type containing the destination's MAC.
* \param src_hw_addr address_type containing the source's MAC.
*/
EthernetII(const address_type &dst_hw_addr = address_type(),
const address_type &src_hw_addr = address_type());
/**
* \brief Constructs a EthernetII object from a buffer and adds
* all identifiable PDUs found in the buffer as children of
* this one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for a EthernetII header in the
* buffer, a malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
EthernetII(const uint8_t *buffer, uint32_t total_sz);
/* Getters */
/**
* \brief Getter for the destination's hardware address.
*
* \return address_type containing the destination hardware
* address.
*/
address_type dst_addr() const { return _eth.dst_mac; }
/**
* \brief Getter for the source's hardware address.
*
* \return address_type containing the source hardware address.
*/
address_type src_addr() const { return _eth.src_mac; }
/**
* \brief Getter for the payload_type
* \return The payload type.
*/
uint16_t payload_type() const { return Endian::be_to_host(_eth.payload_type); };
/* Setters */
/**
* \brief Setter for the destination hardware address.
*
* \param new_dst_addr the destination hardware address to be set.
*/
void dst_addr(const address_type &new_dst_addr);
/**
* \brief Setter for the source hardware address.
*
* \param new_src_addr the source hardware address to be set.
*/
void src_addr(const address_type &new_src_addr);
/**
* \brief Setter for the payload type.
*
* \param new_payload_type the new value of the payload type field.
*/
void payload_type(uint16_t new_payload_type);
/* Virtual methods */
/**
* \brief Returns the ethernet frame's header length.
*
* \return An uint32_t with the header's size.
* \sa PDU::header_size()
*/
uint32_t header_size() const;
/**
* \brief Returns the ethernet II frame's padding.
*
* \return An uint32_t with the padding size.
* \sa PDU::trailer_size()
*/
uint32_t trailer_size() const;
// Windows does not support sending L2 PDUs.
#ifndef WIN32
/**
* \sa PDU::send()
*/
void send(PacketSender &sender, const NetworkInterface &iface);
#endif // WIN32
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
#ifndef WIN32
/**
* \brief Receives a matching response for this packet.
*
* \sa PDU::recv_response
*/
PDU *recv_response(PacketSender &sender, const NetworkInterface &iface);
#endif // WIN32
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::ETHERNET_II; }
/**
* \sa PDU::clone
*/
EthernetII *clone() const {
return new EthernetII(*this);
}
private:
/**
* Struct that represents the Ethernet II header
*/
TINS_BEGIN_PACK
struct ethhdr {
uint8_t dst_mac[address_type::address_size];
uint8_t src_mac[address_type::address_size];
uint16_t payload_type;
} TINS_END_PACK;
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
ethhdr _eth;
};
}
#endif // TINS_ETHERNET_II_H

View File

@@ -1,173 +0,0 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_EXCEPTIONS_H
#define TINS_EXCEPTIONS_H
#include <string>
#include <stdexcept>
namespace Tins {
/**
* \brief Exception thrown when an option is not found.
*/
class option_not_found : public std::runtime_error {
public:
option_not_found()
: std::runtime_error(std::string()) { }
// try to avoid allocations by doing this.
const char* what() const throw() {
return "Option not found";
}
};
/**
* \brief Exception thrown when a malformed packet is parsed.
*/
class malformed_packet : public std::runtime_error {
public:
malformed_packet()
: std::runtime_error(std::string()) { }
const char* what() const throw() {
return "Malformed packet";
}
};
/**
* \brief Exception thrown when a PDU is not found when using PDU::rfind_pdu.
*/
class pdu_not_found : public std::runtime_error {
public:
pdu_not_found()
: std::runtime_error(std::string()) { }
const char* what() const throw() {
return "PDU not found";
}
};
/**
* \brief Exception thrown when PDU::send requires a valid interface,
* but an invalid is used.
*/
class invalid_interface : public std::runtime_error {
public:
invalid_interface()
: std::runtime_error(std::string()) { }
const char* what() const throw() {
return "Invalid interface";
}
};
/**
* \brief Exception thrown when PacketSender fails to open a socket.
*/
class socket_open_error : public std::runtime_error {
public:
socket_open_error(const std::string &msg)
: std::runtime_error(msg) { }
};
/**
* \brief Exception thrown when PacketSender fails to close a socket.
*/
class socket_close_error : public std::runtime_error {
public:
socket_close_error(const std::string &msg)
: std::runtime_error(msg) { }
};
/**
* \brief Exception thrown when PacketSender fails to write on a socket.
*/
class socket_write_error : public std::runtime_error {
public:
socket_write_error(const std::string &msg)
: std::runtime_error(msg) { }
};
/**
* \brief Exception thrown when an invalid socket type is provided
* to PacketSender.
*/
class invalid_socket_type : public std::exception {
public:
const char *what() const throw() {
return "The provided socket type is invalid";
}
};
/**
* \brief Exception thrown when an unkown link layer PDU type is
* found while sniffing.
*/
class unknown_link_type : public std::exception {
public:
const char *what() const throw() {
return "The sniffed link layer PDU type is unknown";
}
};
/**
* \brief Exception thrown when a malformed option is found.
*/
class malformed_option : public std::exception {
public:
const char *what() const throw() {
return "Malformed option";
}
};
/**
* \brief Exception thrown when a call to tins_cast fails.
*/
class bad_tins_cast : public std::exception {
public:
const char *what() const throw() {
return "Bad Tins cast";
}
};
/**
* \brief Exception thrown when sniffing a protocol that
* has been disabled at compile time.
*/
class protocol_disabled : public std::exception {
public:
const char *what() const throw() {
return "Protocol disabled";
}
};
} // Tins
#endif // TINS_EXCEPTIONS_H

View File

@@ -1,169 +0,0 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "config.h"
#if !defined(TINS_HANDSHAKE_CAPTURER_H) && defined(HAVE_DOT11)
#define TINS_HANDSHAKE_CAPTURER_H
#include <vector>
#include <map>
#include <utility>
#include "hw_address.h"
#include "eapol.h"
// .h
namespace Tins {
/**
* \brief Generic EAPOL handshake.
*
* Stores both the client and supplicant addresses, as well as
* all of the EAPOL packets used during the handshake.
*/
template<typename T>
class EAPOLHandshake {
public:
typedef std::vector<T> container_type;
typedef HWAddress<6> address_type;
/**
* \brief Default constructor.
*/
EAPOLHandshake() { }
/**
* Constructs an EAPOLHandshake object.
*
* \param client_address The client address.
* \param supplicant_address The supplicant address.
* \param cont The container that holds the EAPOL packets used
* in the handshake.
*/
EAPOLHandshake(const address_type &client_address,
const address_type &supplicant_address, const container_type &cont)
: cl_address_(client_address), suppl_address_(supplicant_address),
handshake_(cont)
{
}
/**
* \return const address_type&
*/
const address_type &client_address() const {
return cl_address_;
}
/**
* \return const address_type&
*/
const address_type &supplicant_address() const {
return suppl_address_;
}
/**
* \return const container_type&
*/
const container_type &handshake() const {
return handshake_;
}
private:
address_type cl_address_, suppl_address_;
container_type handshake_;
};
/**
* The type used to store RSN handshakes.
*/
typedef EAPOLHandshake<RSNEAPOL> RSNHandshake;
/**
* Captures 802.1X RSN handshakes.
*/
class RSNHandshakeCapturer {
public:
/**
* The type of handshakes that will be captured.
*/
typedef RSNHandshake handshake_type;
/**
* The type in which all of the captured handshakes
* will be stored.
*/
typedef std::vector<handshake_type> handshakes_type;
/**
* \brief Processes a packet.
*
* This will fetch the RSNEAPOL layer, if any, and store
* it in an intermediate storage. When a handshake is
* completed, it will be stored separately.
*
* \sa RSNHandshakeCapturer::handshakes
*/
bool process_packet(const PDU &pdu);
/**
* \brief Retrieves the completed handshakes.
*
* This will return the handshakes that have been completed
* so far. A handshake is completed when the 4-way handshake
* is captured.
*
* \sa RSNHandshakeCapturer::clear_handshakes
*/
const handshakes_type &handshakes() const {
return completed_handshakes_;
}
/**
* \brief Clears the completed handshakes.
*
* Since completed handshakes are stored in a std::vector,
* it is advisable to remove all of them once they have been
* processed.
*/
void clear_handshakes() {
completed_handshakes_.clear();
}
private:
typedef handshake_type::address_type address_type;
typedef handshake_type::container_type eapol_list;
typedef std::map<std::pair<address_type, address_type>, eapol_list> handshake_map;
bool do_insert(const handshake_map::key_type &key, const RSNEAPOL *eapol,
size_t expected);
handshake_map handshakes_;
handshakes_type completed_handshakes_;
};
}
#endif // TINS_HANDSHAKE_CAPTURER_H

View File

@@ -1,406 +0,0 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_ICMP_H
#define TINS_ICMP_H
// Windows likes to define macros with not-so-common-names, which break
// this code
#ifdef WIN32
#ifdef TIMESTAMP_REQUEST
#undef TIMESTAMP_REQUEST
#endif // TIMESTAMP_REQUEST
#ifdef TIMESTAMP_REPLY
#undef TIMESTAMP_REPLY
#endif // TIMESTAMP_REPLY
#endif // WIN32
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
#include "ip_address.h"
namespace Tins {
/** \brief Class that represents an ICMP PDU.
*
* ICMP is the representation of the ICMP PDU. Instances of this class
* must be sent over a level 3 PDU, this will otherwise fail.
*/
class ICMP : public PDU {
public:
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::ICMP;
/**
* The type used to store addresses.
*/
typedef IPv4Address address_type;
/** \brief ICMP flags
*/
enum Flags {
ECHO_REPLY = 0,
DEST_UNREACHABLE = 3,
SOURCE_QUENCH = 4,
REDIRECT = 5,
ECHO_REQUEST = 8,
TIME_EXCEEDED = 11,
PARAM_PROBLEM = 12,
TIMESTAMP_REQUEST = 13,
TIMESTAMP_REPLY = 14,
INFO_REQUEST = 15,
INFO_REPLY = 16,
ADDRESS_MASK_REQUEST = 17,
ADDRESS_MASK_REPLY = 18
};
/**
* \brief Creates an instance of ICMP.
*
* If no flag is specified, then ECHO_REQUEST will be used.
* \param flag The type flag which will be set.
*/
ICMP(Flags flag = ECHO_REQUEST);
/**
* \brief Constructs an ICMP object from a buffer.
*
* If there is not enough size for an ICMP header, a
* malformed_packet exception is thrown.
*
* Any extra data in the buffer will be stored in a RawPDU.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
ICMP(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Sets the code field.
*
* \param new_code The code which will be stored in the ICMP struct.
*/
void code(uint8_t new_code);
/** \brief Sets the type field.
*
* \param type The type which will be stored in the ICMP struct.
*/
void type(Flags type);
/**
* \brief Setter for the id field.
*
* \param new_id uint16_t with the new id.
*/
void id(uint16_t new_id);
/**
* \brief Setter for the sequence field.
*
* \param new_seq uint16_t with the new sequence.
*/
void sequence(uint16_t new_seq);
/**
* \brief Setter for the gateway field.
*
* \param new_gw The new value for the gateway field.
*/
void gateway(address_type new_gw);
/**
* \brief Setter for the mtu field.
*
* \param new_mtu uint16_t with the new sequence.
*/
void mtu(uint16_t new_mtu);
/**
* \brief Setter for the pointer field.
*
* \param new_pointer uint8_t with the new pointer.
*/
void pointer(uint8_t new_pointer);
/**
* \brief Setter for the original timestamp field.
*
* \param new_timestamp the value to be set.
*/
void original_timestamp(uint32_t new_timestamp);
/**
* \brief Setter for the receive timestamp field.
*
* \param new_timestamp the value to be set.
*/
void receive_timestamp(uint32_t new_timestamp);
/**
* \brief Setter for the transmit timestamp field.
*
* \param new_timestamp the value to be set.
*/
void transmit_timestamp(uint32_t new_timestamp);
/**
* \brief Setter for the address mask field.
*
* \param new_mask the value to be set.
*/
void address_mask(address_type new_mask);
/**
* \brief Sets echo request flag for this PDU.
*
* \param id The identifier for this request.
* \param seq The sequence number for this request.
*/
void set_echo_request(uint16_t id, uint16_t seq);
/**
* \brief Sets echo reply flag for this PDU.
*
* \param id The identifier for this request.
* \param seq The sequence number for this request.
*/
void set_echo_reply(uint16_t id, uint16_t seq);
/**
* \brief Sets information request flag for this PDU.
*
* \param id The identifier for this request.
* \param seq The sequence number for this request.
*/
void set_info_request(uint16_t id, uint16_t seq);
/**
* \brief Sets information reply flag for this PDU.
*
* \param id The identifier for this request.
* \param seq The sequence number for this request.
*/
void set_info_reply(uint16_t id, uint16_t seq);
/**
* \brief Sets destination unreachable for this PDU.
*/
void set_dest_unreachable();
/**
* \brief Sets time exceeded flag for this PDU.
*
* \param ttl_exceeded If true this PDU will represent a ICMP ttl
* exceeded, otherwise it will represent a fragment reassembly
* time exceeded.
*/
void set_time_exceeded(bool ttl_exceeded = true);
/**
* \brief Sets parameter problem flag for this PDU.
*
* \param set_pointer Indicates wether a pointer to the bad octet
* is provided.
* \param bad_octet Identifies the octet in which the error was
* detected. If set_pointer == false, it is ignored.
*/
void set_param_problem(bool set_pointer = false, uint8_t bad_octet = 0);
/**
* \brief Sets source quench flag for this PDU.
*/
void set_source_quench();
/**
* \brief Sets redirect flag for this PDU.
*
* \param icode The code to be set.
* \param address Address of the gateway to which traffic should
* be sent.
*/
void set_redirect(uint8_t icode, address_type address);
/**
* \brief Getter for the ICMP type flag.
*
* \return The type flag for this ICMP PDU.
*/
Flags type() const { return (Flags)_icmp.type; }
/**
* \brief Getter for the ICMP code flag.
*
* \return The code flag for this ICMP PDU.
*/
uint8_t code() const { return _icmp.code; }
/**
* \brief Getter for the checksum field.
*
* \return Returns the checksum as an unit16_t.
*/
uint16_t checksum() const { return Endian::be_to_host(_icmp.check); }
/**
* \brief Getter for the echo id.
*
* \return Returns the echo id.
*/
uint16_t id() const { return Endian::be_to_host(_icmp.un.echo.id); }
/**
* \brief Getter for the echo sequence number.
*
* \return Returns the echo sequence number.
*/
uint16_t sequence() const { return Endian::be_to_host(_icmp.un.echo.sequence); }
/**
* \brief Getter for the gateway field.
*
* \return Returns the gateway field value.
*/
address_type gateway() const {
return address_type(Endian::be_to_host(_icmp.un.gateway));
}
/**
* \brief Getter for the pointer field.
*
* \return Returns the pointer field value.
*/
uint8_t pointer() const { return this->_icmp.un.pointer; }
/**
* \brief Getter for the mtu field.
*
* \return Returns the mtu field value.
*/
uint16_t mtu() const { return Endian::be_to_host(_icmp.un.frag.mtu); }
/**
* \brief Getter for the original timestamp field.
*
* \return Returns the original timestamp value.
*/
uint32_t original_timestamp() const { return Endian::be_to_host(_orig_timestamp_or_address_mask); }
/**
* \brief Getter for the receive timestamp field.
*
* \return Returns the receive timestamp value.
*/
uint32_t receive_timestamp() const { return Endian::be_to_host(_recv_timestamp); }
/**
* \brief Getter for the transmit timestamp field.
*
* \return Returns the transmit timestamp value.
*/
uint32_t transmit_timestamp() const { return Endian::be_to_host(_trans_timestamp); }
/**
* \brief Getter for the address mask field.
*
* \return Returns the address mask value.
*/
address_type address_mask() const {
return address_type(Endian::be_to_host(_orig_timestamp_or_address_mask));
}
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. This size includes the
* payload and options size. \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \brief Getter for the PDU's type.
*
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::ICMP; }
/**
* \sa PDU::clone
*/
ICMP *clone() const {
return new ICMP(*this);
}
private:
TINS_BEGIN_PACK
struct icmphdr {
uint8_t type;
uint8_t code;
uint16_t check;
union {
struct {
uint16_t id;
uint16_t sequence;
} echo;
uint32_t gateway;
struct {
uint16_t unused;
uint16_t mtu;
} frag;
uint8_t pointer;
} un;
} TINS_END_PACK;
void checksum(uint16_t new_check);
/** \brief Serialices this ICMP PDU.
* \param buffer The buffer in which the PDU will be serialized.
* \param total_sz The size available in the buffer.
* \param parent The PDU that's one level below this one on the stack.
*/
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
icmphdr _icmp;
uint32_t _orig_timestamp_or_address_mask, _recv_timestamp, _trans_timestamp;
};
}
#endif // TINS_ICMP_H

View File

@@ -1,662 +0,0 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_IP_H
#define TINS_IP_H
#include <list>
#include "pdu.h"
#include "small_uint.h"
#include "endianness.h"
#include "ip_address.h"
#include "pdu_option.h"
#include "macros.h"
#include "cxxstd.h"
namespace Tins {
/**
* \brief Class that represents an IP PDU.
*
* By default, IP PDUs are initialized, setting TTL to IP::DEFAULT_TTL,
* id field to 1 and version to 4. Taking this into account, users
* should set destination and source port and would be enough to send one.
*/
class IP : public PDU {
public:
/**
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::IP;
/**
* The type used to store addresses.
*/
typedef IPv4Address address_type;
/**
* \brief Enum indicating the option's class.
*
* Enum OptionClass represents the different classes of
* IP Options.
*/
enum OptionClass {
CONTROL = 0,
MEASUREMENT = 2
};
/**
* \brief Enum indicating the option's id number.
*
* Enum Option indicates the possible IP Options.
*/
enum OptionNumber {
END = 0,
NOOP = 1,
SEC = 2,
LSSR = 3,
TIMESTAMP = 4,
EXTSEC = 5,
RR = 7,
SID = 8,
SSRR = 9,
MTUPROBE = 11,
MTUREPLY = 12,
EIP = 17,
TR = 18,
ADDEXT = 19,
RTRALT = 20,
SDB = 21,
DPS = 23,
UMP = 24,
QS = 25
};
/**
* \brief The type used to represent an option's type.
*/
TINS_BEGIN_PACK
struct option_identifier {
#if TINS_IS_LITTLE_ENDIAN
uint8_t number:5,
op_class:2,
copied:1;
#elif TINS_IS_BIG_ENDIAN
uint8_t copied:1,
op_class:2,
number:5;
#endif
/**
* \brief Default constructor.
*
* Initializes every field to 0.
*/
option_identifier()
#if TINS_IS_LITTLE_ENDIAN
: number(0), op_class(0), copied(0) {}
#else
: copied(0), op_class(0), number(0) {}
#endif
/**
* \brief Constructs this option from a single uint8_t value.
*
* This parses the value and initializes each field with the
* appropriate value.
*
* \param value The value to be parsed and used for
* initialization
*/
option_identifier(uint8_t value)
#if TINS_IS_LITTLE_ENDIAN
: number(value & 0x1f),
op_class((value >> 5) & 0x03),
copied((value >> 7) & 0x01) {}
#elif TINS_IS_BIG_ENDIAN
: copied((value >> 7) & 0x01),
op_class((value >> 5) & 0x03),
number(value & 0x1f) {}
#endif
/**
* Constructor using user provided values for each field.
* \param number The number field value.
* \param op_class The option class field value.
* \param copied The copied field value.
*/
option_identifier(OptionNumber number, OptionClass op_class,
small_uint<1> copied)
#if TINS_IS_LITTLE_ENDIAN
: number(number), op_class(op_class), copied(copied) {}
#else
: copied(copied), op_class(op_class), number(number) {}
#endif
/**
* \brief Equality operator.
*/
bool operator==(const option_identifier &rhs) const {
return number == rhs.number && op_class == rhs.op_class && copied == rhs.copied;
}
} TINS_END_PACK;
/**
* The IP options type.
*/
typedef PDUOption<option_identifier, IP> option;
/**
* The type of the security option.
*/
struct security_type {
uint16_t security, compartments;
uint16_t handling_restrictions;
small_uint<24> transmission_control;
security_type(uint16_t sec = 0, uint16_t comp = 0,
uint16_t hand_res = 0, small_uint<24> tcc = 0)
: security(sec), compartments(comp),
handling_restrictions(hand_res), transmission_control(tcc)
{}
static security_type from_option(const option &opt);
};
/**
* The type of the Loose Source and Record Route
*/
struct generic_route_option_type {
typedef std::vector<address_type> routes_type;
uint8_t pointer;
routes_type routes;
generic_route_option_type(uint8_t ptr = 0,
routes_type rts = routes_type())
: pointer(ptr), routes(rts) {}
static generic_route_option_type from_option(const option &opt);
};
/**
* The type of the Loose Source and Record Route
*/
typedef generic_route_option_type lsrr_type;
/**
* The type of the Strict Source and Record Route
*/
typedef generic_route_option_type ssrr_type;
/**
* The type of the Record Route
*/
typedef generic_route_option_type record_route_type;
/**
* The type used to store IP options.
*/
typedef std::list<option> options_type;
/**
* \brief Constructor for building the IP PDU.
*
* Both the destination and source IP address can be supplied.
* By default, those fields are initialized using the IP
* address 0.0.0.0.
*
* \param ip_dst The destination ip address(optional).
* \param ip_src The source ip address(optional).
*/
IP(address_type ip_dst = address_type(),
address_type ip_src = address_type());
/**
* \brief Constructs an IP object from a buffer and adds all
* identifiable PDUs found in the buffer as children of this
* one.
*
* If there is not enough size for an IP header, a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
IP(const uint8_t *buffer, uint32_t total_sz);
/* Getters */
/**
* \brief Getter for the header length field.
*
* \return The number of dwords the header occupies in an uin8_t.
*/
small_uint<4> head_len() const { return this->_ip.ihl; }
/**
* \brief Getter for the type of service field.
*
* \return The this IP PDU's type of service.
*/
uint8_t tos() const { return _ip.tos; }
/**
* \brief Getter for the total length field.
*
* \return The total length of this IP PDU.
*/
uint16_t tot_len() const {
return Endian::be_to_host(_ip.tot_len);
}
/**
* \brief Getter for the id field.
*
* \return The id for this IP PDU.
*/
uint16_t id() const { return Endian::be_to_host(_ip.id); }
/**
* \brief Getter for the fragment offset field.
*
* \return The fragment offset for this IP PDU.
*/
uint16_t frag_off() const { return Endian::be_to_host(_ip.frag_off); }
/**
* \brief Getter for the time to live field.
*
* \return The time to live for this IP PDU.
*/
uint8_t ttl() const { return _ip.ttl; }
/**
* \brief Getter for the protocol field.
*
* \return The protocol for this IP PDU.
*/
uint8_t protocol() const { return _ip.protocol; }
/**
* \brief Getter for the checksum field.
*
* \return The checksum for this IP PDU.
*/
uint16_t checksum() const { return Endian::be_to_host(_ip.check); }
/**
* \brief Getter for the source address field.
*
* \return The source address for this IP PDU.
*/
address_type src_addr() const { return address_type(_ip.saddr); }
/**
* \brief Getter for the destination address field.
* \return The destination address for this IP PDU.
*/
address_type dst_addr() const { return address_type(_ip.daddr); }
/**
* \brief Getter for the version field.
* \return The version for this IP PDU.
*/
small_uint<4> version() const { return _ip.version; }
/**
* \brief Getter for the IP options.
* \return The stored options.
*/
const options_type &options() const { return _ip_options; }
/* Setters */
/**
* \brief Setter for the type of service field.
*
* \param new_tos The new type of service.
*/
void tos(uint8_t new_tos);
/**
* \brief Setter for the id field.
*
* \param new_id The new id.
*/
void id(uint16_t new_id);
/**
* \brief Setter for the fragment offset field.
*
* \param new_frag_off The new fragment offset.
*/
void frag_off(uint16_t new_frag_off);
/**
* \brief Setter for the time to live field.
*
* \param new_ttl The new time to live.
*/
void ttl(uint8_t new_ttl);
/**
* \brief Setter for the protocol field.
*
* Note that this protocol will be overwritten using the
* inner_pdu's protocol type during serialization unless the IP
* datagram is fragmented.
*
* If the packet is fragmented and was originally sniffed, the
* original protocol type will be kept when serialized.
*
* If this packet has been crafted manually and the inner_pdu
* is, for example, a RawPDU, then setting the protocol yourself
* is necessary.
*
* \param new_protocol The new protocol.
*/
void protocol(uint8_t new_protocol);
/**
* \brief Setter for the source address field.
*
* \param ip The source address to be set.
*/
void src_addr(address_type ip);
/**
* \brief Setter for the destination address field.
*
* \param ip The destination address to be set.
*/
void dst_addr(address_type ip);
/**
* \brief Setter for the version field.
*
* \param ver The version field to be set.
*/
void version(small_uint<4> ver);
/**
* \brief Adds an IP option.
*
* The option is added after the last option in the option
* fields.
*
* \param opt The option to be added
*/
void add_option(const option &opt);
#if TINS_IS_CXX11
/**
* \brief Adds an IP option.
*
* The option is move-constructed.
*
* \param opt The option to be added.
*/
void add_option(option &&opt) {
internal_add_option(opt);
_ip_options.push_back(std::move(opt));
}
/**
* \brief Adds an IP option.
*
* The option is constructed from the provided parameters.
*
* \param args The arguments to be used in the option's
* constructor.
*/
template<typename... Args>
void add_option(Args&&... args) {
_ip_options.emplace_back(std::forward<Args>(args)...);
internal_add_option(_ip_options.back());
}
#endif
/**
* \brief Searchs for an option that matchs the given flag.
*
* If the option is not found, a null pointer is returned.
* Deleting the returned pointer will result in <b>undefined
* behaviour</b>.
*
* \param id The option identifier to be searched.
*/
const option *search_option(option_identifier id) const;
// Option setters
/**
* \brief Adds an End Of List option.
*/
void eol();
/**
* \brief Adds a NOP option.
*/
void noop();
/**
* \brief Adds a security option.
*
* \param data The data to be stored in this option.
*/
void security(const security_type &data);
/**
* \brief Adds a Loose Source and Record Route option.
*
* \param data The data to be stored in this option.
*/
void lsrr(const lsrr_type &data) {
add_route_option(131, data);
}
/**
* \brief Adds a Strict Source and Record Route option.
*
* \param data The data to be stored in this option.
*/
void ssrr(const ssrr_type &data) {
add_route_option(137, data);
}
/**
* \brief Adds a Record Route option.
*
* \param data The data to be stored in this option.
*/
void record_route(const record_route_type &data) {
add_route_option(7, data);
}
/**
* \brief Adds a Stream Identifier option.
*
* \param stream_id The stream id to be stored in this option.
*/
void stream_identifier(uint16_t stream_id);
// Option getters
/**
* \brief Searchs and returns a security option.
*
* If no such option exists, an option_not_found exception
* is thrown.
*
* \return security_type containing the option found.
*/
security_type security() const;
/**
* \brief Searchs and returns a Loose Source and Record Route
* option.
*
* If no such option exists, an option_not_found exception
* is thrown.
*
* \return lsrr_type containing the option found.
*/
lsrr_type lsrr() const {
return search_route_option(131);
}
/**
* \brief Searchs and returns a Strict Source and Record Route
* option.
*
* If no such option exists, an option_not_found exception
* is thrown.
*
* \return ssrr_type containing the option found.
*/
ssrr_type ssrr() const {
return search_route_option(137);
}
/**
* \brief Searchs and returns a Record Route option.
*
* If no such option exists, an option_not_found exception
* is thrown.
*
* \return record_route_type containing the option found.
*/
record_route_type record_route() const {
return search_route_option(7);
}
/**
* \brief Searchs and returns a Stream Identifier option.
*
* If no such option exists, an option_not_found exception
* is thrown.
*
* \return uint16_t containing the option found.
*/
uint16_t stream_identifier() const;
/* Virtual methods */
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \sa PDU::send()
*/
void send(PacketSender &sender, const NetworkInterface &);
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \brief 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 &);
/**
* Indicates whether this PDU is fragmented.
*
* \return true if this PDU is fragmented, false otherwise.
*/
bool is_fragmented() const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::IP; }
/**
* \sa PDU::clone
*/
IP *clone() const {
return new IP(*this);
}
private:
static const uint8_t DEFAULT_TTL;
TINS_BEGIN_PACK
struct iphdr {
#if TINS_IS_LITTLE_ENDIAN
uint8_t ihl:4,
version:4;
#else
uint8_t version:4,
ihl:4;
#endif
uint8_t tos;
uint16_t tot_len;
uint16_t id;
uint16_t frag_off;
uint8_t ttl;
uint8_t protocol;
uint16_t check;
uint32_t saddr;
uint32_t daddr;
/*The options start here. */
} TINS_END_PACK;
void head_len(small_uint<4> new_head_len);
void tot_len(uint16_t new_tot_len);
void prepare_for_serialize(const PDU *parent);
void internal_add_option(const option &option);
void init_ip_fields();
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
uint8_t* write_option(const option &opt, uint8_t* buffer);
void add_route_option(option_identifier id, const generic_route_option_type &data);
generic_route_option_type search_route_option(option_identifier id) const;
void checksum(uint16_t new_check);
iphdr _ip;
uint16_t _options_size, _padded_options_size;
options_type _ip_options;
};
}
#endif // TINS_IP_H

View File

@@ -1,402 +0,0 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_IEEE8022_H
#define TINS_IEEE8022_H
#include <list>
#include <vector>
#include <stdint.h>
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
namespace Tins {
/**
* \brief Class representing a LLC frame.
*
* This PDU follows the standard LLC frame described in the IEEE 802.2 specs.
*/
class LLC : public PDU {
public:
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::LLC;
/**
* \brief Represents the LLC global DSAP address.
*/
static const uint8_t GLOBAL_DSAP_ADDR;
/**
* \brief Represents the LLC NULL address.
*/
static const uint8_t NULL_ADDR;
/**
* \brief LLC Format flags.
*/
enum Format {
INFORMATION = 0,
SUPERVISORY = 1,
UNNUMBERED = 3
};
/**
* \brief LLC Modifier functions.
*/
enum ModifierFunctions {
UI = 0x00,
XID = 0x1D,
TEST = 0x07,
SABME = 0x1E,
DISC = 0x02,
UA = 0x06,
DM = 0x18,
FRMR = 0x11
};
/**
* \brief LLC Supervisory functions
*/
enum SupervisoryFunctions {
RECEIVE_READY = 0,
REJECT = 2,
RECEIVE_NOT_READY = 1
};
/**
* \brief Default constructor.
*/
LLC();
/**
* \brief Constructs an instance of LLC, setting the dsap and ssap.
* The control field is set to 0.
* \param dsap The dsap value to be set.
* \param ssap The ssap value to be set.
*/
LLC(uint8_t dsap, uint8_t ssap);
/**
* \brief Constructs a LLC object from a buffer and adds all
* identifiable PDUs found in the buffer as children of this one.
*
* If there is not enough size for a LLC header, a malformed_packet
* exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
LLC(const uint8_t *buffer, uint32_t total_sz);
/* Setters */
/**
* \brief Setter for the group destination bit.
* \param value The value to be set.
*/
void group(bool value);
/**
* \brief Setter for the dsap field.
* \param new_dsap The new dsap field.
*/
void dsap(uint8_t new_dsap);
/**
* \brief Setter for the response bit.
* \param value The value to be set.
*/
void response(bool value);
/**
* \brief Setter for the ssap field.
* \param new_ssap The new ssap field.
*/
void ssap(uint8_t new_ssap);
/**
* \brief Setter for the LLC frame format type.
* \param type The LLC frame format to set.
*/
void type(Format type);
/**
* \brief Setter for sender send sequence number.
* Only applied if format is INFORMATION.
* \param seq_number New sender send sequence number to be set.
*/
void send_seq_number(uint8_t seq_number);
/**
* \brief Setter for sender receive sequence number.
* Only applied if format is INFORMATION or SUPERVISORY.
* \param seq_number New sender receive sequence number to be set.
*/
void receive_seq_number(uint8_t seq_number);
/**
* \brief Setter for the poll/final flag.
* \param value Bool indicating the value of the flag.
*/
void poll_final(bool value);
/**
* \brief Setter for the supervisory function.
* Only applied if format is SUPERVISORY.
* \param new_func Value to set on the supervisory function field.
*/
void supervisory_function(SupervisoryFunctions new_func);
/**
* \brief Setter for the modifier function field.
* Only applied if format is UNNUMBERED.
* \param modifier_func Value to set on the modifier function field.
*/
void modifier_function(ModifierFunctions mod_func);
/**
* \brief Add a xid information field.
* Only applied if format is UNNUMBERED and function is XID.
* \param xid_id XID information of the MAC sublayer.
* \param llc_type_class Value to set the llc_type_class field.
* \param receive_window XID sender's receive window size.
*/
void add_xid_information(uint8_t xid_id, uint8_t llc_type_class, uint8_t receive_window);
//TODO: Add Acknowledged connectionless information
/* Getters */
/**
* \brief Getter for the group destination bit.
* \return Whether the group bit is set or not.
*/
bool group() {return _header.dsap & 0x01; }
/**
* \brief Getter for the dsap field.
* \return The dsap field value
*/
uint8_t dsap() {return _header.dsap; }
/**
* \brief Getter for the response bit.
* \return Whether the response bit is set or not.
*/
bool response() {return (_header.ssap & 0x01); }
/**
* \brief Getter for the ssap field.
* \return The ssap field.
*/
uint8_t ssap() {return _header.ssap; }
/**
* \brief Getter for the LLC frame format type.
* \return The LLC frame format.
*/
uint8_t type() {return _type; }
/**
* \brief Getter for sender send sequence number.
*
* \return The sender send sequence number if format is INFORMATION else 0.
*/
uint8_t send_seq_number() {
return (type() == INFORMATION) ? (control_field.info.send_seq_num) : 0;
}
/**
* \brief Getter for sender receive sequence number.
*
* \return The sender receive sequence number if format is
* INFORMATION or SUPERVISORY else 0.
*/
uint8_t receive_seq_number() {
switch (type()) {
case INFORMATION:
return control_field.info.recv_seq_num;
case SUPERVISORY:
return control_field.super.recv_seq_num;
case UNNUMBERED:
return 0;
default:
return 0;
}
}
/**
* \brief Getter for the poll/final flag.
* \return Whether the poll/final flag is set.
*/
bool poll_final() {
switch (type()) {
case UNNUMBERED:
return control_field.unnumbered.poll_final_bit;
case INFORMATION:
return control_field.info.poll_final_bit;
case SUPERVISORY:
return control_field.super.poll_final_bit;
default:
return false;
}
}
/**
* \brief Getter for the supervisory function.
*
* \return The supervisory function if format is SUPERVISORY else 0.
*/
uint8_t supervisory_function() {
if (type() == SUPERVISORY)
return control_field.super.supervisory_func;
return 0;
}
/**
* \brief Getter for the modifier function field.
*
* \return The modifier function if format is UNNUMBERED else 0.
*/
uint8_t modifier_function() {
if (type() == UNNUMBERED)
return (control_field.unnumbered.mod_func1 << 3) + control_field.unnumbered.mod_func2;
return 0;
}
/**
* \brief Returns the LLC frame's header length.
*
* \return The header's size.
* \sa PDU::header_size()
*/
uint32_t header_size() const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \brief Delete all the information fields added.
*/
void clear_information_fields();
/**
* \brief Clones this PDU.
*
* \sa PDU::clone
*/
LLC *clone() const {
return new LLC(*this);
}
private:
TINS_BEGIN_PACK
struct llchdr {
uint8_t dsap;
uint8_t ssap;
} TINS_END_PACK;
#if TINS_IS_LITTLE_ENDIAN
TINS_BEGIN_PACK
struct info_control_field {
uint16_t
type_bit:1,
send_seq_num:7,
poll_final_bit:1,
recv_seq_num:7;
} TINS_END_PACK;
TINS_BEGIN_PACK
struct super_control_field {
uint16_t type_bit:2,
supervisory_func:2,
unused:4,
poll_final_bit:1,
recv_seq_num:7;
} TINS_END_PACK;
TINS_BEGIN_PACK
struct un_control_field {
uint8_t type_bits:2,
mod_func1:2,
poll_final_bit:1,
mod_func2:3;
} TINS_END_PACK;
#elif TINS_IS_BIG_ENDIAN
TINS_BEGIN_PACK
struct info_control_field {
uint16_t send_seq_num:7,
type_bit:1,
recv_seq_num:7,
poll_final_bit:1;
} TINS_END_PACK;
TINS_BEGIN_PACK
struct super_control_field {
uint16_t unused:4,
supervisory_func:2,
type_bit:2,
recv_seq_num:7,
poll_final_bit:1;
} TINS_END_PACK;
TINS_BEGIN_PACK
struct un_control_field {
uint8_t mod_func2:3,
poll_final_bit:1,
mod_func1:2,
type_bits:2;
} TINS_END_PACK;
#endif
typedef std::vector<uint8_t> field_type;
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
llchdr _header;
uint8_t control_field_length;
union {
info_control_field info;
super_control_field super;
un_control_field unnumbered;
} control_field;
Format _type;
uint8_t information_field_length;
std::list<field_type> information_fields;
};
}
#endif // TINS_IEEE8022_H

View File

@@ -1,335 +0,0 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_PACKET_SENDER_H
#define TINS_PACKET_SENDER_H
#include <string>
#include <stdexcept>
#include <vector>
#include <stdint.h>
#include <map>
#include "network_interface.h"
#include "macros.h"
#include "cxxstd.h"
struct timeval;
struct sockaddr;
namespace Tins {
class PDU;
/**
* \brief Class that enables sending the created PDUs
*
* PacketSender class is responsible for sending the packets using the
* correct PDU layer. It is responsible for opening the raw sockets.
*/
class PacketSender {
public:
/**
* The default timeout for receive actions.
*/
static const uint32_t DEFAULT_TIMEOUT;
/**
* Flags to indicate the socket type.
*/
enum SocketType {
ETHER_SOCKET,
IP_TCP_SOCKET,
IP_UDP_SOCKET,
IP_RAW_SOCKET,
ARP_SOCKET,
ICMP_SOCKET,
IPV6_SOCKET,
SOCKETS_END
};
/**
* \brief Constructor for PacketSender objects.
*
* \param iface The default interface in which to send the packets.
* \param recv_timeout The timeout which will be used when receiving responses.
*/
PacketSender(const NetworkInterface &iface = NetworkInterface(),
uint32_t recv_timeout = DEFAULT_TIMEOUT, uint32_t usec = 0);
#if TINS_IS_CXX11
/**
* \brief Move constructor.
* \param rhs The sender to be moved.
*/
PacketSender(PacketSender &&rhs) NOEXCEPT {
*this = std::move(rhs);
}
/**
* \brief Move assignment operator.
* \param rhs The sender to be moved.
*/
PacketSender& operator=(PacketSender &&rhs) NOEXCEPT {
_sockets = std::move(rhs._sockets);
rhs._sockets = std::vector<int>(SOCKETS_END, INVALID_RAW_SOCKET);
#ifndef WIN32
#if defined(BSD) || defined(__FreeBSD_kernel__)
_ether_socket = std::move(rhs._ether_socket);
#else
_ether_socket = rhs._ether_socket;
rhs._ether_socket = INVALID_RAW_SOCKET;
#endif
#endif
_types = rhs._types; // no move
_timeout = rhs._timeout;
_timeout_usec = rhs._timeout_usec;
default_iface = rhs.default_iface;
return *this;
}
#endif
/**
* \brief PacketSender destructor.
*
* This gracefully closes all open sockets.
*/
~PacketSender();
#ifndef WIN32
/**
* \brief Opens a layer 2 socket.
*
* If this operation fails, then a socket_open_error will be thrown.
*/
void open_l2_socket(const NetworkInterface& iface = NetworkInterface());
#endif // WIN32
/**
* \brief Opens a layer 3 socket, using the corresponding protocol
* for the given flag.
*
* If this operation fails, then a socket_open_error will be thrown.
* If the provided socket type is not valid, an invalid_socket_type
* exception will be throw.
*
* \param type The type of socket which will be used to pick the protocol flag
* for this socket.
*/
void open_l3_socket(SocketType type);
/**
* \brief Closes the socket associated with the given flag.
*
* If the provided type is invalid, meaning no such open socket
* exists, an invalid_socket_type exception is thrown.
*
* If any socket close errors are encountered, a socket_close_error
* is thrown.
*
* \param type The type of the socket to be closed.
*/
void close_socket(SocketType type, const NetworkInterface &iface = NetworkInterface());
/**
* \brief Sets the default interface.
*
* The interface will be used whenever PacketSender::send(PDU&)
* is called.
*/
void default_interface(const NetworkInterface &iface);
/**
* \brief Gets the default interface.
*
* \sa PacketSender::default_interface
*/
const NetworkInterface& default_interface() const;
/**
* \brief Sends a PDU.
*
* This method opens the appropriate socket, if it's not open yet,
* and sends the PDU on the open socket.
*
* If any send error occurs, then a socket_write_error is thrown.
*
* If the PDU contains a link layer protocol, then default_interface
* is used.
*
* \sa PacketSender::default_interface
*
* \param pdu The PDU to be sent.
*/
void send(PDU &pdu);
/**
* \brief Sends a PDU.
*
* \sa PacketSender::send
*
* This overload takes a NetworkInterface. The packet is sent
* through that interface if a link-layer PDU is present,
* otherwise this call is equivalent to send(PDU&).
*
* The interface stored in the link layer PDU(if any), is restored
* after this method ends.
*
* \param pdu The PDU to be sent.
* \param iface The network interface to use.
*/
void send(PDU &pdu, const NetworkInterface &iface);
/**
* \brief Sends a PDU and waits for its response.
*
* This method is used to send PDUs and receive their response.
* It opens the required socket(if it's not open yet). This can be used
* to expect responses for ICMP, ARP, and such packets that are normally
* answered by the host that receives the packet.
*
* \param pdu The PDU to send.
* \return Returns the response PDU, 0 if not response was received.
*/
PDU *send_recv(PDU &pdu);
/**
* \brief Sends a PDU and waits for its response.
*
* This method is used to send PDUs and receive their response.
* It opens the required socket(if it's not open yet). This can be used
* to expect responses for ICMP, ARP, and such packets that are normally
* answered by the host that receives the packet.
*
* \param pdu The PDU to send.
* \param iface The network interface in which to send and receive.
* \return Returns the response PDU, 0 if not response was received.
*/
PDU *send_recv(PDU &pdu, const NetworkInterface &iface);
#ifndef WIN32
/**
* \brief Receives a layer 2 PDU response to a previously sent PDU.
*
* This PacketSender will receive data from a raw socket, open using the corresponding flag,
* according to the given type of protocol, until a match for the given PDU is received.
*
* \param pdu The PDU which will try to match the responses.
* \param link_addr The sockaddr struct which will be used to receive the PDU.
* \param len_addr The sockaddr struct length.
* \return Returns the response PDU. If no response is received, then 0 is returned.
*/
PDU *recv_l2(PDU &pdu, struct sockaddr *link_addr, uint32_t len_addr,
const NetworkInterface &iface = NetworkInterface());
/**
* \brief Sends a level 2 PDU.
*
* This method sends a layer 2 PDU, using a raw socket, open
* using the corresponding flag, according to the given type of
* protocol.
*
* If any socket write error occurs, a socket_write_error is thrown.
*
* \param pdu The PDU to send.
* \param link_addr The sockaddr struct which will be used to send the PDU.
* \param len_addr The sockaddr struct length.
*/
void send_l2(PDU &pdu, struct sockaddr* link_addr, uint32_t len_addr,
const NetworkInterface &iface = NetworkInterface());
#endif // WIN32
/**
* \brief Receives a layer 3 PDU response to a previously sent PDU.
*
* This PacketSender will receive data from a raw socket, open using the corresponding flag,
* according to the given type of protocol, until a match for the given PDU is received.
*
* \param pdu The PDU which will try to match the responses.
* \param link_addr The sockaddr struct which will be used to receive the PDU.
* \param len_addr The sockaddr struct length.
* \param type The socket protocol type.
* \return Returns the response PDU. If no response is received, then 0 is returned.
*/
PDU *recv_l3(PDU &pdu, struct sockaddr *link_addr, uint32_t len_addr, SocketType type);
/**
* \brief Sends a level 3 PDU.
*
* This method sends a layer 3 PDU, using a raw socket, open using the corresponding flag,
* according to the given type of protocol.
*
* If any socket write error occurs, a socket_write_error is thrown.
*
* \param pdu The PDU to send.
* \param link_addr The sockaddr struct which will be used to send the PDU.
* \param len_addr The sockaddr struct length.
* \param type The socket protocol type.
*/
void send_l3(PDU &pdu, struct sockaddr *link_addr, uint32_t len_addr, SocketType type);
private:
static const int INVALID_RAW_SOCKET;
typedef std::map<SocketType, int> SocketTypeMap;
PacketSender(const PacketSender&);
PacketSender& operator=(const PacketSender&);
int find_type(SocketType type);
int timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y);
#ifndef WIN32
bool ether_socket_initialized(const NetworkInterface& iface = NetworkInterface()) const;
int get_ether_socket(const NetworkInterface& iface = NetworkInterface());
#endif
template<typename T>
void send(PDU &pdu, const NetworkInterface &iface) {
static_cast<T&>(pdu).send(*this, iface);
}
PDU *recv_match_loop(const std::vector<int>& sockets, PDU &pdu, struct sockaddr* link_addr,
uint32_t addrlen);
std::vector<int> _sockets;
#ifndef WIN32
#if defined(BSD) || defined(__FreeBSD_kernel__)
typedef std::map<uint32_t, int> BSDEtherSockets;
BSDEtherSockets _ether_socket;
#else
int _ether_socket;
#endif
#endif
SocketTypeMap _types;
uint32_t _timeout, _timeout_usec;
NetworkInterface default_iface;
// In BSD we need to store the buffer size, retrieved using BIOCGBLEN
#if defined(BSD) || defined(__FreeBSD_kernel__)
int buffer_size;
#endif
};
}
#endif // TINS_PACKET_SENDER_H

View File

@@ -1,505 +0,0 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_PDU_H
#define TINS_PDU_H
#include <stdint.h>
#include <vector>
#include "macros.h"
#include "cxxstd.h"
#include "exceptions.h"
/** \brief The Tins namespace.
*/
namespace Tins {
class PacketSender;
class NetworkInterface;
/**
* The type used to store several PDU option values.
*/
typedef std::vector<uint8_t> byte_array;
/** \brief Base class for protocol data units.
*
* Every PDU implementation must inherit this one. PDUs can be serialized,
* therefore allowing a PacketSender to send them through the corresponding
* sockets. PDUs are created upwards: upper layers will be children of the
* lower ones. Each PDU must provide its flag identifier. This will be most
* likely added to its parent's data, hence it should be a valid identifier.
* For example, IP should provide IPPROTO_IP.
*/
class PDU {
public:
/**
* The type that will be returned when serializing PDUs.
*/
typedef byte_array serialization_type;
/**
* The typep used to identify the endianness of every PDU.
*/
enum endian_type {
BE,
LE
};
/**
* \brief Enum which identifies each type of PDU.
*
* This enum is used to identify the PDU type.
*/
enum PDUType {
RAW,
ETHERNET_II,
IEEE802_3,
RADIOTAP,
DOT11,
DOT11_ACK,
DOT11_ASSOC_REQ,
DOT11_ASSOC_RESP,
DOT11_AUTH,
DOT11_BEACON,
DOT11_BLOCK_ACK,
DOT11_BLOCK_ACK_REQ,
DOT11_CF_END,
DOT11_DATA,
DOT11_CONTROL,
DOT11_DEAUTH,
DOT11_DIASSOC,
DOT11_END_CF_ACK,
DOT11_MANAGEMENT,
DOT11_PROBE_REQ,
DOT11_PROBE_RESP,
DOT11_PS_POLL,
DOT11_REASSOC_REQ,
DOT11_REASSOC_RESP,
DOT11_RTS,
DOT11_QOS_DATA,
LLC,
SNAP,
IP,
ARP,
TCP,
UDP,
ICMP,
BOOTP,
DHCP,
EAPOL,
RC4EAPOL,
RSNEAPOL,
DNS,
LOOPBACK,
IPv6,
ICMPv6,
SLL,
DHCPv6,
DOT1Q,
PPPOE,
STP,
PPI,
IPSEC_AH,
IPSEC_ESP,
USER_DEFINED_PDU = 1000
};
/**
* The endianness used by this PDU. This can be overriden
* by subclasses.
*/
static const endian_type endianness = BE;
/**
* \brief Default constructor.
*/
PDU();
#if TINS_IS_CXX11
/**
* \brief Move constructor.
*
* \param rhs The PDU to be moved.
*/
PDU(PDU &&rhs) NOEXCEPT
: _inner_pdu(0)
{
std::swap(_inner_pdu, rhs._inner_pdu);
}
/**
* \brief Move assignment operator.
*
* \param rhs The PDU to be moved.
*/
PDU& operator=(PDU &&rhs) NOEXCEPT {
std::swap(_inner_pdu, rhs._inner_pdu);
return *this;
}
#endif
/**
* \brief PDU destructor.
*
* Deletes the inner pdu, as a consequence every child pdu is
* deleted.
*/
virtual ~PDU();
/** \brief The header's size
*/
virtual uint32_t header_size() const = 0;
/** \brief Trailer's size.
*
* Some protocols require a trailer(like Ethernet). This defaults to 0.
*/
virtual uint32_t trailer_size() const { return 0; }
/** \brief The whole chain of PDU's size, including this one.
*
* Returns the sum of this and all children PDUs' size.
*/
uint32_t size() const;
/**
* \brief Getter for the inner PDU.
* \return The current inner PDU. Might be 0.
*/
PDU *inner_pdu() const { return _inner_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
* 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();
/**
* \brief Sets the child PDU.
*
* 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.
*/
serialization_type serialize();
/**
* \brief Finds and returns the first PDU that matches the given flag.
*
* This method searches for the first PDU which has the same type flag as
* the given one. If the first PDU matches that flag, it is returned.
* If no PDU matches, 0 is returned.
* \param flag The flag which being searched.
*/
template<typename T>
T *find_pdu(PDUType type = T::pdu_flag) {
PDU *pdu = this;
while(pdu) {
if(pdu->matches_flag(type))
return static_cast<T*>(pdu);
pdu = pdu->inner_pdu();
}
return 0;
}
/**
* \brief Finds and returns the first PDU that matches the given flag.
*
* \param flag The flag which being searched.
*/
template<typename T>
const T *find_pdu(PDUType type = T::pdu_flag) const {
return const_cast<PDU*>(this)->find_pdu<T>();
}
/**
* \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>
T &rfind_pdu(PDUType type = T::pdu_flag) {
T *ptr = find_pdu<T>(type);
if(!ptr)
throw pdu_not_found();
return *ptr;
}
/**
* \brief Finds and returns the first PDU that matches the given flag.
*
* \param flag The flag which being searched.
*/
template<typename T>
const T &rfind_pdu(PDUType type = T::pdu_flag) const {
return const_cast<PDU*>(this)->rfind_pdu<T>();
}
/**
* \brief Clones this packet.
*
* This method clones this PDU and clones every inner PDU,
* therefore obtaining a clone of the whole inner PDU chain.
* The pointer returned must be deleted by the user.
* \return A pointer to a clone of this packet.
*/
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
* 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 wether ptr points to a valid response for this PDU.
*
* This method must check wether the buffer pointed by ptr is a valid
* response for this PDU. If it is valid, then it might want to propagate
* the call to the next PDU. Note that in some cases, such as ICMP
* Host Unreachable, there is no need to ask the next layer for matching.
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
virtual bool matches_response(const uint8_t *ptr, uint32_t total_sz) const {
return false;
}
/**
* \brief Check wether this PDU matches the specified flag.
*
* This method should be reimplemented in PDU classes which have
* subclasses, and try to match the given PDU to each of its parent
* classes' flag.
* \param flag The flag to match.
*/
virtual bool matches_flag(PDUType flag) const {
return flag == pdu_type();
}
/**
* \brief Getter for the PDU's type.
*
* \return Returns the PDUType corresponding to the PDU.
*/
virtual PDUType pdu_type() const = 0;
protected:
/**
* \brief Copy constructor.
*/
PDU(const PDU &other);
/**
* \brief Copy assignment operator.
*/
PDU &operator=(const PDU &other);
/**
* \brief Copy other PDU's inner PDU(if any).
* \param pdu The PDU from which to copy the inner PDU.
*/
void copy_inner_pdu(const PDU &pdu);
/**
* \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
*
* \param parent The parent PDU.
*/
virtual void prepare_for_serialize(const PDU *parent) { }
/**
* \brief Serializes this PDU and propagates this action to child PDUs.
*
* \param buffer The buffer in which to store this PDU's serialization.
* \param total_sz The total size of the buffer.
* \param parent The parent PDU. Will be 0 if there's the parent does not exist.
*/
void serialize(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
/**
* \brief Serializes this TCP PDU.
*
* Each PDU must override this method and implement it's own
* serialization.
* \param buffer The buffer in which the PDU will be serialized.
* \param total_sz The size available in the buffer.
* \param parent The PDU that's one level below this one on the stack. Might be 0.
*/
virtual void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) = 0;
private:
PDU *_inner_pdu;
};
/**
* \brief Concatenation operator.
*
* 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
* 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.
*/
template<typename T>
T &operator/= (T &lop, const PDU &rop) {
PDU *last = &lop;
while(last->inner_pdu())
last = last->inner_pdu();
last->inner_pdu(rop.clone());
return lop;
}
/**
* \brief Concatenation operator.
*
* \sa operator/=
*/
template<typename T>
T operator/ (T lop, const PDU &rop) {
lop /= rop;
return lop;
}
/**
* \brief Concatenation operator on PDU pointers.
*
* \sa operator/=
*/
template<typename T>
T *operator/= (T* lop, const PDU &rop) {
*lop /= rop;
return lop;
}
namespace Internals {
template<typename T>
struct remove_pointer {
typedef T type;
};
template<typename T>
struct remove_pointer<T*> {
typedef T type;
};
}
template<typename T, typename U>
T tins_cast(U *pdu) {
typedef typename Internals::remove_pointer<T>::type TrueT;
return pdu && (TrueT::pdu_flag == pdu->pdu_type()) ?
static_cast<T>(pdu) :
0;
}
template<typename T, typename U>
T &tins_cast(U &pdu) {
T *ptr = tins_cast<T*>(&pdu);
if(!ptr)
throw bad_tins_cast();
return *ptr;
}
}
#endif // TINS_PDU_H

View File

@@ -1,433 +0,0 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "config.h"
#if !defined(TINS_RADIOTAP_H) && defined(HAVE_DOT11)
#define TINS_RADIOTAP_H
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
namespace Tins {
class PacketSender;
/**
* \brief Class that represents the IEEE 802.11 radio tap header.
*
* By default, RadioTap PDUs set the necesary fields to send an 802.11
* PDU as its inner pdu, avoiding packet drops. As a consequence,
* the FCS-at-end flag is on, the channel is set to 1, TSFT is set to 0,
* dbm_signal is set to 0xce, and the rx_flag and antenna fields to 0.
*/
class RadioTap : public PDU {
public:
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::RADIOTAP;
/**
* \brief Enumeration of the different channel type flags.
*
* These channel type flags can be OR'd and set using the
* RadioTap::channel() method.
*/
enum ChannelType {
TURBO = 0x10,
CCK = 0x20,
OFDM = 0x40,
TWO_GZ = 0x80,
FIVE_GZ = 0x100,
PASSIVE = 0x200,
DYN_CCK_OFDM = 0x400,
GFSK = 0x800
};
/**
* \brief Flags used in the present field.
*
* \sa RadioTap::present()
*/
enum PresentFlags {
TSTF = 1,
FLAGS = 2,
RATE = 4,
CHANNEL = 8,
FHSS = 16,
DBM_SIGNAL = 32,
DBM_NOISE = 64,
LOCK_QUALITY = 128,
TX_ATTENUATION = 256,
DB_TX_ATTENUATION = 512,
DBM_TX_ATTENUATION = 1024,
ANTENNA = 2048,
DB_SIGNAL = 4096,
DB_NOISE = 8192,
RX_FLAGS = 16382,
CHANNEL_PLUS = 262144
};
/**
* \brief Flags used in the RadioTap::flags() method.
*/
enum FrameFlags {
CFP = 1,
PREAMBLE = 2,
WEP = 4,
FRAGMENTATION = 8,
FCS = 16,
PADDING = 32,
FAILED_FCS = 64,
SHORT_GI = 128
};
/**
* \brief Default constructor.
*/
RadioTap();
/**
* \brief Constructs a RadioTap object from a buffer and adds all
* identifiable PDUs found in the buffer as children of this one.
*
* If there is not enough size for a RadioTap header, a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
RadioTap(const uint8_t *buffer, uint32_t total_sz);
/* Setters */
#ifndef WIN32
/**
* \sa PDU::send()
*/
void send(PacketSender &sender, const NetworkInterface &iface);
#endif
/**
* \brief Setter for the version field.
* \param new_version The new version.
*/
void version(uint8_t new_version);
/**
* \brief Setter for the padding field.
* \param new_padding The new padding.
*/
void padding(uint8_t new_padding);
/**
* \brief Setter for the length field.
* \param new_length The new length.
*/
void length(uint16_t new_length);
/**
* \brief Setter for the TSFT field.
* \param new_tsft The new TSFT
*/
void tsft(uint64_t new_tsft);
/**
* \brief Setter for the flags field.
* \param new_flags The new flags.
*/
void flags(FrameFlags new_flags);
/**
* \brief Setter for the rate field.
* \param new_rate The new rate.
*/
void rate(uint8_t new_rate);
/**
* \brief Setter for the channel frequency and type field.
* \param new_freq The new channel frequency.
* \param new_type The new channel type.
*/
void channel(uint16_t new_freq, uint16_t new_type);
/**
* \brief Setter for the dbm signal field.
* \param new_dbm_signal The new dbm signal.
*/
void dbm_signal(uint8_t new_dbm_signal);
/**
* \brief Setter for the dbm noise field.
* \param new_dbm_noise The new dbm noise.
*/
void dbm_noise(uint8_t new_dbm_noise);
/**
* \brief Setter for the signal quality field.
* \param new_antenna The signal quality signal.
*/
void signal_quality(uint8_t new_signal_quality);
/**
* \brief Setter for the antenna field.
* \param new_antenna The antenna signal.
*/
void antenna(uint8_t new_antenna);
/**
* \brief Setter for the db signal field.
* \param new_antenna The db signal signal.
*/
void db_signal(uint8_t new_db_signal);
/**
* \brief Setter for the rx flag field.
* \param new_rx_flag The antenna signal.
*/
void rx_flags(uint16_t new_rx_flag);
/* Getters */
/**
* \brief Getter for the version field.
* \return The version field.
*/
uint8_t version() const { return _radio.it_version; }
/**
* \brief Getter for the padding field.
* \return The padding field.
*/
uint8_t padding() const { return _radio.it_pad; }
/**
* \brief Getter for the length field.
* \return The length field.
*/
uint16_t length() const { return Endian::le_to_host(_radio.it_len); }
/**
* \brief Getter for the tsft field.
* \return The tsft field.
*/
uint64_t tsft() const { return Endian::le_to_host(_tsft); }
/**
* \brief Getter for the flags field.
* \return The flags field.
*/
FrameFlags flags() const { return (FrameFlags)_flags; }
/**
* \brief Getter for the rate field.
* \return The rate field.
*/
uint8_t rate() const { return _rate; }
/**
* \brief Getter for the channel frequency field.
* \return The channel frequency field.
*/
uint16_t channel_freq() const { return Endian::le_to_host(_channel_freq); }
/**
* \brief Getter for the channel type field.
* \return The channel type field.
*/
uint16_t channel_type() const { return Endian::le_to_host(_channel_type); }
/**
* \brief Getter for the dbm signal field.
* \return The dbm signal field.
*/
uint8_t dbm_signal() const { return _dbm_signal; }
/**
* \brief Getter for the dbm noise field.
* \return The dbm noise field.
*/
uint8_t dbm_noise() const { return _dbm_noise; }
/**
* \brief Getter for the signal quality field.
* \return The signal quality field.
*/
uint16_t signal_quality() const { return _signal_quality; }
/**
* \brief Getter for the antenna field.
* \return The antenna field.
*/
uint8_t antenna() const { return _antenna; }
/**
* \brief Getter for the db signal field.
* \return The db signal field.
*/
uint8_t db_signal() const { return _db_signal; }
/**
* \brief Getter for the channel+ field.
* \return The channel+ field.
*/
uint32_t channel_plus() const { return Endian::le_to_host<uint32_t>(_channel_type); }
/**
* \brief Getter for the rx flags field.
* \return The rx flags field.
*/
uint16_t rx_flags() const { return Endian::le_to_host(_rx_flags); }
/**
* \brief Getter for the present bit fields.
*
* Use this method and masks created from the values taken from
* the PresentFlags enum to find out which fields are set.
* Accessing non-initialized fields, the behaviour is undefined
* will be undefined. It is only safe to use the getter of a field
* if its corresponding bit flag is set in the present field.
*/
PresentFlags present() const {
//return (PresentFlags)*(uint32_t*)(&_radio.it_len + 1);
return (PresentFlags)Endian::le_to_host(_radio.flags_32);
}
/** \brief Check wether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \brief Returns the RadioTap frame's header length.
*
* \return An uint32_t with the header's size.
* \sa PDU::header_size()
*/
uint32_t header_size() const;
/**
* \brief Returns the frame's trailer size.
* \return The trailer's size.
*/
uint32_t trailer_size() const;
/**
* \sa PDU::clone
*/
RadioTap *clone() const {
return new RadioTap(*this);
}
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::RADIOTAP; }
private:
TINS_BEGIN_PACK
struct radiotap_hdr {
#if TINS_IS_LITTLE_ENDIAN
uint8_t it_version;
uint8_t it_pad;
uint16_t it_len;
union {
struct {
uint32_t tsft:1,
flags:1,
rate:1,
channel:1,
fhss:1,
dbm_signal:1,
dbm_noise:1,
lock_quality:1,
tx_attenuation:1,
db_tx_attenuation:1,
dbm_tx_attenuation:1,
antenna:1,
db_signal:1,
db_noise:1,
rx_flags:1,
reserved1:3,
channel_plus:1,
reserved2:12,
ext:1;
} flags;
uint32_t flags_32;
};
#else
uint8_t it_pad;
uint8_t it_version;
uint16_t it_len;
union {
struct {
uint32_t lock_quality:1,
dbm_noise:1,
dbm_signal:1,
fhss:1,
channel:1,
rate:1,
flags:1,
tsft:1,
reserved3:1,
rx_flags:1,
db_tx_attenuation:1,
dbm_tx_attenuation:1,
antenna:1,
db_signal:1,
db_noise:1,
tx_attenuation:1,
reserved2:5,
channel_plus:1,
reserved1:2,
reserved4:7,
ext:1;
} flags;
uint32_t flags_32;
};
#endif
} TINS_END_PACK;
void init();
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
radiotap_hdr _radio;
// present fields...
uint64_t _tsft;
uint16_t _channel_type, _channel_freq, _rx_flags, _signal_quality;
uint8_t _antenna, _flags, _rate, _dbm_signal, _dbm_noise, _channel, _max_power, _db_signal;
};
}
#endif // TINS_RADIOTAP_H

View File

@@ -1,160 +0,0 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_RAWPDU_H
#define TINS_RAWPDU_H
#include <vector>
#include <string>
#include "pdu.h"
namespace Tins {
/** \brief Represents a PDU which holds raw data.
*
* In order to send payloads over TCP, UDP, or other transport layer or
* higher level protocols, RawPDU can be used as a wrapper for raw byte arrays.
*/
class RawPDU : public PDU {
public:
/**
* The type used to store the payload.
*/
typedef std::vector<uint8_t> payload_type;
/**
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::RAW;
/**
* \brief Creates an instance of RawPDU.
*
* The payload is copied, therefore the original payload's memory
* must be freed by the user.
* \param pload The payload which the RawPDU will contain.
* \param size The size of the payload.
*/
RawPDU(const uint8_t *pload, uint32_t size);
/**
* \brief Creates an instance of RawPDU from an input string.
*
* \param data The content of the payload.
*/
RawPDU(const std::string &data);
/**
* \brief Setter for the payload field
* \param pload The payload to be set.
*/
void payload(const payload_type &pload);
/**
* \brief Setter for the payload field
* \param start The start of the new payload.
* \param end The end of the new payload.
*/
template<typename ForwardIterator>
void payload(ForwardIterator start, ForwardIterator end) {
_payload.assign(start, end);
}
/**
* \brief Const getter for the payload.
* \return The RawPDU's payload.
*/
const payload_type &payload() const { return _payload; }
/**
* \brief Non-const getter for the payload.
* \return The RawPDU's payload.
*/
payload_type &payload() { return _payload; }
/**
* \brief Returns the header size.
*
* This returns the same as RawPDU::payload_size().
*
* This metod overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \brief Returns the payload size.
*
* \return uint32_t containing the payload size.
*/
uint32_t payload_size() const {
return _payload.size();
}
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* This always returns true, since we don't know what this
* RawPDU is holding.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::RAW; }
/**
* \brief Constructs the given PDU type from the raw data stored
* in this RawPDU.
*/
template<typename T>
T to() const {
return T(&_payload[0], _payload.size());
}
/**
* \sa PDU::clone
*/
RawPDU *clone() const {
return new RawPDU(*this);
}
private:
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
payload_type _payload;
};
}
#endif // TINS_RAWPDU_H

View File

@@ -1,177 +0,0 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_SNAP_H
#define TINS_SNAP_H
#include <stdint.h>
#include "pdu.h"
#include "macros.h"
#include "endianness.h"
#include "small_uint.h"
namespace Tins {
/**
* \brief Class representing a SNAP frame.
*
* Note that this PDU contains the 802.3 LLC structure + SNAP frame.
* So far only unnumbered information structure is supported.
*/
class SNAP : public PDU {
public:
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::SNAP;
/**
* \brief Creates an instance of SNAP
* This constructor sets the dsap and ssap fields to 0xaa, and
* the id field to 3.
*/
SNAP();
/**
* \brief Constructs a SNAP object from a buffer and adds all
* identifiable PDUs found in the buffer as children of this one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for a SNAP header in the
* buffer, a malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
SNAP(const uint8_t *buffer, uint32_t total_sz);
/* Setters */
/**
* \brief Setter for the Control field.
* \param new_id The new Control to be set.
*/
void control(uint8_t new_control);
/**
* \brief Setter for the Organization Code field.
* \param new_org The new Organization Code to be set.
*/
void org_code(small_uint<24> new_org);
/**
* \brief Setter for the Ethernet Type field.
* \param new_eth The new Ethernet Type to be set.
*/
void eth_type(uint16_t new_eth);
/* Getters */
/**
* \brief Getter for the DSAP field.
* \return The DSAP field.
*/
uint8_t dsap() const { return _snap.dsap; }
/**
* \brief Getter for the SSAP field.
* \return The SSAP field.
*/
uint8_t ssap() const { return _snap.ssap; }
/**
* \brief Getter for the Control field.
* \return The Control field.
*/
uint8_t control() const {
#if TINS_IS_LITTLE_ENDIAN
return (_snap.control_org) & 0xff;
#else
return (_snap.control_org >> 24) & 0xff;
#endif
}
/**
* \brief Getter for the Organization Code field.
* \return The Organization Code field.
*/
small_uint<24> org_code() const {
#if TINS_IS_LITTLE_ENDIAN
return Endian::be_to_host<uint32_t>(_snap.control_org & 0xffffff00);
#else
return _snap.control_org & 0xffffff;
#endif
}
/**
* \brief Getter for the Ethernet Type field.
* \return The Ethernet Type field.
*/
uint16_t eth_type() const { return Endian::be_to_host(_snap.eth_type); }
/**
* \brief Returns the SNAP frame's header length.
*
* \return The header's size.
* \sa PDU::header_size()
*/
uint32_t header_size() const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \brief Clones this PDU.
*
* \sa PDU::clone
*/
SNAP *clone() const {
return new SNAP(*this);
}
private:
TINS_BEGIN_PACK
struct snaphdr {
uint8_t dsap;
uint8_t ssap;
uint32_t control_org;
uint16_t eth_type;
} TINS_END_PACK;
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
snaphdr _snap;
};
}
#endif // TINS_SNAP_H

View File

@@ -1,436 +0,0 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_SNIFFER_H
#define TINS_SNIFFER_H
#include <pcap.h>
#include <string>
#include <memory>
#include <stdexcept>
#include <iterator>
#include "pdu.h"
#include "packet.h"
#include "cxxstd.h"
#include "exceptions.h"
#include "internals.h"
namespace Tins {
class SnifferIterator;
/**
* \class BaseSniffer
* \brief Base class for sniffers.
*
* This class implements the basic sniffing operations. Subclasses
* should only initialize this object using a pcap_t pointer, which
* will be used to extract packets.
*
* Initialization must be done using the BaseSniffer::init method.
*/
class BaseSniffer {
public:
/**
* The iterator type.
*/
typedef SnifferIterator iterator;
#if TINS_IS_CXX11
/**
* \brief Move constructor.
* This constructor is available only in C++11.
*/
BaseSniffer(BaseSniffer &&rhs) NOEXCEPT
: handle(nullptr), mask()
{
*this = std::move(rhs);
}
/**
* \brief Move assignment operator.
* This operator is available only in C++11.
*/
BaseSniffer& operator=(BaseSniffer &&rhs) NOEXCEPT
{
using std::swap;
swap(handle, rhs.handle);
swap(mask, rhs.mask);
return *this;
}
#endif
/**
* \brief Sniffer destructor.
* This frees all memory used by the pcap handle.
*/
virtual ~BaseSniffer();
/**
* \brief Compiles a filter and uses it to capture one packet.
*
* This method returns the first valid sniffed packet that matches the
* sniffer's filter, or the first sniffed packet if no filter has
* been set.
*
* The return type is a thin wrapper over a PDU* and a Timestamp
* object. This wrapper can be both implicitly converted to a
* PDU* and a Packet object. So doing this:
*
* \code
* Sniffer s(...);
* std::unique_ptr<PDU> pdu(s.next_packet());
* // Packet takes care of the PDU*.
* Packet packet(s.next_packet());
* \endcode
*
* Is fine, but this:
*
* \code
* // bad!!
* PtrPacket p = s.next_packet();
* \endcode
*
* Is not, since PtrPacket can't be copy constructed.
*
* \sa Packet::release_pdu
*
* \return A captured packet. If an error occured, PtrPacket::pdu
* will return 0. Caller takes ownership of the PDU pointer stored in
* the PtrPacket.
*/
PtrPacket next_packet();
/**
* \brief Starts a sniffing loop, using a callback functor for every
* sniffed packet.
*
* The functor must implement an operator with one of the
* following signatures:
*
* \code
* bool(PDU&);
* bool(const PDU&);
* \endcode
*
* This functor will be called using the each of the sniffed packets
* as its argument. Using PDU member functions that modify the PDU,
* such as PDU::release_inner_pdu, is perfectly valid.
*
* Note that if you're using a functor object, it will be copied using
* its copy constructor, so it should be some kind of proxy to
* another object which will process the packets(e.g. std::bind).
*
* Sniffing will stop when either max_packets are sniffed(if it is != 0),
* or when the functor returns false.
*
* This method catches both malformed_packet and pdu_not_found exceptions,
* which allows writing much cleaner code, since you can call PDU::rfind_pdu
* without worrying about catching the exception that can be thrown. This
* allows writing code such as the following:
*
* \code
* bool callback(const PDU& pdu) {
* // If either RawPDU is not found, or construction of the DNS
* // object fails, the BaseSniffer object will trap the exceptions,
* // so we don't need to worry about it.
* DNS dns = pdu.rfind_pdu<RawPDU>().to<DNS>();
* return true;
* }
* \endcode
*
* \param function The callback handler object which should process packets.
* \param max_packets The maximum amount of packets to sniff. 0 == infinite.
*/
template<class Functor>
void sniff_loop(Functor function, uint32_t max_packets = 0);
/**
* \brief Sets a filter on this sniffer.
* \param filter The filter to be set.
* \return True iif it was possible to apply the filter.
*/
bool set_filter(const std::string &filter);
/**
* \brief Stops sniffing loops.
*
* This method must be called from the same thread from which
* BaseSniffer::sniff_loop was called.
*/
void stop_sniff();
/**
* \brief Gets the file descriptor associated with the sniffer.
*/
int get_fd();
/**
* \brief Sets the read timeout for this sniffer.
*
* This calls pcap_set_timeout using the provided parameter.
* \param ms The amount of milliseconds.
*/
void set_timeout(int ms);
/**
* \brief Sets whether to extract RawPDUs or fully parsed packets.
*
* By default, packets will be parsed starting from link layer.
* However, if you're parsing a lot of traffic, then you might
* want to extract packets and push them into a queue,
* so a consumer can parse them when they're popped.
*
* This method allows doing that. If the parameter is true,
* then packets taken from this BaseSniffer will only contain
* a RawPDU which will have to entire contents of the packet.
*
* \param value Whether to extract RawPDUs or not.
*/
void set_extract_raw_pdus(bool value);
/**
* \brief Retrieves this sniffer's link type.
*
* This calls pcap_datalink on the stored pcap handle and
* returns its result.
*/
int link_type() const;
/**
* Retrieves an iterator to the next packet in this sniffer.
*/
iterator begin();
/**
* Retrieves an end iterator.
*/
iterator end();
protected:
/**
* Default constructor.
*/
BaseSniffer();
/**
* \brief Initialices this BaseSniffer.
*
* \param phandle The pcap handle to be used for sniffing.
* \param filter The pcap filter which will be applied to the
* stream.
* \param if_mask The interface's subnet mask. If 0 is provided,
* then some IP broadcast tests won't work correctly.
*/
void init(pcap_t *phandle, const std::string &filter, bpf_u_int32 if_mask);
private:
BaseSniffer(const BaseSniffer&);
BaseSniffer &operator=(const BaseSniffer&);
pcap_t *handle;
bpf_u_int32 mask;
bool extract_raw;
};
/**
* \class Sniffer
* \brief Sniffs packets from a network interface.
*/
class Sniffer : public BaseSniffer {
public:
enum promisc_type {
NON_PROMISC,
PROMISC
};
/**
* Constructs an instance of Sniffer.
*
* By default the interface won't be put into promiscuous mode, and won't
* be put into monitor mode.
*
* \param device The device which will be sniffed.
* \param max_packet_size The maximum packet size to be read.
* \param promisc bool indicating wether to put the interface in promiscuous mode.(optional)
* \param filter A capture filter to be used on the sniffing session.(optional);
* \param rfmon Indicates if the interface should be put in monitor mode.(optional);
*/
Sniffer(const std::string &device, unsigned max_packet_size,
bool promisc = false, const std::string &filter = "", bool rfmon = false);
/**
* \brief Constructs an instance of Sniffer.
*
* The maximum capture size is set to 65535. By default the interface won't
* be put into promiscuous mode, and won't be put into monitor mode.
*
* \param device The device which will be sniffed.
* \param promisc Indicates if the interface should be put in promiscuous mode.
* \param filter A capture filter to be used on the sniffing session.(optional);
* \param rfmon Indicates if the interface should be put in monitor mode.(optional);
*/
Sniffer(const std::string &device, promisc_type promisc = NON_PROMISC,
const std::string &filter = "", bool rfmon = false);
private:
void init_sniffer(const std::string &device, unsigned max_packet_size,
bool promisc = false, const std::string &filter = "", bool rfmon = false);
};
/**
* \class FileSniffer
* \brief Reads pcap files and interprets the packets in it.
*
* This class acts exactly in the same way that Sniffer, but reads
* packets from a pcap file instead of an interface.
*/
class FileSniffer : public BaseSniffer {
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);
*/
FileSniffer(const std::string &file_name, const std::string &filter = "");
};
template<class T>
class HandlerProxy {
public:
typedef T* ptr_type;
typedef bool (T::*fun_type)(PDU&) ;
HandlerProxy(ptr_type ptr, fun_type function)
: object(ptr), fun(function) {}
bool operator()(PDU &pdu) {
return (object->*fun)(pdu);
}
private:
ptr_type object;
fun_type fun;
};
template<class T>
HandlerProxy<T> make_sniffer_handler(T *ptr, typename HandlerProxy<T>::fun_type function)
{
return HandlerProxy<T>(ptr, function);
}
/**
* \brief Iterates over packets sniffed by a BaseSniffer.
*/
class SnifferIterator : public std::iterator<std::forward_iterator_tag, PDU> {
public:
/**
* Constructs a SnifferIterator.
* \param sniffer The sniffer to iterate.
*/
SnifferIterator(BaseSniffer *sniffer = 0)
: sniffer(sniffer)
{
if(sniffer)
advance();
}
/**
* Advances the iterator.
*/
SnifferIterator& operator++() {
advance();
return *this;
}
/**
* Advances the iterator.
*/
SnifferIterator operator++(int) {
SnifferIterator other(*this);
advance();
return other;
}
/**
* Dereferences the iterator.
* \return reference to the current packet.
*/
PDU &operator*() {
return *pkt.pdu();
}
/**
* Dereferences the iterator.
* \return pointer to the current packet.
*/
PDU *operator->() {
return &(**this);
}
/**
* Compares this iterator for equality.
* \param rhs The iterator to be compared to.
*/
bool operator==(const SnifferIterator &rhs) const {
return sniffer == rhs.sniffer;
}
/**
* Compares this iterator for in-equality.
* \param rhs The iterator to be compared to.
*/
bool operator!=(const SnifferIterator &rhs) const {
return !(*this == rhs);
}
private:
void advance() {
pkt = sniffer->next_packet();
if(!pkt)
sniffer = 0;
}
BaseSniffer *sniffer;
Packet pkt;
};
template<class Functor>
void Tins::BaseSniffer::sniff_loop(Functor function, uint32_t max_packets) {
for(iterator it = begin(); it != end(); ++it) {
try {
// If the functor returns false, we're done
if(!function(*it))
return;
}
catch(malformed_packet&) { }
catch(pdu_not_found&) { }
if(max_packets && --max_packets == 0)
return;
}
}
}
#endif // TINS_SNIFFER_H

View File

@@ -1,526 +0,0 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_TCP_H
#define TINS_TCP_H
#include <list>
#include <vector>
#include <stdint.h>
#include <stdexcept>
#include <utility>
#include "pdu.h"
#include "macros.h"
#include "endianness.h"
#include "small_uint.h"
#include "pdu_option.h"
#include "cxxstd.h"
namespace Tins {
/**
* \brief Class that represents an TCP PDU.
*
* TCP is the representation of the TCP PDU. Instances of this class
* must be sent over a level 3 PDU, this will otherwise fail.
*/
class TCP : public PDU {
public:
/**
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::TCP;
/**
* \brief TCP flags enum.
*
* These flags identify those supported by the TCP PDU.
*/
enum Flags {
FIN = 1,
SYN = 2,
RST = 4,
PSH = 8,
ACK = 16,
URG = 32,
ECE = 64,
CWR = 128
};
/**
* \brief TCP options enum.
*
* This enum identifies valid options supported by TCP PDU.
*/
enum OptionTypes {
EOL = 0,
NOP = 1,
MSS = 2,
WSCALE = 3,
SACK_OK = 4,
SACK = 5,
TSOPT = 8,
ALTCHK = 14
};
/**
* \brief Alternate checksum enum.
*/
enum AltChecksums {
CHK_TCP,
CHK_8FLETCHER,
CHK_16FLETCHER
};
/**
* The type used to store TCP options.
*/
typedef PDUOption<uint8_t, TCP> option;
/**
* The type used to store the options.
*/
typedef std::list<option> options_type;
/**
* The type used to store the sack option.
*/
typedef std::vector<uint32_t> sack_type;
/**
* \brief TCP constructor.
*
* Creates an instance of TCP. Destination and source port can
* be provided, otherwise both will be 0.
* \param dport Destination port.
* \param sport Source port.
* */
TCP(uint16_t dport = 0, uint16_t sport = 0);
/**
* \brief Constructs TCP object from a buffer.
*
* If there is not enough size for a TCP header, or any of the
* TLV options are malformed a malformed_packet exception is
* thrown.
*
* Any extra data will be stored in a RawPDU.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
TCP(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Getter for the destination port field.
*
* \return The destination port in an uint16_t.
*/
uint16_t dport() const { return Endian::be_to_host(_tcp.dport); }
/**
* \brief Getter for the source port field.
*
* \return The source port in an uint16_t.
*/
uint16_t sport() const { return Endian::be_to_host(_tcp.sport); }
/**
* \brief Getter for the sequence number field.
*
* \return The sequence number in an uint32_t.
*/
uint32_t seq() const { return Endian::be_to_host(_tcp.seq); }
/**
* \brief Getter for the acknowledge number field.
*
* \return The acknowledge number in an uint32_t.
*/
uint32_t ack_seq() const { return Endian::be_to_host(_tcp.ack_seq); }
/**
* \brief Getter for the window size field.
*
* \return The window size in an uint32_t.
*/
uint16_t window() const { return Endian::be_to_host(_tcp.window); }
/**
* \brief Getter for the checksum field.
*
* \return The checksum field in an uint16_t.
*/
uint16_t checksum() const { return Endian::be_to_host(_tcp.check); }
/**
* \brief Getter for the urgent pointer field.
*
* \return The urgent pointer in an uint16_t.
*/
uint16_t urg_ptr() const { return Endian::be_to_host(_tcp.urg_ptr); }
/**
* \brief Getter for the data offset field.
*
* \return Data offset in an uint8_t.
*/
small_uint<4> data_offset() const { return this->_tcp.doff; }
/**
* \brief Getter for the option list.
*
* \return The options list.
*/
const options_type &options() const { return _options; }
/**
* \brief Gets the value of a flag.
*
* \param tcp_flag The polled flag.
* \return The value of the flag.
*/
small_uint<1> get_flag(Flags tcp_flag) const;
/**
*
* \brief Gets the flags' values.
*
* All of the set flags will be joined together into
* a 12 bit value. This way, you can check for multiple
* flags at the same time:
*
* \code
* TCP tcp = ...;
* if(tcp.flags() == (TCP::SYN | TCP::ACK))
* // It's a SYN+ACK!
* \endcode
*
* \return The value of the flags field.
*/
small_uint<12> flags() const;
/* Setters */
/**
* \brief Setter for the destination port field.
*
* \param new_dport The new destination port.
*/
void dport(uint16_t new_dport);
/**
* \brief Setter for the source port field.
*
* \param new_sport The new source port.
*/
void sport(uint16_t new_sport);
/**
* \brief Setter for the sequence number.
*
* \param new_seq The new sequence number.
*/
void seq(uint32_t new_seq);
/**
* \brief Setter for the acknowledge number.
*
* \param new_ack_seq The new acknowledge number.
*/
void ack_seq(uint32_t new_ack_seq);
/**
* \brief Setter for the window size.
*
* \param new_window The new window size.
*/
void window(uint16_t new_window);
/**
* \brief Setter for the urgent pointer field.
*
* \param new_urg_ptr The new urgent pointer.
*/
void urg_ptr(uint16_t new_urg_ptr);
/**
* \brief Setter for the data offset pointer field.
*
* \param new_doff The new data offset pointer.
*/
void data_offset(small_uint<4> new_doff);
// Options
/**
* \brief Add a maximum segment size option.
*
* \param value The new maximum segment size.
*/
void mss(uint16_t value);
/**
* \brief Searchs for a maximum segment size option.
* \param value A pointer in which the option's value will be stored.
* \return True if the option was found, false otherwise.
*/
uint16_t mss() const;
/**
* \brief Add a window scale option.
*
* \param value The new window scale.
*/
void winscale(uint8_t value);
/**
* \brief Searchs for a window scale option.
* \param value A pointer in which the option's value will be stored.
* \return True if the option was found, false otherwise.
*/
uint8_t winscale() const;
/**
* \brief Add a sack permitted option.
*/
void sack_permitted();
/**
* \brief Searchs for a sack permitted option.
* \return True if the option was found, false otherwise.
*/
bool has_sack_permitted() const;
/**
* \brief Add a sack option.
*
* \param value The new window scale.
*/
void sack(const sack_type &edges);
/**
* \brief Searchs for a sack option.
* \param value A pointer in which the option's value will be stored.
* \return True if the option was found, false otherwise.
*/
sack_type sack() const;
/**
* \brief Add a timestamp option.
*
* \param value The current value of the timestamp clock.
* \param reply The echo reply field.
*/
void timestamp(uint32_t value, uint32_t reply);
/**
* \brief Searchs for a timestamp option.
* \param value A pointer in which the option's value will be stored.
* \param reply A pointer in which the option's reply value will be stored.
* \return True if the option was found, false otherwise.
*/
std::pair<uint32_t, uint32_t> timestamp() const;
/**
* \brief Add a alternate checksum option.
*
* \param value The new alternate checksum scale.
*/
void altchecksum(AltChecksums value);
/**
* \brief Searchs for a alternate checksum option.
* \param value A pointer in which the option's value will be stored.
* \return True if the option was found, false otherwise.
*/
AltChecksums altchecksum() const;
/**
* \brief Set a TCP flag value.
*
* \param tcp_flag The flag to be set.
* \param value The new value for this flag. Must be 0 or 1.
*/
void set_flag(Flags tcp_flag, small_uint<1> value);
/**
* \brief Sets the value of the flag fields.
*
* This method can be used to set several flags at the
* same time.
*
* \code
* TCP tcp = ...;
* tcp.flags(TCP::SYN | TCP::ACK);
* // ...
* // only set the ACK, keeping the rest of the old flags.
* tcp.flags(tcp.flags() | TCP::ACK);
* \endcode
*
* \param value The new value of the flags.
*/
void flags(small_uint<12> value);
/**
* \brief Adds a TCP option.
*
* \param option The option to be added.
*/
void add_option(const option &opt);
#if TINS_IS_CXX11
/**
* \brief Adds a TCP option.
*
* This move-constructs the option.
*
* \param option The option to be added.
*/
void add_option(option &&opt) {
internal_add_option(opt);
_options.push_back(std::move(opt));
}
/**
* \brief Adds a TCP option using the provided arguments.
*
* The option is constructed from the provided parameters.
*
* \param args The arguments to be used in the option's
* constructor.
*/
template<typename... Args>
void add_option(Args&&... args) {
_options.emplace_back(std::forward<Args>(args)...);
internal_add_option(_options.back());
}
#endif
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. This size includes the
* payload and options size.
*
* \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \brief Getter for the PDU's type.
*
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::TCP; }
/**
* \brief Searchs for an option that matchs the given flag.
* \param opt_flag The flag to be searched.
* \return A pointer to the option, or 0 if it was not found.
*/
const option *search_option(OptionTypes opt) const;
/**
* \sa PDU::clone
*/
TCP *clone() const {
return new TCP(*this);
}
private:
TINS_BEGIN_PACK
struct tcphdr {
uint16_t sport;
uint16_t dport;
uint32_t seq;
uint32_t ack_seq;
#if TINS_IS_LITTLE_ENDIAN
uint16_t res1:4,
doff:4,
fin:1,
syn:1,
rst:1,
psh:1,
ack:1,
urg:1,
ece:1,
cwr:1;
#elif TINS_IS_BIG_ENDIAN
uint16_t doff:4,
res1:4,
cwr:1,
ece:1,
urg:1,
ack:1,
psh:1,
rst:1,
syn:1,
fin:1;
#else
#error "Endian is not LE nor BE..."
#endif
uint16_t window;
uint16_t check;
uint16_t urg_ptr;
} TINS_END_PACK;
static const uint16_t DEFAULT_WINDOW;
template<class T>
T generic_search(OptionTypes opt_type) const {
const option *opt = search_option(opt_type);
if(!opt)
throw option_not_found();
return opt->to<T>();
}
void internal_add_option(const option &option);
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
void checksum(uint16_t new_check);
uint8_t *write_option(const option &opt, uint8_t *buffer);
tcphdr _tcp;
uint16_t _options_size, _total_options_size;
options_type _options;
};
}
#endif // TINS_TCP_H

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -53,9 +53,8 @@ public:
*
* \param first The address held by this iterator.
*/
AddressRangeIterator(const value_type &addr)
: addr(addr), reached_end(false)
{
AddressRangeIterator(const value_type& address)
: address_(address), reached_end_(false) {
}
@@ -64,24 +63,23 @@ public:
*
* \param first The address held by this iterator.
*/
AddressRangeIterator(const value_type &address, end_iterator)
: addr(address)
{
reached_end = Internals::increment(addr);
AddressRangeIterator(const value_type& address, end_iterator)
: address_(address) {
reached_end_ = Internals::increment(address_);
}
/**
* Retrieves the current address pointed by this iterator.
*/
const value_type& operator*() const {
return addr;
return address_;
}
/**
* Retrieves a pointer to the current address pointed by this iterator.
*/
const value_type* operator->() const {
return &addr;
return& address_;
}
/**
@@ -89,8 +87,8 @@ public:
*
* \param rhs The iterator with which to compare.
*/
bool operator==(const AddressRangeIterator &rhs) const {
return reached_end == rhs.reached_end && addr == rhs.addr;
bool operator==(const AddressRangeIterator& rhs) const {
return reached_end_ == rhs.reached_end_ && address_ == rhs.address_;
}
/**
@@ -98,7 +96,7 @@ public:
*
* \param rhs The iterator with which to compare.
*/
bool operator!=(const AddressRangeIterator &rhs) const {
bool operator!=(const AddressRangeIterator& rhs) const {
return !(*this == rhs);
}
@@ -106,8 +104,8 @@ public:
* Increments this iterator.
*/
AddressRangeIterator& operator++() {
reached_end = Internals::increment(addr);
return *this;
reached_end_ = Internals::increment(address_);
return* this;
}
/**
@@ -119,8 +117,8 @@ public:
return copy;
}
private:
Address addr;
bool reached_end;
Address address_;
bool reached_end_;
};
/**
@@ -135,7 +133,7 @@ private:
*
* \code
* auto range = IPv4Address("192.168.5.0") / 24;
* for(const auto &addr : range) {
* for(const auto& addr : range) {
* // process 192.168.5.1-254, .0 and .255 are discarded
* process(addr);
* }
@@ -151,7 +149,7 @@ private:
*
* \code
* AddressRange<IPv4Address> range("192.168.5.0", "192.168.5.255");
* for(const auto &addr : range) {
* for(const auto& addr : range) {
* // process 192.168.5.0-255, no addresses are discarded
* process(addr);
* }
@@ -197,11 +195,11 @@ public:
* \param only_hosts Indicates whether only host addresses
* should be accessed when using iterators.
*/
AddressRange(const address_type &first, const address_type &last, bool only_hosts = false)
: first(first), last(last), only_hosts(only_hosts)
{
if(last < first)
AddressRange(const address_type& first, const address_type& last, bool only_hosts = false)
: first_(first), last_(last), only_hosts_(only_hosts){
if (last_ < first_) {
throw std::runtime_error("Invalid address range");
}
}
/**
@@ -211,7 +209,7 @@ public:
* \param first The base address.
* \param mask The network mask to be used.
*/
static AddressRange from_mask(const address_type &first, const address_type &mask) {
static AddressRange from_mask(const address_type& first, const address_type& mask) {
return AddressRange<address_type>(
first,
Internals::last_address_from_mask(first, mask),
@@ -224,8 +222,8 @@ public:
* \param addr The address to test.
* \return a bool indicating whether the address is in the range.
*/
bool contains(const address_type &addr) const {
return (first < addr && addr < last) || addr == first || addr == last;
bool contains(const address_type& addr) const {
return (first_ < addr && addr < last_) || addr == first_ || addr == last_;
}
/**
@@ -233,9 +231,10 @@ public:
* \brief const_iterator pointing to the beginning of this range.
*/
const_iterator begin() const {
address_type addr = first;
if(only_hosts)
address_type addr = first_;
if (only_hosts_) {
Internals::increment(addr);
}
return const_iterator(addr);
}
@@ -244,9 +243,10 @@ public:
* \brief const_iterator pointing to the end of this range.
*/
const_iterator end() const {
address_type addr = last;
if(only_hosts)
address_type addr = last_;
if (only_hosts_) {
Internals::decrement(addr);
}
return const_iterator(addr, typename const_iterator::end_iterator());
}
@@ -266,21 +266,23 @@ public:
*/
bool is_iterable() const {
// Since first < last, it's iterable
if(!only_hosts)
if (!only_hosts_) {
return true;
}
// We need that distance(first, last) >= 4
address_type addr(first);
for(int i = 0; i < 3; ++i) {
address_type addr(first_);
for (int i = 0; i < 3; ++i) {
// If there's overflow before the last iteration, we're done
if(Internals::increment(addr) && i != 2)
if (Internals::increment(addr) && i != 2) {
return false;
}
}
// If addr <= last, it's OK.
return addr < last || addr == last;
return addr < last_ || addr == last_;
}
private:
address_type first, last;
bool only_hosts;
address_type first_, last_;
bool only_hosts_;
};
/**
@@ -299,12 +301,13 @@ typedef AddressRange<IPv6Address> IPv6Range;
* \param mask The bit-length of the prefix.
*/
template<size_t n>
AddressRange<HWAddress<n> > operator/(const HWAddress<n> &addr, int mask) {
if(mask > 48)
AddressRange<HWAddress<n> > operator/(const HWAddress<n>& addr, int mask) {
if (mask > 48) {
throw std::logic_error("Prefix length cannot exceed 48");
}
HWAddress<n> last_addr;
typename HWAddress<n>::iterator it = last_addr.begin();
while(mask > 8) {
while (mask > 8) {
*it = 0xff;
++it;
mask -= 8;
@@ -318,14 +321,14 @@ AddressRange<HWAddress<n> > operator/(const HWAddress<n> &addr, int mask) {
* \param addr The range's first address.
* \param mask The bit-length of the prefix.
*/
IPv6Range operator/(const IPv6Address &addr, int mask);
IPv6Range operator/(const IPv6Address& addr, int mask);
/**
* \brief Constructs an IPv4Range from a base IPv4Address and a mask.
* \param addr The range's first address.
* \param mask The bit-length of the prefix.
*/
IPv4Range operator/(const IPv4Address &addr, int mask);
IPv4Range operator/(const IPv4Address& addr, int mask);
} // namespace Tins
#endif // TINS_ADDRESS_RANGE

336
include/tins/arp.h Normal file
View File

@@ -0,0 +1,336 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_ARP_H
#define TINS_ARP_H
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
#include "hw_address.h"
#include "ip_address.h"
namespace Tins {
class NetworkInterface;
class EthernetII;
/**
* \class ARP
* \brief Represents an ARP PDU.
*
*/
class TINS_API ARP : public PDU {
public:
/**
* The type of the hardware address.
*/
typedef HWAddress<6> hwaddress_type;
/**
* The type of the IP address.
*/
typedef IPv4Address ipaddress_type;
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::ARP;
/**
* \brief Enum which indicates the type of ARP packet.
*/
enum Flags {
REQUEST = 0x0001,
REPLY = 0x0002
};
/**
* \brief Constructs an ARP object using the provided addresses.
*
* ARP requests and replies can be constructed easily using
* ARP::make_arp_request/reply static member functions.
*
* \sa ARP::make_arp_request
* \sa ARP::make_arp_reply
*
* \param target_ip The target IP address.
* \param sender_ip The sender IP address.
* \param target_hw The target hardware address.
* \param sender_hw The sender hardware address.
*/
ARP(ipaddress_type target_ip = ipaddress_type(),
ipaddress_type sender_ip = ipaddress_type(),
const hwaddress_type& target_hw = hwaddress_type(),
const hwaddress_type& sender_hw = hwaddress_type());
/**
* \brief Constructs an ARP object from a buffer.
*
* If there is not enough size for an ARP header in the buffer,
* a malformed_packet exception is thrown.
*
* If the buffer is bigger than the size of the ARP header,
* then the extra data is stored in a RawPDU.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
ARP(const uint8_t* buffer, uint32_t total_sz);
/* Getters */
/**
* \brief Getter for the sender's hardware address.
*
* \return The sender hardware address.
*/
hwaddress_type sender_hw_addr() const {
return header_.sender_hw_address;
}
/**
* \brief Getter for the sender's IP address.
*
* \return The sender IP address.
*/
ipaddress_type sender_ip_addr() const {
return ipaddress_type(header_.sender_ip_address);
}
/**
* \brief Getter for the target's hardware address.
*
* \return The target hardware address.
*/
hwaddress_type target_hw_addr() const {
return header_.target_hw_address;
}
/**
* \brief Getter for the target's IP address.
*
* \return The target IP address.
*/
ipaddress_type target_ip_addr() const {
return ipaddress_type(header_.target_ip_address);
}
/**
* \brief Getter for the hardware address format field.
*
* \return The hardware address format.
*/
uint16_t hw_addr_format() const {
return Endian::be_to_host(header_.hw_address_format);
}
/**
* \brief Getter for the protocol address format field.
*
* \return The protocol address format.
*/
uint16_t prot_addr_format() const {
return Endian::be_to_host(header_.proto_address_format);
}
/**
* \brief Getter for the hardware address length field.
*
* \return The hardware address length.
*/
uint8_t hw_addr_length() const {
return header_.hw_address_length;
}
/**
* \brief Getter for the protocol address length field.
*
* \return The protocol address length.
*/
uint8_t prot_addr_length() const {
return header_.proto_address_length;
}
/**
* \brief Getter for the ARP opcode field.
*
* \return The ARP opcode.
*/
uint16_t opcode() const {
return Endian::be_to_host(header_.opcode);
}
/**
* \brief Getter for the header size.
* \return Returns the ARP header size.
* \sa PDU::header_size
*/
uint32_t header_size() const;
/* Setters */
/**
* \brief Setter for the sender's hardware address.
*
* \param address The new sender hardware address.
*/
void sender_hw_addr(const hwaddress_type& address);
/**
* \brief Setter for the sender's IP address.
*
* \param address The new sender IP address.
*/
void sender_ip_addr(ipaddress_type address);
/**
* \brief Setter for the target's hardware address.
*
* \param address The new target hardware address.
*/
void target_hw_addr(const hwaddress_type& address);
/**
* \brief Setter for the target's IP address.
*
* \param address The new target IP address.
*/
void target_ip_addr(ipaddress_type address);
/**
* \brief Setter for the hardware address format field.
*
* \param format The new hardware address format.
*/
void hw_addr_format(uint16_t format);
/**
* \brief Setter for the protocol address format field.
*
* \param format The new protocol address format.
*/
void prot_addr_format(uint16_t format);
/**
* \brief Setter for the hardware address length field.
*
* \param length The new hardware address length.
*/
void hw_addr_length(uint8_t length);
/**
* \brief Setter for the protocol address length field.
*
* \param length The new protocol address length.
*/
void prot_addr_length(uint8_t length);
/**
* \brief Setter for the ARP opcode field.
*
* \param code Flag enum value of the ARP opcode to set.
*/
void opcode(Flags code);
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \brief Creates an ARP Request within an EthernetII PDU.
*
* Creates an ARP Request PDU and embeds it inside an EthernetII
* PDU.
*
* \param target The target's IP address.
* \param sender The sender's IP address.
* \param hw_snd The sender's hardware address.
* \return EthernetII object containing the ARP Request.
*/
static EthernetII make_arp_request(ipaddress_type target,
ipaddress_type sender,
const hwaddress_type& hw_snd = hwaddress_type());
/**
* \brief Creates an ARP Reply within an EthernetII PDU.
*
* Creates an ARP Reply PDU and embeds it inside an EthernetII
* PDU.
*
* \param target The target's IP address.
* \param sender The sender's IP address.
* \param hw_tgt The target's hardware address.
* \param hw_snd The sender's hardware address.
* \return EthetnetII containing the ARP Replay.
*/
static EthernetII make_arp_reply(ipaddress_type target,
ipaddress_type sender,
const hwaddress_type& hw_tgt = hwaddress_type(),
const hwaddress_type& hw_snd = hwaddress_type());
/**
* \brief Check whether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
/**
* \sa PDU::clone
*/
ARP* clone() const {
return new ARP(*this);
}
private:
TINS_BEGIN_PACK
struct arp_header {
uint16_t hw_address_format;
uint16_t proto_address_format;
uint8_t hw_address_length;
uint8_t proto_address_length;
uint16_t opcode;
uint8_t sender_hw_address[hwaddress_type::address_size];
uint32_t sender_ip_address;
uint8_t target_hw_address[hwaddress_type::address_size];
uint32_t target_ip_address;
} TINS_END_PACK;
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
arp_header header_;
};
} // Tins
#endif // TINS_ARP_H

364
include/tins/bootp.h Normal file
View File

@@ -0,0 +1,364 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_BOOTP_H
#define TINS_BOOTP_H
#include <stdint.h>
#include <algorithm>
#include <vector>
#include "pdu.h"
#include "macros.h"
#include "endianness.h"
#include "ip_address.h"
#include "hw_address.h"
namespace Tins {
/**
* \class BootP
* \brief Represents a BootP PDU
*/
class TINS_API BootP : public PDU {
public:
/**
* The type of the IP addresses.
*/
typedef IPv4Address ipaddress_type;
/**
* The type of the chaddr field.
*/
typedef HWAddress<16> chaddr_type;
/**
* The type of the vend field.
*/
typedef std::vector<uint8_t> vend_type;
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::BOOTP;
/**
* \brief Enum which contains the different opcodes BootP messages.
*/
enum OpCodes {
BOOTREQUEST = 1,
BOOTREPLY = 2
};
/**
* \brief Creates an instance of BootP.
*
* This sets the size of the vend field to 64, as the BootP RFC
* states.
*/
BootP();
/**
* \brief Constructs a BootP object from a buffer .
*
* If there's not enough size for a BootP header, then a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
* \param vend_field_size The vend field size to allocate.
* Subclasses might use 0 to provide their own interpretation of this field.
*/
BootP(const uint8_t* buffer, uint32_t total_sz, uint32_t vend_field_size = 64);
/* Getters */
/**
* \brief Getter for the opcode field.
* \return The opcode field for this BootP PDU.
*/
uint8_t opcode() const { return bootp_.opcode; }
/**
* \brief Getter for the htype field.
* \return The htype field for this BootP PDU.
*/
uint8_t htype() const { return bootp_.htype; }
/**
* \brief Getter for the hlen field.
* \return The hlen field for this BootP PDU.
*/
uint8_t hlen() const { return bootp_.hlen; }
/**
* \brief Getter for the hops field.
* \return The hops field for this BootP PDU.
*/
uint8_t hops() const { return bootp_.hops; }
/**
* \brief Getter for the xid field.
* \return The xid field for this BootP PDU.
*/
uint32_t xid() const { return Endian::be_to_host(bootp_.xid); }
/**
* \brief Getter for the secs field.
* \return The secs field for this BootP PDU.
*/
uint16_t secs() const { return Endian::be_to_host(bootp_.secs); }
/** \brief Getter for the padding field.
* \return The padding field for this BootP PDU.
*/
uint16_t padding() const { return Endian::be_to_host(bootp_.padding); }
/**
* \brief Getter for the ciaddr field.
* \return The ciaddr field for this BootP PDU.
*/
ipaddress_type ciaddr() const { return ipaddress_type(bootp_.ciaddr); }
/**
* \brief Getter for the yiaddr field.
* \return The yiaddr field for this BootP PDU.
*/
ipaddress_type yiaddr() const { return ipaddress_type(bootp_.yiaddr); }
/**
* \brief Getter for the siaddr field.
* \return The siaddr field for this BootP PDU.
*/
ipaddress_type siaddr() const { return ipaddress_type(bootp_.siaddr); }
/**
* \brief Getter for the giaddr field.
* \return The giaddr field for this BootP PDU.
*/
ipaddress_type giaddr() const { return ipaddress_type(bootp_.giaddr); }
/**
* \brief Getter for the chaddr field.
* \return The chddr field for this BootP PDU.
*/
chaddr_type chaddr() const { return bootp_.chaddr; }
/**
* \brief Getter for the sname field.
* \return The sname field for this BootP PDU.
*/
const uint8_t* sname() const { return bootp_.sname; }
/**
* \brief Getter for the file field.
* \return The file field for this BootP PDU.
*/
const uint8_t* file() const { return bootp_.file; }
/**
* \brief Getter for the vend field.
* \return The vend field for this BootP PDU.
*/
const vend_type& vend() const { return vend_; }
/**
* \brief Getter for the header size.
* \return Returns the BOOTP header size.
* \sa PDU::header_size
*/
uint32_t header_size() const;
/* Setters */
/**
* \brief Setter for the opcode field.
* \param code The opcode to be set.
*/
void opcode(uint8_t code);
/**
* \brief Setter for the hardware type field.
* \param type The hardware type field value to be set.
*/
void htype(uint8_t type);
/**
* \brief Setter for the hlen field.
* \param length The hlen field value to be set.
*/
void hlen(uint8_t length);
/**
* \brief Setter for the hops field.
* \param count The hops field value to be set.
*/
void hops(uint8_t count);
/**
* \brief Setter for the xid field.
* \param identifier The xid to be set.
*/
void xid(uint32_t identifier);
/**
* \brief Setter for the secs field.
* \param value The secs to be set.
*/
void secs(uint16_t value);
/**
* \brief Setter for the padding field.
* \param value The padding to be set.
*/
void padding(uint16_t value);
/**
* \brief Setter for the ciaddr field.
* \param address The ciaddr to be set.
*/
void ciaddr(ipaddress_type address);
/**
* \brief Setter for the yiaddr field.
* \param address The yiaddr to be set.
*/
void yiaddr(ipaddress_type address);
/**
* \brief Setter for the siaddr field.
* \param address The siaddr to be set.
*/
void siaddr(ipaddress_type address);
/**
* \brief Setter for the giaddr field.
* \param address The giaddr to be set.
*/
void giaddr(ipaddress_type address);
/**
* \brief Setter for the chaddr field.
* The new_chaddr pointer must be at least BOOTP::hlen() bytes long.
* \param new_chaddr The chaddr to be set.
*/
template<size_t n>
void chaddr(const HWAddress<n>& new_chaddr) {
// Copy the new addr
uint8_t* end = std::copy(
new_chaddr.begin(),
new_chaddr.begin() + std::min(n, sizeof(bootp_.chaddr)),
bootp_.chaddr
);
// Fill what's left with zeros
if (end < bootp_.chaddr + chaddr_type::address_size) {
std::fill(end, bootp_.chaddr + chaddr_type::address_size, 0);
}
}
/**
* \brief Setter for the sname field.
* \param new_sname The sname to be set.
*/
void sname(const uint8_t* new_sname);
/**
* \brief Setter for the file field.
* \param new_file The file to be set.
*/
void file(const uint8_t* new_file);
/**
* \brief Setter for the vend field.
* \param newvend_ The vend to be set.
*/
void vend(const vend_type& newvend_);
/**
* \brief Check whether ptr points to a valid response for this PDU.
*
* This returns true if the xid field is equal.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \sa PDU::clone
*/
BootP* clone() const {
return new BootP(*this);
}
protected:
/**
* \brief Getter for the vend field.
*
* This getter can be used by subclasses to avoid copying the
* vend field around.
*
* \return The vend field for this BootP PDU.
*/
vend_type& vend() { return vend_; }
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
private:
/**
* Struct that represents the Bootp datagram.
*/
TINS_BEGIN_PACK
struct bootp_header {
uint8_t opcode;
uint8_t htype;
uint8_t hlen;
uint8_t hops;
uint32_t xid;
uint16_t secs;
uint16_t padding;
uint32_t ciaddr;
uint32_t yiaddr;
uint32_t siaddr;
uint32_t giaddr;
uint8_t chaddr[16];
uint8_t sname[64];
uint8_t file[128];
} TINS_END_PACK;
bootp_header bootp_;
vend_type vend_;
};
} // Tins
#endif // TINS_BOOTP_H

View File

@@ -1,3 +1,5 @@
#ifndef TINS_CONFIG_H
#define TINS_CONFIG_H
/* Define if the compiler supports basic C++11 syntax */
#cmakedefine HAVE_CXX11
@@ -7,3 +9,8 @@
/* Have WPA2 decryption library */
#cmakedefine HAVE_WPA2_DECRYPTION
/* Use pcap_sendpacket to send l2 packets */
#cmakedefine HAVE_PACKET_SENDER_PCAP_SENDPACKET
#endif // TINS_CONFIG_H

163
include/tins/constants.h Normal file
View File

@@ -0,0 +1,163 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_CONSTANTS_H
#define TINS_CONSTANTS_H
namespace Tins {
/**
* \brief Constants used in protocols.
*/
namespace Constants {
/** \cond */
struct IP {
/** \endcond */
enum e {
PROTO_IP = 0, // Dummy protocol for TCP.
PROTO_HOPOPTS = 0, // IPv6 Hop-by-Hop options.
PROTO_ICMP = 1, // Internet Control Message Protocol.
PROTO_IGMP = 2, // Internet Group Management Protocol.
PROTO_IPIP = 4, // IPIP tunnels (older KA9Q tunnels use 94).
PROTO_TCP = 6, // Transmission Control Protocol.
PROTO_EGP = 8, // Exterior Gateway Protocol.
PROTO_PUP = 12, // PUP protocol.
PROTO_UDP = 17, // User Datagram Protocol.
PROTO_IDP = 22, // XNS IDP protocol.
PROTO_TP = 29, // SO Transport Protocol Class 4.
PROTO_DCCP = 33, // Datagram Congestion Control Protocol.
PROTO_IPV6 = 41, // IPv6 header.
PROTO_ROUTING = 43, // IPv6 routing header.
PROTO_FRAGMENT = 44, // IPv6 fragmentation header.
PROTO_RSVP = 46, // Reservation Protocol.
PROTO_GRE = 47, // General Routing Encapsulation.
PROTO_ESP = 50, // encapsulating security payload.
PROTO_AH = 51, // authentication header.
PROTO_ICMPV6 = 58, // ICMPv6.
PROTO_NONE = 59, // IPv6 no next header.
PROTO_DSTOPTS = 60, // IPv6 destination options.
PROTO_MTP = 92, // Multicast Transport Protocol.
PROTO_ENCAP = 98, // Encapsulation Header.
PROTO_PIM = 103, // Protocol Independent Multicast.
PROTO_COMP = 108, // Compression Header Protocol.
PROTO_SCTP = 132, // Stream Control Transmission Protocol.
PROTO_UDPLITE = 136, // UDP-Lite protocol.
PROTO_RAW = 255 // Raw IP packets.
};
};
struct Ethernet {
enum e {
UNKNOWN = 0,
SPRITE = 0x0500, // Sprite
IP = 0x0800, // IP
ARP = 0x0806, // Address resolution
MPLS = 0x8847, // MPLS
REVARP = 0x8035, // Reverse ARP
AT = 0x809B, // AppleTalk protocol
AARP = 0x80F3, // AppleTalk ARP
VLAN = 0x8100, // IEEE 802.1Q VLAN tagging
QINQ = 0x88a8, // IEEE 802.1ad VLAN tagging
OLD_QINQ = 0x9100, // IEEE 802.1ad VLAN tagging (old, deprecated, value)
IPX = 0x8137, // IPX
IPV6 = 0x86dd, // IP protocol version 6
PPPOED = 0x8863, // PPPoE Discovery
PPPOES = 0x8864, // PPPoE Session
EAPOL = 0x888e, // EAPOL
LOOPBACK = 0x9000 // used to test interfaces
};
};
struct ARP {
enum e {
NETROM = 0, // From KA9Q: NET/ROM pseudo.
ETHER = 1, // Ethernet 10/100Mbps.
EETHER = 2, // Experimental Ethernet.
AX25 = 3, // AX.25 Level 2.
PRONET = 4, // PROnet token ring.
CHAOS = 5, // Chaosnet.
IEEE802 = 6, // IEEE 802.2 Ethernet/TR/TB.
ARCNET = 7, // ARCnet.
APPLETLK = 8, // APPLEtalk.
DLCI = 15, // Frame Relay DLCI.
ATM = 19, // ATM.
METRICOM = 23, // Metricom STRIP (new IANA id).
IEEE1394 = 24, // IEEE 1394 IPv4 - RFC 2734.
EUI64 = 27, // EUI-64.
INFINIBAND = 32, // InfiniBand.
SLIP = 256,
CSLIP = 257,
SLIP6 = 258,
CSLIP6 = 259,
RSRVD = 260, // Notional KISS type.
ADAPT = 264,
ROSE = 270,
X25 = 271, // CCITT X.25.
HWX25 = 272, // Boards with X.25 in firmware.
PPP = 512,
CISCO = 513, // Cisco HDLC.
HDLC = CISCO,
LAPB = 516, // LAPB.
DDCMP = 517, // Digital's DDCMP.
RAWHDLC = 518, // Raw HDLC.
TUNNEL = 768, // IPIP tunnel.
TUNNEL6 = 769, // IPIP6 tunnel.
FRAD = 770, // Frame Relay Access Device.
SKIP = 771, // SKIP vif.
LOOPBACK = 772, // Loopback device.
LOCALTLK = 773, // Localtalk device.
FDDI = 774, // Fiber Distributed Data Interface.
BIF = 775, // AP1000 BIF.
SIT = 776, // sit0 device - IPv6-in-IPv4.
IPDDP = 777, // IP-in-DDP tunnel.
IPGRE = 778, // GRE over IP.
PIMREG = 779, // PIMSM register interface.
HIPPI = 780, // High Performance Parallel I'face.
ASH = 781, // (Nexus Electronics) Ash.
ECONET = 782, // Acorn Econet.
IRDA = 783, // Linux-IrDA.
FCPP = 784, // Point to point fibrechanel.
FCAL = 785, // Fibrechanel arbitrated loop.
FCPL = 786, // Fibrechanel public loop.
FCFABRIC = 787, // Fibrechanel fabric.
IEEE802_TR = 800, // Magic type ident for TR.
IEEE80211 = 801, // IEEE 802.11.
IEEE80211_PRISM = 802, // IEEE 802.11 + Prism2 header.
IEEE80211_RADIOTAP = 803, // IEEE 802.11 + radiotap header.
IEEE802154 = 804, // IEEE 802.15.4 header.
IEEE802154_PHY = 805, // IEEE 802.15.4 PHY header.
VOID_TYPE = 0xFFFF, // Void type, nothing is known.
NONE = 0xFFFE // Zero header length.
};
};
} // Constants
} // Tins
#endif // TINS_CONSTANTS_H

541
include/tins/crypto.h Normal file
View File

@@ -0,0 +1,541 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "config.h"
#if !defined(TINS_CRYPTO_H) && defined(HAVE_DOT11)
#define TINS_CRYPTO_H
#include <map>
#include <string>
#include <algorithm>
#include <vector>
#include "utils.h"
#include "snap.h"
#include "rawpdu.h"
#include "macros.h"
#include "handshake_capturer.h"
namespace Tins {
class PDU;
class Dot11;
class Dot11Data;
namespace Crypto {
struct RC4Key;
#ifdef HAVE_WPA2_DECRYPTION
namespace WPA2 {
/**
* \brief Class that represents the keys used to decrypt a session.
*/
class TINS_API SessionKeys {
public:
/**
* The size of the Pairwise Master Key.
*/
static const size_t PMK_SIZE;
/**
* The size of the Pairwise Transient Key.
*/
static const size_t PTK_SIZE;
/**
* The type used to hold the PTK (this has to be PTK_SIZE bytes long).
*/
typedef std::vector<uint8_t> ptk_type;
/**
* The type used to hold the PMK (this has to be PMK_SIZE bytes long).
*/
typedef std::vector<uint8_t> pmk_type;
/**
* Default constructs a SessionKeys object.
*/
SessionKeys();
/**
* \brief Constructs an instance using the provided PTK and a flag
* indicating whether it should use ccmp.
*
* \param ptk The PTK to use.
* \param is_ccmp Indicates whether to use CCMP to decrypt this traffic.
*/
SessionKeys(const ptk_type& ptk, bool is_ccmp);
/**
* \brief Constructs an instance using a handshake and a PMK.
*
* This will internally construct the PTK from the input parameters.
*
* \param hs The handshake to use.
* \param pmk The PMK to use.
*/
SessionKeys(const RSNHandshake& hs, const pmk_type& pmk);
/**
* \brief Decrypts a unicast packet.
*
* \param dot11 The encrypted packet to decrypt.
* \param raw The raw layer on the packet to decrypt.
* \return A SNAP layer containing the decrypted traffic or a null pointer
* if decryption failed.
*/
SNAP* decrypt_unicast(const Dot11Data& dot11, RawPDU& raw) const;
/**
* \brief Gets the PTK for this session keys.
* \return The Pairwise Transcient Key.
*/
const ptk_type& get_ptk() const;
/**
* \brief Indicates whether CCMP is used to decrypt packets
* /return true iff CCMP is used.
*/
bool uses_ccmp() const;
private:
SNAP* ccmp_decrypt_unicast(const Dot11Data& dot11, RawPDU& raw) const;
SNAP* tkip_decrypt_unicast(const Dot11Data& dot11, RawPDU& raw) const;
RC4Key generate_rc4_key(const Dot11Data& dot11, const RawPDU& raw) const;
ptk_type ptk_;
bool is_ccmp_;
};
/**
* \brief Represents a WPA2 supplicant's data.
*
* Objects of this class can be given the pre-shared key and the SSID
* of some access point, and this will generate the Pairwise Master Key
* from those parameters.
*/
class TINS_API SupplicantData {
public:
/**
* The type used to store the PMK.
*/
typedef SessionKeys::pmk_type pmk_type;
/**
* \brief Constructs a SupplicantData.
* \param psk The pre-shared key.
* \param ssid The access point's SSID.
*/
SupplicantData(const std::string& psk, const std::string& ssid);
/**
* \brief Getter for the PMK.
* \return The generated PMK.
*/
const pmk_type& pmk() const;
private:
pmk_type pmk_;
};
} // WPA2
#endif // HAVE_WPA2_DECRYPTION
/**
* \brief RC4 Key abstraction.
*/
struct RC4Key {
static const size_t data_size = 256;
/**
* \brief Initializes the key using the provided iterator range.
*
* \param start The start of the range.
* \param end The end of the range.
*/
template<typename ForwardIterator>
RC4Key(ForwardIterator start, ForwardIterator end);
/**
* The actual key data.
*/
uint8_t data[data_size];
};
/**
* \brief Decrypts WEP-encrypted traffic.
*/
class TINS_API WEPDecrypter {
public:
typedef HWAddress<6> address_type;
/**
* \brief Constructs a WEPDecrypter object.
*/
WEPDecrypter();
/**
* \brief Adds a decryption password.
*
* \param addr The access point's BSSID.
* \param password The password which will be used to decrypt
* packets sent from and to the AP identifier by the BSSID addr.
*/
void add_password(const address_type& addr, const std::string& password);
/**
* \brief Removes a decryption password
*
* \param addr The BSSID of the access point.
*/
void remove_password(const address_type& addr);
/**
* \brief Decrypts the provided PDU.
*
* A Dot11Data PDU is looked up inside the provided PDU chain.
* If no such PDU exists or there is no password associated
* with the Dot11 packet's BSSID, then the PDU is left intact.
*
* Otherwise, the packet is decrypted using the given password.
* If the CRC found after decrypting is invalid, false is
* returned.
*
* \return false if no decryption was performed or decryption
* failed, true otherwise.
*/
bool decrypt(PDU& pdu);
private:
typedef std::map<address_type, std::string> passwords_type;
PDU* decrypt(RawPDU& raw, const std::string& password);
passwords_type passwords_;
std::vector<uint8_t> key_buffer_;
};
#ifdef HAVE_WPA2_DECRYPTION
/**
* \brief Decrypts WPA2-encrypted traffic.
*
* This class takes valid PSK and SSID tuples, captures client handshakes,
* and decrypts their traffic afterwards.
*/
class TINS_API WPA2Decrypter {
public:
/*
* \brief The type used to store Dot11 addresses.
*/
typedef HWAddress<6> address_type;
/**
* \brief Represents a pair of mac addresses.
*
* This is used to identify a host and the access point to which
* it is connected. The first element in the pair will always de
* lower or equal than the second one, so that given any host and
* the access point it's connected to, we can uniquely identify
* it with an address pair.
*/
typedef std::pair<address_type, address_type> addr_pair;
/**
* \brief Maps an address pair to the session keys.
*
* This type associates an address pair (host, access point) with the
* session keys, as generated using the packets seen on a handshake.
*
* \sa addr_pair
*/
typedef std::map<addr_pair, WPA2::SessionKeys> keys_map;
/**
* \brief Adds an access points's information.
*
* This associates an SSID with a PSK, and allows the decryption of
* any BSSIDs that broadcast the same SSID.
*
* The decrypter will inspect beacon frames, looking for SSID tags
* that contain the given SSID.
*
* Note that using this overload, the decryption of data frames and
* handshake capturing will be disabled until any access point
* broadcasts the provided SSID(this shouldn't take long at all).
* If this is not the desired behaviour, then you should check out
* the ovther add_ap_data overload.
*
* \param psk The PSK associated with the SSID.
* \param ssid The network's SSID.
*/
void add_ap_data(const std::string& psk, const std::string& ssid);
/**
* \brief Adds a access points's information, including its BSSID.
*
* This overload can be used if the BSSID associated with this SSID is
* known beforehand. The addr parameter indicates which specific BSSID
* is associated to the SSID.
*
* Note that if any other access point broadcasts the provided SSID,
* it will be taken into account as well.
*
* \param psk The PSK associated with this SSID.
* \param ssid The network's SSID.
* \param addr The access point's BSSID.
*/
void add_ap_data(const std::string& psk,
const std::string& ssid,
const address_type& addr);
/**
* \brief Explicitly add decryption keys.
*
* This method associates a pair (host, access point) with the given decryption keys.
* All encrypted packets sent between the given addresses will be decrypted using the
* provided keys.
*
* This method shouldn't normally be required. The WPA2Decrypter will be waiting for
* handshakes and will automatically extract the session keys, decrypting all
* encrypted packets with them. You should only use this method if for some reason
* you know the actual keys being used (because you checked and stored the keys_map
* somewhere).
*
* The actual order of the addresses doesn't matter, this method will make sure
* they're sorted.
*
* \param addresses The address pair (host, access point) to associate.
* \param session_keys The keys to use when decrypting messages sent between the
* given addresses.
*/
void add_decryption_keys(const addr_pair& addresses,
const WPA2::SessionKeys& session_keys);
/**
* \brief Decrypts the provided PDU.
*
* A Dot11Data PDU is looked up inside the provided PDU chain.
* If no such PDU exists or no PSK was associated with the SSID
* broadcasted by the Dot11 packet's BSSID, or no EAPOL handshake
* was captured for the client involved in the communication,
* then the PDU is left intact.
*
* Otherwise, the packet is decrypted using the generated PTK.
* If the resulting MIC is invalid, then the packet is left intact.
*
* \return false if no decryption was performed, or the decryption
* failed, true otherwise.
*/
bool decrypt(PDU& pdu);
/**
* \brief Getter for the keys on this decrypter
*
* The returned map will be populated every time a new, complete, handshake
* is captured.
*
* \return The WPA2Decrypter keys map.
*/
const keys_map& get_keys() const;
private:
typedef std::map<std::string, WPA2::SupplicantData> pmks_map;
typedef std::map<address_type, WPA2::SupplicantData> bssids_map;
void try_add_keys(const Dot11Data& dot11, const RSNHandshake& hs);
addr_pair make_addr_pair(const address_type& addr1, const address_type& addr2) {
return (addr1 < addr2) ?
std::make_pair(addr1, addr2) :
std::make_pair(addr2, addr1);
}
addr_pair extract_addr_pair(const Dot11Data& dot11);
addr_pair extract_addr_pair_dst(const Dot11Data& dot11);
bssids_map::const_iterator find_ap(const Dot11Data& dot11);
void add_access_point(const std::string& ssid, const address_type& addr);
RSNHandshakeCapturer capturer_;
pmks_map pmks_;
bssids_map aps_;
keys_map keys_;
};
#endif // HAVE_WPA2_DECRYPTION
/**
* \brief Pluggable decrypter object which can be used to decrypt
* data on sniffing sessions.
*
* This class holds a decrypter object and a functor, and implements
* a suitable operator() to be used on BaseSniffer::sniff_loop, which
* decrypts packets and forwards them to the given functor.
*/
template<typename Functor, typename Decrypter>
class DecrypterProxy {
public:
/**
* The type of the functor object.
*/
typedef Functor functor_type;
/**
* The type of the decrypter object.
*/
typedef Decrypter decrypter_type;
/**
* \brief Constructs an object from a functor and a decrypter.
* \param func The functor to be used to forward decrypted
* packets.
* \param decrypter The decrypter which will be used to decrypt
* packets
*/
DecrypterProxy(const functor_type& func,
const decrypter_type& decr = decrypter_type());
/**
* \brief Retrieves a reference to the decrypter object.
*/
decrypter_type& decrypter();
/**
* \brief Retrieves a const reference to the decrypter object.
*/
const decrypter_type& decrypter() const;
/**
* \brief The operator() which decrypts packets and forwards
* them to the functor.
*/
bool operator() (PDU& pdu);
private:
Functor functor_;
decrypter_type decrypter_;
};
/**
* \brief Performs RC4 encription/decryption of the given byte range,
* using the provided key.
*
* The decrypted range will be copied to the OutputIterator provided.
*
* \param start The beginning of the range.
* \param start The end of the range.
* \param key The key to be used.
* \param output The iterator in which to write the output.
*/
template<typename ForwardIterator, typename OutputIterator>
void rc4(ForwardIterator start, ForwardIterator end, RC4Key& key, OutputIterator output);
/**
* \brief Wrapper function to create a DecrypterProxy using a
* WEPDecrypter as the Decrypter template parameter.
*
* \param functor The functor to be forwarded to the DecrypterProxy
* constructor.
*/
template<typename Functor>
DecrypterProxy<Functor, WEPDecrypter> make_wep_decrypter_proxy(const Functor& functor);
#ifdef HAVE_WPA2_DECRYPTION
/**
* \brief Wrapper function to create a DecrypterProxy using a
* WPA2Decrypter as the Decrypter template parameter.
*
* \param functor The functor to be forwarded to the DecrypterProxy
* constructor.
*/
template<typename Functor>
DecrypterProxy<Functor, WPA2Decrypter> make_wpa2_decrypter_proxy(const Functor& functor) {
return DecrypterProxy<Functor, WPA2Decrypter>(functor);
}
#endif // HAVE_WPA2_DECRYPTION
// Implementation section
// DecrypterProxy
template<typename Functor, typename Decrypter>
DecrypterProxy<Functor, Decrypter>::DecrypterProxy(const functor_type& func,
const decrypter_type& decr)
: functor_(func), decrypter_(decr) {
}
template<typename Functor, typename Decrypter>
typename DecrypterProxy<Functor, Decrypter>::decrypter_type &
DecrypterProxy<Functor, Decrypter>::decrypter() {
return decrypter_;
}
template<typename Functor, typename Decrypter>
const typename DecrypterProxy<Functor, Decrypter>::decrypter_type &
DecrypterProxy<Functor, Decrypter>::decrypter() const {
return decrypter_;
}
template<typename Functor, typename Decrypter>
bool DecrypterProxy<Functor, Decrypter>::operator() (PDU& pdu) {
return decrypter_.decrypt(pdu) ? functor_(pdu) : true;
}
template<typename Functor>
DecrypterProxy<Functor, WEPDecrypter> make_wep_decrypter_proxy(const Functor& functor) {
return DecrypterProxy<Functor, WEPDecrypter>(functor);
}
// RC4 stuff
template<typename ForwardIterator>
RC4Key::RC4Key(ForwardIterator start, ForwardIterator end) {
for (size_t i = 0; i < data_size; ++i) {
data[i] = static_cast<uint8_t>(i);
}
size_t j = 0;
ForwardIterator iter = start;
for (size_t i = 0; i < data_size; ++i) {
j = (j + data[i] + *iter++) % 256;
if(iter == end) {
iter = start;
}
std::swap(data[i], data[j]);
}
}
template<typename ForwardIterator, typename OutputIterator>
void rc4(ForwardIterator start, ForwardIterator end, RC4Key& key, OutputIterator output) {
size_t i = 0, j = 0;
while (start != end) {
i = (i + 1) % RC4Key::data_size;
j = (j + key.data[i]) % RC4Key::data_size;
std::swap(key.data[i], key.data[j]);
*output++ = *start++ ^ key.data[(key.data[i] + key.data[j]) % RC4Key::data_size];
}
}
} // Crypto
} // Tins
#endif // TINS_CRYPTO_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,6 +30,8 @@
#ifndef TINS_CXXSTD_H
#define TINS_CXXSTD_H
#include "config.h"
#include <memory>
#ifdef __GXX_EXPERIMENTAL_CXX0X__
@@ -38,8 +40,10 @@
#define TINS_CXXSTD_GCC_FIX 0
#endif // __GXX_EXPERIMENTAL_CXX0X__
#ifndef TINS_IS_CXX11
#if !defined(TINS_IS_CXX11) && defined(HAVE_CXX11)
#define TINS_IS_CXX11 (__cplusplus > 199711L || TINS_CXXSTD_GCC_FIX == 1 || _MSC_VER >= 1800)
#elif !defined(TINS_IS_CXX11)
#define TINS_IS_CXX11 0
#endif // TINS_IS_CXX11
namespace Tins{

View File

@@ -0,0 +1,81 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_DATA_LINK_TYPE_H
#define TINS_DATA_LINK_TYPE_H
#include <pcap.h>
namespace Tins {
class EthernetII;
class RadioTap;
class Dot11;
class Dot3;
class SLL;
class Loopback;
class PPI;
/**
* \struct DataLinkType
* \brief Maps a libtins link layer PDU to a libpcap data link identifier.
*
* This is an empty class that should be instantiated with any object that
* represents a link layer PDU (EthernetII, Dot11, RadioTap, etc):
*
* \code
* // Instantiate it and pass it to PacketWriter's constructor.
* PacketWriter writer("file.pcap", DataLinkType<RadioTap>());
* \endcode
*/
template<typename T>
struct DataLinkType;
#define TINS_MAKE_DATA_LINK_TYPE(tins_type, pcap_type) \
template<> \
struct DataLinkType<tins_type> { \
static const int type = pcap_type; \
int get_type() const { \
return type; \
} \
};
TINS_MAKE_DATA_LINK_TYPE(EthernetII, DLT_EN10MB)
TINS_MAKE_DATA_LINK_TYPE(Dot3, DLT_EN10MB)
TINS_MAKE_DATA_LINK_TYPE(SLL, DLT_LINUX_SLL)
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)
#undef TINS_MAKE_DATA_LINK_TYPE
} // Tins
#endif // TINS_DATA_LINK_TYPE_H

526
include/tins/dhcp.h Normal file
View File

@@ -0,0 +1,526 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_DHCP_H
#define TINS_DHCP_H
#include <list>
#include <vector>
#include <string>
#include "bootp.h"
#include "macros.h"
#include "pdu_option.h"
#include "cxxstd.h"
namespace Tins {
/**
* \class DHCP
* \brief Represents the DHCP PDU.
*
* This class represents a DHCP PDU. It contains helpers methods
* which make it easy to set/get specific option values.
*
* Note that when adding options, the "End" option is not added
* automatically, so you will have to add it yourself.
*
* Options can be retrieved easily from DHCP PDUs:
*
* \code
* // Sniff a packet from somewhere
* DHCP dhcp = get_dhcp_from_somewhere();
*
* // This retrieves the Domain Name Servers option and converts
* // it to a std::vector<IPv4Address>. Note that if this option
* // is not present, an option_not_found exception is thrown.
* for(const auto& address : dhcp.domain_name_servers()) {
* // address is an ip
* }
*
* \endcode
*/
class TINS_API DHCP : public BootP {
public:
/**
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::DHCP;
/**
* DHCP flags.
*/
enum Flags {
DISCOVER = 1,
OFFER = 2,
REQUEST = 3,
DECLINE = 4,
ACK = 5,
NAK = 6,
RELEASE = 7,
INFORM = 8
};
/**
* \brief DHCP options enum.
*/
enum OptionTypes {
PAD,
SUBNET_MASK,
TIME_OFFSET,
ROUTERS,
TIME_SERVERS,
NAME_SERVERS,
DOMAIN_NAME_SERVERS,
LOG_SERVERS,
COOKIE_SERVERS,
LPR_SERVERS,
IMPRESS_SERVERS,
RESOURCE_LOCATION_SERVERS,
HOST_NAME,
BOOT_SIZE,
MERIT_DUMP,
DOMAIN_NAME,
SWAP_SERVER,
ROOT_PATH,
EXTENSIONS_PATH,
IP_FORWARDING,
NON_LOCAL_SOURCE_ROUTING,
POLICY_FILTER,
MAX_DGRAM_REASSEMBLY,
DEFAULT_IP_TTL,
PATH_MTU_AGING_TIMEOUT,
PATH_MTU_PLATEAU_TABLE,
INTERFACE_MTU,
ALL_SUBNETS_LOCAL,
BROADCAST_ADDRESS,
PERFORM_MASK_DISCOVERY,
MASK_SUPPLIER,
ROUTER_DISCOVERY,
ROUTER_SOLICITATION_ADDRESS,
STATIC_ROUTES,
TRAILER_ENCAPSULATION,
ARP_CACHE_TIMEOUT,
IEEE802_3_ENCAPSULATION,
DEFAULT_TCP_TTL,
TCP_KEEPALIVE_INTERVAL,
TCP_KEEPALIVE_GARBAGE,
NIS_DOMAIN,
NIS_SERVERS,
NTP_SERVERS,
VENDOR_ENCAPSULATED_OPTIONS,
NETBIOS_NAME_SERVERS,
NETBIOS_DD_SERVER,
NETBIOS_NODE_TYPE,
NETBIOS_SCOPE,
FONT_SERVERS,
X_DISPLAY_MANAGER,
DHCP_REQUESTED_ADDRESS,
DHCP_LEASE_TIME,
DHCP_OPTION_OVERLOAD,
DHCP_MESSAGE_TYPE,
DHCP_SERVER_IDENTIFIER,
DHCP_PARAMETER_REQUEST_LIST,
DHCP_MESSAGE,
DHCP_MAX_MESSAGE_SIZE,
DHCP_RENEWAL_TIME,
DHCP_REBINDING_TIME,
VENDOR_CLASS_IDENTIFIER,
DHCP_CLIENT_IDENTIFIER,
NWIP_DOMAIN_NAME,
NWIP_SUBOPTIONS,
USER_CLASS = 77,
FQDN = 81,
DHCP_AGENT_OPTIONS = 82,
SUBNET_SELECTION = 118,
AUTHENTICATE = 210,
END = 255
};
/**
* The DHCP option type.
*/
typedef PDUOption<uint8_t, DHCP> option;
/**
* The type used to store the DHCP options.
*/
typedef std::list<option> options_type;
/**
* \brief Creates an instance of DHCP.
*
* This sets the hwtype and hlen fields to match the ethernet
* type and length.
*/
DHCP();
/**
* \brief Constructs a DHCP object from a buffer.
*
* If there is not enough size for a BootP header, or any of
* the TLV options contains an invalid size field, then a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
DHCP(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Adds a new option to this DHCP PDU.
* \param opt The option to be added.
*/
void add_option(const option& opt);
#if TINS_IS_CXX11
/**
* \brief Adds a new option to this DHCP PDU.
*
* The option is move-constructed.
*
* \param opt The option to be added.
*/
void add_option(option &&opt) {
internal_add_option(opt);
options_.push_back(std::move(opt));
}
#endif
/**
* \brief Removes a DHCP option.
*
* If there are multiple options of the given type, only the first one
* will be removed.
*
* \param type The type of the option to be removed.
* \return true if the option was removed, false otherwise.
*/
bool remove_option(OptionTypes type);
/**
* \brief Searchs for an option that matchs the given flag.
* \param opt_flag The flag to be searched.
* \return A pointer to the option, or 0 if it was not found.
*/
const option* search_option(OptionTypes opt) const;
/**
* \brief Adds a type option to the option list.
*
* The new option is appended at the end of the list.
*
* \param type The type of this DHCP PDU.
*/
void type(Flags type);
/**
* \brief Adds an end option to the option list.
*
* The new option is appended at the end of the list.
*
* The END option is not added automatically. You should explicitly
* add it at the end of the DHCP options for the PDU to be
* standard-compliant.
*/
void end();
/**
* \brief Adds a server identifier option.
*
* The new option is appended at the end of the list.
*
* \param ip The server's IP address.
*/
void server_identifier(ipaddress_type ip);
/**
* \brief Adds an IP address lease time option.
*
* The new option is appended at the end of the list.
*
* \param time The lease time.
*/
void lease_time(uint32_t time);
/**
* \brief Adds a lease renewal time option.
*
* The new option is appended at the end of the list.
*
* \param time The lease renew time.
*/
void renewal_time(uint32_t time);
/**
* \brief Adds a rebind time option.
*
* The new option is appended at the end of the list.
*
* \param time The lease rebind time.
*/
void rebind_time(uint32_t time);
/**
* \brief Adds a subnet mask option.
*
* The new option is appended at the end of the list.
*
* \param mask The subnet mask.
*/
void subnet_mask(ipaddress_type mask);
/**
* \brief Adds a routers option.
*
* The new option is appended at the end of the list.
*
* \param routers A list of ip addresses.
*/
void routers(const std::vector<ipaddress_type>& routers);
/**
* \brief Adds a domain name servers option.
*
* The new option is appended at the end of the list.
*
* \param dns A list of ip addresses.
*/
void domain_name_servers(const std::vector<ipaddress_type>& dns);
/**
* \brief Adds a broadcast address option.
*
* The new option is appended at the end of the list.
*
* \param addr The broadcast address.
*/
void broadcast(ipaddress_type addr);
/**
* \brief Adds a requested address option.
*
* The new option is appended at the end of the list.
*
* \param addr The requested address.
*/
void requested_ip(ipaddress_type addr);
/**
* \brief Adds a domain name option.
*
* The new option is appended at the end of the list.
*
* \param name The domain name.
*/
void domain_name(const std::string& name);
/**
* \brief Adds a hostname option.
*
* The new option is appended at the end of the list.
*
* \param name The hostname.
*/
void hostname(const std::string& name);
// Option getters
/**
* \brief Searchs for a type option.
*
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return uint8_t containing the type option.
*/
uint8_t type() const;
/**
* \brief Searchs for a server identifier option.
*
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return ipaddress_type Containing the server identifier.
*/
ipaddress_type server_identifier() const;
/**
* \brief Searchs for a lease time option.
*
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return uint32_t Containing the lease time.
*/
uint32_t lease_time() const;
/**
* \brief Searchs for a lease renewal time option.
*
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return uint32_t Containing the renewal time.
*/
uint32_t renewal_time() const;
/**
* \brief Searchs for a rebind time option.
*
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return uint32_t Containing the rebind time.
*/
uint32_t rebind_time() const;
/**
* \brief Searchs for a subnet mask option.
*
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return ipaddress_type Containing the subnet mask.
*/
ipaddress_type subnet_mask() const;
/**
* \brief Searchs for a routers option.
*
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return std::vector<ipaddress_type> Containing the routers
* option data.
*/
std::vector<ipaddress_type> routers() const;
/**
* \brief Searchs for a dns option.
*
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return std::list<ipaddress_type> Contanining the DNS servers
* provided.
*/
std::vector<ipaddress_type> domain_name_servers() const;
/**
* \brief Searchs for a broadcast option.
*
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return ipaddress_type Containing the broadcast address.
*/
ipaddress_type broadcast() const;
/**
* \brief Searchs for a requested option.
*
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return ipaddress_type Containing the requested IP address.
*/
ipaddress_type requested_ip() const;
/**
* \brief Searchs for a domain name option.
*
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return std::string Containing the domain name.
*/
std::string domain_name() const;
/**
* \brief Searchs for a hostname option.
*
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return std::string Containing the hostname.
*/
std::string hostname() const;
/**
* \brief Getter for the options list.
* \return The option list.
*/
const options_type options() const { return options_; }
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \brief Getter for the header size.
* \return Returns the BOOTP header size.
* \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \sa PDU::clone
*/
DHCP* clone() const {
return new DHCP(*this);
}
private:
static const uint32_t MAX_DHCP_SIZE;
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
template <typename T>
T search_and_convert(OptionTypes opt) const {
const option* option = search_option(opt);
if (!option) {
throw option_not_found();
}
return option->to<T>();
}
void internal_add_option(const option& opt);
serialization_type serialize_list(const std::vector<ipaddress_type>& ip_list);
options_type::const_iterator search_option_iterator(OptionTypes opt) const;
options_type::iterator search_option_iterator(OptionTypes opt);
options_type options_;
uint32_t size_;
};
} // Tins
#endif // TINS_DHCP_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,16 +33,24 @@
#include <cstring>
#include <list>
#include "pdu.h"
#include "macros.h"
#include "endianness.h"
#include "small_uint.h"
#include "ipv6_address.h"
#include "pdu_option.h"
namespace Tins {
namespace Tins {
namespace Memory {
class OutputMemoryStream;
} // Memory
/**
* Represents a DHCPv6 PDU.
* \class DHCPv6
* \brief Represents a DHCPv6 PDU.
*/
class DHCPv6 : public PDU {
class TINS_API DHCPv6 : public PDU {
public:
/**
* Represents a DHCPv6 option.
@@ -181,7 +189,7 @@ public:
const options_type& options = options_type())
: id(id), t1(t1), t2(t2), options(options) {}
static ia_na_type from_option(const option &opt);
static ia_na_type from_option(const option& opt);
};
/**
@@ -198,7 +206,7 @@ public:
const options_type& options = options_type())
: id(id), options(options) {}
static ia_ta_type from_option(const option &opt);
static ia_ta_type from_option(const option& opt);
};
/**
@@ -217,7 +225,7 @@ public:
: address(address), preferred_lifetime(preferred_lifetime),
valid_lifetime(valid_lifetime), options(options) {}
static ia_address_type from_option(const option &opt);
static ia_address_type from_option(const option& opt);
};
/**
@@ -232,11 +240,11 @@ public:
authentication_type(uint8_t protocol = 0, uint8_t algorithm = 0,
uint8_t rdm = 0, uint64_t replay_detection = 0,
const auth_info_type &auth_info = auth_info_type())
const auth_info_type& auth_info = auth_info_type())
: protocol(protocol), algorithm(algorithm), rdm(rdm),
replay_detection(replay_detection), auth_info(auth_info) {}
static authentication_type from_option(const option &opt);
static authentication_type from_option(const option& opt);
};
/**
@@ -246,10 +254,10 @@ public:
uint16_t code;
std::string message;
status_code_type(uint16_t code = 0, const std::string &message = "")
status_code_type(uint16_t code = 0, const std::string& message = "")
: code(code), message(message) { }
static status_code_type from_option(const option &opt);
static status_code_type from_option(const option& opt);
};
/**
@@ -262,10 +270,10 @@ public:
data_type data;
vendor_info_type(uint32_t enterprise_number = 0,
const data_type &data = data_type())
const data_type& data = data_type())
: enterprise_number(enterprise_number), data(data) { }
static vendor_info_type from_option(const option &opt);
static vendor_info_type from_option(const option& opt);
};
@@ -282,13 +290,10 @@ public:
typedef std::vector<class_option_data_type> data_type;
data_type data;
user_class_type(const data_type &data = data_type())
: data(data)
{
user_class_type(const data_type& data = data_type())
: data(data) { }
}
static user_class_type from_option(const option &opt);
static user_class_type from_option(const option& opt);
};
/**
@@ -301,11 +306,11 @@ public:
class_data_type vendor_class_data;
vendor_class_type(uint32_t enterprise_number = 0,
const class_data_type &vendor_class_data = class_data_type())
const class_data_type& vendor_class_data = class_data_type())
: enterprise_number(enterprise_number),
vendor_class_data(vendor_class_data) { }
static vendor_class_type from_option(const option &opt);
static vendor_class_type from_option(const option& opt);
};
/**
@@ -321,12 +326,12 @@ public:
lladdress_type lladdress;
duid_llt(uint16_t hw_type = 0, uint32_t time = 0,
const lladdress_type &lladdress = lladdress_type())
const lladdress_type& lladdress = lladdress_type())
: hw_type(hw_type), time(time), lladdress(lladdress) {}
PDU::serialization_type serialize() const;
static duid_llt from_bytes(const uint8_t *buffer, uint32_t total_sz);
static duid_llt from_bytes(const uint8_t* buffer, uint32_t total_sz);
};
/**
@@ -340,12 +345,12 @@ public:
identifier_type identifier;
duid_en(uint32_t enterprise_number = 0,
const identifier_type &identifier = identifier_type())
const identifier_type& identifier = identifier_type())
: enterprise_number(enterprise_number), identifier(identifier) {}
PDU::serialization_type serialize() const;
static duid_en from_bytes(const uint8_t *buffer, uint32_t total_sz);
static duid_en from_bytes(const uint8_t* buffer, uint32_t total_sz);
};
/**
@@ -359,12 +364,12 @@ public:
lladdress_type lladdress;
duid_ll(uint16_t hw_type = 0,
const lladdress_type &lladdress = lladdress_type())
const lladdress_type& lladdress = lladdress_type())
: hw_type(hw_type), lladdress(lladdress) {}
PDU::serialization_type serialize() const;
static duid_ll from_bytes(const uint8_t *buffer, uint32_t total_sz);
static duid_ll from_bytes(const uint8_t* buffer, uint32_t total_sz);
};
/**
@@ -377,19 +382,19 @@ public:
uint16_t id;
data_type data;
duid_type(uint16_t id = 0, const data_type &data = data_type())
duid_type(uint16_t id = 0, const data_type& data = data_type())
: id(id), data(data) {}
duid_type(const duid_llt &identifier)
duid_type(const duid_llt& identifier)
: id(duid_llt::duid_id), data(identifier.serialize()) {}
duid_type(const duid_en &identifier)
duid_type(const duid_en& identifier)
: id(duid_en::duid_id), data(identifier.serialize()) {}
duid_type(const duid_ll &identifier)
duid_type(const duid_ll& identifier)
: id(duid_en::duid_id), data(identifier.serialize()) {}
static duid_type from_option(const option &opt);
static duid_type from_option(const option& opt);
};
/**
@@ -422,7 +427,7 @@ public:
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
DHCPv6(const uint8_t *buffer, uint32_t total_sz);
DHCPv6(const uint8_t* buffer, uint32_t total_sz);
// Getters
@@ -432,7 +437,7 @@ public:
* \return The stored message type field.
*/
MessageType msg_type() const {
return static_cast<MessageType>(header_data[0]);
return static_cast<MessageType>(header_data_[0]);
}
/**
@@ -440,7 +445,9 @@ public:
*
* \return The stored hop count field.
*/
uint8_t hop_count() const { return header_data[1]; }
uint8_t hop_count() const {
return header_data_[1];
}
/**
* \brief Getter for the transaction id field.
@@ -448,7 +455,7 @@ public:
* \return The stored transaction id field.
*/
small_uint<24> transaction_id() const {
return (header_data[1] << 16) | (header_data[2] << 8) | header_data[3];
return (header_data_[1] << 16) | (header_data_[2] << 8) | header_data_[3];
}
/**
@@ -456,21 +463,27 @@ public:
*
* \return The stored peer address field.
*/
const ipaddress_type &peer_address() const { return peer_addr; }
const ipaddress_type& peer_address() const {
return peer_addr_;
}
/**
* \brief Getter for the link address field.
*
* \return The stored link address field.
*/
const ipaddress_type &link_address() const { return link_addr; }
const ipaddress_type& link_address() const {
return link_addr_;
}
/**
* \brief Getter for the DHCPv6 options.
*
* \return The stored options.
*/
const options_type &options() const { return options_; }
const options_type& options() const {
return options_;
}
// Setters
/**
@@ -499,14 +512,14 @@ public:
*
* \param count The new peer address.
*/
void peer_address(const ipaddress_type &addr);
void peer_address(const ipaddress_type& addr);
/**
* \brief Setter for the link address field.
*
* \param count The new link address.
*/
void link_address(const ipaddress_type &addr);
void link_address(const ipaddress_type& addr);
// Option getters
@@ -672,7 +685,7 @@ public:
*
* \param value The new IA_NA option data.
*/
void ia_na(const ia_na_type &value);
void ia_na(const ia_na_type& value);
/**
* \brief Setter for the Identity Association for Temporary
@@ -680,21 +693,21 @@ public:
*
* \param value The new IA_TA option data.
*/
void ia_ta(const ia_ta_type &value);
void ia_ta(const ia_ta_type& value);
/**
* \brief Setter for the Identity Association Address option.
*
* \param value The new IA Address option data.
*/
void ia_address(const ia_address_type &value);
void ia_address(const ia_address_type& value);
/**
* \brief Setter for the Identity Association Address option.
*
* \param value The new Option Request option data.
*/
void option_request(const option_request_type &value);
void option_request(const option_request_type& value);
/**
* \brief Setter for the Preference option.
@@ -715,28 +728,28 @@ public:
*
* \param value The new Relay Message option data.
*/
void relay_message(const relay_msg_type &value);
void relay_message(const relay_msg_type& value);
/**
* \brief Setter for the Authentication option.
*
* \param value The new Authentication option data.
*/
void authentication(const authentication_type &value);
void authentication(const authentication_type& value);
/**
* \brief Setter for the Server Unicast option.
*
* \param value The new Server Unicast option data.
*/
void server_unicast(const ipaddress_type &value);
void server_unicast(const ipaddress_type& value);
/**
* \brief Setter for the Status Code option.
*
* \param value The new Status Code option data.
*/
void status_code(const status_code_type &value);
void status_code(const status_code_type& value);
/**
* \brief Adds a Rapid Commit option.
@@ -748,28 +761,28 @@ public:
*
* \param value The new User Class option data.
*/
void user_class(const user_class_type &value);
void user_class(const user_class_type& value);
/**
* \brief Setter for the Vendor Class option.
*
* \param value The new Vendor Class option data.
*/
void vendor_class(const vendor_class_type &value);
void vendor_class(const vendor_class_type& value);
/**
* \brief Setter for the Vendor-specific Information option.
*
* \param value The new Vendor-specific Information option data.
*/
void vendor_info(const vendor_info_type &value);
void vendor_info(const vendor_info_type& value);
/**
* \brief Setter for the Interface ID option.
*
* \param value The new Interface ID option data.
*/
void interface_id(const interface_id_type &value);
void interface_id(const interface_id_type& value);
/**
* \brief Setter for the Reconfigure Message option.
@@ -788,14 +801,14 @@ public:
*
* \param value The new Client Identifier option data.
*/
void client_id(const duid_type &value);
void client_id(const duid_type& value);
/**
* \brief Setter for the Server Identifier option.
*
* \param value The new Server Identifier option data.
*/
void server_id(const duid_type &value);
void server_id(const duid_type& value);
// Other stuff
@@ -812,18 +825,29 @@ public:
*
* \param opt The option to be added
*/
void add_option(const option &opt);
void add_option(const option& opt);
/**
* \brief Searchs for an option that matchs the given flag.
* \brief Removes a DHCPv6 option.
*
* If there are multiple options of the given type, only the first one
* will be removed.
*
* \param type The type of the option to be removed.
* \return true if the option was removed, false otherwise.
*/
bool remove_option(OptionTypes type);
/**
* \brief Searchs for an option that matchs the given type.
*
* If the option is not found, a null pointer is returned.
* Deleting the returned pointer will result in <b>undefined
* behaviour</b>.
*
* \param id The option identifier to be searched.
* \param type The option identifier to be searched.
*/
const option *search_option(OptionTypes id) const;
const option* search_option(OptionTypes type) const;
// PDU stuff
@@ -835,62 +859,70 @@ public:
uint32_t header_size() const;
/**
* \brief Check wether ptr points to a valid response for this PDU.
* \brief Check whether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \sa PDU::clone
*/
DHCPv6 *clone() const {
DHCPv6* clone() const {
return new DHCPv6(*this);
}
private:
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
uint8_t* write_option(const option &option, uint8_t* buffer) const;
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU *);
void write_option(const option& option, Memory::OutputMemoryStream& stream) const;
options_type::const_iterator search_option_iterator(OptionTypes type) const;
options_type::iterator search_option_iterator(OptionTypes type);
template<template <typename> class Functor>
const option *safe_search_option(OptionTypes opt, uint32_t size) const {
const option *option = search_option(opt);
if(!option || Functor<uint32_t>()(option->data_size(), size))
template <template <typename> class Functor>
const option* safe_search_option(OptionTypes opt, uint32_t size) const {
const option* option = search_option(opt);
if (!option || Functor<uint32_t>()(option->data_size(), size)) {
throw option_not_found();
}
return option;
}
template<typename T>
T search_and_convert(OptionTypes opt) const {
const option *option = search_option(opt);
if(!option)
const option* option = search_option(opt);
if (!option) {
throw option_not_found();
}
return option->to<T>();
}
uint8_t header_data[4];
uint32_t options_size;
ipaddress_type link_addr, peer_addr;
uint8_t header_data_[4];
uint32_t options_size_;
ipaddress_type link_addr_, peer_addr_;
options_type options_;
};
namespace Internals {
template<typename InputIterator>
void class_option_data2option(InputIterator start, InputIterator end,
std::vector<uint8_t>& buffer, size_t start_index = 0)
{
void class_option_data2option(InputIterator start,
InputIterator end,
std::vector<uint8_t>& buffer,
size_t start_index = 0) {
size_t index = start_index;
uint16_t uint16_t_buffer;
while(start != end) {
while (start != end) {
buffer.resize(buffer.size() + sizeof(uint16_t) + start->size());
uint16_t_buffer = Endian::host_to_be<uint16_t>(start->size());
uint16_t_buffer = Endian::host_to_be(static_cast<uint16_t>(start->size()));
std::memcpy(&buffer[index], &uint16_t_buffer, sizeof(uint16_t));
index += sizeof(uint16_t);
std::copy(start->begin(), start->end(), buffer.begin() + index);
@@ -901,28 +933,30 @@ void class_option_data2option(InputIterator start, InputIterator end,
}
template<typename OutputType>
OutputType option2class_option_data(const uint8_t *ptr, uint32_t total_sz)
{
OutputType option2class_option_data(const uint8_t* ptr, uint32_t total_sz) {
typedef typename OutputType::value_type value_type;
OutputType output;
size_t index = 0;
while(index + 2 < total_sz) {
while (index + 2 < total_sz) {
uint16_t size;
std::memcpy(&size, ptr + index, sizeof(uint16_t));
size = Endian::be_to_host(size);
index += sizeof(uint16_t);
if(index + size > total_sz)
if (index + size > total_sz) {
throw option_not_found();
}
output.push_back(
value_type(ptr + index, ptr + index + size)
);
index += size;
}
if(index != total_sz)
if (index != total_sz) {
throw malformed_option();
}
return output;
}
}
}
} // Internals
} // Tins
#endif // TINS_DHCPV6_H

1017
include/tins/dns.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,13 +33,14 @@
#define TINS_DOT11_DOT11_ASSOC_H
#include "../dot11/dot11_mgmt.h"
#include "../macros.h"
namespace Tins {
/**
* \brief Class representing a Disassociation frame in the IEEE 802.11 Protocol.
*
*/
class Dot11Disassoc : public Dot11ManagementFrame {
class TINS_API Dot11Disassoc : public Dot11ManagementFrame {
public:
/**
* \brief This PDU's flag.
@@ -55,8 +56,8 @@ public:
* \param dst_hw_addr The destination hardware address.
* \param src_hw_addr The source hardware address.
*/
Dot11Disassoc(const address_type &dst_hw_addr = address_type(),
const address_type &src_hw_addr = address_type());
Dot11Disassoc(const address_type& dst_hw_addr = address_type(),
const address_type& src_hw_addr = address_type());
/**
* \brief Constructs a Dot11Disassoc object from a buffer and
@@ -72,14 +73,16 @@ public:
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11Disassoc(const uint8_t *buffer, uint32_t total_sz);
Dot11Disassoc(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Getter for the reason code field.
*
* \return The stored reason code.
*/
uint16_t reason_code() const { return Endian::le_to_host(_body.reason_code); }
uint16_t reason_code() const {
return Endian::le_to_host(body_.reason_code);
}
/**
* \brief Setter for the reason code field.
@@ -100,10 +103,12 @@ public:
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \brief Check wether this PDU matches the specified flag.
* \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
@@ -116,24 +121,24 @@ public:
*
* \sa PDU::clone
*/
Dot11Disassoc *clone() const {
Dot11Disassoc* clone() const {
return new Dot11Disassoc(*this);
}
private:
struct DisassocBody {
struct dot11_disassoc_body {
uint16_t reason_code;
};
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
DisassocBody _body;
dot11_disassoc_body body_;
};
/**
* \brief Class representing an Association Request frame in the IEEE 802.11 Protocol.
*
*/
class Dot11AssocRequest : public Dot11ManagementFrame {
class TINS_API Dot11AssocRequest : public Dot11ManagementFrame {
public:
/**
* \brief This PDU's flag.
@@ -149,8 +154,8 @@ public:
* \param dst_hw_addr The destination hardware address.
* \param src_hw_addr The source hardware address.
*/
Dot11AssocRequest(const address_type &dst_hw_addr = address_type(),
const address_type &src_hw_addr = address_type());
Dot11AssocRequest(const address_type& dst_hw_addr = address_type(),
const address_type& src_hw_addr = address_type());
/**
* \brief Constructs a Dot11AssocRequest object from a buffer
@@ -166,7 +171,7 @@ public:
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11AssocRequest(const uint8_t *buffer, uint32_t total_sz);
Dot11AssocRequest(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Getter for the Capabilities Information.
@@ -174,7 +179,9 @@ public:
* \return A constant refereence to the stored Capabilities
* Information field.
*/
const capability_information& capabilities() const { return _body.capability;}
const capability_information& capabilities() const {
return body_.capability;
}
/**
* \brief Getter for the Capabilities Information.
@@ -182,14 +189,18 @@ public:
* \return A refereence to the stored Capabilities Information
* field.
*/
capability_information& capabilities() { return _body.capability;}
capability_information& capabilities() {
return body_.capability;
}
/**
* \brief Getter for the listen interval field.
*
* \return The stored listen interval field.
*/
uint16_t listen_interval() const { return Endian::le_to_host(_body.listen_interval); }
uint16_t listen_interval() const {
return Endian::le_to_host(body_.listen_interval);
}
/**
* \brief Setter for the listen interval field.
@@ -210,10 +221,12 @@ public:
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \brief Check wether this PDU matches the specified flag.
* \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
@@ -226,25 +239,25 @@ public:
*
* \sa PDU::clone
*/
Dot11AssocRequest *clone() const {
Dot11AssocRequest* clone() const {
return new Dot11AssocRequest(*this);
}
private:
struct AssocReqBody {
struct dot11_assoc_request_body {
capability_information capability;
uint16_t listen_interval;
};
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
AssocReqBody _body;
dot11_assoc_request_body body_;
};
/**
* \brief Class representing an Association Response frame in the IEEE 802.11 Protocol.
*
*/
class Dot11AssocResponse : public Dot11ManagementFrame {
class TINS_API Dot11AssocResponse : public Dot11ManagementFrame {
public:
/**
* \brief This PDU's flag.
@@ -260,8 +273,8 @@ public:
* \param dst_hw_addr The destination hardware address.
* \param src_hw_addr The source hardware address.
*/
Dot11AssocResponse(const address_type &dst_hw_addr = address_type(),
const address_type &src_hw_addr = address_type());
Dot11AssocResponse(const address_type& dst_hw_addr = address_type(),
const address_type& src_hw_addr = address_type());
/**
* \brief Constructor which creates a Dot11AssocResponse object
@@ -277,7 +290,7 @@ public:
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11AssocResponse(const uint8_t *buffer, uint32_t total_sz);
Dot11AssocResponse(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Getter for the Capabilities Information field.
@@ -285,7 +298,9 @@ public:
* \return A constant reference to the stored Capabilities
* Information field.
*/
const capability_information& capabilities() const { return _body.capability;}
const capability_information& capabilities() const {
return body_.capability;
}
/**
* \brief Getter for the Capabilities Information field.
@@ -293,21 +308,27 @@ public:
* \return A reference to the stored Capabilities
* Information field.
*/
capability_information& capabilities() { return _body.capability;}
capability_information& capabilities() {
return body_.capability;
}
/**
* \brief Getter for the status code field.
*
* \return The stored status code.
*/
uint16_t status_code() const { return Endian::le_to_host(_body.status_code); }
uint16_t status_code() const {
return Endian::le_to_host(body_.status_code);
}
/**
* \brief Getter for the AID field.
*
* \return The stored AID field.
*/
uint16_t aid() const { return Endian::le_to_host(_body.aid); }
uint16_t aid() const {
return Endian::le_to_host(body_.aid);
}
/**
* \brief Setter for the status code.
@@ -335,10 +356,12 @@ public:
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \brief Check wether this PDU matches the specified flag.
* \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
@@ -351,26 +374,26 @@ public:
*
* \sa PDU::clone
*/
Dot11AssocResponse *clone() const {
Dot11AssocResponse* clone() const {
return new Dot11AssocResponse(*this);
}
private:
struct AssocRespBody {
struct dot11_assoc_response_body {
capability_information capability;
uint16_t status_code;
uint16_t aid;
};
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
AssocRespBody _body;
dot11_assoc_response_body body_;
};
/**
* \brief Class representing an ReAssociation Request frame in the IEEE 802.11 Protocol.
*
*/
class Dot11ReAssocRequest : public Dot11ManagementFrame {
class TINS_API Dot11ReAssocRequest : public Dot11ManagementFrame {
public:
/**
* \brief This PDU's flag.
@@ -386,8 +409,8 @@ public:
* \param dst_hw_addr The destination hardware address.
* \param src_hw_addr The source hardware address.
*/
Dot11ReAssocRequest(const address_type &dst_hw_addr = address_type(),
const address_type &src_hw_addr = address_type());
Dot11ReAssocRequest(const address_type& dst_hw_addr = address_type(),
const address_type& src_hw_addr = address_type());
/**
* \brief Constructs a Dot11AssocRequest object from a buffer
@@ -403,7 +426,7 @@ public:
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11ReAssocRequest(const uint8_t *buffer, uint32_t total_sz);
Dot11ReAssocRequest(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Getter for the Capabilities Information.
@@ -411,7 +434,9 @@ public:
* \return A constant reference to the stored Capabilities
* Information field.
*/
const capability_information& capabilities() const { return _body.capability;}
const capability_information& capabilities() const {
return body_.capability;
}
/**
* \brief Getter for the Capabilities Information.
@@ -419,21 +444,27 @@ public:
* \return A reference to the stored Capabilities Information
* field.
*/
capability_information& capabilities() { return _body.capability;}
capability_information& capabilities() {
return body_.capability;
}
/**
* \brief Getter for the listen interval field.
*
* \return The stored listen interval.
*/
uint16_t listen_interval() const { return Endian::le_to_host(_body.listen_interval); }
uint16_t listen_interval() const {
return Endian::le_to_host(body_.listen_interval);
}
/**
* \brief Getter for the current ap field.
*
* \return The current ap.
*/
address_type current_ap() const { return _body.current_ap; }
address_type current_ap() const {
return body_.current_ap;
}
/**
* \brief Setter for the listen interval field.
@@ -447,7 +478,7 @@ public:
*
* \param new_current_ap The address of the current ap.
*/
void current_ap(const address_type &new_current_ap);
void current_ap(const address_type& new_current_ap);
/**
* \brief Returns the frame's header length.
@@ -461,10 +492,12 @@ public:
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \brief Check wether this PDU matches the specified flag.
* \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
@@ -477,26 +510,26 @@ public:
*
* \sa PDU::clone
*/
Dot11ReAssocRequest *clone() const {
Dot11ReAssocRequest* clone() const {
return new Dot11ReAssocRequest(*this);
}
private:
struct ReAssocReqBody {
struct dot11_reassoc_request_body {
capability_information capability;
uint16_t listen_interval;
uint8_t current_ap[address_type::address_size];
};
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
ReAssocReqBody _body;
dot11_reassoc_request_body body_;
};
/**
* \brief IEEE 802.11 ReAssociation Response frame.
*
*/
class Dot11ReAssocResponse : public Dot11ManagementFrame {
class TINS_API Dot11ReAssocResponse : public Dot11ManagementFrame {
public:
/**
* \brief This PDU's flag.
@@ -512,8 +545,8 @@ public:
* \param dst_hw_addr The destination hardware address.
* \param src_hw_addr The source hardware address.
*/
Dot11ReAssocResponse(const address_type &dst_hw_addr = address_type(),
const address_type &src_hw_addr = address_type());
Dot11ReAssocResponse(const address_type& dst_hw_addr = address_type(),
const address_type& src_hw_addr = address_type());
/**
* \brief Constructs a Dot11ReAssocResponse object from a buffer
@@ -529,7 +562,7 @@ public:
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11ReAssocResponse(const uint8_t *buffer, uint32_t total_sz);
Dot11ReAssocResponse(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Getter for the Capabilities Information.
@@ -537,7 +570,9 @@ public:
* \return A constant reference to the stored Capabilities
* Information field.
*/
const capability_information& capabilities() const { return _body.capability;}
const capability_information& capabilities() const {
return body_.capability;
}
/**
* \brief Getter for the Capabilities Information.
@@ -545,21 +580,27 @@ public:
* \return A reference to the stored Capabilities Information
* field.
*/
capability_information& capabilities() { return _body.capability;}
capability_information& capabilities() {
return body_.capability;
}
/**
* \brief Getter for the status code field.
*
* \return The stored status code.
*/
uint16_t status_code() const { return Endian::le_to_host(_body.status_code); }
uint16_t status_code() const {
return Endian::le_to_host(body_.status_code);
}
/**
* \brief Getter for the AID field.
*
* \return The stored AID field value.
*/
uint16_t aid() const { return Endian::le_to_host(_body.aid); }
uint16_t aid() const {
return Endian::le_to_host(body_.aid);
}
/**
* \brief Setter for the status code field.
@@ -587,10 +628,12 @@ public:
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \brief Check wether this PDU matches the specified flag.
* \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
@@ -603,20 +646,21 @@ public:
*
* \sa PDU::clone
*/
Dot11ReAssocResponse *clone() const {
Dot11ReAssocResponse* clone() const {
return new Dot11ReAssocResponse(*this);
}
private:
struct ReAssocRespBody {
struct dot11_reassoc_response_body {
capability_information capability;
uint16_t status_code;
uint16_t aid;
};
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
ReAssocRespBody _body;
dot11_reassoc_response_body body_;
};
} // namespace Tins
#endif // TINS_DOT11_DOT11_ASSOC_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,12 +33,13 @@
#define TINS_DOT11_DOT11_AUTH_H
#include "../dot11/dot11_mgmt.h"
#include "../macros.h"
namespace Tins {
/**
* \brief IEEE 802.11 Authentication Request frame.
*/
class Dot11Authentication : public Dot11ManagementFrame {
class TINS_API Dot11Authentication : public Dot11ManagementFrame {
public:
/**
* \brief This PDU's flag.
@@ -54,8 +55,8 @@ public:
* \param dst_hw_addr The destination hardware address.
* \param src_hw_addr The source hardware address.
*/
Dot11Authentication(const address_type &dst_hw_addr = address_type(),
const address_type &src_hw_addr = address_type());
Dot11Authentication(const address_type& dst_hw_addr = address_type(),
const address_type& src_hw_addr = address_type());
/**
* \brief Constructs a Dot11Authentication object from a buffer
@@ -71,28 +72,33 @@ public:
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11Authentication(const uint8_t *buffer, uint32_t total_sz);
Dot11Authentication(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Getter for the Authetication Algorithm Number field.
*
* \return The stored authentication algorithm number.
*/
uint16_t auth_algorithm() const {return Endian::le_to_host(_body.auth_algorithm); }
uint16_t auth_algorithm() const {
return Endian::le_to_host(body_.auth_algorithm); }
/**
* \brief Getter for the Authetication Sequence Number field.
*
* \return The stored authentication sequence number.
*/
uint16_t auth_seq_number() const {return Endian::le_to_host(_body.auth_seq_number); }
uint16_t auth_seq_number() const {
return Endian::le_to_host(body_.auth_seq_number);
}
/**
* \brief Getter for the status code field.
*
* \return The stored status code.
*/
uint16_t status_code() const { return Endian::le_to_host(_body.status_code); }
uint16_t status_code() const {
return Endian::le_to_host(body_.status_code);
}
/**
* \brief Setter for the Authetication Algorithm Number field.
@@ -129,10 +135,12 @@ public:
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \brief Check wether this PDU matches the specified flag.
* \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
@@ -145,27 +153,26 @@ public:
*
* \sa PDU::clone
*/
Dot11Authentication *clone() const {
Dot11Authentication* clone() const {
return new Dot11Authentication(*this);
}
private:
struct AuthBody {
struct dot11_auth_body {
uint16_t auth_algorithm;
uint16_t auth_seq_number;
uint16_t status_code;
};
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
AuthBody _body;
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
dot11_auth_body body_;
};
/**
* \brief IEEE 802.11 Deauthentication frame.
*
*/
class Dot11Deauthentication : public Dot11ManagementFrame {
class TINS_API Dot11Deauthentication : public Dot11ManagementFrame {
public:
/**
* \brief This PDU's flag.
@@ -181,8 +188,8 @@ public:
* \param dst_hw_addr The destination hardware address.
* \param src_hw_addr The source hardware address.
*/
Dot11Deauthentication(const address_type &dst_hw_addr = address_type(),
const address_type &src_hw_addr = address_type());
Dot11Deauthentication(const address_type& dst_hw_addr = address_type(),
const address_type& src_hw_addr = address_type());
/**
* \brief Constructs a Dot11Deauthentication object from a buffer
@@ -198,14 +205,16 @@ public:
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11Deauthentication(const uint8_t *buffer, uint32_t total_sz);
Dot11Deauthentication(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Getter for the reason code field.
*
* \return The reason code to be set.
*/
uint16_t reason_code() const { return Endian::le_to_host(_body.reason_code); }
uint16_t reason_code() const {
return Endian::le_to_host(body_.reason_code);
}
/**
* \brief Setter for the reason code field.
@@ -226,10 +235,12 @@ public:
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \brief Check wether this PDU matches the specified flag.
* \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
@@ -242,19 +253,19 @@ public:
*
* \sa PDU::clone
*/
Dot11Deauthentication *clone() const {
Dot11Deauthentication* clone() const {
return new Dot11Deauthentication(*this);
}
private:
struct DeauthBody {
struct dot11_deauth_body {
uint16_t reason_code;
};
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
DeauthBody _body;
dot11_deauth_body body_;
};
} // namespace Tins
#endif // TINS_DOT11_DOT11_AUTH_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -42,12 +42,17 @@
#include "../macros.h"
namespace Tins {
namespace Memory {
class InputMemoryStream;
class OutputMemoryStream;
} // Memory
class RSNInformation;
/**
* \brief Class representing an 802.11 frame.
*/
class Dot11 : public PDU {
class TINS_API Dot11 : public PDU {
public:
/**
* The type used to store hardware addresses.
@@ -187,7 +192,7 @@ public:
*
* \param dst_hw_addr The destination hardware address.
*/
Dot11(const address_type &dst_hw_addr = address_type());
Dot11(const address_type& dst_hw_addr = address_type());
/**
* \brief Constructs 802.11 PDU from a buffer and adds all
@@ -201,91 +206,115 @@ public:
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11(const uint8_t *buffer, uint32_t total_sz);
Dot11(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Getter for the protocol version field.
*
* \return The stored protocol version field.
*/
small_uint<2> protocol() const { return _header.control.protocol; }
small_uint<2> protocol() const {
return header_.control.protocol;
}
/**
* \brief Getter for the Type field.
*
* \return The stored Type field.
*/
small_uint<2> type() const { return _header.control.type; }
small_uint<2> type() const {
return header_.control.type;
}
/**
* \brief Getter for the Subtype field.
*
* \return The stored Subtype field.
*/
small_uint<4> subtype() const { return _header.control.subtype; }
small_uint<4> subtype() const {
return header_.control.subtype;
}
/**
* \brief Getter for the To-DS field.
*
* \return The stored To-DS field.
*/
small_uint<1> to_ds() const { return _header.control.to_ds; }
small_uint<1> to_ds() const {
return header_.control.to_ds;
}
/**
* \brief Getter for the From-DS field.
*
* \return The stored From-DS field.
*/
small_uint<1> from_ds() const { return _header.control.from_ds; }
small_uint<1> from_ds() const {
return header_.control.from_ds;
}
/**
* \brief Getter for the More-Frag field.
*
* \return The stored More-Frag field.
*/
small_uint<1> more_frag() const { return _header.control.more_frag; }
small_uint<1> more_frag() const {
return header_.control.more_frag;
}
/**
* \brief Getter for the Retry field.
*
* \return The stored Retry field.
*/
small_uint<1> retry() const { return _header.control.retry; }
small_uint<1> retry() const {
return header_.control.retry;
}
/**
* \brief Getter for the Power-Management field.
*
* \return The stored Power-Management field.
*/
small_uint<1> power_mgmt() const { return _header.control.power_mgmt; }
small_uint<1> power_mgmt() const {
return header_.control.power_mgmt;
}
/**
* \brief Getter for the WEP field.
*
* \return The stored WEP field.
*/
small_uint<1> wep() const { return _header.control.wep; }
small_uint<1> wep() const {
return header_.control.wep;
}
/**
* \brief Getter for the Order field.
*
* \return The stored Order field.
*/
small_uint<1> order() const { return _header.control.order; }
small_uint<1> order() const {
return header_.control.order;
}
/**
* \brief Getter for the Duration-ID field.
*
* \return The stored Duration-ID field.
*/
uint16_t duration_id() const { return Endian::le_to_host(_header.duration_id); }
uint16_t duration_id() const {
return Endian::le_to_host(header_.duration_id);
}
/**
* \brief Getter for the first address.
*
* \return The stored first address.
*/
address_type addr1() const { return _header.addr1; }
address_type addr1() const {
return header_.addr1;
}
// Setters
@@ -371,7 +400,7 @@ public:
*
* \param new_addr1 The new first address.
*/
void addr1(const address_type &new_addr1);
void addr1(const address_type& new_addr1);
/* Virtual methods */
/**
@@ -382,18 +411,18 @@ public:
*/
uint32_t header_size() const;
#ifndef WIN32
#ifndef _WIN32
/**
* \sa PDU::send()
*/
void send(PacketSender &sender, const NetworkInterface &iface);
#endif // WIN32
void send(PacketSender& sender, const NetworkInterface& iface);
#endif // _WIN32
/**
* \brief Adds a new option to this Dot11 PDU.
* \param opt The option to be added.
*/
void add_option(const option &opt);
void add_option(const option& opt);
#if TINS_IS_CXX11
/**
@@ -405,35 +434,48 @@ public:
*/
void add_option(option &&opt) {
internal_add_option(opt);
_options.push_back(std::move(opt));
options_.push_back(std::move(opt));
}
#endif
/**
* \brief Removes a Dot11 option.
*
* If there are multiple options of the given type, only the first one
* will be removed.
*
* \param type The type of the option to be removed.
* \return true if the option was removed, false otherwise.
*/
bool remove_option(OptionTypes type);
/**
* \brief Looks up a tagged option in the option list.
*
* The returned pointer <b>must not</b> be free'd.
*
* \param opt The option identifier.
* \param type The option identifier.
* \return The option found, or 0 if no such option has been set.
*/
const option *search_option(OptionTypes opt) const;
const option* search_option(OptionTypes type) const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \sa PDU::clone
*/
Dot11 *clone() const {
Dot11* clone() const {
return new Dot11(*this);
}
/**
* \brief Check wether this PDU matches the specified flag.
* \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
@@ -446,7 +488,9 @@ public:
*
* \return The options list.
*/
const options_type &options() const { return _options; }
const options_type& options() const {
return options_;
}
/**
* \brief Allocates an Dot11 PDU from a buffer.
@@ -462,18 +506,18 @@ public:
* \param total_sz The total size of the buffer.
* \return The allocated Dot11 PDU.
*/
static Dot11 *from_bytes(const uint8_t *buffer, uint32_t total_sz);
static Dot11* from_bytes(const uint8_t* buffer, uint32_t total_sz);
protected:
virtual uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz) { return 0; }
virtual uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) { return 0; }
void parse_tagged_parameters(const uint8_t *buffer, uint32_t total_sz);
void add_tagged_option(OptionTypes opt, uint8_t len, const uint8_t *val);
virtual void write_ext_header(Memory::OutputMemoryStream& stream) { }
virtual void write_fixed_parameters(Memory::OutputMemoryStream& stream) { }
void parse_tagged_parameters(Memory::InputMemoryStream& stream);
void add_tagged_option(OptionTypes opt, uint8_t len, const uint8_t* val);
protected:
/**
* Struct that represents the 802.11 header
*/
TINS_BEGIN_PACK
struct ieee80211_header {
struct dot11_header {
TINS_BEGIN_PACK
struct {
#if TINS_IS_LITTLE_ENDIAN
@@ -507,16 +551,19 @@ protected:
} TINS_END_PACK;
private:
Dot11(const ieee80211_header *header_ptr);
Dot11(const dot11_header* header_ptr);
void internal_add_option(const option &opt);
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
void internal_add_option(const option& opt);
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
options_type::const_iterator search_option_iterator(OptionTypes type) const;
options_type::iterator search_option_iterator(OptionTypes type);
ieee80211_header _header;
uint32_t _options_size;
options_type _options;
dot11_header header_;
uint32_t options_size_;
options_type options_;
};
}
} // Tins
#endif // TINS_DOT11_DOT11_H

View File

@@ -0,0 +1,179 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "../config.h"
#if !defined(TINS_DOT11_DOT11_BEACON_H) && defined(HAVE_DOT11)
#define TINS_DOT11_DOT11_BEACON_H
#include "../dot11/dot11_mgmt.h"
#include "../macros.h"
namespace Tins {
/**
* \brief Represents an IEEE 802.11 Beacon.
*
*/
class TINS_API Dot11Beacon : public Dot11ManagementFrame {
public:
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::DOT11_BEACON;
/**
* \brief Constructor for creating a 802.11 Beacon.
*
* Constructs a 802.11 Beacon taking destination and source
* hardware address.
*
* \param dst_hw_addr The destination hardware address.
* \param src_hw_addr The source hardware address.
*/
Dot11Beacon(const address_type& dst_hw_addr = address_type(),
const address_type& src_hw_addr = address_type());
/**
* \brief Constructs a Dot11Beacon object from a buffer and adds
* all identifiable PDUs found in the buffer as children of this
* one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for the header in the buffer
* or the input data is malformed, a malformed_packet exception
* is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11Beacon(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Getter for the timestamp field.
*
* \return The stored timestamp value.
*/
uint64_t timestamp() const {
return Endian::le_to_host(body_.timestamp);
}
/**
* \brief Getter for the interval field.
*
* \return The stored interval value.
*/
uint16_t interval() const {
return Endian::le_to_host(body_.interval);
}
/**
* \brief Getter for the Capabilities Information structure.
*
* \return A constant refereence to the stored Capabilities
* Information field.
*/
const capability_information& capabilities() const {
return body_.capability;
}
/**
* \brief Getter for the Capabilities Information.
*
* \return A refereence to the stored Capabilities Information
* field.
*/
capability_information& capabilities() {
return body_.capability;
}
/**
* \brief Setter for the timestamp field.
*
* \param new_timestamp The timestamp to be set.
*/
void timestamp(uint64_t new_timestamp);
/**
* \brief Setter for the interval field.
*
* \param new_interval The interval to be set.
*/
void interval(uint16_t new_interval);
/**
* \brief Returns the frame's header length.
*
* \return An uint32_t with the header's size.
* \sa PDU::header_size()
*/
uint32_t header_size() const;
/**
* \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
}
/**
* \brief Clones this PDU.
*
* \sa PDU::clone
*/
Dot11Beacon* clone() const {
return new Dot11Beacon(*this);
}
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const {
return pdu_flag;
}
private:
TINS_BEGIN_PACK
struct dot11_beacon_body {
uint64_t timestamp;
uint16_t interval;
capability_information capability;
} TINS_END_PACK;
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
dot11_beacon_body body_;
};
} // namespace Tins
#endif // TINS_DOT11_DOT11_BEACON_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,12 +34,13 @@
#define TINS_DOT11_DOT11_CONTROL_H
#include "../dot11/dot11_base.h"
#include "../macros.h"
namespace Tins {
/**
* \brief Class that represents an 802.11 control frame.
* \brief Represents an IEEE 802.11 control frame.
*/
class Dot11Control : public Dot11 {
class TINS_API Dot11Control : public Dot11 {
public:
/**
* \brief This PDU's flag.
@@ -54,7 +55,7 @@ public:
*
* \param dst_addr The destination hardware address.
*/
Dot11Control(const address_type &dst_addr = address_type());
Dot11Control(const address_type& dst_addr = address_type());
/**
* \brief Constructs a Dot11Control object from a buffer and
@@ -70,21 +71,23 @@ public:
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11Control(const uint8_t *buffer, uint32_t total_sz);
Dot11Control(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::DOT11_CONTROL; }
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \brief Check wether this PDU matches the specified flag.
* \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) const {
return flag == PDU::DOT11_CONTROL || Dot11::matches_flag(flag);
return flag == pdu_flag || Dot11::matches_flag(flag);
}
};
@@ -92,18 +95,20 @@ public:
* \brief Class that represents an abstraction of the 802.11 control frames
* that contain a target address.
*/
class Dot11ControlTA : public Dot11Control {
class TINS_API Dot11ControlTA : public Dot11Control {
public:
/**
* \brief Getter for the target address field.
*/
address_type target_addr() const { return _taddr; }
address_type target_addr() const {
return taddr_;
}
/**
* \brief Setter for the target address field.
* \param addr The new target address.
*/
void target_addr(const address_type &addr);
void target_addr(const address_type& addr);
protected:
/**
* \brief Constructor for creating a 802.11 control frame TA PDU
@@ -114,8 +119,8 @@ protected:
* \param dst_addr The destination hardware address.
* \param target_addr The source hardware address.
*/
Dot11ControlTA(const address_type &dst_addr = address_type(),
const address_type &target_addr = address_type());
Dot11ControlTA(const address_type& dst_addr = address_type(),
const address_type& target_addr = address_type());
/**
* \brief Constructs a Dot11ControlTA object from a buffer and
@@ -131,7 +136,7 @@ protected:
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11ControlTA(const uint8_t *buffer, uint32_t total_sz);
Dot11ControlTA(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Returns the 802.11 frame's header length.
@@ -144,18 +149,20 @@ protected:
/**
* \brief Getter for the control ta additional fields size.
*/
uint32_t controlta_size() const { return _taddr.size() + sizeof(ieee80211_header); }
uint32_t controlta_size() const {
return static_cast<uint32_t>(taddr_.size() + sizeof(dot11_header));
}
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
void write_ext_header(Memory::OutputMemoryStream& stream);
private:
address_type _taddr;
address_type taddr_;
};
/**
* \brief IEEE 802.11 RTS frame.
*/
class Dot11RTS : public Dot11ControlTA {
class TINS_API Dot11RTS : public Dot11ControlTA {
public:
/**
* \brief This PDU's flag.
@@ -171,8 +178,8 @@ public:
* \param dst_addr The destination hardware address.
* \param target_addr The source hardware address.
*/
Dot11RTS(const address_type &dst_addr = address_type(),
const address_type &target_addr = address_type());
Dot11RTS(const address_type& dst_addr = address_type(),
const address_type& target_addr = address_type());
/**
* \brief Constructs a Dot11RTS object from a buffer and adds all
@@ -187,14 +194,14 @@ public:
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11RTS(const uint8_t *buffer, uint32_t total_sz);
Dot11RTS(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Clones this PDU.
*
* \sa PDU::clone
*/
Dot11RTS *clone() const {
Dot11RTS* clone() const {
return new Dot11RTS(*this);
}
@@ -202,10 +209,12 @@ public:
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \brief Check wether this PDU matches the specified flag.
* \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
@@ -214,7 +223,7 @@ public:
}
};
class Dot11PSPoll : public Dot11ControlTA {
class TINS_API Dot11PSPoll : public Dot11ControlTA {
public:
/**
* \brief This PDU's flag.
@@ -230,8 +239,8 @@ public:
* \param dst_addr The destination hardware address.
* \param target_addr The source hardware address.
*/
Dot11PSPoll(const address_type &dst_addr = address_type(),
const address_type &target_addr = address_type());
Dot11PSPoll(const address_type& dst_addr = address_type(),
const address_type& target_addr = address_type());
/**
* \brief Constructs a Dot11PSPoll object from a buffer and
@@ -247,14 +256,14 @@ public:
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11PSPoll(const uint8_t *buffer, uint32_t total_sz);
Dot11PSPoll(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Clones this PDU.
*
* \sa PDU::clone
*/
Dot11PSPoll *clone() const {
Dot11PSPoll* clone() const {
return new Dot11PSPoll(*this);
}
@@ -262,10 +271,12 @@ public:
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \brief Check wether this PDU matches the specified flag.
* \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
@@ -274,7 +285,7 @@ public:
}
};
class Dot11CFEnd : public Dot11ControlTA {
class TINS_API Dot11CFEnd : public Dot11ControlTA {
public:
/**
* \brief This PDU's flag.
@@ -290,8 +301,8 @@ public:
* \param dst_addr The destination hardware address.
* \param target_addr The source hardware address.
*/
Dot11CFEnd(const address_type &dst_addr = address_type(),
const address_type &target_addr = address_type());
Dot11CFEnd(const address_type& dst_addr = address_type(),
const address_type& target_addr = address_type());
/**
* \brief Constructs a Dot11CFEnd object from a buffer and adds
@@ -307,14 +318,14 @@ public:
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11CFEnd(const uint8_t *buffer, uint32_t total_sz);
Dot11CFEnd(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Clones this PDU.
*
* \sa PDU::clone
*/
Dot11CFEnd *clone() const {
Dot11CFEnd* clone() const {
return new Dot11CFEnd(*this);
}
@@ -322,19 +333,21 @@ public:
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \brief Check wether this PDU matches the specified flag.
* \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11Control::matches_flag(flag);
return flag == pdu_flag || Dot11Control::matches_flag(flag);
}
};
class Dot11EndCFAck : public Dot11ControlTA {
class TINS_API Dot11EndCFAck : public Dot11ControlTA {
public:
/**
* \brief This PDU's flag.
@@ -350,8 +363,8 @@ public:
* \param dst_addr The destination hardware address.
* \param target_addr The source hardware address.
*/
Dot11EndCFAck(const address_type &dst_addr = address_type(),
const address_type &target_addr = address_type());
Dot11EndCFAck(const address_type& dst_addr = address_type(),
const address_type& target_addr = address_type());
/**
* \brief Constructs a Dot11EndCFAck frame object from a buffer
@@ -367,14 +380,14 @@ public:
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11EndCFAck(const uint8_t *buffer, uint32_t total_sz);
Dot11EndCFAck(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Clones this PDU.
*
* \sa PDU::clone
*/
Dot11EndCFAck *clone() const {
Dot11EndCFAck* clone() const {
return new Dot11EndCFAck(*this);
}
@@ -382,19 +395,21 @@ public:
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \brief Check wether this PDU matches the specified flag.
* \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11Control::matches_flag(flag);
return flag == pdu_flag || Dot11Control::matches_flag(flag);
}
};
class Dot11Ack : public Dot11Control {
class TINS_API Dot11Ack : public Dot11Control {
public:
/**
* \brief This PDU's flag.
@@ -409,7 +424,7 @@ public:
*
* \param dst_addr The destination hardware address.
*/
Dot11Ack(const address_type &dst_addr = address_type());
Dot11Ack(const address_type& dst_addr = address_type());
/**
* \brief Constructs a Dot11Ack frame object from a buffer and
@@ -425,14 +440,14 @@ public:
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11Ack(const uint8_t *buffer, uint32_t total_sz);
Dot11Ack(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Clones this PDU.
*
* \sa PDU::clone
*/
Dot11Ack *clone() const {
Dot11Ack* clone() const {
return new Dot11Ack(*this);
}
@@ -440,22 +455,24 @@ public:
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \brief Check wether this PDU matches the specified flag.
* \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11Control::matches_flag(flag);
return flag == pdu_flag || Dot11Control::matches_flag(flag);
}
};
/**
* \brief Class that represents an 802.11 Block Ack Request PDU.
*/
class Dot11BlockAckRequest : public Dot11ControlTA {
class TINS_API Dot11BlockAckRequest : public Dot11ControlTA {
public:
/**
* \brief This PDU's flag.
@@ -471,8 +488,8 @@ public:
* \param dst_addr The destination hardware address.
* \param target_addr The source hardware address.
*/
Dot11BlockAckRequest(const address_type &dst_addr = address_type(),
const address_type &target_addr = address_type());
Dot11BlockAckRequest(const address_type& dst_addr = address_type(),
const address_type& target_addr = address_type());
/**
* \brief Constructs a Dot11BlockAckRequest object from a buffer
@@ -488,7 +505,7 @@ public:
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11BlockAckRequest(const uint8_t *buffer, uint32_t total_sz);
Dot11BlockAckRequest(const uint8_t* buffer, uint32_t total_sz);
/* Getter */
@@ -498,9 +515,9 @@ public:
*/
small_uint<4> bar_control() const {
#if TINS_IS_LITTLE_ENDIAN
return _bar_control & 0xf;
return bar_control_ & 0xf;
#else
return (_bar_control >> 8) & 0xf;
return (bar_control_ >> 8) & 0xf;
#endif
}
@@ -510,9 +527,9 @@ public:
*/
small_uint<12> start_sequence() const {
#if TINS_IS_LITTLE_ENDIAN
return (_start_sequence >> 4) & 0xfff;
return (start_sequence_ >> 4) & 0xfff;
#else
return (Endian::le_to_host<uint16_t>(_start_sequence) >> 4) & 0xfff;
return (Endian::le_to_host<uint16_t>(start_sequence_) >> 4) & 0xfff;
#endif
}
@@ -522,9 +539,9 @@ public:
*/
small_uint<4> fragment_number() const {
#if TINS_IS_LITTLE_ENDIAN
return _start_sequence & 0xf;
return start_sequence_ & 0xf;
#else
return (_start_sequence >> 8) & 0xf;
return (start_sequence_ >> 8) & 0xf;
#endif
}
@@ -561,7 +578,7 @@ public:
*
* \sa PDU::clone
*/
Dot11BlockAckRequest *clone() const {
Dot11BlockAckRequest* clone() const {
return new Dot11BlockAckRequest(*this);
}
@@ -569,29 +586,29 @@ public:
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \brief Check wether this PDU matches the specified flag.
* \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11Control::matches_flag(flag);
return flag == pdu_flag || Dot11Control::matches_flag(flag);
}
protected:
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
void write_ext_header(Memory::OutputMemoryStream& stream);
private:
void init_block_ack();
uint16_t _bar_control;
uint16_t _start_sequence;
uint16_t bar_control_;
uint16_t start_sequence_;
};
/**
* \brief Class that represents an 802.11 block ack frame.
*/
class Dot11BlockAck : public Dot11ControlTA {
class TINS_API Dot11BlockAck : public Dot11ControlTA {
public:
/**
* \brief This PDU's flag.
@@ -612,8 +629,8 @@ public:
* \param dst_addr The destination hardware address.
* \param target_addr The source hardware address.
*/
Dot11BlockAck(const address_type &dst_addr = address_type(),
const address_type &target_addr = address_type());
Dot11BlockAck(const address_type& dst_addr = address_type(),
const address_type& target_addr = address_type());
/**
* \brief Constructs a Dot11BlockAck frame object from a buffer
@@ -629,7 +646,7 @@ public:
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11BlockAck(const uint8_t *buffer, uint32_t total_sz);
Dot11BlockAck(const uint8_t* buffer, uint32_t total_sz);
/* Getters */
@@ -639,9 +656,9 @@ public:
*/
small_uint<4> bar_control() const {
#if TINS_IS_LITTLE_ENDIAN
return _bar_control & 0xf;
return bar_control_ & 0xf;
#else
return (_bar_control >> 8) & 0xf;
return (bar_control_ >> 8) & 0xf;
#endif
}
@@ -651,9 +668,9 @@ public:
*/
small_uint<12> start_sequence() const {
#if TINS_IS_LITTLE_ENDIAN
return (_start_sequence >> 4) & 0xfff;
return (start_sequence_ >> 4) & 0xfff;
#else
return (Endian::le_to_host<uint16_t>(_start_sequence) >> 4) & 0xfff;
return (Endian::le_to_host<uint16_t>(start_sequence_) >> 4) & 0xfff;
#endif
}
@@ -663,9 +680,9 @@ public:
*/
small_uint<4> fragment_number() const {
#if TINS_IS_LITTLE_ENDIAN
return _start_sequence & 0xf;
return start_sequence_ & 0xf;
#else
return (_start_sequence >> 8) & 0xf;
return (start_sequence_ >> 8) & 0xf;
#endif
}
@@ -704,27 +721,31 @@ public:
*
* \return The bitmap field.
*/
const uint8_t *bitmap() const { return _bitmap; }
const uint8_t* bitmap() const {
return bitmap_;
}
/**
* \brief Setter for the bitmap field.
* \param bit The new bitmap field to be set.
*/
void bitmap(const uint8_t *bit);
void bitmap(const uint8_t* bit);
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \brief Check wether this PDU matches the specified flag.
* \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11Control::matches_flag(flag);
return flag == pdu_flag || Dot11Control::matches_flag(flag);
}
/**
@@ -732,15 +753,16 @@ public:
*
* \sa PDU::clone
*/
Dot11BlockAck *clone() const {
Dot11BlockAck* clone() const {
return new Dot11BlockAck(*this);
}
private:
void init_block_ack();
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
void write_ext_header(Memory::OutputMemoryStream& stream);
uint16_t _bar_control, _start_sequence;
uint8_t _bitmap[bitmap_size];
uint16_t bar_control_, start_sequence_;
uint8_t bitmap_[bitmap_size];
};
} // namespace Tins
#endif // TINS_DOT11_DOT11_CONTROL_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,9 +33,14 @@
#define TINS_DOT11_DOT11_DATA_H
#include "../dot11/dot11_base.h"
#include "../macros.h"
namespace Tins {
class Dot11Data : public Dot11 {
/**
* \brief Represents an IEEE 802.11 data frame
*/
class TINS_API Dot11Data : public Dot11 {
public:
/**
* \brief This PDU's flag.
@@ -51,8 +56,8 @@ public:
* \param dst_hw_addr The destination hardware address.
* \param src_hw_addr The source hardware address.
*/
Dot11Data(const address_type &dst_hw_addr = address_type(),
const address_type &src_hw_addr = address_type());
Dot11Data(const address_type& dst_hw_addr = address_type(),
const address_type& src_hw_addr = address_type());
/**
* \brief Constructs a Dot11Data object from a buffer and adds
@@ -68,21 +73,25 @@ public:
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11Data(const uint8_t *buffer, uint32_t total_sz);
Dot11Data(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Getter for the second address.
*
* \return The stored second address.
*/
address_type addr2() const { return _ext_header.addr2; }
address_type addr2() const {
return ext_header_.addr2;
}
/**
* \brief Getter for the third address.
*
* \return The stored third address.
*/
address_type addr3() const { return _ext_header.addr3; }
address_type addr3() const {
return ext_header_.addr3;
}
/**
* \brief Getter for the fragment number field.
@@ -91,9 +100,9 @@ public:
*/
small_uint<4> frag_num() const {
#if TINS_IS_LITTLE_ENDIAN
return _ext_header.frag_seq & 0xf;
return ext_header_.frag_seq & 0xf;
#else
return (_ext_header.frag_seq >> 8) & 0xf;
return (ext_header_.frag_seq >> 8) & 0xf;
#endif
}
@@ -104,9 +113,9 @@ public:
*/
small_uint<12> seq_num() const {
#if TINS_IS_LITTLE_ENDIAN
return (_ext_header.frag_seq >> 4) & 0xfff;
return (ext_header_.frag_seq >> 4) & 0xfff;
#else
return (Endian::le_to_host<uint16_t>(_ext_header.frag_seq) >> 4) & 0xfff;
return (Endian::le_to_host<uint16_t>(ext_header_.frag_seq) >> 4) & 0xfff;
#endif
}
@@ -115,21 +124,23 @@ public:
*
* \return The fourth address.
*/
address_type addr4() const { return _addr4; }
address_type addr4() const {
return addr4_;
}
/**
* \brief Setter for the second address.
*
* \param new_addr2 The second address to be set.
*/
void addr2(const address_type &new_addr2);
void addr2(const address_type& new_addr2);
/**
* \brief Setter for the third address.
*
* \param new_addr3 The third address to be set.
*/
void addr3(const address_type &new_addr3);
void addr3(const address_type& new_addr3);
/**
* \brief Setter for the fragment number field.
@@ -150,7 +161,7 @@ public:
*
* \param new_addr4 The fourth address to be set.
*/
void addr4(const address_type &new_addr4);
void addr4(const address_type& new_addr4);
/**
* \brief Retrieves the frame's source address.
@@ -161,10 +172,12 @@ public:
* If FromDS == ToDS == 1, the return value is not defined.
*/
address_type src_addr() const {
if(!from_ds() && !to_ds())
if (!from_ds() && !to_ds()) {
return addr2();
if(!from_ds() && to_ds())
}
if (!from_ds() && to_ds()) {
return addr2();
}
return addr3();
}
@@ -177,10 +190,12 @@ public:
* If FromDS == ToDS == 1, the return value is not defined.
*/
address_type dst_addr() const {
if(!from_ds() && !to_ds())
if (!from_ds() && !to_ds()) {
return addr1();
if(!from_ds() && to_ds())
}
if (!from_ds() && to_ds()) {
return addr3();
}
return addr1();
}
@@ -193,10 +208,12 @@ public:
* If FromDS == ToDS == 1, the return value is not defined.
*/
address_type bssid_addr() const {
if(!from_ds() && !to_ds())
if (!from_ds() && !to_ds()) {
return addr3();
if(!from_ds() && to_ds())
}
if (!from_ds() && to_ds()) {
return addr1();
}
return addr2();
}
@@ -212,10 +229,12 @@ public:
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \brief Check wether this PDU matches the specified flag.
* \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
@@ -228,33 +247,28 @@ public:
*
* \sa PDU::clone
*/
Dot11Data *clone() const {
Dot11Data* clone() const {
return new Dot11Data(*this);
}
protected:
TINS_BEGIN_PACK
struct ExtendedHeader {
struct dot11_extended_header {
uint8_t addr2[address_type::address_size];
uint8_t addr3[address_type::address_size];
uint16_t frag_seq;
} TINS_END_PACK;
struct no_inner_pdu { };
Dot11Data(const uint8_t *buffer, uint32_t total_sz, no_inner_pdu);
Dot11Data(const uint8_t* buffer, uint32_t total_sz, no_inner_pdu);
uint32_t init(const uint8_t *buffer, uint32_t total_sz);
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
uint32_t data_frame_size() {
return Dot11::header_size() + sizeof(_ext_header) +
((from_ds() && to_ds()) ? _addr4.size() : 0);
}
uint32_t init(const uint8_t* buffer, uint32_t total_sz);
void write_ext_header(Memory::OutputMemoryStream& stream);
private:
ExtendedHeader _ext_header;
address_type _addr4;
dot11_extended_header ext_header_;
address_type addr4_;
};
class Dot11QoSData : public Dot11Data {
class TINS_API Dot11QoSData : public Dot11Data {
public:
/**
* \brief This PDU's flag.
@@ -270,8 +284,8 @@ public:
* \param dst_hw_addr The destination hardware address.
* \param src_hw_addr The source hardware address.
*/
Dot11QoSData(const address_type &dst_hw_addr = address_type(),
const address_type &src_hw_addr = address_type());
Dot11QoSData(const address_type& dst_hw_addr = address_type(),
const address_type& src_hw_addr = address_type());
/**
* \brief Constructors Dot11QoSData object from a buffer and adds
@@ -287,14 +301,16 @@ public:
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11QoSData(const uint8_t *buffer, uint32_t total_sz);
Dot11QoSData(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Getter for the QOS Control field.
*
* \return The stored QOS Control field value.
*/
uint16_t qos_control() const { return Endian::le_to_host(_qos_control); }
uint16_t qos_control() const {
return Endian::le_to_host(qos_control_);
}
/**
* \brief Setter for the QOS Control field.
@@ -316,7 +332,7 @@ public:
*
* \sa PDU::clone
*/
Dot11QoSData *clone() const {
Dot11QoSData* clone() const {
return new Dot11QoSData(*this);
}
@@ -324,21 +340,22 @@ public:
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::DOT11_QOS_DATA; }
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \brief Check wether this PDU matches the specified flag.
* \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) const {
return flag == PDU::DOT11_QOS_DATA || Dot11Data::matches_flag(flag);
return flag == pdu_flag || Dot11Data::matches_flag(flag);
}
private:
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
uint16_t _qos_control;
uint16_t qos_control_;
};
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,12 +36,13 @@
#include <vector>
#include <utility>
#include "../dot11/dot11_base.h"
#include "../macros.h"
namespace Tins {
/**
* \brief Abstract class that englobes all Management frames in the 802.11 protocol.
* \brief Base class for all management frames in the IEEE 802.11 protocol.
*/
class Dot11ManagementFrame : public Dot11 {
class TINS_API Dot11ManagementFrame : public Dot11 {
public:
/**
* The supported rates container type.
@@ -53,6 +54,11 @@ public:
*/
typedef std::vector<std::pair<uint8_t, uint8_t> > channels_type;
/**
* The channel map container type.
*/
typedef std::vector<std::pair<uint8_t, uint8_t> > channel_map_type;
/**
* The requested information container type.
*/
@@ -63,6 +69,12 @@ public:
*/
static const PDU::PDUType pdu_flag = PDU::DOT11_MANAGEMENT;
/**
* \brief Enum used in the reason code field.
*
* This enumeration can be used to get or set the reason code field in a
* Deauthentication or Disassociation
*/
enum ReasonCodes {
UNSPECIFIED = 1,
PREV_AUTH_NOT_VALID = 2,
@@ -97,6 +109,21 @@ public:
REQUESTED_BY_STA_TIMEOUT = 39,
PEER_STA_NOT_SUPPORT_CIPHER = 45
};
/**
* \brief Enum that represents the map field within a channels map field.
*
* These bitmasks can be used to get or set the second value of
* ibss_dfs_params().channel_map
*/
enum MapMask {
BSS = 0x1,
OFDM_PREAMBLE = 0x2,
UNIDENTIFIED_SIGNAL = 0x4,
RADAR = 0x8,
UNMEASURED = 0x10,
RESERVED = 0xE0
};
/**
* Represents the IEEE 802.11 frames' capability information.
@@ -105,39 +132,39 @@ public:
class capability_information {
private:
#if TINS_IS_LITTLE_ENDIAN
uint16_t _ess:1,
_ibss:1,
_cf_poll:1,
_cf_poll_req:1,
_privacy:1,
_short_preamble:1,
_pbcc:1,
_channel_agility:1,
_spectrum_mgmt:1,
_qos:1,
_sst:1,
_apsd:1,
_reserved:1,
_dsss_ofdm:1,
_delayed_block_ack:1,
_immediate_block_ack:1;
uint16_t ess_:1,
ibss_:1,
cf_poll_:1,
cf_poll_req_:1,
privacy_:1,
short_preamble_:1,
pbcc_:1,
channel_agility_:1,
spectrum_mgmt_:1,
qos_:1,
sst_:1,
apsd_:1,
radio_measurement_:1,
dsss_ofdm_:1,
delayed_block_ack_:1,
immediate_block_ack_:1;
#elif TINS_IS_BIG_ENDIAN
uint16_t _channel_agility:1,
_pbcc:1,
_short_preamble:1,
_privacy:1,
_cf_poll_req:1,
_cf_poll:1,
_ibss:1,
_ess:1,
_immediate_block_ack:1,
_delayed_block_ack:1,
_dsss_ofdm:1,
_reserved:1,
_apsd:1,
_sst:1,
_qos:1,
_spectrum_mgmt:1;
uint16_t channel_agility_:1,
pbcc_:1,
short_preamble_:1,
privacy_:1,
cf_poll_req_:1,
cf_poll_:1,
ibss_:1,
ess_:1,
immediate_block_ack_:1,
delayed_block_ack_:1,
dsss_ofdm_:1,
radio_measurement_:1,
apsd_:1,
sst_:1,
qos_:1,
spectrum_mgmt_:1;
#endif
public:
/**
@@ -145,225 +172,288 @@ public:
*
* \return Bool indicating the flag's value.
*/
bool ess() const { return _ess; }
bool ess() const {
return ess_;
}
/**
* \brief Getter for the ibss flag.
*
* \return Bool indicating the flag's value.
*/
bool ibss() const { return _ibss; }
bool ibss() const {
return ibss_;
}
/**
* \brief Getter for the cf_poll flag.
*
* \return Bool indicating the flag's value.
*/
bool cf_poll() const { return _cf_poll; }
bool cf_poll() const {
return cf_poll_;
}
/**
* \brief Getter for the cf_poll_req flag.
*
* \return Bool indicating the flag's value.
*/
bool cf_poll_req() const { return _cf_poll_req; }
bool cf_poll_req() const {
return cf_poll_req_;
}
/**
* \brief Getter for the privacy flag.
*
* \return Bool indicating the flag's value.
*/
bool privacy() const { return _privacy; }
bool privacy() const {
return privacy_;
}
/**
* \brief Getter for the short_preamble flag.
*
* \return Bool indicating the flag's value.
*/
bool short_preamble() const { return _short_preamble; }
bool short_preamble() const {
return short_preamble_;
}
/**
* \brief Getter for the pbcc flag.
*
* \return Bool indicating the flag's value.
*/
bool pbcc() const { return _pbcc; }
bool pbcc() const {
return pbcc_;
}
/**
* \brief Getter for the channel_agility flag.
*
* \return Bool indicating the flag's value.
*/
bool channel_agility() const { return _channel_agility; }
bool channel_agility() const {
return channel_agility_;
}
/**
* \brief Getter for the spectrum_mgmt flag.
*
* \return Bool indicating the flag's value.
*/
bool spectrum_mgmt() const { return _spectrum_mgmt; }
bool spectrum_mgmt() const {
return spectrum_mgmt_;
}
/**
* \brief Getter for the qos flag.
*
* \return Bool indicating the flag's value.
*/
bool qos() const { return _qos; }
bool qos() const {
return qos_;
}
/**
* \brief Getter for the sst flag.
*
* \return Bool indicating the flag's value.
*/
bool sst() const { return _sst; }
bool sst() const {
return sst_;
}
/**
* \brief Getter for the apsd flag.
*
* \return Bool indicating the flag's value.
*/
bool apsd() const { return _apsd; }
bool apsd() const {
return apsd_;
}
/**
* \brief Getter for the reserved flag.
* \brief Getter for the radio measurement flag.
*
* \return Bool indicating the flag's value.
*/
bool reserved() const { return _reserved; }
bool radio_measurement() const {
return radio_measurement_;
}
/**
* \brief Getter for the dsss_ofdm flag.
*
* \return Bool indicating the flag's value.
*/
bool dsss_ofdm() const { return _dsss_ofdm; }
bool dsss_ofdm() const {
return dsss_ofdm_;
}
/**
* \brief Getter for the delayed_block_ack flag.
*
* \return Bool indicating the flag's value.
*/
bool delayed_block_ack() const { return _delayed_block_ack; }
bool delayed_block_ack() const {
return delayed_block_ack_;
}
/**
* \brief Getter for the immediate_block_ack flag.
*
* \return Bool indicating the flag's value.
*/
bool immediate_block_ack() const { return _immediate_block_ack; }
bool immediate_block_ack() const {
return immediate_block_ack_;
}
/**
* \brief Setter for the ess flag.
*
* \param new_value bool indicating the flag's new value.
*/
void ess(bool new_value) { _ess = new_value; }
void ess(bool new_value) {
ess_ = new_value;
}
/**
* \brief Setter for the ibss flag.
*
* \param new_value bool indicating the flag's new value.
*/
void ibss(bool new_value) { _ibss = new_value; }
void ibss(bool new_value) {
ibss_ = new_value;
}
/**
* \brief Setter for the cf_poll flag.
*
* \param new_value bool indicating the flag's new value.
*/
void cf_poll(bool new_value) { _cf_poll = new_value; }
void cf_poll(bool new_value) {
cf_poll_ = new_value;
}
/**
* \brief Setter for the cf_poll_req flag.
*
* \param new_value bool indicating the flag's new value.
*/
void cf_poll_req(bool new_value) { _cf_poll_req = new_value; }
void cf_poll_req(bool new_value) {
cf_poll_req_ = new_value;
}
/**
* \brief Setter for the privacy flag.
*
* \param new_value bool indicating the flag's new value.
*/
void privacy(bool new_value) { _privacy = new_value; }
void privacy(bool new_value) {
privacy_ = new_value;
}
/**
* \brief Setter for the short_preamble flag.
*
* \param new_value bool indicating the flag's new value.
*/
void short_preamble(bool new_value) { _short_preamble = new_value; }
void short_preamble(bool new_value) {
short_preamble_ = new_value;
}
/**
* \brief Setter for the pbcc flag.
*
* \param new_value bool indicating the flag's new value.
*/
void pbcc(bool new_value) { _pbcc = new_value; }
void pbcc(bool new_value) {
pbcc_ = new_value;
}
/**
* \brief Setter for the channel_agility flag.
*
* \param new_value bool indicating the flag's new value.
*/
void channel_agility(bool new_value) { _channel_agility = new_value; }
void channel_agility(bool new_value) {
channel_agility_ = new_value;
}
/**
* \brief Setter for the spectrum_mgmt flag.
*
* \param new_value bool indicating the flag's new value.
*/
void spectrum_mgmt(bool new_value) { _spectrum_mgmt = new_value; }
void spectrum_mgmt(bool new_value) {
spectrum_mgmt_ = new_value;
}
/**
* \brief Setter for the qos flag.
*
* \param new_value bool indicating the flag's new value.
*/
void qos(bool new_value) { _qos = new_value; }
void qos(bool new_value) {
qos_ = new_value;
}
/**
* \brief Setter for the sst flag.
*
* \param new_value bool indicating the flag's new value.
*/
void sst(bool new_value) { _sst = new_value; }
void sst(bool new_value) {
sst_ = new_value;
}
/**
* \brief Setter for the apsd flag.
*
* \param new_value bool indicating the flag's new value.
*/
void apsd(bool new_value) { _apsd = new_value; }
void apsd(bool new_value) {
apsd_ = new_value;
}
/**
* \brief Setter for the reserved flag.
* \brief Setter for the radio measurement flag.
*
* \param new_value bool indicating the flag's new value.
*/
void reserved(bool new_value) { _reserved = new_value; }
void radio_measurement(bool new_value) {
radio_measurement_ = new_value;
}
/**
* \brief Setter for the dsss_ofdm flag.
*
* \param new_value bool indicating the flag's new value.
*/
void dsss_ofdm(bool new_value) { _dsss_ofdm = new_value; }
void dsss_ofdm(bool new_value) {
dsss_ofdm_ = new_value;
}
/**
* \brief Setter for the delayed_block_ack flag.
*
* \param new_value bool indicating the flag's new value.
*/
void delayed_block_ack(bool new_value) { _delayed_block_ack = new_value; }
void delayed_block_ack(bool new_value) {
delayed_block_ack_ = new_value;
}
/**
* \brief Setter for the immediate_block_ack flag.
*
* \param new_value bool indicating the flag's new value.
*/
void immediate_block_ack(bool new_value) { _immediate_block_ack = new_value; }
void immediate_block_ack(bool new_value) {
immediate_block_ack_ = new_value;
}
} TINS_END_PACK;
/**
@@ -375,12 +465,14 @@ public:
fh_params_set() {}
fh_params_set(uint16_t dwell_time, uint8_t hop_set,
uint8_t hop_pattern, uint8_t hop_index)
fh_params_set(uint16_t dwell_time,
uint8_t hop_set,
uint8_t hop_pattern,
uint8_t hop_index)
: dwell_time(dwell_time), hop_set(hop_set),
hop_pattern(hop_pattern), hop_index(hop_index) {}
static fh_params_set from_option(const option &opt);
static fh_params_set from_option(const option& opt);
};
/**
@@ -392,13 +484,15 @@ public:
cf_params_set() {}
cf_params_set(uint8_t cfp_count, uint8_t cfp_period,
uint16_t cfp_max_duration, uint16_t cfp_dur_remaining)
cf_params_set(uint8_t cfp_count,
uint8_t cfp_period,
uint16_t cfp_max_duration,
uint16_t cfp_dur_remaining)
: cfp_count(cfp_count), cfp_period(cfp_period),
cfp_max_duration(cfp_max_duration),
cfp_dur_remaining(cfp_dur_remaining) {}
static cf_params_set from_option(const option &opt);
static cf_params_set from_option(const option& opt);
};
/**
@@ -409,16 +503,17 @@ public:
address_type dfs_owner;
uint8_t recovery_interval;
channels_type channel_map;
channel_map_type channel_map;
ibss_dfs_params() {}
ibss_dfs_params(const address_type &addr,
uint8_t recovery_interval, const channels_type &channels)
ibss_dfs_params(const address_type& addr,
uint8_t recovery_interval,
const channel_map_type& channel_map)
: dfs_owner(addr), recovery_interval(recovery_interval),
channel_map(channels) {}
channel_map(channel_map) {}
static ibss_dfs_params from_option(const option &opt);
static ibss_dfs_params from_option(const option& opt);
};
/**
@@ -433,12 +528,14 @@ public:
country_params() {}
country_params(const std::string &country, const byte_array &first,
const byte_array &number, const byte_array &max)
country_params(const std::string& country,
const byte_array& first,
const byte_array& number,
const byte_array& max)
: country(country), first_channel(first), number_channels(number),
max_transmit_power(max) {}
static country_params from_option(const option &opt);
static country_params from_option(const option& opt);
};
/**
@@ -452,12 +549,15 @@ public:
fh_pattern_type() {}
fh_pattern_type(uint8_t flag, uint8_t sets, uint8_t modulus,
uint8_t offset, const byte_array& table)
fh_pattern_type(uint8_t flag,
uint8_t sets,
uint8_t modulus,
uint8_t offset,
const byte_array& table)
: flag(flag), number_of_sets(sets), modulus(modulus),
offset(offset), random_table(table) {}
static fh_pattern_type from_option(const option &opt);
static fh_pattern_type from_option(const option& opt);
};
/**
@@ -468,10 +568,12 @@ public:
channel_switch_type() {}
channel_switch_type(uint8_t mode, uint8_t channel, uint8_t count)
channel_switch_type(uint8_t mode,
uint8_t channel,
uint8_t count)
: switch_mode(mode), new_channel(channel), switch_count(count) { }
static channel_switch_type from_option(const option &opt);
static channel_switch_type from_option(const option& opt);
};
/**
@@ -483,12 +585,14 @@ public:
quiet_type() {}
quiet_type(uint8_t count, uint8_t period, uint16_t duration,
uint16_t offset)
quiet_type(uint8_t count,
uint8_t period,
uint16_t duration,
uint16_t offset)
: quiet_count(count), quiet_period(period),
quiet_duration(duration), quiet_offset(offset) {}
static quiet_type from_option(const option &opt);
static quiet_type from_option(const option& opt);
};
/**
@@ -501,12 +605,11 @@ public:
bss_load_type() {}
bss_load_type(uint16_t count, uint8_t utilization,
uint16_t capacity)
bss_load_type(uint16_t count, uint8_t utilization, uint16_t capacity)
: station_count(count), available_capacity(capacity),
channel_utilization(utilization) {}
static bss_load_type from_option(const option &opt);
static bss_load_type from_option(const option& opt);
};
/**
@@ -518,12 +621,14 @@ public:
tim_type() {}
tim_type(uint8_t count, uint8_t period, uint8_t control,
const byte_array &bitmap)
tim_type(uint8_t count,
uint8_t period,
uint8_t control,
const byte_array& bitmap)
: dtim_count(count), dtim_period(period), bitmap_control(control),
partial_virtual_bitmap(bitmap) {}
static tim_type from_option(const option &opt);
static tim_type from_option(const option& opt);
};
/**
@@ -535,11 +640,11 @@ public:
oui_type oui;
byte_array data;
vendor_specific_type(const oui_type &oui = oui_type(),
const byte_array &data = byte_array())
vendor_specific_type(const oui_type& oui = oui_type(),
const byte_array& data = byte_array())
: oui(oui), data(data) { }
static vendor_specific_type from_bytes(const uint8_t *buffer, uint32_t sz);
static vendor_specific_type from_bytes(const uint8_t* buffer, uint32_t sz);
};
/**
@@ -552,14 +657,18 @@ public:
*
* \return address_type containing the second address.
*/
address_type addr2() const { return _ext_header.addr2; }
address_type addr2() const {
return ext_header_.addr2;
}
/**
* \brief Getter for the third address.
*
* \return address_type containing the third address.
*/
address_type addr3() const { return _ext_header.addr3; }
address_type addr3() const {
return ext_header_.addr3;
}
/**
* \brief Getter for the fragment number.
@@ -568,9 +677,9 @@ public:
*/
small_uint<4> frag_num() const {
#if TINS_IS_LITTLE_ENDIAN
return _ext_header.frag_seq & 0xf;
return ext_header_.frag_seq & 0xf;
#else
return (_ext_header.frag_seq >> 8) & 0xf;
return (ext_header_.frag_seq >> 8) & 0xf;
#endif
}
@@ -581,9 +690,9 @@ public:
*/
small_uint<12> seq_num() const {
#if TINS_IS_LITTLE_ENDIAN
return (_ext_header.frag_seq >> 4) & 0xfff;
return (ext_header_.frag_seq >> 4) & 0xfff;
#else
return (Endian::le_to_host<uint16_t>(_ext_header.frag_seq) >> 4) & 0xfff;
return (Endian::le_to_host<uint16_t>(ext_header_.frag_seq) >> 4) & 0xfff;
#endif
}
@@ -592,21 +701,23 @@ public:
*
* \return The stored fourth address.
*/
const address_type &addr4() const { return _addr4; }
const address_type& addr4() const {
return addr4_;
}
/**
* \brief Setter for the second address.
*
* \param new_addr2 The new second address to be set.
*/
void addr2(const address_type &new_addr2);
void addr2(const address_type& new_addr2);
/**
* \brief Setter for the third address.
*
* \param new_addr3 The new third address to be set.
*/
void addr3(const address_type &new_addr3);
void addr3(const address_type& new_addr3);
/**
* \brief Setter for the fragment number.
@@ -627,7 +738,7 @@ public:
*
* \param new_addr4 The new fourth address to be set.
*/
void addr4(const address_type &new_addr4);
void addr4(const address_type& new_addr4);
// Option setter helpers
@@ -636,7 +747,7 @@ public:
*
* \param new_ssid The SSID to be set.
*/
void ssid(const std::string &new_ssid);
void ssid(const std::string& new_ssid);
/**
* \brief Helper method to set the RSN information option.
@@ -650,14 +761,14 @@ public:
*
* \param new_rates The new rates to be set.
*/
void supported_rates(const rates_type &new_rates);
void supported_rates(const rates_type& new_rates);
/**
* \brief Helper method to set the extended supported rates option.
*
* \param new_rates The new rates to be set.
*/
void extended_supported_rates(const rates_type &new_rates);
void extended_supported_rates(const rates_type& new_rates);
/**
* \brief Helper method to set the QoS capabilities option.
@@ -683,7 +794,7 @@ public:
*
* \param new_channels A list of channels to be set.
*/
void supported_channels(const channels_type &new_channels);
void supported_channels(const channels_type& new_channels);
/**
* \brief Helper method to set the EDCA Parameter Set.
@@ -707,7 +818,7 @@ public:
*
* \param fh_params The new FH parameter set value.
*/
void fh_parameter_set(const fh_params_set &fh_params);
void fh_parameter_set(const fh_params_set& fh_params);
/**
* \brief Helper method to set the DS parameter tagged option.
@@ -721,7 +832,7 @@ public:
*
* \param params The new CF parameter set value.
*/
void cf_parameter_set(const cf_params_set &params);
void cf_parameter_set(const cf_params_set& params);
/**
* \brief Helper method to set the IBSS parameter set tagged option.
@@ -735,14 +846,14 @@ public:
*
* \param params The IBSS DFS data to be set.
*/
void ibss_dfs(const ibss_dfs_params &params);
void ibss_dfs(const ibss_dfs_params& params);
/**
* \brief Helper method to set the country tagged option.
*
* \param params The data to be used for this country option.
*/
void country(const country_params &params);
void country(const country_params& params);
/**
* \brief Helper method to set the FH parameters set tagged option.
@@ -757,7 +868,7 @@ public:
*
* \param params The data to be used for this FH pattern table option.
*/
void fh_pattern_table(const fh_pattern_type &params);
void fh_pattern_table(const fh_pattern_type& params);
/**
* \brief Helper method to set the Power Constraint tagged option.
@@ -771,14 +882,14 @@ public:
*
* \param data The value of the Channel Switch option.
*/
void channel_switch(const channel_switch_type &data);
void channel_switch(const channel_switch_type& data);
/**
* \brief Helper method to set the Quiet tagged option.
*
* \param data The value of the quiet count field.
*/
void quiet(const quiet_type &data);
void quiet(const quiet_type& data);
/**
* \brief Helper method to set the TPC Report tagged option.
@@ -800,28 +911,28 @@ public:
*
* \param data The value to set in this bss load option.
*/
void bss_load(const bss_load_type &data);
void bss_load(const bss_load_type& data);
/**
* \brief Helper method to set the TIM tagged option.
*
* \brief data The value to set in this tim option.
*/
void tim(const tim_type &data);
void tim(const tim_type& data);
/**
* \brief Helper method to set the Challenge Text tagged option.
*
* \brief text The challenge text to be added.
*/
void challenge_text(const std::string &text);
void challenge_text(const std::string& text);
/**
* \brief Helper method to add a Vendor Specific tagged option.
*
* \brief text The option to be added.
*/
void vendor_specific(const vendor_specific_type &data);
void vendor_specific(const vendor_specific_type& data);
// Option searching helpers
@@ -834,7 +945,7 @@ public:
*
* \return std::string containing the ssid.
*/
RSNInformation rsn_information();
RSNInformation rsn_information() const;
/**
* \brief Helper method to search for this PDU's SSID.
@@ -1096,10 +1207,12 @@ public:
*
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \brief Check wether this PDU matches the specified flag.
* \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
@@ -1108,15 +1221,15 @@ public:
}
protected:
TINS_BEGIN_PACK
struct ExtendedHeader {
struct dot11_extended_header {
uint8_t addr2[address_type::address_size];
uint8_t addr3[address_type::address_size];
uint16_t frag_seq;
} TINS_END_PACK;
Dot11ManagementFrame(const address_type &dst_hw_addr = address_type(),
const address_type &src_hw_addr = address_type());
Dot11ManagementFrame(const address_type& dst_hw_addr = address_type(),
const address_type& src_hw_addr = address_type());
/**
* \brief Constructs a Dot11ManagementFrame object from a buffer
@@ -1132,29 +1245,30 @@ protected:
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11ManagementFrame(const uint8_t *buffer, uint32_t total_sz);
Dot11ManagementFrame(const uint8_t* buffer, uint32_t total_sz);
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
void write_ext_header(Memory::OutputMemoryStream& stream);
uint32_t management_frame_size() {
return sizeof(ieee80211_header) + sizeof(_ext_header) +
((from_ds() && to_ds()) ? address_type::address_size : 0);
return Dot11ManagementFrame::header_size();
}
private:
static uint8_t *serialize_rates(const rates_type &rates);
static rates_type deserialize_rates(const option *option);
static std::vector<uint8_t> serialize_rates(const rates_type& rates);
static rates_type deserialize_rates(const option* option);
template<typename T>
T search_and_convert(OptionTypes opt_type) const {
const option *opt = search_option(opt_type);
if(!opt)
const option* opt = search_option(opt_type);
if (!opt) {
throw option_not_found();
}
return opt->to<T>();
}
ExtendedHeader _ext_header;
address_type _addr4;
dot11_extended_header ext_header_;
address_type addr4_;
};
} // namespace Tins
#endif // TINS_DOT11_DOT11_MGMT_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,13 +34,14 @@
#define TINS_DOT11_DOT11_PROBE_H
#include "../dot11/dot11_mgmt.h"
#include "../macros.h"
namespace Tins {
/**
* \brief Class representing an Probe Request frame in the IEEE 802.11 Protocol.
*
*/
class Dot11ProbeRequest : public Dot11ManagementFrame {
class TINS_API Dot11ProbeRequest : public Dot11ManagementFrame {
public:
/**
* \brief This PDU's flag.
@@ -56,8 +57,8 @@ public:
* \param dst_hw_addr The destination hardware address.
* \param src_hw_addr The source hardware address.
*/
Dot11ProbeRequest(const address_type &dst_hw_addr = address_type(),
const address_type &src_hw_addr = address_type());
Dot11ProbeRequest(const address_type& dst_hw_addr = address_type(),
const address_type& src_hw_addr = address_type());
/**
* \brief Constructs a Dot11ProbeRequest object from a buffer
@@ -73,16 +74,18 @@ public:
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11ProbeRequest(const uint8_t *buffer, uint32_t total_sz);
Dot11ProbeRequest(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::DOT11_PROBE_REQ; }
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \brief Check wether this PDU matches the specified flag.
* \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
@@ -105,7 +108,7 @@ public:
* \brief Class representing an Probe Response frame in the IEEE 802.11 Protocol.
*
*/
class Dot11ProbeResponse : public Dot11ManagementFrame {
class TINS_API Dot11ProbeResponse : public Dot11ManagementFrame {
public:
/**
* \brief This PDU's flag.
@@ -121,8 +124,8 @@ public:
* \param dst_hw_addr The destination hardware address.
* \param src_hw_addr The source hardware address.
*/
Dot11ProbeResponse(const address_type &dst_hw_addr = address_type(),
const address_type &src_hw_addr = address_type());
Dot11ProbeResponse(const address_type& dst_hw_addr = address_type(),
const address_type& src_hw_addr = address_type());
/**
* \brief Constructs a Dot11ProbeResponse object from a buffer
@@ -138,21 +141,25 @@ public:
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11ProbeResponse(const uint8_t *buffer, uint32_t total_sz);
Dot11ProbeResponse(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Getter for the timestamp field.
*
* \return The stored timestamp value.
*/
uint64_t timestamp() const { return Endian::le_to_host(_body.timestamp); }
uint64_t timestamp() const {
return Endian::le_to_host(body_.timestamp);
}
/**
* \brief Getter for the interval field.
*
* \return The stored interval value.
*/
uint16_t interval() const { return Endian::le_to_host(_body.interval); }
uint16_t interval() const {
return Endian::le_to_host(body_.interval);
}
/**
* \brief Getter for the Capabilities Information.
@@ -160,7 +167,9 @@ public:
* \return A constant reference to the stored Capabilities
* Information field.
*/
const capability_information& capabilities() const { return _body.capability;}
const capability_information& capabilities() const {
return body_.capability;
}
/**
* \brief Getter for the Capabilities Information.
@@ -168,7 +177,9 @@ public:
* \return A reference to the stored Capabilities Information
* field.
*/
capability_information& capabilities() { return _body.capability;}
capability_information& capabilities() {
return body_.capability;
}
/**
* \brief Setter for the timestamp field.
@@ -208,26 +219,26 @@ public:
PDUType pdu_type() const { return pdu_flag; }
/**
* \brief Check wether this PDU matches the specified flag.
* \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
}
protected:
private:
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
TINS_BEGIN_PACK
struct ProbeResp {
struct dot11_probe_response_header {
uint64_t timestamp;
uint16_t interval;
capability_information capability;
} TINS_END_PACK;
ProbeResp _body;
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
dot11_probe_response_header body_;
};
} // namespace Tins
#endif // TINS_DOT11_DOT11_PROBE_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,14 +31,17 @@
#define TINS_DOT1Q_H
#include "pdu.h"
#include "macros.h"
#include "endianness.h"
#include "small_uint.h"
namespace Tins {
/**
* \class Dot1Q
* Represents an IEEE 802.1q PDU.
*/
class Dot1Q : public PDU {
class TINS_API Dot1Q : public PDU {
public:
/**
* This PDU's flag.
@@ -63,7 +66,7 @@ public:
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot1Q(const uint8_t *buffer, uint32_t total_sz);
Dot1Q(const uint8_t* buffer, uint32_t total_sz);
// Getters
@@ -85,7 +88,7 @@ public:
* \return The stored priority field value.
*/
small_uint<3> priority() const {
return _header.priority;
return header_.priority;
}
/**
@@ -93,7 +96,7 @@ public:
* \return The stored CFI field value.
*/
small_uint<1> cfi() const {
return _header.cfi;
return header_.cfi;
}
/**
@@ -102,9 +105,9 @@ public:
*/
small_uint<12> id() const {
#if TINS_IS_LITTLE_ENDIAN
return _header.idL | (_header.idH << 8);
return header_.idL | (header_.idH << 8);
#else
return _header.id;
return header_.id;
#endif
}
@@ -113,19 +116,21 @@ public:
* \return The stored type field value.
*/
uint16_t payload_type() const {
return Endian::be_to_host(_header.type);
return Endian::be_to_host(header_.type);
}
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \sa PDU::clone
*/
Dot1Q *clone() const {
Dot1Q* clone() const {
return new Dot1Q(*this);
}
@@ -134,7 +139,7 @@ public:
* appended at the end of this packet.
*/
bool append_padding() const {
return _append_padding;
return append_padding_;
}
// Setters
@@ -176,15 +181,15 @@ public:
void append_padding(bool value);
/**
* \brief Check wether ptr points to a valid response for this PDU.
* \brief Check whether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
private:
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
TINS_BEGIN_PACK
struct dot1q_hdr {
@@ -202,10 +207,10 @@ private:
#endif
} TINS_END_PACK;
static uint16_t get_id(const dot1q_hdr *hdr);
static uint16_t get_id(const dot1q_hdr* hdr);
dot1q_hdr _header;
bool _append_padding;
dot1q_hdr header_;
bool append_padding_;
};
}

201
include/tins/dot3.h Normal file
View File

@@ -0,0 +1,201 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_DOT3_H
#define TINS_DOT3_H
#include <stdint.h>
#include "macros.h"
#include "pdu.h"
#include "config.h"
#include "endianness.h"
#include "hw_address.h"
namespace Tins {
/**
* \class Dot3
* \brief Class representing an IEEE 802.3 PDU.
*/
class TINS_API Dot3 : public PDU {
public:
/**
* \brief The address type.
*/
typedef HWAddress<6> address_type;
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::IEEE802_3;
/**
* \brief Represents the Dot3 broadcast address.
*/
static const address_type BROADCAST;
/**
* \brief Constructor for creating an Dot3 PDU
*
* Constructor that builds an Dot3 PDU taking the interface name,
* destination's and source's MAC.
*
* \param dst_hw_addr The destination hardware address.
* \param src_hw_addr The source hardware address.
* \param child The PDU which will be set as the inner PDU.
*/
Dot3(const address_type& dst_hw_addr = address_type(),
const address_type& src_hw_addr = address_type());
/**
* \brief Constructs a Dot3 object from a buffer and adds a
* LLC object with the remaining data as the inner PDU.
*
* If there is not enough size for a Dot3 header, a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot3(const uint8_t* buffer, uint32_t total_sz);
/* Getters */
/**
* \brief Getter for the destination hardware address.
*
* \return The destination hardware address.
*/
address_type dst_addr() const {
return header_.dst_mac;
}
/**
* \brief Getter for the source hardware address.
*
* \return The source hardware address.
*/
address_type src_addr() const {
return header_.src_mac;
}
/**
* \brief Getter for the length field.
* \return The length field value.
*/
uint16_t length() const {
return Endian::be_to_host(header_.length);
}
/* Setters */
/**
* \brief Setter for the destination hardware address.
*
* \param address The new destination hardware address.
*/
void dst_addr(const address_type& address);
/**
* \brief Setter for the source hardware address.
*
* \param address The new source hardware address.
*/
void src_addr(const address_type& address);
/**
* \brief Setter for the length field.
*
* \param value The new value for the length field
*/
void length(uint16_t value);
// Virtual methods
/**
* \brief Returns the Dot3 frame's header length.
*
* \return An uint32_t with the header's size.
* \sa PDU::header_size()
*/
uint32_t header_size() const;
#if !defined(_WIN32) || defined(HAVE_PACKET_SENDER_PCAP_SENDPACKET)
/**
* \sa PDU::send()
*/
void send(PacketSender& sender, const NetworkInterface& iface);
#endif // !_WIN32 || HAVE_PACKET_SENDER_PCAP_SENDPACKET
/**
* \brief Check whether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
#ifndef _WIN32
/**
* \sa PDU::recv_response
*/
PDU* recv_response(PacketSender& sender, const NetworkInterface& iface);
#endif // _WIN32
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \sa PDU::clone
*/
Dot3* clone() const {
return new Dot3(*this);
}
private:
/**
* Struct that represents the Ethernet II header
*/
TINS_BEGIN_PACK
struct dot3_header {
uint8_t dst_mac[address_type::address_size];
uint8_t src_mac[address_type::address_size];
uint16_t length;
} TINS_END_PACK;
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
dot3_header header_;
};
} // Tins
#endif // TINS_DOT3_H

825
include/tins/eapol.h Normal file
View File

@@ -0,0 +1,825 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_EAPOL_H
#define TINS_EAPOL_H
#include <stdint.h>
#include "pdu.h"
#include "macros.h"
#include "small_uint.h"
#include "endianness.h"
namespace Tins {
namespace Memory {
class OutputMemoryStream;
} // Memory
/** \cond
* Forward declaration. Avoid header inclusion.
*/
class RSNInformation;
/** \endcond */
/**
* \class EAPOL
* \brief Represents the EAP encapsulation over LAN.
*/
class TINS_API EAPOL : public PDU {
public:
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::EAPOL;
/**
* The EAPOL type enum.
*/
enum EAPOLTYPE {
RC4 = 1,
RSN,
EAPOL_WPA = 254
};
/**
* \brief Static method to instantiate the correct EAPOL subclass
* based on a raw buffer.
*
* If no valid EAPOL type is detected, a null pointer is returned.
*
* \sa RC4EAPOL
* \sa RSNEAPOL
*
* \param buffer The buffer from which the data will be taken.
* \param total_sz The total size of the buffer.
*/
static EAPOL* from_bytes(const uint8_t* buffer, uint32_t total_sz);
/* Getters */
/**
* \brief Getter for the version field.
* \return The version field.
*/
uint8_t version() const {
return header_.version;
}
/**
* \brief Getter for the packet type field.
* \return The packet type field.
*/
uint8_t packet_type() const {
return header_.packet_type;
}
/**
* \brief Getter for the length field.
* \return The length field.
*/
uint16_t length() const {
return Endian::be_to_host(header_.length);
}
/**
* \brief Getter for the type field.
* \return The type field.
*/
uint8_t type() const {
return header_.type;
}
/* Setters */
/**
* \brief Sets the version field.
* \param value The new version to be set.
*/
void version(uint8_t value);
/**
* \brief Sets the packet type field.
* \param value The new packet type to be set.
*/
void packet_type(uint8_t value);
/**
* \brief Sets the length field.
* \param value The new length to be set.
*/
void length(uint16_t value);
/**
* \brief Sets the type field.
* \param value The new type to be set.
*/
void type(uint8_t value);
/**
* \brief Getter for the PDU's type.
* \return Returns the PDUType corresponding to the PDU.
*/
PDUType pdu_type() const { return PDU::EAPOL; }
protected:
/**
* \brief Protected constructor that sets the packet_type and type fields.
*/
EAPOL(uint8_t packet_type, EAPOLTYPE type);
/**
* \brief Constructor which creates an EAPOL object from a buffer.
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
EAPOL(const uint8_t* buffer, uint32_t total_sz);
TINS_BEGIN_PACK
struct eapol_header {
uint8_t version, packet_type;
uint16_t length;
uint8_t type;
} TINS_END_PACK;
/**
* \brief Virtual method which should serialize the subclass specific
* body and save it in a byte array.
*
* \param buffer The pointer in which to save the serialization.
* \param total_sz The total size of the buffer.
*/
virtual void write_body(Memory::OutputMemoryStream& stream) = 0;
private:
/**
* \brief Serialices this EAPOL PDU.
* \param buffer The buffer in which the PDU will be serialized.
* \param total_sz The size available in the buffer.
* \param parent The PDU that's one level below this one on the stack.
*/
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
eapol_header header_;
};
/**
* \brief Class that represents the RC4 EAPOL PDU.
*/
class TINS_API RC4EAPOL : public EAPOL {
public:
/**
* The type used to store the key.
*/
typedef std::vector<uint8_t> key_type;
/**
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::RC4EAPOL;
/**
* The length of the key IV field
*/
static const size_t key_iv_size = 16;
/**
* The length of the key sign field
*/
static const size_t key_sign_size = 16;
/**
* \brief Default constructor.
*/
RC4EAPOL();
/**
* \brief Constructs a RC4EAPOL object from a buffer.
*
* If there is not enough size for a RC4EAPOL header in the
* buffer, a malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
RC4EAPOL(const uint8_t* buffer, uint32_t total_sz);
/* Getters */
/**
* \brief Getter for the key length field.
* \return The key length field.
*/
uint16_t key_length() const {
return Endian::be_to_host(header_.key_length);
}
/**
* \brief Getter for the replay counter field.
* \return The replay counter field.
*/
uint64_t replay_counter() const {
return Endian::be_to_host(header_.replay_counter);
}
/**
* \brief Getter for the key IV field.
* \return The key IV field.
*/
const uint8_t* key_iv() const {
return header_.key_iv;
}
/**
* \brief Getter for the key flag field.
* \return The key flag field.
*/
small_uint<1> key_flag() const {
return header_.key_flag;
}
/**
* \brief Getter for the key index field.
* \return The key index field.
*/
small_uint<7> key_index() const {
return header_.key_index;
}
/**
* \brief Getter for the key signature field.
* \return The key signature field.
*/
const uint8_t* key_sign() const {
return header_.key_sign;
}
/**
* \brief Getter for the key field.
* \return The key field.
*/
const key_type& key() const {
return key_;
}
/* Setters */
/**
* \brief Sets the key length field.
* \param value The new key length to be set.
*/
void key_length(uint16_t value);
/**
* \brief Sets the replay counter field.
* \param value The new replay counter to be set.
*/
void replay_counter(uint64_t value);
/**
* \brief Sets the key IV field.
* \param value The new key IV to be set.
*/
void key_iv(const uint8_t* value);
/**
* \brief Sets the key flag field.
* \param value The new key flag to be set.
*/
void key_flag(small_uint<1> value);
/**
* \brief Sets the key index field.
* \param value The new key index to be set.
*/
void key_index(small_uint<7> value);
/**
* \brief Sets the key signature field.
* \param value The new key signature to be set.
*/
void key_sign(const uint8_t* value);
/**
* \brief Sets the key field.
* \param value The new key to be set.
*/
void key(const key_type& value);
/* Virtual method override. */
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. This size includes the
* payload and options size.
*
* \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \brief Getter for the PDU's type.
* \return Returns the PDUType corresponding to the PDU.
*/
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || EAPOL::matches_flag(flag);
}
/**
* \brief Clones this PDU.
*
* \sa PDU::clone
*/
RC4EAPOL* clone() const {
return new RC4EAPOL(*this);
}
private:
TINS_BEGIN_PACK
struct rc4_eapol_header {
uint16_t key_length;
uint64_t replay_counter;
uint8_t key_iv[key_iv_size];
uint8_t key_index:7,
key_flag:1;
uint8_t key_sign[16];
} TINS_END_PACK;
void write_body(Memory::OutputMemoryStream& stream);
key_type key_;
rc4_eapol_header header_;
};
/**
* \brief Class that represents the RSN EAPOL PDU.
*/
class TINS_API RSNEAPOL : public EAPOL {
public:
/**
* The type used to store the key.
*/
typedef std::vector<uint8_t> key_type;
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::RSNEAPOL;
/**
* The length of the key IV field
*/
static const size_t key_iv_size = 16;
/**
* The length of the nonce field
*/
static const size_t nonce_size = 32;
/**
* The length of the mic field
*/
static const size_t mic_size = 16;
/**
* The length of the rsc field
*/
static const size_t rsc_size = 8;
/**
* The length of the id field
*/
static const size_t id_size = 8;
/**
* \brief Creates an instance of RSNEAPOL.
*/
RSNEAPOL();
/**
* \brief Constructs a RSNEAPOL object from a buffer.
*
* If there is not enough size for the RSNEAPOL header, a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
RSNEAPOL(const uint8_t* buffer, uint32_t total_sz);
/* Getters */
/**
* \brief Getter for the key length field.
* \return The key length field.
*/
uint16_t key_length() const {
return Endian::be_to_host(header_.key_length);
}
/**
* \brief Getter for the replay counter field.
* \return The replay counter field.
*/
uint64_t replay_counter() const {
return Endian::be_to_host(header_.replay_counter);
}
/**
* \brief Getter for the key IV field.
* \return The key IV field.
*/
const uint8_t* key_iv() const {
return header_.key_iv;
}
/**
* \brief Getter for the nonce field.
* \return The nonce field.
*/
const uint8_t* nonce() const {
return header_.nonce;
}
/**
* \brief Getter for the rsc field.
* \return The rsc field.
*/
const uint8_t* rsc() const {
return header_.rsc;
}
/**
* \brief Getter for the id field.
* \return The id field.
*/
const uint8_t* id() const {
return header_.id;
}
/**
* \brief Getter for the mic field.
* \return The mic field.
*/
const uint8_t* mic() const {
return header_.mic;
}
/**
* \brief Getter for the wpa length field.
* \return The wpa length field.
*/
uint16_t wpa_length() const {
return Endian::be_to_host(header_.wpa_length);
}
/**
* \brief Getter for the key field.
* \return The key field.
*/
const key_type& key() const {
return key_;
}
/**
* \brief Getter for the key mic field.
* \return 1 if this EAPOL PDU contains a valid MIC, 0 otherwise.
*/
small_uint<1> key_mic() const {
return header_.key_mic;
}
/**
* \brief Getter for the secure field.
* \return The secure field.
*/
small_uint<1> secure() const {
return header_.secure;
}
/**
* \brief Getter for the error field.
* \return The error field.
*/
small_uint<1> error() const {
return header_.error;
}
/**
* \brief Getter for the request field.
* \return The request field.
*/
small_uint<1> request() const {
return header_.request;
}
/**
* \brief Getter for the encrypted field.
* \return The encrypted field.
*/
small_uint<1> encrypted() const {
return header_.encrypted;
}
/**
* \brief Getter for the key descriptor field.
* \return The key descriptor field.
*/
small_uint<3> key_descriptor() const {
return header_.key_descriptor;
}
/**
* \brief Getter for the key type field.
*
* \return 1 if this is a pairwise key, 0 otherwise.
*/
small_uint<1> key_t() const {
return header_.key_t;
}
/**
* \brief Getter for the key_index field.
* \return The key_index field.
*/
small_uint<2> key_index() const {
return header_.key_index;
}
/**
* \brief Getter for the install field.
* \return The install field.
*/
small_uint<1> install() const {
return header_.install;
}
/**
* \brief Getter for the key_ack field.
* \return The key_ack field.
*/
small_uint<1> key_ack() const {
return header_.key_ack;
}
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. This size includes the
* payload and options size.
*
* \sa PDU::header_size
*/
uint32_t header_size() const;
/* Setters */
/**
* \brief Sets the key length field.
* \param value The new key length to be set.
*/
void key_length(uint16_t value);
/**
* \brief Sets the replay counter field.
* \param value The new replay counter to be set.
*/
void replay_counter(uint64_t value);
/**
* \brief Sets the key IV field.
*
* The input pointer has to contain at least key_iv_size bytes. The IV
* will be copied into this PDU.
*
* \param ptr The new key IV to be set.
*/
void key_iv(const uint8_t* ptr);
/**
* \brief Sets the nonce field.
*
* The pointer has to contain at least nonce_size bytes. The pointer's contents
* will be copied.
*
* \param ptr The new nonce to be set.
*/
void nonce(const uint8_t* ptr);
/**
* \brief Sets the rsc field.
*
* The pointer has to contain at least rsc_size bytes. The pointer's contents
* will be copied.
*
* \param ptr The new rsc to be set.
*/
void rsc(const uint8_t* ptr);
/**
* \brief Sets the id field.
*
* The pointer has to contain at least id_size bytes. The pointer's contents
* will be copied.
*
* \param ptr The new id to be set.
*/
void id(const uint8_t* ptr);
/**
* \brief Sets the mic field.
*
* The pointer has to contain at least mic_size bytes. The pointer's contents
* will be copied.
*
* \param ptr The new mic to be set.
*/
void mic(const uint8_t* ptr);
/**
* \brief Sets the wpa length field.
* \param length The new wpa length to be set.
*/
void wpa_length(uint16_t length);
/**
* \brief Sets the key field.
* \param value The new key to be set.
*/
void key(const key_type& value);
/**
* \brief Setter for the key_mic field.
* \param value The new to be set.
*/
void key_mic(small_uint<1> value);
/**
* \brief Setter for the secure field.
* \param value The new to be set.
*/
void secure(small_uint<1> value);
/**
* \brief Setter for the error field.
* \param flag The new to be set.
*/
void error(small_uint<1> flag);
/**
* \brief Setter for the request field.
* \param flag The new to be set.
*/
void request(small_uint<1> flag);
/**
* \brief Setter for the encrypted field.
* \param flag The new to be set.
*/
void encrypted(small_uint<1 > flag);
/**
* \brief Setter for the key_descriptor field.
* \param value The new to be set.
*/
void key_descriptor(small_uint<3> value);
/**
* \brief Setter for the key_t field.
* \param flag The new to be set.
*/
void key_t(small_uint<1> flag);
/**
* \brief Setter for the key_index field.
* \param value The new to be set.
*/
void key_index(small_uint<2> value);
/**
* \brief Setter for the install field.
* \param flag The new to be set.
*/
void install(small_uint<1> flag);
/**
* \brief Setter for the key_ack field.
* \param flag The new to be set.
*/
void key_ack(small_uint<1> flag);
/**
* \brief Getter for the PDU's type.
* \return Returns the PDUType corresponding to the PDU.
*/
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || EAPOL::matches_flag(flag);
}
/**
* \brief Clones this PDU.
*
* \sa PDU::clone
*/
RSNEAPOL* clone() const {
return new RSNEAPOL(*this);
}
private:
TINS_BEGIN_PACK
struct rsn_eapol_header {
#if TINS_IS_LITTLE_ENDIAN
uint16_t key_mic:1,
secure:1,
error:1,
request:1,
encrypted:1,
reserved:3,
key_descriptor:3,
key_t:1,
key_index:2,
install:1,
key_ack:1;
uint16_t key_length;
uint64_t replay_counter;
uint8_t nonce[nonce_size], key_iv[key_iv_size];
uint8_t rsc[rsc_size], id[id_size];
uint8_t mic[mic_size];
uint16_t wpa_length;
#else
uint16_t reserved:3,
encrypted:1,
request:1,
error:1,
secure:1,
key_mic:1,
key_ack:1,
install:1,
key_index:2,
key_t:1,
key_descriptor:3;
uint16_t key_length;
uint64_t replay_counter;
uint8_t nonce[nonce_size], key_iv[key_iv_size];
uint8_t rsc[rsc_size], id[id_size];
uint8_t mic[mic_size];
uint16_t wpa_length;
#endif
} TINS_END_PACK;
void write_body(Memory::OutputMemoryStream& stream);
rsn_eapol_header header_;
key_type key_;
};
} // Tins
#endif // TINS_EAPOL_H

233
include/tins/endianness.h Normal file
View File

@@ -0,0 +1,233 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_ENDIANNESS_H
#define TINS_ENDIANNESS_H
#include <stdint.h>
#include "macros.h"
#if defined(__APPLE__)
#include <sys/types.h>
#define TINS_IS_LITTLE_ENDIAN (BYTE_ORDER == LITTLE_ENDIAN)
#define TINS_IS_BIG_ENDIAN (BYTE_ORDER == BIG_ENDIAN)
#elif defined(BSD)
#include <sys/endian.h>
#define TINS_IS_LITTLE_ENDIAN (_BYTE_ORDER == _LITTLE_ENDIAN)
#define TINS_IS_BIG_ENDIAN (_BYTE_ORDER == _BIG_ENDIAN)
#elif defined(_WIN32)
// Assume windows == little endian. fixme later
#define TINS_IS_LITTLE_ENDIAN 1
#define TINS_IS_BIG_ENDIAN 0
#else
#include <endian.h>
#define TINS_IS_LITTLE_ENDIAN (__BYTE_ORDER == __LITTLE_ENDIAN)
#define TINS_IS_BIG_ENDIAN (__BYTE_ORDER == __BIG_ENDIAN)
#endif
namespace Tins {
namespace Endian {
/**
* \brief "Changes" a 8-bit integral value's endianess. This is an
* identity function.
*
* \param data The data to convert.
*/
inline uint8_t do_change_endian(uint8_t data) {
return data;
}
/**
* \brief Changes a 16-bit integral value's endianess.
*
* \param data The data to convert.
*/
inline uint16_t do_change_endian(uint16_t data) {
return ((data & 0xff00) >> 8) | ((data & 0x00ff) << 8);
}
/**
* \brief Changes a 32-bit integral value's endianess.
*
* \param data The data to convert.
*/
inline uint32_t do_change_endian(uint32_t data) {
return (((data & 0xff000000) >> 24) | ((data & 0x00ff0000) >> 8) |
((data & 0x0000ff00) << 8) | ((data & 0x000000ff) << 24));
}
/**
* \brief Changes a 64-bit integral value's endianess.
*
* \param data The data to convert.
*/
inline uint64_t do_change_endian(uint64_t data) {
return (((uint64_t)(do_change_endian((uint32_t)(data & 0xffffffff))) << 32) |
(do_change_endian(((uint32_t)(data >> 32)))));
}
/**
* \cond
*/
// Helpers to convert
template<typename T>
struct conversion_dispatch_helper {
static T dispatch(T data) {
return do_change_endian(data);
}
};
template<size_t>
struct conversion_dispatcher;
template<>
struct conversion_dispatcher<sizeof(uint8_t)>
: public conversion_dispatch_helper<uint8_t> { };
template<>
struct conversion_dispatcher<sizeof(uint16_t)>
: public conversion_dispatch_helper<uint16_t> { };
template<>
struct conversion_dispatcher<sizeof(uint32_t)>
: public conversion_dispatch_helper<uint32_t> { };
template<>
struct conversion_dispatcher<sizeof(uint64_t)>
: public conversion_dispatch_helper<uint64_t> { };
/**
* \endcond
*/
/**
* \brief Changes an integral value's endianess.
*
* This dispatchs to the corresponding function.
*
* \param data The data to convert.
*/
template<typename T>
inline T change_endian(T data) {
return conversion_dispatcher<sizeof(T)>::dispatch(data);
}
#if TINS_IS_LITTLE_ENDIAN
/**
* \brief Convert any integral type to big endian.
*
* \param data The data to convert.
*/
template<typename T>
inline T host_to_be(T data) {
return change_endian(data);
}
/**
* \brief Convert any integral type to little endian.
*
* On little endian platforms, the parameter is simply returned.
*
* \param data The data to convert.
*/
template<typename T>
inline T host_to_le(T data) {
return data;
}
/**
* \brief Convert any big endian value to the host's endianess.
*
* \param data The data to convert.
*/
template<typename T>
inline T be_to_host(T data) {
return change_endian(data);
}
/**
* \brief Convert any little endian value to the host's endianess.
*
* \param data The data to convert.
*/
template<typename T>
inline T le_to_host(T data) {
return data;
}
#elif TINS_IS_BIG_ENDIAN
/**
* \brief Convert any integral type to big endian.
*
* \param data The data to convert.
*/
template<typename T>
inline T host_to_be(T data) {
return data;
}
/**
* \brief Convert any integral type to little endian.
*
* On little endian platforms, the parameter is simply returned.
*
* \param data The data to convert.
*/
template<typename T>
inline T host_to_le(T data) {
return change_endian(data);
}
/**
* \brief Convert any big endian value to the host's endianess.
*
* \param data The data to convert.
*/
template<typename T>
inline T be_to_host(T data) {
return data;
}
/**
* \brief Convert any little endian value to the host's endianess.
*
* \param data The data to convert.
*/
template<typename T>
inline T le_to_host(T data) {
return change_endian(data);
}
#endif
} // Endian
} // Tins
#endif // TINS_ENDIANNESS_H

210
include/tins/ethernetII.h Normal file
View File

@@ -0,0 +1,210 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_ETHERNET_II_H
#define TINS_ETHERNET_II_H
#include <stdint.h>
#include "macros.h"
#include "pdu.h"
#include "config.h"
#include "endianness.h"
#include "hw_address.h"
namespace Tins {
/**
* \class EthernetII
* \brief Represents an Ethernet II PDU.
*/
class TINS_API EthernetII : public PDU {
public:
/**
* \brief The hardware address type.
*/
typedef HWAddress<6> address_type;
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::ETHERNET_II;
/**
* \brief Represents the ethernetII broadcast address.
*/
static const address_type BROADCAST;
/**
* \brief Constructs an ethernet II PDU.
*
* \param dst_hw_addr address_type containing the destination's MAC.
* \param src_hw_addr address_type containing the source's MAC.
*/
EthernetII(const address_type& dst_hw_addr = address_type(),
const address_type& src_hw_addr = address_type());
/**
* \brief Constructs a EthernetII object from a buffer and adds
* all identifiable PDUs found in the buffer as children of
* this one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for a EthernetII header in the
* buffer, a malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
EthernetII(const uint8_t* buffer, uint32_t total_sz);
/* Getters */
/**
* \brief Getter for the destination's hardware address.
*
* \return address_type containing the destination hardware
* address.
*/
address_type dst_addr() const {
return header_.dst_mac;
}
/**
* \brief Getter for the source's hardware address.
*
* \return address_type containing the source hardware address.
*/
address_type src_addr() const {
return header_.src_mac;
}
/**
* \brief Getter for the payload_type
* \return The payload type.
*/
uint16_t payload_type() const {
return Endian::be_to_host(header_.payload_type);
}
/* Setters */
/**
* \brief Setter for the destination hardware address.
*
* \param new_dst_addr the destination hardware address to be set.
*/
void dst_addr(const address_type& new_dst_addr);
/**
* \brief Setter for the source hardware address.
*
* \param new_src_addr the source hardware address to be set.
*/
void src_addr(const address_type& new_src_addr);
/**
* \brief Setter for the payload type.
*
* \param new_payload_type the new value of the payload type field.
*/
void payload_type(uint16_t new_payload_type);
/* Virtual methods */
/**
* \brief Returns the ethernet frame's header length.
*
* \return An uint32_t with the header's size.
* \sa PDU::header_size()
*/
uint32_t header_size() const;
/**
* \brief Returns the ethernet II frame's padding.
*
* \return An uint32_t with the padding size.
* \sa PDU::trailer_size()
*/
uint32_t trailer_size() const;
/**
* \sa PDU::send()
*/
void send(PacketSender& sender, const NetworkInterface& iface);
/**
* \brief Check whether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
#ifndef _WIN32
/**
* \brief Receives a matching response for this packet.
*
* \sa PDU::recv_response
*/
PDU* recv_response(PacketSender& sender, const NetworkInterface& iface);
#endif // _WIN32
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \sa PDU::clone
*/
EthernetII* clone() const {
return new EthernetII(*this);
}
private:
/**
* Struct that represents the Ethernet II header
*/
TINS_BEGIN_PACK
struct ethernet_header {
uint8_t dst_mac[address_type::address_size];
uint8_t src_mac[address_type::address_size];
uint16_t payload_type;
} TINS_END_PACK;
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
ethernet_header header_;
};
} // Tins
#endif // TINS_ETHERNET_II_H

292
include/tins/exceptions.h Normal file
View File

@@ -0,0 +1,292 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_EXCEPTIONS_H
#define TINS_EXCEPTIONS_H
#include <string>
#include <stdexcept>
namespace Tins {
/**
* \brief Base class for all libtins exceptions.
*/
class exception_base : public std::runtime_error {
public:
exception_base()
: std::runtime_error(std::string()) { }
exception_base(const std::string& message)
: std::runtime_error(message) { }
};
/**
* \brief Exception thrown when an option is not found.
*/
class option_not_found : public exception_base {
public:
// try to avoid allocations by doing this.
const char* what() const throw() {
return "Option not found";
}
};
/**
* \brief Exception thrown when a malformed packet is parsed.
*/
class malformed_packet : public exception_base {
public:
const char* what() const throw() {
return "Malformed packet";
}
};
/**
* \brief Exception thrown when serializing a packet fails.
*/
class serialization_error : public exception_base {
public:
const char* what() const throw() {
return "Serialization error";
}
};
/**
* \brief Exception thrown when a PDU is not found when using PDU::rfind_pdu.
*/
class pdu_not_found : public exception_base {
public:
const char* what() const throw() {
return "PDU not found";
}
};
/**
* \brief Exception thrown when PDU::send requires a valid interface,
* but an invalid is used.
*/
class invalid_interface : public exception_base {
public:
const char* what() const throw() {
return "Invalid interface";
}
};
/**
* \brief Exception thrown when an invalid string representation of an address
* is provided
*/
class invalid_address : public exception_base {
public:
const char* what() const throw() {
return "Invalid address";
}
};
/**
* \brief Exception thrown when a field is not present in frame.
*/
class field_not_present : public exception_base {
public:
const char* what() const throw() {
return "Field not present";
}
};
/**
* \brief Exception thrown when PacketSender fails to open a socket.
*/
class socket_open_error : public exception_base {
public:
socket_open_error(const std::string& msg)
: exception_base(msg) { }
};
/**
* \brief Exception thrown when PacketSender fails to close a socket.
*/
class socket_close_error : exception_base {
public:
socket_close_error(const std::string& msg)
: exception_base(msg) { }
};
/**
* \brief Exception thrown when PacketSender fails to write on a socket.
*/
class socket_write_error : public exception_base {
public:
socket_write_error(const std::string& msg)
: exception_base(msg) { }
};
/**
* \brief Exception thrown when an invalid socket type is provided
* to PacketSender.
*/
class invalid_socket_type : public exception_base {
public:
const char* what() const throw() {
return "The provided socket type is invalid";
}
};
/**
* \brief Exception thrown when an unkown link layer PDU type is
* found while sniffing.
*/
class unknown_link_type : public exception_base {
public:
const char* what() const throw() {
return "The sniffed link layer PDU type is unknown";
}
};
/**
* \brief Exception thrown when a malformed option is found.
*/
class malformed_option : public exception_base {
public:
const char* what() const throw() {
return "Malformed option";
}
};
/**
* \brief Exception thrown when a call to tins_cast fails.
*/
class bad_tins_cast : public exception_base {
public:
const char* what() const throw() {
return "Bad Tins cast";
}
};
/**
* \brief Exception thrown when sniffing a protocol that
* has been disabled at compile time.
*/
class protocol_disabled : public exception_base {
public:
const char* what() const throw() {
return "Protocol disabled";
}
};
/**
* \brief Exception thrown when a payload is too large to fit
* into a PDUOption.
*/
class option_payload_too_large : public exception_base {
public:
const char* what() const throw() {
return "Option payload too large";
}
};
/**
* \brief Generic pcap error
*/
class pcap_error : public exception_base {
public:
pcap_error(const char* message) : exception_base(message) {
}
};
/**
* \brief Exception thrown when an invalid pcap filter is compiled
*/
class invalid_pcap_filter : public exception_base {
public:
invalid_pcap_filter(const char* message) : exception_base(message) {
}
};
/**
* \brief Exception thrown when serialiation of a non-serializable PDU
* is attempted
*/
class pdu_not_serializable : public exception_base {
public:
const char* what() const throw() {
return "PDU not serializable";
}
};
/**
* \brief Exception thrown when opening a pcap handle fails
*/
class pcap_open_failed : public exception_base {
public:
const char* what() const throw() {
return "Failed to create pcap handle";
}
};
/**
* \brief Exception thrown when a function not supported on the current OS
* is called
*/
class unsupported_function : public exception_base {
public:
const char* what() const throw() {
return "Function is not supported on this OS";
}
};
/**
* \brief Exception thrown when an invalid domain name is parsed
*/
class invalid_domain_name : public exception_base {
public:
const char* what() const throw() {
return "Invalid domain name";
}
};
namespace Crypto {
namespace WPA2 {
/**
* \brief Exception thrown when an invalid WPA2 handshake is found.
*/
class invalid_handshake : public exception_base {
public:
const char* what() const throw() {
return "Invalid WPA2 handshake";
}
};
} // WPA2
} // Crypto
} // Tins
#endif // TINS_EXCEPTIONS_H

View File

@@ -0,0 +1,170 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "config.h"
#if !defined(TINS_HANDSHAKE_CAPTURER_H) && defined(HAVE_DOT11)
#define TINS_HANDSHAKE_CAPTURER_H
#include <vector>
#include <map>
#include <utility>
#include "hw_address.h"
#include "macros.h"
#include "eapol.h"
namespace Tins {
/**
* \brief Generic EAPOL handshake.
*
* Stores both the client and supplicant addresses, as well as
* all of the EAPOL packets used during the handshake.
*/
template<typename T>
class EAPOLHandshake {
public:
typedef std::vector<T> container_type;
typedef HWAddress<6> address_type;
/**
* \brief Default constructor.
*/
EAPOLHandshake() { }
/**
* Constructs an EAPOLHandshake object.
*
* \param client_address The client address.
* \param supplicant_address The supplicant address.
* \param cont The container that holds the EAPOL packets used
* in the handshake.
*/
EAPOLHandshake(const address_type& client_address,
const address_type& supplicant_address,
const container_type& cont)
: cl_address_(client_address), suppl_address_(supplicant_address),
handshake_(cont) {
}
/**
* \return const address_type&
*/
const address_type& client_address() const {
return cl_address_;
}
/**
* \return const address_type&
*/
const address_type& supplicant_address() const {
return suppl_address_;
}
/**
* \return const container_type&
*/
const container_type& handshake() const {
return handshake_;
}
private:
address_type cl_address_, suppl_address_;
container_type handshake_;
};
/**
* The type used to store RSN handshakes.
*/
typedef EAPOLHandshake<RSNEAPOL> RSNHandshake;
/**
* Captures 802.1X RSN handshakes.
*/
class TINS_API RSNHandshakeCapturer {
public:
/**
* The type of handshakes that will be captured.
*/
typedef RSNHandshake handshake_type;
/**
* The type in which all of the captured handshakes
* will be stored.
*/
typedef std::vector<handshake_type> handshakes_type;
/**
* \brief Processes a packet.
*
* This will fetch the RSNEAPOL layer, if any, and store
* it in an intermediate storage. When a handshake is
* completed, it will be stored separately.
*
* \sa RSNHandshakeCapturer::handshakes
*/
bool process_packet(const PDU& pdu);
/**
* \brief Retrieves the completed handshakes.
*
* This will return the handshakes that have been completed
* so far. A handshake is completed when the 4-way handshake
* is captured.
*
* \sa RSNHandshakeCapturer::clear_handshakes
*/
const handshakes_type& handshakes() const {
return completed_handshakes_;
}
/**
* \brief Clears the completed handshakes.
*
* Since completed handshakes are stored in a std::vector,
* it is advisable to remove all of them once they have been
* processed.
*/
void clear_handshakes() {
completed_handshakes_.clear();
}
private:
typedef handshake_type::address_type address_type;
typedef handshake_type::container_type eapol_list;
typedef std::map<std::pair<address_type, address_type>, eapol_list> handshake_map;
bool do_insert(const handshake_map::key_type& key, const RSNEAPOL* eapol,
size_t expected);
handshake_map handshakes_;
handshakes_type completed_handshakes_;
};
} // Tins
#endif // TINS_HANDSHAKE_CAPTURER_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -40,9 +40,26 @@
#include "cxxstd.h"
namespace Tins {
/**
* \class HWAddress
* \brief Represents a hardware address.
*
* This class represents a hardware (MAC) address. It can
* be constructed from it's string representation and you can
* iterate over the bytes that compose it.
*
* For example:
*
* \code
* // Construct it from a string.
* HWAddress<6> address("00:01:fa:9e:1a:cd");
*
* // Iterate over its bytes.
* for(auto element : address) {
* // element will be each of the bytes(\x00, \x01, \xfa, etc)
* }
* \endcode
*/
template<size_t n, typename Storage = uint8_t>
class HWAddress {
@@ -79,7 +96,8 @@ public:
* \brief Constructor from a const storage_type*.
*
* If no pointer or a null pointer is provided, the address is
* initialized to 00:00:.....
* initialized to 00:00:00:00:00:00.
*
* This constructor is very usefull when passing zero initialized
* addresses as arguments to other functions. You can use a
* literal 0, which will be implicitly converted to the empty address.
@@ -90,10 +108,12 @@ public:
* \param ptr The pointer from which to construct this address.
*/
HWAddress(const storage_type* ptr = 0) {
if(ptr)
std::copy(ptr, ptr + address_size, buffer);
else
if (ptr) {
std::copy(ptr, ptr + address_size, buffer_);
}
else {
std::fill(begin(), end(), storage_type());
}
}
/**
@@ -107,15 +127,15 @@ public:
*
* \param address The hex-notation address to be parsed.
*/
HWAddress(const std::string &address) {
convert(address, buffer);
HWAddress(const std::string& address) {
convert(address, buffer_);
}
/**
* \brief Overload provided basically for string literals.
*
* This constructor takes a const char array of i elements in
* hex-notation. \sa HWAddress::HWAddress(const std::string &address)
* hex-notation. \sa HWAddress::HWAddress(const std::string& address)
*
* This is mostly used when providing string literals. If this where
* a const char*, then there would be an ambiguity when providing
@@ -126,7 +146,7 @@ public:
*/
template<size_t i>
HWAddress(const char (&address)[i]) {
convert(address, buffer);
convert(address, buffer_);
}
/**
@@ -142,7 +162,7 @@ public:
* \param rhs The HWAddress to be constructed from.
*/
template<size_t i>
HWAddress(const HWAddress<i> &rhs) {
HWAddress(const HWAddress<i>& rhs) {
// Fill extra bytes
std::fill(
// Copy as most as we can
@@ -164,7 +184,7 @@ public:
* \return iterator.
*/
iterator begin() {
return buffer;
return buffer_;
}
/**
@@ -174,7 +194,7 @@ public:
* \return const_iterator.
*/
const_iterator begin() const {
return buffer;
return buffer_;
}
/**
@@ -184,7 +204,7 @@ public:
* \return iterator.
*/
iterator end() {
return buffer + address_size;
return buffer_ + address_size;
}
/**
@@ -194,7 +214,7 @@ public:
* \return const_iterator.
*/
const_iterator end() const {
return buffer + address_size;
return buffer_ + address_size;
}
/**
@@ -204,7 +224,7 @@ public:
*
* \return bool indicating whether addresses are equal.
*/
bool operator==(const HWAddress &rhs) const {
bool operator==(const HWAddress& rhs) const {
return std::equal(begin(), end(), rhs.begin());
}
@@ -215,7 +235,7 @@ public:
*
* \return bool indicating whether addresses are distinct.
*/
bool operator!=(const HWAddress &rhs) const {
bool operator!=(const HWAddress& rhs) const {
return !(*this == rhs);
}
@@ -226,7 +246,7 @@ public:
*
* \return bool indicating whether this address is less-than rhs.
*/
bool operator<(const HWAddress &rhs) const {
bool operator<(const HWAddress& rhs) const {
return std::lexicographical_compare(begin(), end(), rhs.begin(), rhs.end());
}
@@ -243,14 +263,14 @@ public:
* \brief Indicates whether this is a broadcast address.
*/
bool is_broadcast() const {
return *this == broadcast;
return* this == broadcast;
}
/**
* \brief Indicates whether this is a multicast address.
*/
bool is_multicast() const {
return (buffer[0] & 0x01);
return (*begin() & 0x01);
}
/**
@@ -267,7 +287,7 @@ public:
*/
std::string to_string() const {
std::ostringstream oss;
oss << *this;
oss <<* this;
return oss.str();
}
@@ -277,7 +297,7 @@ public:
* \param i The element to retrieve.
*/
storage_type operator[](size_t i) const {
return buffer[i];
return begin()[i];
}
/**
@@ -287,14 +307,14 @@ public:
* \param addr The parameter to be written.
* \return std::ostream& pointing to the os parameter.
*/
friend std::ostream &operator<<(std::ostream &os, const HWAddress &addr) {
friend std::ostream& operator<<(std::ostream& os, const HWAddress& addr) {
std::transform(
addr.begin(),
addr.end() - 1,
std::ostream_iterator<std::string>(os, ":"),
&HWAddress::storage_to_string
);
return os << storage_to_string(addr.buffer[HWAddress::address_size-1]);
return os << storage_to_string(addr.begin()[HWAddress::address_size - 1]);
}
/**
@@ -308,80 +328,104 @@ public:
* But since some PDUs return a HWAddress<> by value, this function
* can be used to avoid temporaries.
*
* \param iter The output iterator in which to store this address.
* \param output The output iterator in which to store this address.
* \return OutputIterator pointing to one-past the last position
* written.
*/
template<typename OutputIterator>
OutputIterator copy(OutputIterator iter) const {
return std::copy(begin(), end(), iter);
OutputIterator copy(OutputIterator output) const {
for (const_iterator iter = begin(); iter != end(); ++iter) {
*output++ = *iter;
}
return output;
}
private:
template<typename OutputIterator>
static void convert(const std::string &hw_addr, OutputIterator output);
static void convert(const std::string& hw_addr, OutputIterator output);
static HWAddress<n> make_broadcast_address() {
// Build a buffer made of n 0xff bytes
uint8_t buffer[n];
for (size_t i = 0; i < n; ++i) {
buffer[i] = 0xff;
}
return HWAddress<n>(buffer);
}
static std::string storage_to_string(storage_type element) {
std::ostringstream oss;
oss << std::hex;
if(element < 0x10)
if (element < 0x10) {
oss << '0';
}
oss << (unsigned)element;
return oss.str();
}
storage_type buffer[n];
storage_type buffer_[n];
};
template<size_t n, typename Storage>
template<typename OutputIterator>
void HWAddress<n, Storage>::convert(const std::string &hw_addr,
OutputIterator output)
{
void HWAddress<n, Storage>::convert(const std::string& hw_addr,
OutputIterator output) {
unsigned i(0);
size_t count(0);
storage_type tmp;
while(i < hw_addr.size() && count < n) {
while (i < hw_addr.size() && count < n) {
const unsigned end = i+2;
tmp = storage_type();
while(i < end) {
if(hw_addr[i] >= 'a' && hw_addr[i] <= 'f')
while (i < end) {
if (hw_addr[i] >= 'a' && hw_addr[i] <= 'f') {
tmp = (tmp << 4) | (hw_addr[i] - 'a' + 10);
else if(hw_addr[i] >= 'A' && hw_addr[i] <= 'F')
}
else if (hw_addr[i] >= 'A' && hw_addr[i] <= 'F') {
tmp = (tmp << 4) | (hw_addr[i] - 'A' + 10);
else if(hw_addr[i] >= '0' && hw_addr[i] <= '9')
}
else if (hw_addr[i] >= '0' && hw_addr[i] <= '9') {
tmp = (tmp << 4) | (hw_addr[i] - '0');
else if(hw_addr[i] == ':')
}
else if (hw_addr[i] == ':') {
break;
else
}
else {
throw std::runtime_error("Invalid byte found");
}
i++;
}
*(output++) = tmp;
count++;
if(i < hw_addr.size()) {
if(hw_addr[i] == ':')
if (i < hw_addr.size()) {
if (hw_addr[i] == ':') {
i++;
else
}
else {
throw std::runtime_error("Invalid separator");
}
}
}
while(count++ < n) {
while (count++ < n) {
*(output++) = storage_type();
}
}
template<size_t n, typename Storage>
const HWAddress<n, Storage> HWAddress<n, Storage>::broadcast("ff:ff:ff:ff:ff:ff");
const HWAddress<n, Storage> HWAddress<n, Storage>::broadcast = make_broadcast_address();
} // namespace Tins
#if TINS_IS_CXX11
namespace std
{
namespace std {
// Specialization of std::hash for HWAddress
template<size_t n>
struct hash<Tins::HWAddress<n>> {
size_t operator()(const Tins::HWAddress<n> &addr) const {
size_t operator()(const Tins::HWAddress<n>& addr) const {
return std::hash<std::string>()(addr.to_string());
}
};
} // namespace std
#endif
#endif // TINS_IS_CXX11
#endif // TINS_HWADDRESS_H

508
include/tins/icmp.h Normal file
View File

@@ -0,0 +1,508 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_ICMP_H
#define TINS_ICMP_H
// Windows likes to define macros with not-so-common-names, which break
// this code
#ifdef _WIN32
#ifdef TIMESTAMP_REQUEST
#undef TIMESTAMP_REQUEST
#endif // TIMESTAMP_REQUEST
#ifdef TIMESTAMP_REPLY
#undef TIMESTAMP_REPLY
#endif // TIMESTAMP_REPLY
#endif // _WIN32
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
#include "ip_address.h"
#include "icmp_extension.h"
namespace Tins {
namespace Memory {
class InputMemoryStream;
} // Memory
/**
* \class ICMP
* \brief Class that represents an ICMP PDU.
*
* ICMP is the representation of the ICMP PDU. Instances of this class
* must be sent over a level 3 PDU, this will otherwise fail.
*/
class TINS_API ICMP : public PDU {
public:
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::ICMP;
/**
* The type used to store addresses.
*/
typedef IPv4Address address_type;
/** \brief ICMP flags
*/
enum Flags {
ECHO_REPLY = 0,
DEST_UNREACHABLE = 3,
SOURCE_QUENCH = 4,
REDIRECT = 5,
ECHO_REQUEST = 8,
TIME_EXCEEDED = 11,
PARAM_PROBLEM = 12,
TIMESTAMP_REQUEST = 13,
TIMESTAMP_REPLY = 14,
INFO_REQUEST = 15,
INFO_REPLY = 16,
ADDRESS_MASK_REQUEST = 17,
ADDRESS_MASK_REPLY = 18
};
/**
* \brief Creates an instance of ICMP.
*
* If no flag is specified, then ECHO_REQUEST will be used.
* \param flag The type flag which will be set.
*/
ICMP(Flags flag = ECHO_REQUEST);
/**
* \brief Constructs an ICMP object from a buffer.
*
* If there is not enough size for an ICMP header, a
* malformed_packet exception is thrown.
*
* Any extra data in the buffer will be stored in a RawPDU.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
ICMP(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Sets the code field.
*
* \param new_code The code which will be stored in the ICMP struct.
*/
void code(uint8_t new_code);
/** \brief Sets the type field.
*
* \param type The type which will be stored in the ICMP struct.
*/
void type(Flags type);
/**
* \brief Setter for the id field.
*
* \param new_id uint16_t with the new id.
*/
void id(uint16_t new_id);
/**
* \brief Setter for the sequence field.
*
* \param new_seq uint16_t with the new sequence.
*/
void sequence(uint16_t new_seq);
/**
* \brief Setter for the gateway field.
*
* \param new_gw The new value for the gateway field.
*/
void gateway(address_type new_gw);
/**
* \brief Setter for the mtu field.
*
* \param new_mtu uint16_t with the new sequence.
*/
void mtu(uint16_t new_mtu);
/**
* \brief Setter for the pointer field.
*
* \param new_pointer uint8_t with the new pointer.
*/
void pointer(uint8_t new_pointer);
/**
* \brief Setter for the original timestamp field.
*
* \param new_timestamp the value to be set.
*/
void original_timestamp(uint32_t new_timestamp);
/**
* \brief Setter for the receive timestamp field.
*
* \param new_timestamp the value to be set.
*/
void receive_timestamp(uint32_t new_timestamp);
/**
* \brief Setter for the transmit timestamp field.
*
* \param new_timestamp the value to be set.
*/
void transmit_timestamp(uint32_t new_timestamp);
/**
* \brief Setter for the address mask field.
*
* \param new_mask the value to be set.
*/
void address_mask(address_type new_mask);
/**
* \brief Sets echo request flag for this PDU.
*
* \param id The identifier for this request.
* \param seq The sequence number for this request.
*/
void set_echo_request(uint16_t id, uint16_t seq);
/**
* \brief Sets echo reply flag for this PDU.
*
* \param id The identifier for this request.
* \param seq The sequence number for this request.
*/
void set_echo_reply(uint16_t id, uint16_t seq);
/**
* \brief Sets information request flag for this PDU.
*
* \param id The identifier for this request.
* \param seq The sequence number for this request.
*/
void set_info_request(uint16_t id, uint16_t seq);
/**
* \brief Sets information reply flag for this PDU.
*
* \param id The identifier for this request.
* \param seq The sequence number for this request.
*/
void set_info_reply(uint16_t id, uint16_t seq);
/**
* \brief Sets destination unreachable for this PDU.
*/
void set_dest_unreachable();
/**
* \brief Sets time exceeded flag for this PDU.
*
* \param ttl_exceeded If true this PDU will represent a ICMP ttl
* exceeded, otherwise it will represent a fragment reassembly
* time exceeded.
*/
void set_time_exceeded(bool ttl_exceeded = true);
/**
* \brief Sets parameter problem flag for this PDU.
*
* \param set_pointer Indicates whether a pointer to the bad octet
* is provided.
* \param bad_octet Identifies the octet in which the error was
* detected. If set_pointer == false, it is ignored.
*/
void set_param_problem(bool set_pointer = false, uint8_t bad_octet = 0);
/**
* \brief Sets source quench flag for this PDU.
*/
void set_source_quench();
/**
* \brief Sets redirect flag for this PDU.
*
* \param icode The code to be set.
* \param address Address of the gateway to which traffic should
* be sent.
*/
void set_redirect(uint8_t icode, address_type address);
/**
* \brief Getter for the ICMP type flag.
*
* \return The type flag for this ICMP PDU.
*/
Flags type() const {
return (Flags)header_.type;
}
/**
* \brief Getter for the ICMP code flag.
*
* \return The code flag for this ICMP PDU.
*/
uint8_t code() const {
return header_.code;
}
/**
* \brief Getter for the checksum field.
*
* \return Returns the checksum as an unit16_t.
*/
uint16_t checksum() const {
return Endian::be_to_host(header_.check);
}
/**
* \brief Getter for the echo id.
*
* \return Returns the echo id.
*/
uint16_t id() const {
return Endian::be_to_host(header_.un.echo.id);
}
/**
* \brief Getter for the echo sequence number.
*
* \return Returns the echo sequence number.
*/
uint16_t sequence() const {
return Endian::be_to_host(header_.un.echo.sequence);
}
/**
* \brief Getter for the gateway field.
*
* \return Returns the gateway field value.
*/
address_type gateway() const {
return address_type(Endian::be_to_host(header_.un.gateway));
}
/**
* \brief Getter for the pointer field.
*
* \return Returns the pointer field value.
*/
uint8_t pointer() const {
return header_.un.rfc4884.pointer;
}
/**
* \brief Getter for the length field.
*
* \return Returns the length field value.
*/
uint8_t length() const {
return header_.un.rfc4884.length;
}
/**
* \brief Getter for the mtu field.
*
* \return Returns the mtu field value.
*/
uint16_t mtu() const {
return Endian::be_to_host(header_.un.frag.mtu);
}
/**
* \brief Getter for the original timestamp field.
*
* \return Returns the original timestamp value.
*/
uint32_t original_timestamp() const {
return Endian::be_to_host(orig_timestamp_or_address_mask_);
}
/**
* \brief Getter for the receive timestamp field.
*
* \return Returns the receive timestamp value.
*/
uint32_t receive_timestamp() const {
return Endian::be_to_host(recv_timestamp_);
}
/**
* \brief Getter for the transmit timestamp field.
*
* \return Returns the transmit timestamp value.
*/
uint32_t transmit_timestamp() const {
return Endian::be_to_host(trans_timestamp_);
}
/**
* \brief Getter for the address mask field.
*
* \return Returns the address mask value.
*/
address_type address_mask() const {
return address_type(Endian::be_to_host(orig_timestamp_or_address_mask_));
}
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. This size includes the
* payload and options size.
*
* \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \brief Returns the trailer size.
*
* This metod overrides PDU::trailer_size. This size will hold the extensions size
*
* \sa PDU::header_size
*/
uint32_t trailer_size() const;
/**
* \brief Check whether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
/**
* \brief Getter for the extensions field.
*
* \return The extensions field
*/
const ICMPExtensionsStructure& extensions() const {
return extensions_;
}
/**
* \brief Getter for the extensions field.
*
* \return The extensions field
*/
ICMPExtensionsStructure& extensions() {
return extensions_;
}
/**
* \brief Indicates whether this object contains ICMP extensions
*/
bool has_extensions() const {
return !extensions_.extensions().empty();
}
/**
* \brief Sets whether the length field will be set for packets that use it
*
* As defined in RFC 4884, some ICMP packet types can have a length field. This
* method controlers whether the length field is set or not.
*
* Note that this only indicates that the packet should use this field. The
* actual value will be set during the packet's serialization.
*
* Note that, in order to br RFC compliant, if the size of the encapsulated
* PDU is greater than 128, the length field will always be set, regardless
* of whether this method was called or not.
*
* /param value true iff the length field should be set appropriately
*/
void use_length_field(bool value);
/**
* \brief Getter for the PDU's type.
*
* \sa PDU::pdu_type
*/
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \sa PDU::clone
*/
ICMP* clone() const {
return new ICMP(*this);
}
private:
TINS_BEGIN_PACK
struct icmp_header {
uint8_t type;
uint8_t code;
uint16_t check;
union {
struct {
uint16_t id;
uint16_t sequence;
} echo;
uint32_t gateway;
struct {
uint16_t unused;
uint16_t mtu;
} frag;
struct {
uint8_t pointer;
uint8_t length;
uint16_t unused;
} rfc4884;
} un;
} TINS_END_PACK;
void checksum(uint16_t new_check);
/** \brief Serialices this ICMP PDU.
* \param buffer The buffer in which the PDU will be serialized.
* \param total_sz The size available in the buffer.
* \param parent The PDU that's one level below this one on the stack.
*/
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
uint32_t get_adjusted_inner_pdu_size() const;
void try_parse_extensions(Memory::InputMemoryStream& stream);
bool are_extensions_allowed() const;
icmp_header header_;
uint32_t orig_timestamp_or_address_mask_, recv_timestamp_, trans_timestamp_;
ICMPExtensionsStructure extensions_;
};
} // Tins
#endif // TINS_ICMP_H

View File

@@ -0,0 +1,308 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_ICMP_EXTENSION_H
#define TINS_ICMP_EXTENSION_H
#include <vector>
#include <list>
#include <stdint.h>
#include "macros.h"
#include "small_uint.h"
#include "endianness.h"
namespace Tins {
class MPLS;
/**
* \brief Class that represents an ICMP extension object
*/
class TINS_API ICMPExtension {
public:
/**
* The type used to store the payload
*/
typedef std::vector<uint8_t> payload_type;
/**
* The type that will be returned when serializing an extensions
* structure object
*/
typedef std::vector<uint8_t> serialization_type;
/**
* \brief Default constructor
*/
ICMPExtension();
/**
* \brief Constructor taking class and type
*
* \param ext_class The extension class
* \param ext_type The extension sub-type
*/
ICMPExtension(uint8_t ext_class, uint8_t ext_type);
/**
* \brief Constructs an ICMP extension from a buffer
*
* \param buffer The input buffer
* \param total_sz The input buffer size
*/
ICMPExtension(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Setter for the extension class field
*
* \param value The new extension class field value
*/
void extension_class(uint8_t value);
/**
* \brief Setter for the extension sub-type field
*
* \param value The new extension sub-type field value
*/
void extension_type(uint8_t value);
/**
* \brief Setter for the payload field
*
* \param value The new payload field value
*/
void payload(const payload_type& value);
/**
* \brief Getter for the extension class field
*
* \return The extension class field value
*/
uint8_t extension_class() const {
return extension_class_;
}
/**
* \brief Getter for the extension sub-type field
*
* \return The extension sub-type field value
*/
uint8_t extension_type() const {
return extension_type_;
}
/**
* \brief Getter for the extension payload field
*
* \return The extension payload field value
*/
const payload_type& payload() const {
return payload_;
}
/**
* \brief Gets the size of this ICMP extension
*
* This returns the basic header size + the payload size
*
* \return The size of this extension
*/
uint32_t size() const;
/**
* \brief Serializes this extension into a buffer
*
* \param buffer The output buffer in which to store the serialization
* \param buffer_size The size of the output buffer
*/
void serialize(uint8_t* buffer, uint32_t buffer_size) const;
/**
* \brief Serializes this extension object
*
* \return The serialized extension
*/
serialization_type serialize() const;
private:
static const uint32_t BASE_HEADER_SIZE;
payload_type payload_;
uint8_t extension_class_, extension_type_;
};
/**
* \brief Class that represents an ICMP extensions structure
*/
class TINS_API ICMPExtensionsStructure {
public:
/**
* The minimum ICMP payload size that has to be present when the PDU
* contains extensions.
*/
static const uint32_t MINIMUM_ICMP_PAYLOAD;
/**
* The type that will be returned when serializing an extensions
* structure object
*/
typedef ICMPExtension::serialization_type serialization_type;
/**
* The type used to store the list of ICMP extensions in this structure
*/
typedef std::list<ICMPExtension> extensions_type;
/**
* \brief Default constructor
*
* This sets the version to 2, as specified in RFC 4884
*/
ICMPExtensionsStructure();
/**
* \brief Constructor from a buffer.
*
* This constructor will find, parse and store the extension
* stack in the buffer.
*/
ICMPExtensionsStructure(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Setter for the version field
*
* \param value The new version field value
*/
void version(small_uint<4> value);
/**
* \brief Setter for the reserved field
*
* \param value The new reserved field value
*/
void reserved(small_uint<12> value);
/**
* \brief Getter for the version field
*
* \return The version field value
*/
small_uint<4> version() const {
uint16_t value = Endian::be_to_host(version_and_reserved_);
return (value >> 12) & 0xf;
}
/**
* \brief Getter for the reserved field
*
* \return The reserved field value
*/
small_uint<12> reserved() const {
uint16_t value = Endian::be_to_host(version_and_reserved_);
return value & 0xfff;
}
/**
* \brief Getter for the checksum field
*
* \return The checksum field value
*/
uint16_t checksum() const {
return Endian::be_to_host(checksum_);
}
/**
* \brief Getter for the extensions stored by this structure
*
* \return The extensions stored in this structure
*/
const extensions_type& extensions() const {
return extensions_;
}
/**
* \brief Adds an extension to this structure
*
* \param extension The extension to be added
*/
void add_extension(const ICMPExtension& extension);
/**
* \brief Adds an MPLS extension to this structure
*
* This will construct an extension using the provided MPLS packet as
* its payload. The class and type fields will be set appropriately.
*
* \param extension The MPLS payload to be used for the new extension
*/
void add_extension(MPLS& mpls);
/**
* \brief Gets the size of this ICMP extensions structure
*
* \return The size of this structure
*/
uint32_t size() const;
/**
* \brief Serializes this extension structure into a buffer
*
* \param buffer The output buffer in which to store the serialization
* \param buffer_size The size of the output buffer
*/
void serialize(uint8_t* buffer, uint32_t buffer_size);
/**
* \brief Serializes this extension structure
*
* \return The serialized extension structure
*/
serialization_type serialize();
/**
* \brief Validates if the given input contains a valid extension structure
*
* The validation is performed by calculating the checksum of the input
* and comparing to the checksum value in the input buffer.
*
* \param buffer The input buffer
* \param total_sz The size of the input buffer
* \return true iff the buffer contains a valid ICMP extensions structure
*/
static bool validate_extensions(const uint8_t* buffer, uint32_t total_sz);
private:
static const uint32_t BASE_HEADER_SIZE;
uint16_t version_and_reserved_;
uint16_t checksum_;
extensions_type extensions_;
};
} // Tins
#endif // TINS_ICMP_EXTENSION_H

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View File

@@ -1,18 +1,18 @@
/*
* Copyright (c) 2014, Matias Fontanini
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -26,10 +26,14 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_INTERNALS_H
#define TINS_INTERNALS_H
#if TINS_IS_CXX11
#include <type_traits>
#endif
#include <sstream>
#include <string>
#include <stdint.h>
@@ -41,54 +45,60 @@
* \cond
*/
namespace Tins {
namespace Memory {
class InputMemoryStream;
} // Memory
class IPv4Address;
class IPv6Address;
class ICMPExtensionsStructure;
namespace Internals {
template<size_t n>
class byte_array {
public:
typedef uint8_t* iterator;
typedef const uint8_t* const_iterator;
byte_array() {
std::fill(begin(), end(), 0);
}
template<typename InputIterator>
byte_array(InputIterator start, InputIterator last) {
std::copy(start, last, data);
}
template<typename InputIterator>
byte_array(InputIterator start) {
std::copy(start, n, data);
}
uint8_t &operator[](size_t i) {
uint8_t& operator[](size_t i) {
return data[i];
}
uint8_t operator[](size_t i) const{
return data[i];
}
iterator begin() {
return data;
}
iterator end() {
return data + n;
}
const_iterator begin() const {
return data;
}
const_iterator end() const {
return data + n;
}
size_t size() const {
return n;
}
@@ -96,8 +106,8 @@ private:
uint8_t data[n];
};
void skip_line(std::istream &input);
bool from_hex(const std::string &str, uint32_t &result);
void skip_line(std::istream& input);
bool from_hex(const std::string& str, uint32_t& result);
template<bool, typename T = void>
struct enable_if {
@@ -106,71 +116,79 @@ struct enable_if {
template<typename T>
struct enable_if<false, T> {
};
PDU *pdu_from_flag(Constants::Ethernet::e flag, const uint8_t *buffer,
PDU* pdu_from_flag(Constants::Ethernet::e flag, const uint8_t* buffer,
uint32_t size, bool rawpdu_on_no_match = true);
PDU *pdu_from_flag(Constants::IP::e flag, const uint8_t *buffer,
PDU* pdu_from_flag(Constants::IP::e flag, const uint8_t* buffer,
uint32_t size, bool rawpdu_on_no_match = true);
PDU *pdu_from_flag(PDU::PDUType type, const uint8_t *buffer, uint32_t size);
PDU* pdu_from_dlt_flag(int flag, const uint8_t* buffer,
uint32_t size, bool rawpdu_on_no_match = true);
PDU* pdu_from_flag(PDU::PDUType type, const uint8_t* buffer, uint32_t size);
Constants::Ethernet::e pdu_flag_to_ether_type(PDU::PDUType flag);
Constants::IP::e pdu_flag_to_ip_type(PDU::PDUType flag);
uint32_t get_padded_icmp_inner_pdu_size(const PDU* inner_pdu, uint32_t pad_alignment);
void try_parse_icmp_extensions(Memory::InputMemoryStream& stream,
uint32_t payload_length, ICMPExtensionsStructure& extensions);
template<typename T>
bool increment_buffer(T &addr) {
bool increment_buffer(T& addr) {
typename T::iterator it = addr.end() - 1;
while(it >= addr.begin() && *it == 0xff) {
while (it >= addr.begin() && *it == 0xff) {
*it = 0;
--it;
}
// reached end
if(it < addr.begin())
if (it < addr.begin()) {
return true;
}
(*it)++;
return false;
}
template<typename T>
bool decrement_buffer(T &addr) {
bool decrement_buffer(T& addr) {
typename T::iterator it = addr.end() - 1;
while(it >= addr.begin() && *it == 0) {
while (it >= addr.begin() && *it == 0) {
*it = 0xff;
--it;
}
// reached end
if(it < addr.begin())
if (it < addr.begin()) {
return true;
}
(*it)--;
return false;
}
bool increment(IPv4Address &addr);
bool increment(IPv6Address &addr);
bool decrement(IPv4Address &addr);
bool decrement(IPv6Address &addr);
bool increment(IPv4Address& addr);
bool increment(IPv6Address& addr);
bool decrement(IPv4Address& addr);
bool decrement(IPv6Address& addr);
template<size_t n>
bool increment(HWAddress<n> &addr) {
bool increment(HWAddress<n>& addr) {
return increment_buffer(addr);
}
template<size_t n>
bool decrement(HWAddress<n> &addr) {
bool decrement(HWAddress<n>& addr) {
return decrement_buffer(addr);
}
IPv4Address last_address_from_mask(IPv4Address addr, IPv4Address mask);
IPv6Address last_address_from_mask(IPv6Address addr, const IPv6Address &mask);
IPv6Address last_address_from_mask(IPv6Address addr, const IPv6Address& mask);
template<size_t n>
HWAddress<n> last_address_from_mask(HWAddress<n> addr, const HWAddress<n> &mask) {
HWAddress<n> last_address_from_mask(HWAddress<n> addr, const HWAddress<n>& mask) {
typename HWAddress<n>::iterator addr_iter = addr.begin();
for(typename HWAddress<n>::const_iterator it = mask.begin(); it != mask.end(); ++it, ++addr_iter) {
for (typename HWAddress<n>::const_iterator it = mask.begin(); it != mask.end(); ++it, ++addr_iter) {
*addr_iter = *addr_iter | ~*it;
}
return addr;
}
inline bool is_dot3(const uint8_t *ptr, size_t sz) {
inline bool is_dot3(const uint8_t* ptr, size_t sz) {
return (sz >= 13 && ptr[12] < 8);
}
@@ -198,6 +216,37 @@ template<>
struct is_unsigned_integral<uint64_t> {
static const bool value = true;
};
#if TINS_IS_CXX11 && !defined(_MSC_VER)
// Template metaprogramming trait to determine if a functor can accept another parameter as an argument
template <typename T, typename P, typename=void>
struct accepts_type : std::false_type { };
template <typename T, typename P>
struct accepts_type<T, P,
typename std::enable_if<
std::is_same< decltype( std::declval<T>()(std::declval<P>()) ), bool>::value
>::type
> : std::true_type { };
// use enable_if to invoke the Packet&& version of the sniff_loop handler if possible - otherwise fail to old behavior
template <typename Functor, typename Packet>
bool invoke_loop_cb(Functor& f, Packet& p, typename std::enable_if<accepts_type<Functor, Packet>::value, bool>::type* = 0) {
return f(std::move(p));
}
template <typename Functor, typename Packet>
bool invoke_loop_cb(Functor& f, Packet& p, typename std::enable_if<!accepts_type<Functor, Packet>::value && accepts_type<Functor, Packet&>::value, bool>::type* = 0) {
return f(p);
}
template <typename Functor, typename Packet>
bool invoke_loop_cb(Functor& f, Packet& p, typename std::enable_if<!accepts_type<Functor, Packet>::value && !accepts_type<Functor, Packet&>::value, bool>::type* = 0) {
return f(*p.pdu());
}
#endif
} // namespace Internals
} // namespace Tins
/**

770
include/tins/ip.h Normal file
View File

@@ -0,0 +1,770 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_IP_H
#define TINS_IP_H
#include <list>
#include "pdu.h"
#include "small_uint.h"
#include "endianness.h"
#include "ip_address.h"
#include "pdu_option.h"
#include "macros.h"
#include "cxxstd.h"
namespace Tins {
namespace Memory {
class OutputMemoryStream;
} // Memory
/**
* \class IP
* \brief Class that represents an IP PDU.
*
* By default, IP PDUs are initialized, setting TTL to IP::DEFAULT_TTL,
* id field to 1 and version to 4. Taking this into account, users
* should set destination and source port and would be enough to send one.
*
* When IP is the lowest layer on a packet, and the packet is serialized
* this willc heck if the source address is different than 0.0.0.0. If it is,
* the address of the interface in which the packet is going to be sent
* is retrieved (by using the routing table and the destination address)
* and set as the source address. If you don't want this behaviour, simply
* set the source address to 0.0.0.0.
*/
class TINS_API IP : public PDU {
public:
/**
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::IP;
/**
* The type used to store addresses.
*/
typedef IPv4Address address_type;
/**
* Type used to represent the different IP flags.
*/
enum Flags {
FLAG_RESERVED = 4,
DONT_FRAGMENT = 2,
MORE_FRAGMENTS = 1
};
/**
* \brief Enum indicating the option's class.
*
* Enum OptionClass represents the different classes of
* IP Options.
*/
enum OptionClass {
CONTROL = 0,
MEASUREMENT = 2
};
/**
* \brief Enum indicating the option's id number.
*
* Enum Option indicates the possible IP Options.
*/
enum OptionNumber {
END = 0,
NOOP = 1,
SEC = 2,
LSRR = 3,
TIMESTAMP = 4,
EXTSEC = 5,
RR = 7,
SID = 8,
SSRR = 9,
MTUPROBE = 11,
MTUREPLY = 12,
EIP = 17,
TR = 18,
ADDEXT = 19,
RTRALT = 20,
SDB = 21,
DPS = 23,
UMP = 24,
QS = 25
};
/**
* \brief The type used to represent an option's type.
*/
TINS_BEGIN_PACK
struct option_identifier {
#if TINS_IS_LITTLE_ENDIAN
uint8_t number:5,
op_class:2,
copied:1;
#elif TINS_IS_BIG_ENDIAN
uint8_t copied:1,
op_class:2,
number:5;
#endif
/**
* \brief Default constructor.
*
* Initializes every field to 0.
*/
option_identifier()
#if TINS_IS_LITTLE_ENDIAN
: number(0), op_class(0), copied(0) {}
#else
: copied(0), op_class(0), number(0) {}
#endif
/**
* \brief Constructs this option from a single uint8_t value.
*
* This parses the value and initializes each field with the
* appropriate value.
*
* \param value The value to be parsed and used for
* initialization
*/
option_identifier(uint8_t value)
#if TINS_IS_LITTLE_ENDIAN
: number(value & 0x1f),
op_class((value >> 5) & 0x03),
copied((value >> 7) & 0x01) {}
#elif TINS_IS_BIG_ENDIAN
: copied((value >> 7) & 0x01),
op_class((value >> 5) & 0x03),
number(value & 0x1f) {}
#endif
/**
* Constructor using user provided values for each field.
* \param number The number field value.
* \param op_class The option class field value.
* \param copied The copied field value.
*/
option_identifier(OptionNumber number, OptionClass op_class,
small_uint<1> copied)
#if TINS_IS_LITTLE_ENDIAN
: number(number), op_class(op_class), copied(copied) {}
#else
: copied(copied), op_class(op_class), number(number) {}
#endif
/**
* \brief Equality operator.
*/
bool operator==(const option_identifier& rhs) const {
return number == rhs.number && op_class == rhs.op_class && copied == rhs.copied;
}
} TINS_END_PACK;
/**
* The IP options type.
*/
typedef PDUOption<option_identifier, IP> option;
/**
* The type of the security option.
*/
struct security_type {
uint16_t security, compartments;
uint16_t handling_restrictions;
small_uint<24> transmission_control;
security_type(uint16_t sec = 0,
uint16_t comp = 0,
uint16_t hand_res = 0,
small_uint<24> tcc = 0)
: security(sec), compartments(comp),
handling_restrictions(hand_res), transmission_control(tcc) { }
static security_type from_option(const option& opt);
};
/**
* The type of the Loose Source and Record Route
*/
struct generic_route_option_type {
typedef std::vector<address_type> routes_type;
uint8_t pointer;
routes_type routes;
generic_route_option_type(uint8_t ptr = 0, routes_type rts = routes_type())
: pointer(ptr), routes(rts) {}
static generic_route_option_type from_option(const option& opt);
};
/**
* The type of the Loose Source and Record Route
*/
typedef generic_route_option_type lsrr_type;
/**
* The type of the Strict Source and Record Route
*/
typedef generic_route_option_type ssrr_type;
/**
* The type of the Record Route
*/
typedef generic_route_option_type record_route_type;
/**
* The type used to store IP options.
*/
typedef std::list<option> options_type;
/**
* \brief Constructor for building the IP PDU.
*
* Both the destination and source IP address can be supplied.
* By default, those fields are initialized using the IP
* address 0.0.0.0.
*
* \param ip_dst The destination ip address(optional).
* \param ip_src The source ip address(optional).
*/
IP(address_type ip_dst = address_type(),
address_type ip_src = address_type());
/**
* \brief Constructs an IP object from a buffer and adds all
* identifiable PDUs found in the buffer as children of this
* one.
*
* If there is not enough size for an IP header, a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
IP(const uint8_t* buffer, uint32_t total_sz);
/* Getters */
/**
* \brief Getter for the header length field.
*
* \return The number of dwords the header occupies in an uin8_t.
*/
small_uint<4> head_len() const {
return this->ip_.ihl;
}
/**
* \brief Getter for the type of service field.
*
* \return The this IP PDU's type of service.
*/
uint8_t tos() const {
return ip_.tos;
}
/**
* \brief Getter for the total length field.
*
* \return The total length of this IP PDU.
*/
uint16_t tot_len() const {
return Endian::be_to_host(ip_.tot_len);
}
/**
* \brief Getter for the id field.
*
* \return The id for this IP PDU.
*/
uint16_t id() const {
return Endian::be_to_host(ip_.id);
}
/**
* \brief Getter for the fragment offset field.
*
* This method is deprecated. Use IP::fragment_offset and IP::flags.
*
* \deprecated
* \return The fragment offset for this IP PDU.
* \sa IP::fragment_offset
* \sa IP::flags
*/
TINS_DEPRECATED(uint16_t frag_off() const) {
return Endian::be_to_host(ip_.frag_off);
}
/**
* \brief Getter for the fragment offset field.
*
* This will return the fragment offset field, as present in the packet,
* which indicates the offset of this fragment in blocks of 8 bytes.
*
* \return The fragment offset, measured in units of 8 byte blocks
*/
small_uint<13> fragment_offset() const {
return Endian::be_to_host(ip_.frag_off) & 0x1fff;
}
/**
* \brief Getter for the flags field.
*
* \return The IP flags field
*/
Flags flags() const {
return static_cast<Flags>(Endian::be_to_host(ip_.frag_off) >> 13);
}
/**
* \brief Getter for the time to live field.
*
* \return The time to live for this IP PDU.
*/
uint8_t ttl() const {
return ip_.ttl;
}
/**
* \brief Getter for the protocol field.
*
* \return The protocol for this IP PDU.
*/
uint8_t protocol() const {
return ip_.protocol;
}
/**
* \brief Getter for the checksum field.
*
* \return The checksum for this IP PDU.
*/
uint16_t checksum() const {
return Endian::be_to_host(ip_.check);
}
/**
* \brief Getter for the source address field.
*
* \return The source address for this IP PDU.
*/
address_type src_addr() const {
return address_type(ip_.saddr);
}
/**
* \brief Getter for the destination address field.
* \return The destination address for this IP PDU.
*/
address_type dst_addr() const {
return address_type(ip_.daddr);
}
/**
* \brief Getter for the version field.
* \return The version for this IP PDU.
*/
small_uint<4> version() const {
return ip_.version;
}
/**
* \brief Getter for the IP options.
* \return The stored options.
*/
const options_type& options() const {
return ip_options_;
}
/* Setters */
/**
* \brief Setter for the type of service field.
*
* \param new_tos The new type of service.
*/
void tos(uint8_t new_tos);
/**
* \brief Setter for the id field.
*
* \param new_id The new id.
*/
void id(uint16_t new_id);
/**
* \brief Setter for the fragment offset field.
*
* This method is deprecated. Use IP::fragment_offset and IP::flags.
*
* \deprecated
* \param new_frag_off The new fragment offset.
* \sa IP::fragment_offset
* \sa IP::flags
*/
TINS_DEPRECATED(void frag_off(uint16_t new_frag_off));
/**
* \brief Setter for the fragment offset field.
*
* The value provided is measured in units of 8 byte blocks. This means that
* if you want this packet to have a fragment offset of <i>X</i>,
* you need to provide <i>X / 8</i> as the argument to this method.
*
* \param new_frag_off The new fragment offset, measured in units of 8 byte blocks.
*/
void fragment_offset(small_uint<13> new_frag_off);
/**
* \brief Setter for the flags field.
*
* \param new_flags The new IP flags field value.
*/
void flags(Flags new_flags);
/**
* \brief Setter for the time to live field.
*
* \param new_ttl The new time to live.
*/
void ttl(uint8_t new_ttl);
/**
* \brief Setter for the protocol field.
*
* Note that this protocol will be overwritten using the
* inner_pdu's protocol type during serialization unless the IP
* datagram is fragmented.
*
* If the packet is fragmented and was originally sniffed, the
* original protocol type will be kept when serialized.
*
* If this packet has been crafted manually and the inner_pdu
* is, for example, a RawPDU, then setting the protocol yourself
* is necessary.
*
* \param new_protocol The new protocol.
*/
void protocol(uint8_t new_protocol);
/**
* \brief Setter for the source address field.
*
* \param ip The source address to be set.
*/
void src_addr(address_type ip);
/**
* \brief Setter for the destination address field.
*
* \param ip The destination address to be set.
*/
void dst_addr(address_type ip);
/**
* \brief Setter for the version field.
*
* \param ver The version field to be set.
*/
void version(small_uint<4> ver);
/**
* \brief Adds an IP option.
*
* The option is added after the last option in the option
* fields.
*
* \param opt The option to be added
*/
void add_option(const option& opt);
#if TINS_IS_CXX11
/**
* \brief Adds an IP option.
*
* The option is move-constructed.
*
* \param opt The option to be added.
*/
void add_option(option &&opt) {
internal_add_option(opt);
ip_options_.push_back(std::move(opt));
}
/**
* \brief Adds an IP option.
*
* The option is constructed from the provided parameters.
*
* \param args The arguments to be used in the option's
* constructor.
*/
template<typename... Args>
void add_option(Args&&... args) {
ip_options_.emplace_back(std::forward<Args>(args)...);
internal_add_option(ip_options_.back());
}
#endif
/**
* \brief Removes an IP option.
*
* If there are multiple options of the given type, only the first one
* will be removed.
*
* \param type The type of the option to be removed.
* \return true if the option was removed, false otherwise.
*/
bool remove_option(option_identifier id);
/**
* \brief Searchs for an option that matchs the given flag.
*
* If the option is not found, a null pointer is returned.
* Deleting the returned pointer will result in <b>undefined
* behaviour</b>.
*
* \param id The option identifier to be searched.
*/
const option* search_option(option_identifier id) const;
// Option setters
/**
* \brief Adds an End Of List option.
*/
void eol();
/**
* \brief Adds a NOP option.
*/
void noop();
/**
* \brief Adds a security option.
*
* \param data The data to be stored in this option.
*/
void security(const security_type& data);
/**
* \brief Adds a Loose Source and Record Route option.
*
* \param data The data to be stored in this option.
*/
void lsrr(const lsrr_type& data) {
add_route_option(131, data);
}
/**
* \brief Adds a Strict Source and Record Route option.
*
* \param data The data to be stored in this option.
*/
void ssrr(const ssrr_type& data) {
add_route_option(137, data);
}
/**
* \brief Adds a Record Route option.
*
* \param data The data to be stored in this option.
*/
void record_route(const record_route_type& data) {
add_route_option(7, data);
}
/**
* \brief Adds a Stream Identifier option.
*
* \param stream_id The stream id to be stored in this option.
*/
void stream_identifier(uint16_t stream_id);
// Option getters
/**
* \brief Searchs and returns a security option.
*
* If no such option exists, an option_not_found exception
* is thrown.
*
* \return security_type containing the option found.
*/
security_type security() const;
/**
* \brief Searchs and returns a Loose Source and Record Route
* option.
*
* If no such option exists, an option_not_found exception
* is thrown.
*
* \return lsrr_type containing the option found.
*/
lsrr_type lsrr() const {
return search_route_option(131);
}
/**
* \brief Searchs and returns a Strict Source and Record Route
* option.
*
* If no such option exists, an option_not_found exception
* is thrown.
*
* \return ssrr_type containing the option found.
*/
ssrr_type ssrr() const {
return search_route_option(137);
}
/**
* \brief Searchs and returns a Record Route option.
*
* If no such option exists, an option_not_found exception
* is thrown.
*
* \return record_route_type containing the option found.
*/
record_route_type record_route() const {
return search_route_option(7);
}
/**
* \brief Searchs and returns a Stream Identifier option.
*
* If no such option exists, an option_not_found exception
* is thrown.
*
* \return uint16_t containing the option found.
*/
uint16_t stream_identifier() const;
/* Virtual methods */
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \sa PDU::send()
*/
void send(PacketSender& sender, const NetworkInterface &);
/**
* \brief Check whether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
/**
* \brief 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 &);
/**
* Indicates whether this PDU is fragmented.
*
* \return true if this PDU is fragmented, false otherwise.
*/
bool is_fragmented() const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \sa PDU::clone
*/
IP* clone() const {
return new IP(*this);
}
private:
static const uint8_t DEFAULT_TTL;
TINS_BEGIN_PACK
struct ip_header {
#if TINS_IS_LITTLE_ENDIAN
uint8_t ihl:4,
version:4;
#else
uint8_t version:4,
ihl:4;
#endif
uint8_t tos;
uint16_t tot_len;
uint16_t id;
uint16_t frag_off;
uint8_t ttl;
uint8_t protocol;
uint16_t check;
uint32_t saddr;
uint32_t daddr;
} TINS_END_PACK;
void head_len(small_uint<4> new_head_len);
void tot_len(uint16_t new_tot_len);
void prepare_for_serialize(const PDU* parent);
void internal_add_option(const option& option);
void init_ip_fields();
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
void write_option(const option& opt, Memory::OutputMemoryStream& stream);
void add_route_option(option_identifier id, const generic_route_option_type& data);
generic_route_option_type search_route_option(option_identifier id) const;
void checksum(uint16_t new_check);
options_type::const_iterator search_option_iterator(option_identifier id) const;
options_type::iterator search_option_iterator(option_identifier id);
void update_padded_options_size();
ip_header ip_;
uint16_t options_size_, padded_options_size_;
options_type ip_options_;
};
} // Tins
#endif // TINS_IP_H

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