1
0
mirror of https://github.com/mfontanini/libtins synced 2026-01-29 13:04:28 +01:00

229 Commits
v3.2 ... v3.4

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

4
.gitmodules vendored Normal file
View File

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

27
.travis.yml Normal file
View File

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

230
CHANGES
View File

@@ -1,4 +1,221 @@
v3.2 v3.4 - Wed Mar 9 20:24:54 PST 2016
- Check the secure bit on HandshakeCapturer to detect 2nd packet
- Add info members directly into NetworkInterface
- Add IPv6 addresses to NetworkInterface::Info
- Make *MemoryStream use size_t rather than uint32_t
- Add WPA2Decrypter callback interface
- Set MACOSX_RPATH to ON
- Don't fail configuration if openssl is missing
- Build layer 5 as RawPDU if IPv6 has fragment header
- Fix examples so they build on gcc 4.6
- Fix flag value for sniffer's immediate mode
- Fix IP fragment reassemble when packet has flags DF+MF
- Add extract_metadata to main PDU classes
- Fix examples to make them work on Windows
- Use timercmp/sub and std::chrono to subtract timevals on PacketSender
- Build examples against local libtins build
- Add uninstall target
- Prefix HAVE_ config.h macros with TINS_
- Use compiler intrinsics to swap bytes
- Use C++11 mode by default
- Add missing TINS_API to PDU classes.
- Extend/fix ICMPv6 enum values and unify naming
- Return an empty string for dot11 ssid, if ssid is present but empty
- Implement new TCP stream follower mechanism
- Use ExternalProject_Add rather than including the gtest directory
- Fix invalid endian on IP fragment offset on OSX
v3.3 - Sun Jan 31 21:06:04 PST 2016
- Add TCP connection close example
- Move implementations on utils.h to utils.cpp
- Add ICMPv6 Multicast Listener Query Messages support
- Add ICMPv6 Multicast Listener Report Message support
- Make DNS::Query and DNS::Resource lowercase and deprecate the old names
- Change DNS::query/resource::type to query_type and deprecate old name
- Add DNS Start Of Authority parsing and serialization
- Parse and serialize MX preference field correctly
- Add NetworkInterface::friendly_name to get Windows friendly names
- Mask 16 bits on random number generated on traceroute example
- Fix TCP sequence number addition/subtraction when wrapping around
- Use 802.1ad protocol flag when seralizing stacked Dot1Q
- Code cleanup and use same syntax on the entire project
- Correctly serialize PPPoE session packets
- Fix IPv6 extension headers parsing/serialization
- Include examples before src to avoid duplicate tins target issue
- Add MPLS PDU and hook it up with ICMP extensions
- Set UDP checksum to 0xffff if it's 0
- Don't define TINS_STATIC in config.h
- Fix invalid RSNEAPOL parsing issue
- Remove special clang on OSX case when building gtest
- Update pseudoheader_checksum signature
- Fix overall checksum calculation
- Set ICMP payload length without padding if no extensions are present
- Export classes on Windows shared lib builds
- Use google/googletest submodule and update to HEAD
- Remove unused cassert header inclusions
- Add input/output memory stream classes port PDU classes to use them
- Add extensions for ICMP/ICMPv6
- Fix RSNInformation issues on big endian architectures
- Add IP::fragment_offset and IP::flags
- Don't set Ethernet type if inner PDU type is unknown
- Don't run IP source address overwrite tests on OSX
- Always calculate IP/IPv6 checksum
- Fix invalid constant value on PPPoE
- Define default constructor for PKTAP
- Guard 802.11 parsing code on PPI around HAVE_DOT11
- Fix parsing of Dot11 packets encapsulated on PPI having FCS-at-end
- Fix DataLinkType typo on doxygen docs
- Update docs on sniff_loop handle persistency
- Use uint32_t for DNS resource TTL setter
- Erase streams when they're reassembed on IPv4Reassembler
- Make all exceptions derive from exception_base
- Add remove_option member to IP, TCP, Dot11, ICMPv6, DHCP and DHCPv6
- Allow HW addresses to be 00:00:00:00:00 on NetworkInterface::info
- Increment option size when adding a new DHCPv6 option
- Use NOMINMAX on examples
- Add metric field to RouteEntry
- Allow setting immediate mode on Sniffer
- Use one flags field for all flags on SnifferConfiguration
- Add ICMP responses example
- Add interfaces_info example
- Fix bug on SessionKeys::SessionKeys
- Fix compilation errors on android platform
- Fix example compilation on Windows
- Add PacketWriter::write overload that takes a Packet
- Use different IP addresses on IP tests depending on OS
- Allow retrieving keys on WPA2Decrypter
- Add NetworkInterface::is_up and NetworkInterface::info
- Add NetworkInterface::Info::is_up
- Fix compilation warnings on Windows x64
- Fix FindPCAP.cmake to find winpcap on x64
- Fix more tests warnings triggered on Windows
- Fix tests compilation warnings on Windows
- Fix error on VC triggered by pcap redefining the "inline" keyword
- Soften DNS parsing rules
- Replace WIN32 macro with _WIN32
- Fix IPv6Address::to_string on Windows
- Fix DNS issues triggered on VC
- Add google test as git submodule
- Perserve IP protocol when using RawPDU
- Use pcap_sendpacket by default to send packets on Windows
- Don't allow receiving l2 packets on windows
- Added RadioTap channel map type
- Made rsn_information() a const member function to make Dot11ManagementFrame
immutable
- Ensure HAVE_CXX11 is checked when defining TINS_IS_CXX11
- Use one integer field for all flags on TCP
- Fix invalid DNS IPv4 address parsing on big endian arch
- Don't compile WPA2 test if LIBTINS_ENABLE_WPA2=0
- Add Dot11 radio measurement name corresponding to IEEE 802.11-2012
-------------------------------------------------------------------------------
v3.2 - Fri Mar 20 22:12:23 PST 2015
- Added include guard for config.h. - Added include guard for config.h.
@@ -79,6 +296,8 @@ conversion on integral constant.
- IPv4Address now uses inet_pton when constructing from string. - IPv4Address now uses inet_pton when constructing from string.
-------------------------------------------------------------------------------
v3.1 - Sun Aug 24 21:39:43 ART 2014 v3.1 - Sun Aug 24 21:39:43 ART 2014
- Fixed ICMPv6 checksum error on serialization. - Fixed ICMPv6 checksum error on serialization.
@@ -87,6 +306,8 @@ v3.1 - Sun Aug 24 21:39:43 ART 2014
- Changed the build system to CMake. - Changed the build system to CMake.
-------------------------------------------------------------------------------
v3.0 - Thu Aug 7 21:39:09 ART 2014 v3.0 - Thu Aug 7 21:39:09 ART 2014
- Timestamps can now be constructed from std::chrono::duration. - Timestamps can now be constructed from std::chrono::duration.
@@ -150,6 +371,8 @@ PDU types.
- Fixed bug triggered by not including the string header. - Fixed bug triggered by not including the string header.
-------------------------------------------------------------------------------
v2.0 - Thu Jan 23 11:09:38 ART 2014 v2.0 - Thu Jan 23 11:09:38 ART 2014
- DNSResourceRecord was removed. Now DNS records are added using - DNSResourceRecord was removed. Now DNS records are added using
@@ -204,6 +427,8 @@ capture size.
- Added tins_cast as a replacement for dynamic_cast on PDUs. - Added tins_cast as a replacement for dynamic_cast on PDUs.
-------------------------------------------------------------------------------
v1.2 - Mon oct 7 23:33:49 ART 2013 v1.2 - Mon oct 7 23:33:49 ART 2013
- Added BaseSniffer::begin and BaseSniffer::end. - Added BaseSniffer::begin and BaseSniffer::end.
@@ -298,6 +523,8 @@ that used them.
- Added Utils::resolve_domain and Utils::resolve_domain6 - Added Utils::resolve_domain and Utils::resolve_domain6
-------------------------------------------------------------------------------
v0.3 - Thu Jan 31 16:47:27 ART 2013 v0.3 - Thu Jan 31 16:47:27 ART 2013
- Added IPv6, ICMPv6 and DHCPv6 classes. - Added IPv6, ICMPv6 and DHCPv6 classes.
@@ -317,6 +544,7 @@ pseudo protocol.
- Fixed several bugs in DNS. - Fixed several bugs in DNS.
-------------------------------------------------------------------------------
v0.2 - Sat Oct 20 11:26:40 2012 v0.2 - Sat Oct 20 11:26:40 2012

View File

@@ -9,8 +9,22 @@ ELSE(NOT CMAKE_BUILD_TYPE)
MESSAGE(STATUS "Using specified '${CMAKE_BUILD_TYPE}' build type.") MESSAGE(STATUS "Using specified '${CMAKE_BUILD_TYPE}' build type.")
ENDIF(NOT CMAKE_BUILD_TYPE) ENDIF(NOT CMAKE_BUILD_TYPE)
# Default compilation settings # 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") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
ENDIF()
IF(APPLE)
# This is set to ON as of policy CMP0042
SET(CMAKE_MACOSX_RPATH ON)
ENDIF()
# Build output checks # Build output checks
OPTION(LIBTINS_BUILD_SHARED "Build libtins as a shared library." ON) OPTION(LIBTINS_BUILD_SHARED "Build libtins as a shared library." ON)
@@ -24,11 +38,12 @@ IF(LIBTINS_BUILD_SHARED)
ELSE(LIBTINS_BUILD_SHARED) ELSE(LIBTINS_BUILD_SHARED)
MESSAGE(STATUS "Build will generate a static library.") MESSAGE(STATUS "Build will generate a static library.")
SET(LIBTINS_TYPE STATIC) SET(LIBTINS_TYPE STATIC)
ADD_DEFINITIONS("-DTINS_STATIC=1")
ENDIF(LIBTINS_BUILD_SHARED) ENDIF(LIBTINS_BUILD_SHARED)
# The version number. # The version number.
SET(LIBTINS_VERSION_MAJOR 3) SET(LIBTINS_VERSION_MAJOR 3)
SET(LIBTINS_VERSION_MINOR 2) SET(LIBTINS_VERSION_MINOR 4)
SET(LIBTINS_VERSION "${LIBTINS_VERSION_MAJOR}.${LIBTINS_VERSION_MINOR}") SET(LIBTINS_VERSION "${LIBTINS_VERSION_MAJOR}.${LIBTINS_VERSION_MINOR}")
# Required Packages # Required Packages
@@ -43,22 +58,36 @@ IF(WIN32)
SET(LIBTINS_OS_LIBS Ws2_32.lib Iphlpapi.lib) SET(LIBTINS_OS_LIBS Ws2_32.lib Iphlpapi.lib)
# Add the NOMINMAX macro to avoid Windows' min and max macros. # Add the NOMINMAX macro to avoid Windows' min and max macros.
# While compiling on windows, for some reason, WIN32 is not defined, ADD_DEFINITIONS(-DNOMINMAX)
# maybe we could fix this later, but it's OK for now.
ADD_DEFINITIONS(-DNOMINMAX -DWIN32)
ENDIF(WIN32) ENDIF(WIN32)
INCLUDE(ExternalProject)
# *******************
# Compilation options # Compilation options
OPTION(LIBTINS_ENABLE_CXX11 "Compile libtins with c++11 features" OFF) # *******************
# Always check for C++ features
INCLUDE(CheckCXXFeatures)
IF(HAS_GCC_BUILTIN_SWAP)
SET(TINS_HAVE_GCC_BUILTIN_SWAP ON)
ENDIF()
# C++11 support
OPTION(LIBTINS_ENABLE_CXX11 "Compile libtins with c++11 features" ON)
IF(LIBTINS_ENABLE_CXX11) IF(LIBTINS_ENABLE_CXX11)
SET(HAVE_CXX11 ON) # We only use declval and decltype on gcc/clang as VC fails to build that code,
INCLUDE(CheckCXX11Features) # at least on VC2013
IF(HAS_CXX11_NULLPTR AND HAS_CXX11_RVALUE_REFERENCES) IF(HAS_CXX11_RVALUE_REFERENCES AND HAS_CXX11_FUNCTIONAL AND HAS_CXX11_CHRONO AND
((HAS_CXX11_DECLVAL AND HAS_CXX11_DECLTYPE) OR MSVC))
SET(TINS_HAVE_CXX11 ON)
MESSAGE(STATUS "Enabling C++11 features") MESSAGE(STATUS "Enabling C++11 features")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX11_COMPILER_FLAGS}") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX11_COMPILER_FLAGS}")
ELSE(HAS_CXX11_NULLPTR AND HAS_CXX11_RVALUE_REFERENCES) ELSE()
MESSAGE(FATAL_ERROR "C++11 features requested but the compiler does not support them.") MESSAGE(WARNING "The compiler doesn't support the necessary C++11 features. "
ENDIF(HAS_CXX11_NULLPTR AND HAS_CXX11_RVALUE_REFERENCES) "Disabling C++11 on this build")
ENDIF()
ELSE(LIBTINS_ENABLE_CXX11) ELSE(LIBTINS_ENABLE_CXX11)
MESSAGE( MESSAGE(
WARNING WARNING
@@ -67,20 +96,64 @@ ELSE(LIBTINS_ENABLE_CXX11)
"as it increases the library's performance") "as it increases the library's performance")
ENDIF(LIBTINS_ENABLE_CXX11) 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_DOT11 "Compile libtins with IEEE 802.11 support" ON)
OPTION(LIBTINS_ENABLE_WPA2 "Compile libtins with WPA2 decryption features (requires OpenSSL)" ON) OPTION(LIBTINS_ENABLE_WPA2 "Compile libtins with WPA2 decryption features (requires OpenSSL)" ON)
IF(LIBTINS_ENABLE_DOT11) IF(LIBTINS_ENABLE_DOT11)
SET(HAVE_DOT11 ON) SET(TINS_HAVE_DOT11 ON)
MESSAGE(STATUS "Enabling IEEE 802.11 support.") MESSAGE(STATUS "Enabling IEEE 802.11 support.")
IF(LIBTINS_ENABLE_WPA2) IF(LIBTINS_ENABLE_WPA2)
FIND_PACKAGE(OpenSSL REQUIRED) FIND_PACKAGE(OpenSSL)
SET(HAVE_WPA2_DECRYPTION ON) IF(OPENSSL_FOUND)
SET(TINS_HAVE_WPA2_DECRYPTION ON)
MESSAGE(STATUS "Enabling WPA2 decryption support.") MESSAGE(STATUS "Enabling WPA2 decryption support.")
ELSE()
MESSAGE(WARNING "Disabling WPA2 decryption support since OpenSSL was not found")
# Default this to empty strings
SET(OPENSSL_INCLUDE_DIR "")
SET(OPENSSL_LIBRARIES "")
ENDIF()
ELSE(LIBTINS_ENABLE_WPA2) ELSE(LIBTINS_ENABLE_WPA2)
MESSAGE(STATUS "Disabling WPA2 decryption support.") MESSAGE(STATUS "Disabling WPA2 decryption support.")
ENDIF(LIBTINS_ENABLE_WPA2) ENDIF(LIBTINS_ENABLE_WPA2)
ENDIF(LIBTINS_ENABLE_DOT11) ENDIF(LIBTINS_ENABLE_DOT11)
OPTION(LIBTINS_ENABLE_ACK_TRACKER "Enable TCP ACK tracking support" ON)
IF(LIBTINS_ENABLE_ACK_TRACKER AND TINS_HAVE_CXX11)
FIND_PACKAGE(Boost)
IF (Boost_FOUND)
MESSAGE(STATUS "Enabling TCP ACK tracking support.")
INCLUDE_DIRECTORIES(Boost_INCLUDE_DIRS)
SET(TINS_HAVE_ACK_TRACKER ON)
ELSE()
MESSAGE(WARNING "Disabling ACK tracking support as boost.icl was not found")
SET(TINS_HAVE_ACK_TRACKER OFF)
ENDIF()
ELSE()
SET(TINS_HAVE_ACK_TRACKER OFF)
MESSAGE(STATUS "Disabling ACK tracking support")
ENDIF()
OPTION(LIBTINS_ENABLE_WPA2_CALLBACKS "Enable WPA2 callback interface" ON)
IF(LIBTINS_ENABLE_WPA2_CALLBACKS AND TINS_HAVE_WPA2_DECRYPTION AND TINS_HAVE_CXX11)
SET(STATUS "Enabling WPA2 callback interface")
SET(TINS_HAVE_WPA2_CALLBACKS ON)
ENDIF()
# Use pcap_sendpacket to send l2 packets rather than raw sockets
IF(WIN32)
SET(USE_PCAP_SENDPACKET_DEFAULT ON)
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(TINS_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 # Add a target to generate API documentation using Doxygen
FIND_PACKAGE(Doxygen QUIET) FIND_PACKAGE(Doxygen QUIET)
IF(DOXYGEN_FOUND) IF(DOXYGEN_FOUND)
@@ -97,6 +170,7 @@ IF(DOXYGEN_FOUND)
) )
ENDIF(DOXYGEN_FOUND) ENDIF(DOXYGEN_FOUND)
# The library output directory
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
@@ -107,25 +181,67 @@ CONFIGURE_FILE(
) )
# Support for pkg-config # Support for pkg-config
set(CMAKE_INSTALL_LIBDIR lib) SET(CMAKE_INSTALL_LIBDIR lib)
set(pkgconfig_prefix ${CMAKE_INSTALL_PREFIX}) SET(pkgconfig_prefix ${CMAKE_INSTALL_PREFIX})
set(pkgconfig_exec_prefix ${CMAKE_INSTALL_PREFIX}) SET(pkgconfig_exec_prefix ${CMAKE_INSTALL_PREFIX})
set(pkgconfig_libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}) SET(pkgconfig_libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
set(pkgconfig_version ${LIBTINS_VERSION}) SET(pkgconfig_version ${LIBTINS_VERSION})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libtins.pc.in CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libtins.pc.in
${CMAKE_CURRENT_BINARY_DIR}/libtins.pc @ONLY) ${CMAKE_CURRENT_BINARY_DIR}/libtins.pc @ONLY)
install( INSTALL(
FILES FILES
${CMAKE_CURRENT_BINARY_DIR}/libtins.pc ${CMAKE_CURRENT_BINARY_DIR}/libtins.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
) )
ENABLE_TESTING() # Confiugure the uninstall script
CONFIGURE_FILE(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY
)
# Add uninstall target
ADD_CUSTOM_TARGET(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
# ******************
# Add subdirectories
# ******************
ADD_SUBDIRECTORY(include) ADD_SUBDIRECTORY(include)
ADD_SUBDIRECTORY(src)
ADD_SUBDIRECTORY(tests)
ADD_SUBDIRECTORY(examples) 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(GOOGLETEST_ROOT ${CMAKE_SOURCE_DIR}/googletest)
SET(GOOGLETEST_INCLUDE ${GOOGLETEST_ROOT}/googletest/include)
SET(GOOGLETEST_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/googletest)
SET(GOOGLETEST_LIBRARY ${GOOGLETEST_BINARY_DIR}/googletest)
ExternalProject_Add(
googletest
DOWNLOAD_COMMAND ""
SOURCE_DIR ${GOOGLETEST_ROOT}
BINARY_DIR ${GOOGLETEST_BINARY_DIR}
CMAKE_CACHE_ARGS "-DBUILD_GTEST:bool=ON" "-DBUILD_GMOCK:bool=OFF"
"-Dgtest_force_shared_crt:bool=ON"
INSTALL_COMMAND ""
)
# Make sure we build googletest before anything else
ADD_DEPENDENCIES(tins googletest)
ENABLE_TESTING()
ADD_SUBDIRECTORY(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 # Add all targets to the build-tree export set
EXPORT( EXPORT(

30
CONTRIBUTING.md Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -18,6 +18,7 @@
# PCAP_LIBRARY The libpcap library (possibly includes a thread # PCAP_LIBRARY The libpcap library (possibly includes a thread
# library e.g. required by pf_ring's libpcap) # library e.g. required by pf_ring's libpcap)
# HAVE_PF_RING If a found version of libpcap supports PF_RING # 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 find_path(PCAP_ROOT_DIR
NAMES include/pcap.h NAMES include/pcap.h
@@ -28,9 +29,17 @@ find_path(PCAP_INCLUDE_DIR
HINTS ${PCAP_ROOT_DIR}/include 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 find_library(PCAP_LIBRARY
NAMES pcap wpcap NAMES pcap wpcap
HINTS ${PCAP_ROOT_DIR}/lib HINTS ${HINT_DIR}
) )
include(FindPackageHandleStandardArgs) include(FindPackageHandleStandardArgs)
@@ -65,6 +74,7 @@ endif (NOT PCAP_LINKS_SOLO)
include(CheckFunctionExists) include(CheckFunctionExists)
set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY}) set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY})
check_function_exists(pcap_get_pfring_id HAVE_PF_RING) 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) set(CMAKE_REQUIRED_LIBRARIES)
mark_as_advanced( 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
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% -V
deploy_script:
- ps: Push-AppveyorArtifact "install\libtins-$env:Platform-$env:Configuration.zip"
skip_commits:
message: /Update documentation.*/

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -32,6 +32,11 @@
#include <iostream> #include <iostream>
#include <functional> #include <functional>
using std::cout;
using std::endl;
using std::map;
using std::bind;
using namespace Tins; using namespace Tins;
class arp_monitor { class arp_monitor {
@@ -40,13 +45,12 @@ public:
private: 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( sniffer.sniff_loop(
std::bind( bind(
&arp_monitor::callback, &arp_monitor::callback,
this, this,
std::placeholders::_1 std::placeholders::_1
@@ -54,8 +58,7 @@ void arp_monitor::run(Sniffer &sniffer)
); );
} }
bool arp_monitor::callback(const PDU &pdu) bool arp_monitor::callback(const PDU& pdu) {
{
// Retrieve the ARP layer // Retrieve the ARP layer
const ARP& arp = pdu.rfind_pdu<ARP>(); const ARP& arp = pdu.rfind_pdu<ARP>();
// Is it an ARP reply? // Is it an ARP reply?
@@ -65,25 +68,24 @@ bool arp_monitor::callback(const PDU &pdu)
if (iter == addresses.end()) { if (iter == addresses.end()) {
// We haven't seen this address. Save it. // We haven't seen this address. Save it.
addresses.insert({ arp.sender_ip_addr(), arp.sender_hw_addr()}); addresses.insert({ arp.sender_ip_addr(), arp.sender_hw_addr()});
std::cout << "[INFO] " << arp.sender_ip_addr() << " is at " cout << "[INFO] " << arp.sender_ip_addr() << " is at "
<< arp.sender_hw_addr() << std::endl; << arp.sender_hw_addr() << std::endl;
} }
else { else {
// We've seen this address. If it's not the same HW address, inform it // We've seen this address. If it's not the same HW address, inform it
if (arp.sender_hw_addr() != iter->second) { if (arp.sender_hw_addr() != iter->second) {
std::cout << "[WARNING] " << arp.sender_ip_addr() << " is at " cout << "[WARNING] " << arp.sender_ip_addr() << " is at "
<< iter->second << " but also at " << arp.sender_hw_addr() << iter->second << " but also at " << arp.sender_hw_addr()
<< std::endl; << endl;
} }
} }
} }
return true; return true;
} }
int main(int argc, char *argv[]) int main(int argc, char* argv[]) {
{
if(argc != 2) { if(argc != 2) {
std::cout << "Usage: " << *argv << " <interface>\n"; cout << "Usage: " <<* argv << " <interface>" << endl;
return 1; return 1;
} }
arp_monitor monitor; arp_monitor monitor;
@@ -92,9 +94,14 @@ int main(int argc, char *argv[])
config.set_promisc_mode(true); config.set_promisc_mode(true);
config.set_filter("arp"); config.set_filter("arp");
try {
// Sniff on the provided interface in promiscuous mode // Sniff on the provided interface in promiscuous mode
Sniffer sniffer(argv[1], config); Sniffer sniffer(argv[1], config);
// Only capture arp packets // Only capture arp packets
monitor.run(sniffer); 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -32,20 +32,29 @@
#include <string> #include <string>
#include <stdexcept> #include <stdexcept>
#include <cstdlib> #include <cstdlib>
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
#include <unistd.h> #include <unistd.h>
#endif // _WIN32
#include <tins/arp.h> #include <tins/arp.h>
#include <tins/network_interface.h> #include <tins/network_interface.h>
#include <tins/utils.h> #include <tins/utils.h>
#include <tins/ethernetII.h> #include <tins/ethernetII.h>
#include <tins/packet_sender.h> #include <tins/packet_sender.h>
using namespace std; using std::cout;
using std::runtime_error;
using std::endl;
using namespace Tins; using namespace Tins;
void do_arp_spoofing(NetworkInterface iface, IPv4Address gw, IPv4Address victim, void do_arp_spoofing(NetworkInterface iface,
const NetworkInterface::Info &info) IPv4Address gw,
{ IPv4Address victim,
const NetworkInterface::Info& info) {
PacketSender sender; PacketSender sender;
EthernetII::address_type gw_hw, victim_hw; EthernetII::address_type gw_hw, victim_hw;
@@ -78,13 +87,19 @@ void do_arp_spoofing(NetworkInterface iface, IPv4Address gw, IPv4Address victim,
// Just send them once every 5 seconds. // Just send them once every 5 seconds.
sender.send(to_gw, iface); sender.send(to_gw, iface);
sender.send(to_victim, iface); sender.send(to_victim, iface);
#ifdef _WIN32
Sleep(5);
#else
sleep(5); sleep(5);
#endif
} }
} }
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
if(argc != 3 && cout << "Usage: " << *argv << " <Gateway> <Victim>\n") if (argc != 3) {
cout << "Usage: " <<* argv << " <Gateway> <Victim>" << endl;
return 1; return 1;
}
IPv4Address gw, victim; IPv4Address gw, victim;
EthernetII::address_type own_hw; EthernetII::address_type own_hw;
try { try {
@@ -106,15 +121,15 @@ int main(int argc, char *argv[]) {
// Find the interface hardware and ip address. // Find the interface hardware and ip address.
info = iface.addresses(); info = iface.addresses();
} }
catch(std::runtime_error &ex) { catch (runtime_error& ex) {
cout << ex.what() << endl; cout << ex.what() << endl;
return 3; return 3;
} }
try { try {
do_arp_spoofing(iface, gw, victim, info); do_arp_spoofing(iface, gw, victim, info);
} }
catch(std::runtime_error &ex) { catch (runtime_error& ex) {
std::cout << "Runtime error: " << ex.what() << std::endl; cout << "Runtime error: " << ex.what() << endl;
return 7; return 7;
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -32,14 +32,20 @@
#include <string> #include <string>
#include <tins/tins.h> #include <tins/tins.h>
using std::set;
using std::cout;
using std::endl;
using std::string;
using std::runtime_error;
using namespace Tins; using namespace Tins;
class BeaconSniffer { class BeaconSniffer {
public: public:
void run(const std::string &iface); void run(const string& iface);
private: private:
typedef Dot11::address_type address_type; 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);
@@ -70,13 +76,13 @@ bool BeaconSniffer::callback(PDU &pdu) {
/* If no ssid option is set, then Dot11::ssid will throw /* If no ssid option is set, then Dot11::ssid will throw
* a std::runtime_error. * a std::runtime_error.
*/ */
std::string ssid = beacon.ssid(); string ssid = beacon.ssid();
// Save it so we don't show it again. // Save it so we don't show it again.
ssids.insert(addr); ssids.insert(addr);
// Display the tuple "address - ssid". // 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. // No ssid, just ignore it.
} }
} }
@@ -85,10 +91,11 @@ bool BeaconSniffer::callback(PDU &pdu) {
} }
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
// By default, sniff wlan0 if (argc != 2) {
std::string interface = "wlan0"; cout << "Usage: " <<* argv << " <interface>" << endl;
if(argc == 2) return 1;
interface = argv[1]; }
string interface = argv[1];
BeaconSniffer sniffer; BeaconSniffer sniffer;
sniffer.run(interface); sniffer.run(interface);
} }

118
examples/defragmenter.cpp Normal file
View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -30,12 +30,14 @@
#include <tins/tins.h> #include <tins/tins.h>
#include <iostream> #include <iostream>
using std::cout;
using std::endl;
using namespace Tins; using namespace Tins;
PacketSender sender; PacketSender sender;
bool callback(const PDU &pdu) bool callback(const PDU& pdu) {
{
// The packet probably looks like this: // The packet probably looks like this:
// //
// EthernetII / IP / UDP / RawPDU // EthernetII / IP / UDP / RawPDU
@@ -51,7 +53,7 @@ bool callback(const PDU &pdu)
if (dns.type() == DNS::QUERY) { if (dns.type() == DNS::QUERY) {
// Let's see if there's any query for an "A" record. // Let's see if there's any query for an "A" record.
for (const auto& query : dns.queries()) { for (const auto& query : dns.queries()) {
if(query.type() == DNS::A) { if (query.query_type() == DNS::A) {
// Here's one! Let's add an answer. // Here's one! Let's add an answer.
dns.add_answer( dns.add_answer(
DNS::Resource( DNS::Resource(
@@ -83,10 +85,9 @@ bool callback(const PDU &pdu)
return true; return true;
} }
int main(int argc, char *argv[]) int main(int argc, char* argv[]) {
{
if(argc != 2) { if(argc != 2) {
std::cout << "Usage: " << *argv << " <interface>" << std::endl; cout << "Usage: " <<* argv << " <interface>" << endl;
return 1; return 1;
} }
// Sniff on the provided interface in promiscuos mode // Sniff on the provided interface in promiscuos mode

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -27,6 +27,13 @@
* *
*/ */
#ifdef _WIN32
#define NOMINMAX
#endif // _WIN32
// Fix for gcc 4.6
#define _GLIBCXX_USE_NANOSLEEP
#include <iostream> #include <iostream>
#include <mutex> #include <mutex>
#include <chrono> #include <chrono>
@@ -35,6 +42,25 @@
#include <algorithm> #include <algorithm>
#include <tins/tins.h> #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; using namespace Tins;
// Holds the DNS response time statistics. The response time is // Holds the DNS response time statistics. The response time is
@@ -42,8 +68,8 @@ using namespace Tins;
template<typename Duration> template<typename Duration>
class statistics { class statistics {
public: public:
using duration_type = Duration; typedef Duration duration_type;
using locker_type = std::lock_guard<std::mutex>; typedef lock_guard<mutex> locker_type;
struct information { struct information {
duration_type average, worst; duration_type average, worst;
@@ -51,31 +77,30 @@ public:
}; };
statistics() 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); locker_type _(m_lock);
m_duration += duration; m_duration += duration;
m_count++; 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); locker_type _(m_lock);
if(m_count == 0) if(m_count == 0) {
return { }; return { };
else }
else {
return { m_duration / m_count, m_worst, m_count }; return { m_duration / m_count, m_worst, m_count };
}
}; };
private: private:
duration_type m_duration, m_worst; duration_type m_duration, m_worst;
size_t m_count; 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, // Sniffs and tracks DNS queries. When a matching DNS response is found,
@@ -86,30 +111,29 @@ private:
class dns_monitor { class dns_monitor {
public: public:
// The response times are measured in milliseconds // The response times are measured in milliseconds
using duration_type = std::chrono::milliseconds; typedef milliseconds duration_type;
// The statistics type used. // The statistics type used.
using statistics_type = statistics<duration_type>; typedef statistics<duration_type> statistics_type;
void run(BaseSniffer& sniffer); void run(BaseSniffer& sniffer);
const statistics_type& stats() const { const statistics_type& stats() const {
return m_stats; return m_stats;
} }
private: private:
using packet_info = std::tuple<IPv4Address, IPv4Address, uint16_t>; typedef tuple<IPv4Address, IPv4Address, uint16_t> packet_info;
using clock_type = std::chrono::steady_clock; typedef system_clock clock_type;
using time_point_type = std::chrono::time_point<clock_type>; typedef clock_type::time_point time_point_type;
bool callback(const PDU& pdu); bool callback(const PDU& pdu);
static packet_info make_packet_info(const PDU& pdu, const DNS& dns); static packet_info make_packet_info(const PDU& pdu, const DNS& dns);
statistics_type m_stats; 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( sniffer.sniff_loop(
std::bind( bind(
&dns_monitor::callback, &dns_monitor::callback,
this, this,
std::placeholders::_1 std::placeholders::_1
@@ -117,8 +141,7 @@ 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 now = clock_type::now();
auto dns = pdu.rfind_pdu<RawPDU>().to<DNS>(); auto dns = pdu.rfind_pdu<RawPDU>().to<DNS>();
auto info = make_packet_info(pdu, dns); auto info = make_packet_info(pdu, dns);
@@ -135,7 +158,7 @@ bool dns_monitor::callback(const PDU& pdu)
// We found the query, let's add the response time to the // We found the query, let's add the response time to the
// statistics object. // statistics object.
m_stats.add_response_time( 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. // Forget about the query.
m_packet_info.erase(iter); m_packet_info.erase(iter);
@@ -148,44 +171,48 @@ bool dns_monitor::callback(const PDU& pdu)
// hold the same DNS id as belonging to the same query. // hold the same DNS id as belonging to the same query.
// //
// This function retrieves a tuple (addr, addr, id) that will achieve it. // 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>(); const auto& ip = pdu.rfind_pdu<IP>();
return std::make_tuple( return make_tuple(
// smallest address first // smallest address first
std::min(ip.src_addr(), ip.dst_addr()), min(ip.src_addr(), ip.dst_addr()),
// largest address second // largest address second
std::max(ip.src_addr(), ip.dst_addr()), max(ip.src_addr(), ip.dst_addr()),
dns.id() dns.id()
); );
} }
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
if(argc != 2) { string iface;
std::cout << "Usage: " << *argv << " <interface>\n"; if (argc == 2) {
return 1; // Use the provided interface
iface = argv[1];
}
else {
// Use the default interface
iface = NetworkInterface::default_interface().name();
} }
try { try {
SnifferConfiguration config; SnifferConfiguration config;
config.set_promisc_mode(true); config.set_promisc_mode(true);
config.set_filter("udp and dst port 53"); config.set_filter("udp and port 53");
Sniffer sniffer(argv[1], config); Sniffer sniffer(iface, config);
dns_monitor monitor; dns_monitor monitor;
std::thread thread( thread thread(
[&]() { [&]() {
monitor.run(sniffer); monitor.run(sniffer);
} }
); );
while (true) { while (true) {
auto info = monitor.stats().get_information(); auto info = monitor.stats().get_information();
std::cout << "\rAverage " << info.average.count() cout << "\rAverage " << info.average.count()
<< "ms. Worst: " << info.worst.count() << "ms. Count: " << "ms. Worst: " << info.worst.count() << "ms. Count: "
<< info.count; << info.count << " ";
std::cout.flush(); cout.flush();
std::this_thread::sleep_for(std::chrono::seconds(1)); sleep_for(seconds(1));
} }
} }
catch(std::exception& ex) { catch (exception& ex) {
std::cout << "[-] Error: " << ex.what() << std::endl; cout << "[-] Error: " << ex.what() << endl;
} }
} }

147
examples/http_requests.cpp Normal file
View File

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

140
examples/icmp_responses.cpp Normal file
View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -44,15 +44,23 @@
#include <tins/utils.h> #include <tins/utils.h>
#include <tins/packet_sender.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; using namespace Tins;
typedef std::pair<Sniffer*, std::string> sniffer_data; typedef pair<Sniffer*, string> sniffer_data;
class Scanner { class Scanner {
public: public:
Scanner(const NetworkInterface& interface, const IPv4Address& address, Scanner(const NetworkInterface& interface,
const IPv4Address& address,
const vector<string>& ports); const vector<string>& ports);
void run(); void run();
@@ -68,10 +76,10 @@ private:
Sniffer sniffer; Sniffer sniffer;
}; };
Scanner::Scanner(const NetworkInterface& interface, const IPv4Address& address, Scanner::Scanner(const NetworkInterface& interface,
const IPv4Address& address,
const vector<string>& ports) const vector<string>& ports)
: iface(interface), host_to_scan(address), sniffer(interface.name()) : iface(interface), host_to_scan(address), sniffer(interface.name()) {
{
sniffer.set_filter( sniffer.set_filter(
"tcp and ip src " + address.to_string() + " and tcp[tcpflags] & (tcp-rst|tcp-syn) != 0" "tcp and ip src " + address.to_string() + " and tcp[tcpflags] & (tcp-rst|tcp-syn) != 0"
); );
@@ -86,16 +94,14 @@ void *Scanner::thread_proc(void *param) {
return 0; return 0;
} }
void Scanner::launch_sniffer() void Scanner::launch_sniffer() {
{
sniffer.sniff_loop(make_sniffer_handler(this, &Scanner::callback)); sniffer.sniff_loop(make_sniffer_handler(this, &Scanner::callback));
} }
/* Our scan handler. This will receive SYNs and RSTs and inform us /* Our scan handler. This will receive SYNs and RSTs and inform us
* the scanned port's status. * the scanned port's status.
*/ */
bool Scanner::callback(PDU &pdu) bool Scanner::callback(PDU& pdu) {
{
// Find the layers we want. // Find the layers we want.
const IP& ip = pdu.rfind_pdu<IP>(); const IP& ip = pdu.rfind_pdu<IP>();
const TCP& tcp = pdu.rfind_pdu<TCP>(); const TCP& tcp = pdu.rfind_pdu<TCP>();
@@ -117,8 +123,7 @@ bool Scanner::callback(PDU &pdu)
return true; return true;
} }
void Scanner::run() void Scanner::run() {
{
pthread_t thread; pthread_t thread;
// Launch our sniff thread. // Launch our sniff thread.
pthread_create(&thread, 0, &Scanner::thread_proc, this); pthread_create(&thread, 0, &Scanner::thread_proc, this);
@@ -177,12 +182,14 @@ void scan(int argc, char *argv[]) {
} }
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
if(argc < 3 && cout << "Usage: " << *argv << " <IPADDR> <port1> [port2] [port3]\n") if (argc < 3) {
cout << "Usage: " <<* argv << " <IPADDR> <port1> [port2] [port3]" << endl;
return 1; return 1;
}
try { try {
scan(argc, argv); scan(argc, argv);
} }
catch(std::runtime_error &ex) { catch(runtime_error& ex) {
cout << "Error - " << ex.what() << endl; 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;
}
}

162
examples/stream_dump.cpp Normal file
View File

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

View File

@@ -0,0 +1,107 @@
/*
* 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 <functional>
#include <tins/tins.h>
using std::string;
using std::bind;
using std::cout;
using std::endl;
using std::exception;
using namespace Tins;
// This example will capture TCP packets and send packet that will reset
// the connection when it captures a packet with the SYN and ACK flags on.
class tcp_connection_closer {
public:
tcp_connection_closer() {
}
void run(const string& interface) {
using std::placeholders::_1;
// Make the PacketSender use this interface by default
sender_.default_interface(interface);
// Create the sniffer configuration
SnifferConfiguration config;
config.set_filter("tcp");
// We want to get the packets as fast as possible
config.set_immediate_mode(true);
// Create the sniffer and start the capture
Sniffer sniffer(interface, config);
sniffer.sniff_loop(bind(&tcp_connection_closer::callback, this, _1));
}
private:
bool callback(const PDU& pdu) {
const EthernetII& eth = pdu.rfind_pdu<EthernetII>();
const IP& ip = pdu.rfind_pdu<IP>();
const TCP& tcp = pdu.rfind_pdu<TCP>();
// We'll only close a connection when seeing a SYN|ACK
if (tcp.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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -27,15 +27,44 @@
* *
*/ */
#ifdef _WIN32
#define NOMINMAX
#endif // _WIN32
// Fix for gcc 4.6
#define _GLIBCXX_USE_NANOSLEEP
#include <iostream> #include <iostream>
#include <chrono> #include <chrono>
#include <thread> #include <thread>
#include <cstdint> #include <cstdint>
#include <random>
#include <map> #include <map>
#include <algorithm>
#include <atomic> #include <atomic>
#include <limits>
#include <mutex> #include <mutex>
#include <tins/tins.h> #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; using namespace Tins;
class Traceroute { class Traceroute {
@@ -43,20 +72,21 @@ public:
typedef std::map<uint16_t, IPv4Address> result_type; typedef std::map<uint16_t, IPv4Address> result_type;
Traceroute(NetworkInterface interface, IPv4Address address) 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() { result_type trace() {
// ICMPs that aren't sent from us.
SnifferConfiguration config; SnifferConfiguration config;
config.set_snap_len(500);
config.set_promisc_mode(false); config.set_promisc_mode(false);
// ICMPs that aren't sent from us.
config.set_filter( config.set_filter(
"ip proto \\icmp and not src host " + iface.addresses().ip_addr.to_string()); "ip proto \\icmp and not src host " + iface.addresses().ip_addr.to_string());
Sniffer sniffer(iface.name(), config); Sniffer sniffer(iface.name(), config);
PacketSender sender; PacketSender sender;
// Create our handler // Create our handler
auto handler = std::bind( auto handler = bind(
&Traceroute::sniff_callback, &Traceroute::sniff_callback,
this, this,
std::placeholders::_1 std::placeholders::_1
@@ -64,90 +94,117 @@ public:
// We're running // We're running
running = true; running = true;
// Start the sniff thread // Start the sniff thread
std::thread sniff_thread( thread sniff_thread(
&Sniffer::sniff_loop<decltype(handler)>, [&]() {
&sniffer, sniffer.sniff_loop(handler);
handler, }
0
); );
send_packets(sender); send_packets(sender);
sniff_thread.join(); 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 // Clear our results and return what we've found
return std::move(results); return move(results);
} }
private: 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 // ICMPs are icmp-requests by default
IP ip = IP(addr, iface.addresses().ip_addr) / ICMP(); 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) { for (auto i = 1; i <= 20; ++i) {
// Set this "unique" id // Set this ICMP id
ip.id(i); icmp.id(i);
// Set the time-to-live option // Set the time-to-live option
ip.ttl(i); ip.ttl(i);
// Critical section // Critical section
{ {
std::lock_guard<std::mutex> _(lock); lock_guard<mutex> _(lock);
ttls[i] = i; ttls[i] = i;
} }
sender.send(ip); sender.send(ip);
// Give him a little time // Give it a little time
std::this_thread::sleep_for(std::chrono::milliseconds(100)); sleep_for(milliseconds(100));
} }
running = false; running = false;
sender.send(ip); sender.send(ip);
} }
bool sniff_callback(PDU& pdu) { bool sniff_callback(PDU& pdu) {
// Find IP and ICMP PDUs
const IP& ip = pdu.rfind_pdu<IP>(); const IP& ip = pdu.rfind_pdu<IP>();
ttl_map::const_iterator iter; 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 // Fetch the IP PDU attached to the ICMP response
const IP inner_ip = pdu.rfind_pdu<RawPDU>().to<IP>(); 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;
// Critical section // Critical section
{ {
std::lock_guard<std::mutex> _(lock); std::lock_guard<std::mutex> _(lock);
iter = ttls.find(inner_ip.id()); iter = ttls.find(inner_icmp.id());
} }
// It's an actual response // It's an actual response
if(iter != ttls.end()) { if(iter != ttls.end()) {
// Store it // Store it
results[inner_ip.id()] = ip.src_addr(); 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; return running;
} }
NetworkInterface iface; NetworkInterface iface;
IPv4Address addr; IPv4Address addr;
std::atomic<bool> running; atomic<bool> running;
ttl_map ttls; ttl_map ttls;
result_type results; result_type results;
std::mutex lock; mutex lock;
uint16_t sequence;
int lowest_dest_ttl;
}; };
int main(int argc, char* argv[]) { 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; return 1;
}
try { try {
IPv4Address addr((std::string(argv[1]))); IPv4Address addr = string(argv[1]);
Traceroute tracer(addr, addr); Traceroute tracer(addr, addr);
auto results = tracer.trace(); auto results = tracer.trace();
if(results.empty()) if (results.empty()) {
std::cout << "No hops found" << std::endl; cout << "No hops found" << endl;
}
else { else {
std::cout << "Results: " << std::endl; cout << "Results: " << endl;
for(const auto& entry : results) { for(const auto& entry : results) {
std::cout << entry.first << " - " << entry.second << std::endl; cout << setw(2) << entry.first << " - " << entry.second << endl;
} }
} }
} }
catch(std::runtime_error &ex) { catch (runtime_error& ex) {
std::cout << "Error - " << ex.what() << std::endl; cout << "Error - " << ex.what() << endl;
return 2; return 2;
} }
} }

View File

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

1
googletest Submodule

Submodule googletest added at 13206d6f53

View File

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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -53,9 +53,8 @@ public:
* *
* \param first The address held by this iterator. * \param first The address held by this iterator.
*/ */
AddressRangeIterator(const value_type &addr) AddressRangeIterator(const value_type& address)
: addr(addr), reached_end(false) : address_(address), reached_end_(false) {
{
} }
@@ -65,23 +64,22 @@ public:
* \param first The address held by this iterator. * \param first The address held by this iterator.
*/ */
AddressRangeIterator(const value_type& address, end_iterator) AddressRangeIterator(const value_type& address, end_iterator)
: addr(address) : address_(address) {
{ reached_end_ = Internals::increment(address_);
reached_end = Internals::increment(addr);
} }
/** /**
* Retrieves the current address pointed by this iterator. * Retrieves the current address pointed by this iterator.
*/ */
const value_type& operator*() const { const value_type& operator*() const {
return addr; return address_;
} }
/** /**
* Retrieves a pointer to the current address pointed by this iterator. * Retrieves a pointer to the current address pointed by this iterator.
*/ */
const value_type* operator->() const { const value_type* operator->() const {
return &addr; return& address_;
} }
/** /**
@@ -90,7 +88,7 @@ public:
* \param rhs The iterator with which to compare. * \param rhs The iterator with which to compare.
*/ */
bool operator==(const AddressRangeIterator& rhs) const { bool operator==(const AddressRangeIterator& rhs) const {
return reached_end == rhs.reached_end && addr == rhs.addr; return reached_end_ == rhs.reached_end_ && address_ == rhs.address_;
} }
/** /**
@@ -106,7 +104,7 @@ public:
* Increments this iterator. * Increments this iterator.
*/ */
AddressRangeIterator& operator++() { AddressRangeIterator& operator++() {
reached_end = Internals::increment(addr); reached_end_ = Internals::increment(address_);
return* this; return* this;
} }
@@ -119,8 +117,8 @@ public:
return copy; return copy;
} }
private: private:
Address addr; Address address_;
bool reached_end; bool reached_end_;
}; };
/** /**
@@ -198,11 +196,11 @@ public:
* should be accessed when using iterators. * should be accessed when using iterators.
*/ */
AddressRange(const address_type& first, const address_type& last, bool only_hosts = false) AddressRange(const address_type& first, const address_type& last, bool only_hosts = false)
: first(first), last(last), only_hosts(only_hosts) : first_(first), last_(last), only_hosts_(only_hosts){
{ if (last_ < first_) {
if(last < first)
throw std::runtime_error("Invalid address range"); throw std::runtime_error("Invalid address range");
} }
}
/** /**
* \brief Creates an address range from a base address * \brief Creates an address range from a base address
@@ -225,7 +223,7 @@ public:
* \return a bool indicating whether the address is in the range. * \return a bool indicating whether the address is in the range.
*/ */
bool contains(const address_type& addr) const { bool contains(const address_type& addr) const {
return (first < addr && addr < last) || addr == first || addr == last; return (first_ < addr && addr < last_) || addr == first_ || addr == last_;
} }
/** /**
@@ -233,9 +231,10 @@ public:
* \brief const_iterator pointing to the beginning of this range. * \brief const_iterator pointing to the beginning of this range.
*/ */
const_iterator begin() const { const_iterator begin() const {
address_type addr = first; address_type addr = first_;
if(only_hosts) if (only_hosts_) {
Internals::increment(addr); Internals::increment(addr);
}
return const_iterator(addr); return const_iterator(addr);
} }
@@ -244,9 +243,10 @@ public:
* \brief const_iterator pointing to the end of this range. * \brief const_iterator pointing to the end of this range.
*/ */
const_iterator end() const { const_iterator end() const {
address_type addr = last; address_type addr = last_;
if(only_hosts) if (only_hosts_) {
Internals::decrement(addr); Internals::decrement(addr);
}
return const_iterator(addr, typename const_iterator::end_iterator()); return const_iterator(addr, typename const_iterator::end_iterator());
} }
@@ -266,21 +266,23 @@ public:
*/ */
bool is_iterable() const { bool is_iterable() const {
// Since first < last, it's iterable // Since first < last, it's iterable
if(!only_hosts) if (!only_hosts_) {
return true; return true;
}
// We need that distance(first, last) >= 4 // We need that distance(first, last) >= 4
address_type addr(first); address_type addr(first_);
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
// If there's overflow before the last iteration, we're done // 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; return false;
} }
}
// If addr <= last, it's OK. // If addr <= last, it's OK.
return addr < last || addr == last; return addr < last_ || addr == last_;
} }
private: private:
address_type first, last; address_type first_, last_;
bool only_hosts; bool only_hosts_;
}; };
/** /**
@@ -300,8 +302,9 @@ typedef AddressRange<IPv6Address> IPv6Range;
*/ */
template<size_t n> template<size_t n>
AddressRange<HWAddress<n> > operator/(const HWAddress<n>& addr, int mask) { AddressRange<HWAddress<n> > operator/(const HWAddress<n>& addr, int mask) {
if(mask > 48) if (mask > 48) {
throw std::logic_error("Prefix length cannot exceed 48"); throw std::logic_error("Prefix length cannot exceed 48");
}
HWAddress<n> last_addr; HWAddress<n> last_addr;
typename HWAddress<n>::iterator it = last_addr.begin(); typename HWAddress<n>::iterator it = last_addr.begin();
while (mask > 8) { while (mask > 8) {

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -38,6 +38,7 @@
#include "ip_address.h" #include "ip_address.h"
namespace Tins { namespace Tins {
class NetworkInterface; class NetworkInterface;
class EthernetII; class EthernetII;
@@ -46,7 +47,7 @@ namespace Tins {
* \brief Represents an ARP PDU. * \brief Represents an ARP PDU.
* *
*/ */
class ARP : public PDU { class TINS_API ARP : public PDU {
public: public:
/** /**
* The type of the hardware address. * The type of the hardware address.
@@ -71,6 +72,14 @@ namespace Tins {
REPLY = 0x0002 REPLY = 0x0002
}; };
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/** /**
* \brief Constructs an ARP object using the provided addresses. * \brief Constructs an ARP object using the provided addresses.
* *
@@ -110,63 +119,81 @@ namespace Tins {
* *
* \return The sender hardware address. * \return The sender hardware address.
*/ */
hwaddress_type sender_hw_addr() const { return _arp.ar_sha; } hwaddress_type sender_hw_addr() const {
return header_.sender_hw_address;
}
/** /**
* \brief Getter for the sender's IP address. * \brief Getter for the sender's IP address.
* *
* \return The sender IP address. * \return The sender IP address.
*/ */
ipaddress_type sender_ip_addr() const { return ipaddress_type(_arp.ar_sip); } ipaddress_type sender_ip_addr() const {
return ipaddress_type(header_.sender_ip_address);
}
/** /**
* \brief Getter for the target's hardware address. * \brief Getter for the target's hardware address.
* *
* \return The target hardware address. * \return The target hardware address.
*/ */
hwaddress_type target_hw_addr() const { return _arp.ar_tha; } hwaddress_type target_hw_addr() const {
return header_.target_hw_address;
}
/** /**
* \brief Getter for the target's IP address. * \brief Getter for the target's IP address.
* *
* \return The target IP address. * \return The target IP address.
*/ */
ipaddress_type target_ip_addr() const { return ipaddress_type(_arp.ar_tip); } ipaddress_type target_ip_addr() const {
return ipaddress_type(header_.target_ip_address);
}
/** /**
* \brief Getter for the hardware address format field. * \brief Getter for the hardware address format field.
* *
* \return The hardware address format. * \return The hardware address format.
*/ */
uint16_t hw_addr_format() const { return Endian::be_to_host(_arp.ar_hrd); } uint16_t hw_addr_format() const {
return Endian::be_to_host(header_.hw_address_format);
}
/** /**
* \brief Getter for the protocol address format field. * \brief Getter for the protocol address format field.
* *
* \return The protocol address format. * \return The protocol address format.
*/ */
uint16_t prot_addr_format() const { return Endian::be_to_host(_arp.ar_pro); } uint16_t prot_addr_format() const {
return Endian::be_to_host(header_.proto_address_format);
}
/** /**
* \brief Getter for the hardware address length field. * \brief Getter for the hardware address length field.
* *
* \return The hardware address length. * \return The hardware address length.
*/ */
uint8_t hw_addr_length() const { return _arp.ar_hln; } uint8_t hw_addr_length() const {
return header_.hw_address_length;
}
/** /**
* \brief Getter for the protocol address length field. * \brief Getter for the protocol address length field.
* *
* \return The protocol address length. * \return The protocol address length.
*/ */
uint8_t prot_addr_length() const { return _arp.ar_pln; } uint8_t prot_addr_length() const {
return header_.proto_address_length;
}
/** /**
* \brief Getter for the ARP opcode field. * \brief Getter for the ARP opcode field.
* *
* \return The ARP opcode. * \return The ARP opcode.
*/ */
uint16_t opcode() const { return Endian::be_to_host(_arp.ar_op); } uint16_t opcode() const {
return Endian::be_to_host(header_.opcode);
}
/** /**
* \brief Getter for the header size. * \brief Getter for the header size.
@@ -174,70 +201,71 @@ namespace Tins {
* \sa PDU::header_size * \sa PDU::header_size
*/ */
uint32_t header_size() const; uint32_t header_size() const;
/* Setters */ /* Setters */
/** /**
* \brief Setter for the sender's hardware address. * \brief Setter for the sender's hardware address.
* *
* \param new_snd_hw_addr The new sender hardware address. * \param address The new sender hardware address.
*/ */
void sender_hw_addr(const hwaddress_type &new_snd_hw_addr); void sender_hw_addr(const hwaddress_type& address);
/** /**
* \brief Setter for the sender's IP address. * \brief Setter for the sender's IP address.
* *
* \param new_snd_ip_addr The new sender IP address. * \param address The new sender IP address.
*/ */
void sender_ip_addr(ipaddress_type new_snd_ip_addr); void sender_ip_addr(ipaddress_type address);
/** /**
* \brief Setter for the target's hardware address. * \brief Setter for the target's hardware address.
* *
* \param new_tgt_hw_addr The new target hardware address. * \param address The new target hardware address.
*/ */
void target_hw_addr(const hwaddress_type &new_tgt_hw_addr); void target_hw_addr(const hwaddress_type& address);
/** /**
* \brief Setter for the target's IP address. * \brief Setter for the target's IP address.
* *
* \param new_tgt_ip_addr The new target IP address. * \param address The new target IP address.
*/ */
void target_ip_addr(ipaddress_type new_tgt_ip_addr); void target_ip_addr(ipaddress_type address);
/** /**
* \brief Setter for the hardware address format field. * \brief Setter for the hardware address format field.
* *
* \param new_hw_addr_fmt The new hardware address format. * \param format The new hardware address format.
*/ */
void hw_addr_format(uint16_t new_hw_addr_fmt); void hw_addr_format(uint16_t format);
/** /**
* \brief Setter for the protocol address format field. * \brief Setter for the protocol address format field.
* *
* \param new_prot_addr_fmt The new protocol address format. * \param format The new protocol address format.
*/ */
void prot_addr_format(uint16_t new_prot_addr_fmt); void prot_addr_format(uint16_t format);
/** /**
* \brief Setter for the hardware address length field. * \brief Setter for the hardware address length field.
* *
* \param new_hw_addr_len The new hardware address length. * \param length The new hardware address length.
*/ */
void hw_addr_length(uint8_t new_hw_addr_len); void hw_addr_length(uint8_t length);
/** /**
* \brief Setter for the protocol address length field. * \brief Setter for the protocol address length field.
* *
* \param new_prot_addr_len The new protocol address length. * \param length The new protocol address length.
*/ */
void prot_addr_length(uint8_t new_prot_addr_len); void prot_addr_length(uint8_t length);
/** /**
* \brief Setter for the ARP opcode field. * \brief Setter for the ARP opcode field.
* *
* \param new_opcode Flag enum value of the ARP opcode to set. * \param code Flag enum value of the ARP opcode to set.
*/ */
void opcode(Flags new_opcode); void opcode(Flags code);
/** /**
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
@@ -257,7 +285,8 @@ namespace Tins {
* \return EthernetII object containing the ARP Request. * \return EthernetII object containing the ARP Request.
*/ */
static EthernetII make_arp_request(ipaddress_type target, static EthernetII make_arp_request(ipaddress_type target,
ipaddress_type sender, const hwaddress_type &hw_snd = hwaddress_type()); ipaddress_type sender,
const hwaddress_type& hw_snd = hwaddress_type());
/** /**
* \brief Creates an ARP Reply within an EthernetII PDU. * \brief Creates an ARP Reply within an EthernetII PDU.
@@ -272,11 +301,12 @@ namespace Tins {
* \return EthetnetII containing the ARP Replay. * \return EthetnetII containing the ARP Replay.
*/ */
static EthernetII make_arp_reply(ipaddress_type target, static EthernetII make_arp_reply(ipaddress_type target,
ipaddress_type sender, const hwaddress_type &hw_tgt = hwaddress_type(), ipaddress_type sender,
const hwaddress_type& hw_tgt = hwaddress_type(),
const hwaddress_type& hw_snd = hwaddress_type()); const hwaddress_type& hw_snd = hwaddress_type());
/** /**
* \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 * \sa PDU::matches_response
* \param ptr The pointer to the buffer. * \param ptr The pointer to the buffer.
@@ -292,26 +322,23 @@ namespace Tins {
} }
private: private:
TINS_BEGIN_PACK TINS_BEGIN_PACK
struct arphdr { struct arp_header {
uint16_t ar_hrd; /* format of hardware address */ uint16_t hw_address_format;
uint16_t ar_pro; /* format of protocol address */ uint16_t proto_address_format;
uint8_t ar_hln; /* length of hardware address */ uint8_t hw_address_length;
uint8_t ar_pln; /* length of protocol address */ uint8_t proto_address_length;
uint16_t ar_op; /* ARP opcode (command) */ uint16_t opcode;
uint8_t sender_hw_address[hwaddress_type::address_size];
/* sender hardware address */ uint32_t sender_ip_address;
uint8_t ar_sha[hwaddress_type::address_size]; uint8_t target_hw_address[hwaddress_type::address_size];
/* sender IP address */ uint32_t target_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; } TINS_END_PACK;
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent); void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
arphdr _arp; arp_header header_;
}; };
}
} // Tins
#endif // TINS_ARP_H #endif // TINS_ARP_H

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -39,14 +39,13 @@
#include "ip_address.h" #include "ip_address.h"
#include "hw_address.h" #include "hw_address.h"
namespace Tins { namespace Tins {
/** /**
* \class BootP * \class BootP
* \brief Class representing a BootP packet. * \brief Represents a BootP PDU
*/ */
class BootP : public PDU { class TINS_API BootP : public PDU {
public: public:
/** /**
* The type of the IP addresses. * The type of the IP addresses.
@@ -103,90 +102,90 @@ namespace Tins {
* \brief Getter for the opcode field. * \brief Getter for the opcode field.
* \return The opcode field for this BootP PDU. * \return The opcode field for this BootP PDU.
*/ */
uint8_t opcode() const { return _bootp.opcode; } uint8_t opcode() const { return bootp_.opcode; }
/** /**
* \brief Getter for the htype field. * \brief Getter for the htype field.
* \return The htype field for this BootP PDU. * \return The htype field for this BootP PDU.
*/ */
uint8_t htype() const { return _bootp.htype; } uint8_t htype() const { return bootp_.htype; }
/** /**
* \brief Getter for the hlen field. * \brief Getter for the hlen field.
* \return The hlen field for this BootP PDU. * \return The hlen field for this BootP PDU.
*/ */
uint8_t hlen() const { return _bootp.hlen; } uint8_t hlen() const { return bootp_.hlen; }
/** /**
* \brief Getter for the hops field. * \brief Getter for the hops field.
* \return The hops field for this BootP PDU. * \return The hops field for this BootP PDU.
*/ */
uint8_t hops() const { return _bootp.hops; } uint8_t hops() const { return bootp_.hops; }
/** /**
* \brief Getter for the xid field. * \brief Getter for the xid field.
* \return The xid field for this BootP PDU. * \return The xid field for this BootP PDU.
*/ */
uint32_t xid() const { return Endian::be_to_host(_bootp.xid); } uint32_t xid() const { return Endian::be_to_host(bootp_.xid); }
/** /**
* \brief Getter for the secs field. * \brief Getter for the secs field.
* \return The secs field for this BootP PDU. * \return The secs field for this BootP PDU.
*/ */
uint16_t secs() const { return Endian::be_to_host(_bootp.secs); } uint16_t secs() const { return Endian::be_to_host(bootp_.secs); }
/** \brief Getter for the padding field. /** \brief Getter for the padding field.
* \return The padding field for this BootP PDU. * \return The padding field for this BootP PDU.
*/ */
uint16_t padding() const { return Endian::be_to_host(_bootp.padding); } uint16_t padding() const { return Endian::be_to_host(bootp_.padding); }
/** /**
* \brief Getter for the ciaddr field. * \brief Getter for the ciaddr field.
* \return The ciaddr field for this BootP PDU. * \return The ciaddr field for this BootP PDU.
*/ */
ipaddress_type ciaddr() const { return ipaddress_type(_bootp.ciaddr); } ipaddress_type ciaddr() const { return ipaddress_type(bootp_.ciaddr); }
/** /**
* \brief Getter for the yiaddr field. * \brief Getter for the yiaddr field.
* \return The yiaddr field for this BootP PDU. * \return The yiaddr field for this BootP PDU.
*/ */
ipaddress_type yiaddr() const { return ipaddress_type(_bootp.yiaddr); } ipaddress_type yiaddr() const { return ipaddress_type(bootp_.yiaddr); }
/** /**
* \brief Getter for the siaddr field. * \brief Getter for the siaddr field.
* \return The siaddr field for this BootP PDU. * \return The siaddr field for this BootP PDU.
*/ */
ipaddress_type siaddr() const { return ipaddress_type(_bootp.siaddr); } ipaddress_type siaddr() const { return ipaddress_type(bootp_.siaddr); }
/** /**
* \brief Getter for the giaddr field. * \brief Getter for the giaddr field.
* \return The giaddr field for this BootP PDU. * \return The giaddr field for this BootP PDU.
*/ */
ipaddress_type giaddr() const { return ipaddress_type(_bootp.giaddr); } ipaddress_type giaddr() const { return ipaddress_type(bootp_.giaddr); }
/** /**
* \brief Getter for the chaddr field. * \brief Getter for the chaddr field.
* \return The chddr field for this BootP PDU. * \return The chddr field for this BootP PDU.
*/ */
chaddr_type chaddr() const { return _bootp.chaddr; } chaddr_type chaddr() const { return bootp_.chaddr; }
/** /**
* \brief Getter for the sname field. * \brief Getter for the sname field.
* \return The sname field for this BootP PDU. * \return The sname field for this BootP PDU.
*/ */
const uint8_t *sname() const { return _bootp.sname; } const uint8_t* sname() const { return bootp_.sname; }
/** /**
* \brief Getter for the file field. * \brief Getter for the file field.
* \return The file field for this BootP PDU. * \return The file field for this BootP PDU.
*/ */
const uint8_t *file() const { return _bootp.file; } const uint8_t* file() const { return bootp_.file; }
/** /**
* \brief Getter for the vend field. * \brief Getter for the vend field.
* \return The vend field for this BootP PDU. * \return The vend field for this BootP PDU.
*/ */
const vend_type &vend() const { return _vend; } const vend_type& vend() const { return vend_; }
/** /**
* \brief Getter for the header size. * \brief Getter for the header size.
@@ -198,69 +197,69 @@ namespace Tins {
/** /**
* \brief Setter for the opcode field. * \brief Setter for the opcode field.
* \param new_opcode The opcode to be set. * \param code The opcode to be set.
*/ */
void opcode(uint8_t new_opcode); void opcode(uint8_t code);
/** /**
* \brief Setter for the htype field. * \brief Setter for the hardware type field.
* \param new_htype The htype to be set. * \param type The hardware type field value to be set.
*/ */
void htype(uint8_t new_htype); void htype(uint8_t type);
/** /**
* \brief Setter for the hlen field. * \brief Setter for the hlen field.
* \param new_hlen The hlen to be set. * \param length The hlen field value to be set.
*/ */
void hlen(uint8_t new_hlen); void hlen(uint8_t length);
/** /**
* \brief Setter for the hops field. * \brief Setter for the hops field.
* \param new_hops The hops to be set. * \param count The hops field value to be set.
*/ */
void hops(uint8_t new_hops); void hops(uint8_t count);
/** /**
* \brief Setter for the xid field. * \brief Setter for the xid field.
* \param new_xid The xid to be set. * \param identifier The xid to be set.
*/ */
void xid(uint32_t new_xid); void xid(uint32_t identifier);
/** /**
* \brief Setter for the secs field. * \brief Setter for the secs field.
* \param new_secs The secs to be set. * \param value The secs to be set.
*/ */
void secs(uint16_t new_secs); void secs(uint16_t value);
/** /**
* \brief Setter for the padding field. * \brief Setter for the padding field.
* \param new_padding The padding to be set. * \param value The padding to be set.
*/ */
void padding(uint16_t new_padding); void padding(uint16_t value);
/** /**
* \brief Setter for the ciaddr field. * \brief Setter for the ciaddr field.
* \param new_ciaddr The ciaddr to be set. * \param address The ciaddr to be set.
*/ */
void ciaddr(ipaddress_type new_ciaddr); void ciaddr(ipaddress_type address);
/** /**
* \brief Setter for the yiaddr field. * \brief Setter for the yiaddr field.
* \param new_yiaddr The yiaddr to be set. * \param address The yiaddr to be set.
*/ */
void yiaddr(ipaddress_type new_yiaddr); void yiaddr(ipaddress_type address);
/** /**
* \brief Setter for the siaddr field. * \brief Setter for the siaddr field.
* \param new_siaddr The siaddr to be set. * \param address The siaddr to be set.
*/ */
void siaddr(ipaddress_type new_siaddr); void siaddr(ipaddress_type address);
/** /**
* \brief Setter for the giaddr field. * \brief Setter for the giaddr field.
* \param new_giaddr The giaddr to be set. * \param address The giaddr to be set.
*/ */
void giaddr(ipaddress_type new_giaddr); void giaddr(ipaddress_type address);
/** /**
* \brief Setter for the chaddr field. * \brief Setter for the chaddr field.
@@ -272,12 +271,13 @@ namespace Tins {
// Copy the new addr // Copy the new addr
uint8_t* end = std::copy( uint8_t* end = std::copy(
new_chaddr.begin(), new_chaddr.begin(),
new_chaddr.begin() + std::min(n, sizeof(_bootp.chaddr)), new_chaddr.begin() + std::min(n, sizeof(bootp_.chaddr)),
_bootp.chaddr bootp_.chaddr
); );
// Fill what's left with zeros // Fill what's left with zeros
if(end < _bootp.chaddr + chaddr_type::address_size) if (end < bootp_.chaddr + chaddr_type::address_size) {
std::fill(end, _bootp.chaddr + chaddr_type::address_size, 0); std::fill(end, bootp_.chaddr + chaddr_type::address_size, 0);
}
} }
/** /**
@@ -294,12 +294,12 @@ namespace Tins {
/** /**
* \brief Setter for the vend field. * \brief Setter for the vend field.
* \param new_vend The vend to be set. * \param newvend_ The vend to be set.
*/ */
void vend(const vend_type &new_vend); void vend(const vend_type& newvend_);
/** /**
* \brief Check wether ptr points to a valid response for this PDU. * \brief Check whether ptr points to a valid response for this PDU.
* *
* This returns true if the xid field is equal. * This returns true if the xid field is equal.
* *
@@ -330,15 +330,15 @@ namespace Tins {
* *
* \return The vend field for this BootP PDU. * \return The vend field for this BootP PDU.
*/ */
vend_type &vend() { return _vend; } vend_type& vend() { return vend_; }
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);
private:
/** /**
* Struct that represents the Bootp datagram. * Struct that represents the Bootp datagram.
*/ */
TINS_BEGIN_PACK TINS_BEGIN_PACK
struct bootphdr { struct bootp_header {
uint8_t opcode; uint8_t opcode;
uint8_t htype; uint8_t htype;
uint8_t hlen; uint8_t hlen;
@@ -355,9 +355,11 @@ namespace Tins {
uint8_t file[128]; uint8_t file[128];
} TINS_END_PACK; } TINS_END_PACK;
bootphdr _bootp; private:
vend_type _vend; bootp_header bootp_;
vend_type vend_;
}; };
}
} // Tins
#endif // TINS_BOOTP_H #endif // TINS_BOOTP_H

View File

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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -31,6 +31,7 @@
#define TINS_CONSTANTS_H #define TINS_CONSTANTS_H
namespace Tins { namespace Tins {
/** /**
* \brief Constants used in protocols. * \brief Constants used in protocols.
*/ */
@@ -39,122 +40,124 @@ namespace Tins {
struct IP { struct IP {
/** \endcond */ /** \endcond */
enum e { enum e {
PROTO_IP = 0, /* Dummy protocol for TCP. */ PROTO_IP = 0, // Dummy protocol for TCP.
PROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */ PROTO_HOPOPTS = 0, // IPv6 Hop-by-Hop options.
PROTO_ICMP = 1, /* Internet Control Message Protocol. */ PROTO_ICMP = 1, // Internet Control Message Protocol.
PROTO_IGMP = 2, /* Internet Group Management Protocol. */ PROTO_IGMP = 2, // Internet Group Management Protocol.
PROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94). */ PROTO_IPIP = 4, // IPIP tunnels (older KA9Q tunnels use 94).
PROTO_TCP = 6, /* Transmission Control Protocol. */ PROTO_TCP = 6, // Transmission Control Protocol.
PROTO_EGP = 8, /* Exterior Gateway Protocol. */ PROTO_EGP = 8, // Exterior Gateway Protocol.
PROTO_PUP = 12, /* PUP protocol. */ PROTO_PUP = 12, // PUP protocol.
PROTO_UDP = 17, /* User Datagram Protocol. */ PROTO_UDP = 17, // User Datagram Protocol.
PROTO_IDP = 22, /* XNS IDP protocol. */ PROTO_IDP = 22, // XNS IDP protocol.
PROTO_TP = 29, /* SO Transport Protocol Class 4. */ PROTO_TP = 29, // SO Transport Protocol Class 4.
PROTO_DCCP = 33, /* Datagram Congestion Control Protocol. */ PROTO_DCCP = 33, // Datagram Congestion Control Protocol.
PROTO_IPV6 = 41, /* IPv6 header. */ PROTO_IPV6 = 41, // IPv6 header.
PROTO_ROUTING = 43, /* IPv6 routing header. */ PROTO_ROUTING = 43, // IPv6 routing header.
PROTO_FRAGMENT = 44, /* IPv6 fragmentation header. */ PROTO_FRAGMENT = 44, // IPv6 fragmentation header.
PROTO_RSVP = 46, /* Reservation Protocol. */ PROTO_RSVP = 46, // Reservation Protocol.
PROTO_GRE = 47, /* General Routing Encapsulation. */ PROTO_GRE = 47, // General Routing Encapsulation.
PROTO_ESP = 50, /* encapsulating security payload. */ PROTO_ESP = 50, // encapsulating security payload.
PROTO_AH = 51, /* authentication header. */ PROTO_AH = 51, // authentication header.
PROTO_ICMPV6 = 58, /* ICMPv6. */ PROTO_ICMPV6 = 58, // ICMPv6.
PROTO_NONE = 59, /* IPv6 no next header. */ PROTO_NONE = 59, // IPv6 no next header.
PROTO_DSTOPTS = 60, /* IPv6 destination options. */ PROTO_DSTOPTS = 60, // IPv6 destination options.
PROTO_MTP = 92, /* Multicast Transport Protocol. */ PROTO_MTP = 92, // Multicast Transport Protocol.
PROTO_ENCAP = 98, /* Encapsulation Header. */ PROTO_ENCAP = 98, // Encapsulation Header.
PROTO_PIM = 103, /* Protocol Independent Multicast. */ PROTO_PIM = 103, // Protocol Independent Multicast.
PROTO_COMP = 108, /* Compression Header Protocol. */ PROTO_COMP = 108, // Compression Header Protocol.
PROTO_SCTP = 132, /* Stream Control Transmission Protocol. */ PROTO_SCTP = 132, // Stream Control Transmission Protocol.
PROTO_UDPLITE = 136, /* UDP-Lite protocol. */ PROTO_UDPLITE = 136, // UDP-Lite protocol.
PROTO_RAW = 255 /* Raw IP packets. */ PROTO_RAW = 255 // Raw IP packets.
}; };
}; };
struct Ethernet { struct Ethernet {
enum e { enum e {
UNKNOWN = 0, UNKNOWN = 0,
//~ PUP = 0x0200, /* Xerox PUP */ SPRITE = 0x0500, // Sprite
SPRITE = 0x0500, /* Sprite */ IP = 0x0800, // IP
IP = 0x0800, /* IP */ ARP = 0x0806, // Address resolution
ARP = 0x0806, /* Address resolution */ MPLS = 0x8847, // MPLS
REVARP = 0x8035, /* Reverse ARP */ REVARP = 0x8035, // Reverse ARP
AT = 0x809B, /* AppleTalk protocol */ AT = 0x809B, // AppleTalk protocol
AARP = 0x80F3, /* AppleTalk ARP */ AARP = 0x80F3, // AppleTalk ARP
VLAN = 0x8100, /* IEEE 802.1Q VLAN tagging */ VLAN = 0x8100, // IEEE 802.1Q VLAN tagging
IPX = 0x8137, /* IPX */ QINQ = 0x88a8, // IEEE 802.1ad VLAN tagging
IPV6 = 0x86dd, /* IP protocol version 6 */ OLD_QINQ = 0x9100, // IEEE 802.1ad VLAN tagging (old, deprecated, value)
PPPOED = 0x8863, /* PPPoE Discovery */ IPX = 0x8137, // IPX
PPPOES = 0x8864, /* PPPoE Session */ IPV6 = 0x86dd, // IP protocol version 6
EAPOL = 0x888e, /* EAPOL */ PPPOED = 0x8863, // PPPoE Discovery
LOOPBACK = 0x9000 /* used to test interfaces */ PPPOES = 0x8864, // PPPoE Session
EAPOL = 0x888e, // EAPOL
LOOPBACK = 0x9000 // used to test interfaces
}; };
}; };
struct ARP { struct ARP {
enum e { enum e {
NETROM = 0, /* From KA9Q: NET/ROM pseudo. */ NETROM = 0, // From KA9Q: NET/ROM pseudo.
ETHER = 1, /* Ethernet 10/100Mbps. */ ETHER = 1, // Ethernet 10/100Mbps.
EETHER = 2, /* Experimental Ethernet. */ EETHER = 2, // Experimental Ethernet.
AX25 = 3, /* AX.25 Level 2. */ AX25 = 3, // AX.25 Level 2.
PRONET = 4, /* PROnet token ring. */ PRONET = 4, // PROnet token ring.
CHAOS = 5, /* Chaosnet. */ CHAOS = 5, // Chaosnet.
IEEE802 = 6, /* IEEE 802.2 Ethernet/TR/TB. */ IEEE802 = 6, // IEEE 802.2 Ethernet/TR/TB.
ARCNET = 7, /* ARCnet. */ ARCNET = 7, // ARCnet.
APPLETLK = 8, /* APPLEtalk. */ APPLETLK = 8, // APPLEtalk.
DLCI = 15, /* Frame Relay DLCI. */ DLCI = 15, // Frame Relay DLCI.
ATM = 19, /* ATM. */ ATM = 19, // ATM.
METRICOM = 23, /* Metricom STRIP (new IANA id). */ METRICOM = 23, // Metricom STRIP (new IANA id).
IEEE1394 = 24, /* IEEE 1394 IPv4 - RFC 2734. */ IEEE1394 = 24, // IEEE 1394 IPv4 - RFC 2734.
EUI64 = 27, /* EUI-64. */ EUI64 = 27, // EUI-64.
INFINIBAND = 32, /* InfiniBand. */ INFINIBAND = 32, // InfiniBand.
SLIP = 256, SLIP = 256,
CSLIP = 257, CSLIP = 257,
SLIP6 = 258, SLIP6 = 258,
CSLIP6 = 259, CSLIP6 = 259,
RSRVD = 260, /* Notional KISS type. */ RSRVD = 260, // Notional KISS type.
ADAPT = 264, ADAPT = 264,
ROSE = 270, ROSE = 270,
X25 = 271, /* CCITT X.25. */ X25 = 271, // CCITT X.25.
HWX25 = 272, /* Boards with X.25 in firmware. */ HWX25 = 272, // Boards with X.25 in firmware.
PPP = 512, PPP = 512,
CISCO = 513, /* Cisco HDLC. */ CISCO = 513, // Cisco HDLC.
HDLC = CISCO, HDLC = CISCO,
LAPB = 516, /* LAPB. */ LAPB = 516, // LAPB.
DDCMP = 517, /* Digital's DDCMP. */ DDCMP = 517, // Digital's DDCMP.
RAWHDLC = 518, /* Raw HDLC. */ RAWHDLC = 518, // Raw HDLC.
TUNNEL = 768, /* IPIP tunnel. */ TUNNEL = 768, // IPIP tunnel.
TUNNEL6 = 769, /* IPIP6 tunnel. */ TUNNEL6 = 769, // IPIP6 tunnel.
FRAD = 770, /* Frame Relay Access Device. */ FRAD = 770, // Frame Relay Access Device.
SKIP = 771, /* SKIP vif. */ SKIP = 771, // SKIP vif.
LOOPBACK = 772, /* Loopback device. */ LOOPBACK = 772, // Loopback device.
LOCALTLK = 773, /* Localtalk device. */ LOCALTLK = 773, // Localtalk device.
FDDI = 774, /* Fiber Distributed Data Interface. */ FDDI = 774, // Fiber Distributed Data Interface.
BIF = 775, /* AP1000 BIF. */ BIF = 775, // AP1000 BIF.
SIT = 776, /* sit0 device - IPv6-in-IPv4. */ SIT = 776, // sit0 device - IPv6-in-IPv4.
IPDDP = 777, /* IP-in-DDP tunnel. */ IPDDP = 777, // IP-in-DDP tunnel.
IPGRE = 778, /* GRE over IP. */ IPGRE = 778, // GRE over IP.
PIMREG = 779, /* PIMSM register interface. */ PIMREG = 779, // PIMSM register interface.
HIPPI = 780, /* High Performance Parallel I'face. */ HIPPI = 780, // High Performance Parallel I'face.
ASH = 781, /* (Nexus Electronics) Ash. */ ASH = 781, // (Nexus Electronics) Ash.
ECONET = 782, /* Acorn Econet. */ ECONET = 782, // Acorn Econet.
IRDA = 783, /* Linux-IrDA. */ IRDA = 783, // Linux-IrDA.
FCPP = 784, /* Point to point fibrechanel. */ FCPP = 784, // Point to point fibrechanel.
FCAL = 785, /* Fibrechanel arbitrated loop. */ FCAL = 785, // Fibrechanel arbitrated loop.
FCPL = 786, /* Fibrechanel public loop. */ FCPL = 786, // Fibrechanel public loop.
FCFABRIC = 787, /* Fibrechanel fabric. */ FCFABRIC = 787, // Fibrechanel fabric.
IEEE802_TR = 800, /* Magic type ident for TR. */ IEEE802_TR = 800, // Magic type ident for TR.
IEEE80211 = 801, /* IEEE 802.11. */ IEEE80211 = 801, // IEEE 802.11.
IEEE80211_PRISM = 802, /* IEEE 802.11 + Prism2 header. */ IEEE80211_PRISM = 802, // IEEE 802.11 + Prism2 header.
IEEE80211_RADIOTAP = 803, /* IEEE 802.11 + radiotap header. */ IEEE80211_RADIOTAP = 803, // IEEE 802.11 + radiotap header.
IEEE802154 = 804, /* IEEE 802.15.4 header. */ IEEE802154 = 804, // IEEE 802.15.4 header.
IEEE802154_PHY = 805, /* IEEE 802.15.4 PHY header. */ IEEE802154_PHY = 805, // IEEE 802.15.4 PHY header.
VOID_TYPE = 0xFFFF, /* Void type, nothing is known. */ VOID_TYPE = 0xFFFF, // Void type, nothing is known.
NONE = 0xFFFE /* Zero header length. */ NONE = 0xFFFE // Zero header length.
}; };
}; };
}
}
} // Constants
} // Tins
#endif // TINS_CONSTANTS_H #endif // TINS_CONSTANTS_H

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -29,69 +29,153 @@
#include "config.h" #include "config.h"
#if !defined(TINS_CRYPTO_H) && defined(HAVE_DOT11) #if !defined(TINS_CRYPTO_H) && defined(TINS_HAVE_DOT11)
#define TINS_CRYPTO_H #define TINS_CRYPTO_H
#include <map> #include <map>
#include <string> #include <string>
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
#ifdef TINS_HAVE_WPA2_CALLBACKS
#include <functional>
#endif // TINS_HAVE_WPA2_CALLBACKS
#include "utils.h" #include "utils.h"
#include "snap.h" #include "snap.h"
#include "rawpdu.h" #include "rawpdu.h"
#include "macros.h"
#include "handshake_capturer.h" #include "handshake_capturer.h"
namespace Tins { namespace Tins {
class PDU; class PDU;
class Dot11; class Dot11;
class Dot11Data; class Dot11Data;
namespace Crypto { 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;
struct RC4Key;
#ifdef TINS_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(); 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); 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; 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: private:
SNAP* ccmp_decrypt_unicast(const Dot11Data& dot11, RawPDU& raw) const; SNAP* ccmp_decrypt_unicast(const Dot11Data& dot11, RawPDU& raw) const;
SNAP* tkip_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; RC4Key generate_rc4_key(const Dot11Data& dot11, const RawPDU& raw) const;
ptk_type ptk; ptk_type ptk_;
bool is_ccmp; bool is_ccmp_;
}; };
class SupplicantData { /**
* \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: public:
typedef HWAddress<6> address_type; /**
* The type used to store the PMK.
*/
typedef SessionKeys::pmk_type pmk_type; 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); SupplicantData(const std::string& psk, const std::string& ssid);
/**
* \brief Getter for the PMK.
* \return The generated PMK.
*/
const pmk_type& pmk() const; const pmk_type& pmk() const;
/**
* \brief Getter for the SSID
* \return The access point's SSID
*/
const std::string& ssid() const;
private: private:
pmk_type pmk_; pmk_type pmk_;
std::string ssid_;
}; };
}
#endif // HAVE_WPA2_DECRYPTION } // WPA2
/** #endif // TINS_HAVE_WPA2_DECRYPTION
* \endcond
*/
/** /**
* \brief RC4 Key abstraction. * \brief RC4 Key abstraction.
@@ -117,7 +201,7 @@ namespace Crypto {
/** /**
* \brief Decrypts WEP-encrypted traffic. * \brief Decrypts WEP-encrypted traffic.
*/ */
class WEPDecrypter { class TINS_API WEPDecrypter {
public: public:
typedef HWAddress<6> address_type; typedef HWAddress<6> address_type;
@@ -162,24 +246,71 @@ namespace Crypto {
PDU* decrypt(RawPDU& raw, const std::string& password); PDU* decrypt(RawPDU& raw, const std::string& password);
passwords_type passwords; passwords_type passwords_;
std::vector<uint8_t> key_buffer; std::vector<uint8_t> key_buffer_;
}; };
#ifdef HAVE_WPA2_DECRYPTION #ifdef TINS_HAVE_WPA2_DECRYPTION
/** /**
* \brief Decrypts WPA2-encrypted traffic. * \brief Decrypts WPA2-encrypted traffic.
* *
* This class takes valid PSK and SSID tuples, captures client handshakes, * This class takes valid PSK and SSID tuples, captures client handshakes,
* and decrypts their traffic afterwards. * and decrypts their traffic afterwards.
*/ */
class WPA2Decrypter { class TINS_API WPA2Decrypter {
public: public:
/* /*
* \brief The type used to store Dot11 addresses. * \brief The type used to store Dot11 addresses.
*/ */
typedef HWAddress<6> address_type; typedef HWAddress<6> address_type;
/**
* \brief Represents a pair of mac addresses.
*
* This is used to identify a host and the access point to which
* it is connected. The first element in the pair will always de
* lower or equal than the second one, so that given any host and
* the access point it's connected to, we can uniquely identify
* it with an address pair.
*/
typedef std::pair<address_type, address_type> addr_pair;
/**
* \brief Maps an address pair to the session keys.
*
* This type associates an address pair (host, access point) with the
* session keys, as generated using the packets seen on a handshake.
*
* \sa addr_pair
*/
typedef std::map<addr_pair, WPA2::SessionKeys> keys_map;
#ifdef TINS_HAVE_WPA2_CALLBACKS
/**
* \brief The type used to store the callback type used when a new access
* point is found.
*
* The first argument to the function will be the access point's SSID and
* the second one its BSSID.
*/
typedef std::function<void(const std::string&,
const address_type&)> ap_found_callback_type;
/**
* The type used to store the callback type used when a new handshake
* is captured.
*
* The first argument to the function will be the access point's SSID and
* the second one its BSSID. The third argument will be the client's hardware
* address.
*/
typedef std::function<void(const std::string&,
const address_type&,
const address_type&)> handshake_captured_callback_type;
#endif // TINS_HAVE_WPA2_CALLBACKS
/** /**
* \brief Adds an access points's information. * \brief Adds an access points's information.
* *
@@ -214,7 +345,32 @@ namespace Crypto {
* \param ssid The network's SSID. * \param ssid The network's SSID.
* \param addr The access point's BSSID. * \param addr The access point's BSSID.
*/ */
void add_ap_data(const std::string &psk, const std::string &ssid, const address_type &addr); 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. * \brief Decrypts the provided PDU.
@@ -232,11 +388,43 @@ namespace Crypto {
* failed, true otherwise. * failed, true otherwise.
*/ */
bool decrypt(PDU& pdu); bool decrypt(PDU& pdu);
#ifdef TINS_HAVE_WPA2_CALLBACKS
/**
* \brief Sets the handshake captured callback
*
* This callback will be executed every time a new handshake is captured.
*
* \sa handshake_captured_callback_type
* \param callback The new callback to be set
*/
void handshake_captured_callback(const handshake_captured_callback_type& callback);
/**
* \brief Sets the access point found callback
*
* This callback will be executed every time a new access point is found, that's
* advertising an SSID added when calling add_ap_data.
*
* \sa ap_found_callback_type
* \param callback The new callback to be set
*/
void ap_found_callback(const ap_found_callback_type& callback);
#endif // TINS_HAVE_WPA2_CALLBACKS
/**
* \brief Getter for the keys on this decrypter
*
* The returned map will be populated every time a new, complete, handshake
* is captured.
*
* \return The WPA2Decrypter keys map.
*/
const keys_map& get_keys() const;
private: private:
typedef std::map<std::string, WPA2::SupplicantData> pmks_map; typedef std::map<std::string, WPA2::SupplicantData> pmks_map;
typedef std::map<address_type, WPA2::SupplicantData> bssids_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); void try_add_keys(const Dot11Data& dot11, const RSNHandshake& hs);
addr_pair make_addr_pair(const address_type& addr1, const address_type& addr2) { addr_pair make_addr_pair(const address_type& addr1, const address_type& addr2) {
@@ -249,12 +437,16 @@ namespace Crypto {
bssids_map::const_iterator find_ap(const Dot11Data& dot11); bssids_map::const_iterator find_ap(const Dot11Data& dot11);
void add_access_point(const std::string& ssid, const address_type& addr); void add_access_point(const std::string& ssid, const address_type& addr);
RSNHandshakeCapturer capturer; RSNHandshakeCapturer capturer_;
pmks_map pmks; pmks_map pmks_;
bssids_map aps; bssids_map aps_;
keys_map keys; keys_map keys_;
#ifdef TINS_HAVE_WPA2_CALLBACKS
handshake_captured_callback_type handshake_captured_callback_;
ap_found_callback_type ap_found_callback_;
#endif // TINS_HAVE_WPA2_CALLBACKS
}; };
#endif // HAVE_WPA2_DECRYPTION #endif // TINS_HAVE_WPA2_DECRYPTION
/** /**
* \brief Pluggable decrypter object which can be used to decrypt * \brief Pluggable decrypter object which can be used to decrypt
@@ -331,7 +523,7 @@ namespace Crypto {
template<typename Functor> template<typename Functor>
DecrypterProxy<Functor, WEPDecrypter> make_wep_decrypter_proxy(const Functor& functor); DecrypterProxy<Functor, WEPDecrypter> make_wep_decrypter_proxy(const Functor& functor);
#ifdef HAVE_WPA2_DECRYPTION #ifdef TINS_HAVE_WPA2_DECRYPTION
/** /**
* \brief Wrapper function to create a DecrypterProxy using a * \brief Wrapper function to create a DecrypterProxy using a
* WPA2Decrypter as the Decrypter template parameter. * WPA2Decrypter as the Decrypter template parameter.
@@ -343,43 +535,38 @@ namespace Crypto {
DecrypterProxy<Functor, WPA2Decrypter> make_wpa2_decrypter_proxy(const Functor& functor) { DecrypterProxy<Functor, WPA2Decrypter> make_wpa2_decrypter_proxy(const Functor& functor) {
return DecrypterProxy<Functor, WPA2Decrypter>(functor); return DecrypterProxy<Functor, WPA2Decrypter>(functor);
} }
#endif // HAVE_WPA2_DECRYPTION #endif // TINS_HAVE_WPA2_DECRYPTION
// Implementation section // Implementation section
// DecrypterProxy // DecrypterProxy
template<typename Functor, typename Decrypter> template<typename Functor, typename Decrypter>
DecrypterProxy<Functor, Decrypter>::DecrypterProxy( DecrypterProxy<Functor, Decrypter>::DecrypterProxy(const functor_type& func,
const functor_type &func, const decrypter_type& decr) const decrypter_type& decr)
: functor_(func), decrypter_(decr) : functor_(func), decrypter_(decr) {
{
} }
template<typename Functor, typename Decrypter> template<typename Functor, typename Decrypter>
typename DecrypterProxy<Functor, Decrypter>::decrypter_type & typename DecrypterProxy<Functor, Decrypter>::decrypter_type &
DecrypterProxy<Functor, Decrypter>::decrypter() DecrypterProxy<Functor, Decrypter>::decrypter() {
{
return decrypter_; return decrypter_;
} }
template<typename Functor, typename Decrypter> template<typename Functor, typename Decrypter>
const typename DecrypterProxy<Functor, Decrypter>::decrypter_type & const typename DecrypterProxy<Functor, Decrypter>::decrypter_type &
DecrypterProxy<Functor, Decrypter>::decrypter() const DecrypterProxy<Functor, Decrypter>::decrypter() const {
{
return decrypter_; return decrypter_;
} }
template<typename Functor, typename Decrypter> template<typename Functor, typename Decrypter>
bool DecrypterProxy<Functor, Decrypter>::operator() (PDU &pdu) bool DecrypterProxy<Functor, Decrypter>::operator() (PDU& pdu) {
{
return decrypter_.decrypt(pdu) ? functor_(pdu) : true; return decrypter_.decrypt(pdu) ? functor_(pdu) : true;
} }
template<typename Functor> template<typename Functor>
DecrypterProxy<Functor, WEPDecrypter> make_wep_decrypter_proxy(const Functor &functor) DecrypterProxy<Functor, WEPDecrypter> make_wep_decrypter_proxy(const Functor& functor) {
{
return DecrypterProxy<Functor, WEPDecrypter>(functor); return DecrypterProxy<Functor, WEPDecrypter>(functor);
} }
@@ -387,14 +574,16 @@ namespace Crypto {
template<typename ForwardIterator> template<typename ForwardIterator>
RC4Key::RC4Key(ForwardIterator start, ForwardIterator end) { RC4Key::RC4Key(ForwardIterator start, ForwardIterator end) {
for(size_t i = 0; i < data_size; ++i) for (size_t i = 0; i < data_size; ++i) {
data[i] = i; data[i] = static_cast<uint8_t>(i);
}
size_t j = 0; size_t j = 0;
ForwardIterator iter = start; ForwardIterator iter = start;
for (size_t i = 0; i < data_size; ++i) { for (size_t i = 0; i < data_size; ++i) {
j = (j + data[i] + *iter++) % 256; j = (j + data[i] + *iter++) % 256;
if(iter == end) if(iter == end) {
iter = start; iter = start;
}
std::swap(data[i], data[j]); std::swap(data[i], data[j]);
} }
} }
@@ -409,7 +598,8 @@ namespace Crypto {
*output++ = *start++ ^ key.data[(key.data[i] + key.data[j]) % RC4Key::data_size]; *output++ = *start++ ^ key.data[(key.data[i] + key.data[j]) % RC4Key::data_size];
} }
} }
}
} } // Crypto
} // Tins
#endif // TINS_CRYPTO_H #endif // TINS_CRYPTO_H

View File

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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -30,15 +30,16 @@
#ifndef TINS_DHCP_H #ifndef TINS_DHCP_H
#define TINS_DHCP_H #define TINS_DHCP_H
#include <list> #include <list>
#include <vector> #include <vector>
#include <string> #include <string>
#include "bootp.h" #include "bootp.h"
#include "macros.h"
#include "pdu_option.h" #include "pdu_option.h"
#include "cxxstd.h" #include "cxxstd.h"
namespace Tins { namespace Tins {
/** /**
* \class DHCP * \class DHCP
* \brief Represents the DHCP PDU. * \brief Represents the DHCP PDU.
@@ -64,7 +65,7 @@ namespace Tins {
* *
* \endcode * \endcode
*/ */
class DHCP : public BootP { class TINS_API DHCP : public BootP {
public: public:
/** /**
* This PDU's flag. * This PDU's flag.
@@ -171,6 +172,14 @@ namespace Tins {
*/ */
typedef std::list<option> options_type; typedef std::list<option> options_type;
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/** /**
* \brief Creates an instance of DHCP. * \brief Creates an instance of DHCP.
* *
@@ -207,10 +216,21 @@ namespace Tins {
*/ */
void add_option(option &&opt) { void add_option(option &&opt) {
internal_add_option(opt); internal_add_option(opt);
_options.push_back(std::move(opt)); options_.push_back(std::move(opt));
} }
#endif #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. * \brief Searchs for an option that matchs the given flag.
* \param opt_flag The flag to be searched. * \param opt_flag The flag to be searched.
@@ -465,7 +485,7 @@ namespace Tins {
* \brief Getter for the options list. * \brief Getter for the options list.
* \return The option list. * \return The option list.
*/ */
const options_type options() const { return _options; } const options_type options() const { return options_; }
/** /**
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
@@ -491,20 +511,24 @@ namespace Tins {
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);
template<class T> template <typename T>
T search_and_convert(OptionTypes opt) const { T search_and_convert(OptionTypes opt) const {
const option* option = search_option(opt); const option* option = search_option(opt);
if(!option) if (!option) {
throw option_not_found(); throw option_not_found();
}
return option->to<T>(); return option->to<T>();
} }
void internal_add_option(const option& opt); void internal_add_option(const option& opt);
serialization_type serialize_list(const std::vector<ipaddress_type>& ip_list); 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; options_type options_;
uint32_t _size; uint32_t size_;
}; };
}
} // Tins
#endif // TINS_DHCP_H #endif // TINS_DHCP_H

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -33,17 +33,24 @@
#include <cstring> #include <cstring>
#include <list> #include <list>
#include "pdu.h" #include "pdu.h"
#include "macros.h"
#include "endianness.h" #include "endianness.h"
#include "small_uint.h" #include "small_uint.h"
#include "ipv6_address.h" #include "ipv6_address.h"
#include "pdu_option.h" #include "pdu_option.h"
namespace Tins { namespace Tins {
namespace Memory {
class OutputMemoryStream;
} // Memory
/** /**
* \class DHCPv6 * \class DHCPv6
* \brief Represents a DHCPv6 PDU. * \brief Represents a DHCPv6 PDU.
*/ */
class DHCPv6 : public PDU { class TINS_API DHCPv6 : public PDU {
public: public:
/** /**
* Represents a DHCPv6 option. * Represents a DHCPv6 option.
@@ -284,10 +291,7 @@ public:
data_type data; data_type data;
user_class_type(const data_type& data = data_type()) user_class_type(const data_type& data = data_type())
: data(data) : data(data) { }
{
}
static user_class_type from_option(const option& opt); static user_class_type from_option(const option& opt);
}; };
@@ -408,6 +412,14 @@ public:
*/ */
typedef std::vector<uint8_t> interface_id_type; typedef std::vector<uint8_t> interface_id_type;
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/** /**
* Default constructor. * Default constructor.
*/ */
@@ -433,7 +445,7 @@ public:
* \return The stored message type field. * \return The stored message type field.
*/ */
MessageType msg_type() const { MessageType msg_type() const {
return static_cast<MessageType>(header_data[0]); return static_cast<MessageType>(header_data_[0]);
} }
/** /**
@@ -441,7 +453,9 @@ public:
* *
* \return The stored hop count field. * \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. * \brief Getter for the transaction id field.
@@ -449,7 +463,7 @@ public:
* \return The stored transaction id field. * \return The stored transaction id field.
*/ */
small_uint<24> transaction_id() const { small_uint<24> transaction_id() const {
return (header_data[1] << 16) | (header_data[2] << 8) | header_data[3]; return (header_data_[1] << 16) | (header_data_[2] << 8) | header_data_[3];
} }
/** /**
@@ -457,21 +471,27 @@ public:
* *
* \return The stored peer address field. * \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. * \brief Getter for the link address field.
* *
* \return The stored 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. * \brief Getter for the DHCPv6 options.
* *
* \return The stored options. * \return The stored options.
*/ */
const options_type &options() const { return options_; } const options_type& options() const {
return options_;
}
// Setters // Setters
/** /**
@@ -816,27 +836,38 @@ public:
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. * If the option is not found, a null pointer is returned.
* Deleting the returned pointer will result in <b>undefined * Deleting the returned pointer will result in <b>undefined
* behaviour</b>. * 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 // PDU stuff
/** /**
* \brief Returns the header size. * \brief Returns the header size.
* *
* This metod overrides PDU::header_size. \sa PDU::header_size * This method overrides PDU::header_size. \sa PDU::header_size
*/ */
uint32_t header_size() const; 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 * \sa PDU::matches_response
* \param ptr The pointer to the buffer. * \param ptr The pointer to the buffer.
@@ -848,7 +879,9 @@ public:
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* \sa PDU::pdu_type * \sa PDU::pdu_type
*/ */
PDUType pdu_type() const { return pdu_flag; } PDUType pdu_type() const {
return pdu_flag;
}
/** /**
* \sa PDU::clone * \sa PDU::clone
@@ -858,40 +891,46 @@ public:
} }
private: private:
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU *); void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU *);
uint8_t* write_option(const option &option, uint8_t* buffer) const; 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> template <template <typename> class Functor>
const option* safe_search_option(OptionTypes opt, uint32_t size) const { const option* safe_search_option(OptionTypes opt, uint32_t size) const {
const option* option = search_option(opt); const option* option = search_option(opt);
if(!option || Functor<uint32_t>()(option->data_size(), size)) if (!option || Functor<uint32_t>()(option->data_size(), size)) {
throw option_not_found(); throw option_not_found();
}
return option; return option;
} }
template<typename T> template<typename T>
T search_and_convert(OptionTypes opt) const { T search_and_convert(OptionTypes opt) const {
const option* option = search_option(opt); const option* option = search_option(opt);
if(!option) if (!option) {
throw option_not_found(); throw option_not_found();
}
return option->to<T>(); return option->to<T>();
} }
uint8_t header_data[4]; uint8_t header_data_[4];
uint32_t options_size; uint32_t options_size_;
ipaddress_type link_addr, peer_addr; ipaddress_type link_addr_, peer_addr_;
options_type options_; options_type options_;
}; };
namespace Internals { namespace Internals {
template<typename InputIterator> template<typename InputIterator>
void class_option_data2option(InputIterator start, InputIterator end, void class_option_data2option(InputIterator start,
std::vector<uint8_t>& buffer, size_t start_index = 0) InputIterator end,
{ std::vector<uint8_t>& buffer,
size_t start_index = 0) {
size_t index = start_index; size_t index = start_index;
uint16_t uint16_t_buffer; uint16_t uint16_t_buffer;
while (start != end) { while (start != end) {
buffer.resize(buffer.size() + sizeof(uint16_t) + start->size()); 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)); std::memcpy(&buffer[index], &uint16_t_buffer, sizeof(uint16_t));
index += sizeof(uint16_t); index += sizeof(uint16_t);
std::copy(start->begin(), start->end(), buffer.begin() + index); std::copy(start->begin(), start->end(), buffer.begin() + index);
@@ -902,8 +941,7 @@ void class_option_data2option(InputIterator start, InputIterator end,
} }
template<typename OutputType> 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; typedef typename OutputType::value_type value_type;
OutputType output; OutputType output;
size_t index = 0; size_t index = 0;
@@ -912,18 +950,21 @@ OutputType option2class_option_data(const uint8_t *ptr, uint32_t total_sz)
std::memcpy(&size, ptr + index, sizeof(uint16_t)); std::memcpy(&size, ptr + index, sizeof(uint16_t));
size = Endian::be_to_host(size); size = Endian::be_to_host(size);
index += sizeof(uint16_t); index += sizeof(uint16_t);
if(index + size > total_sz) if (index + size > total_sz) {
throw option_not_found(); throw option_not_found();
}
output.push_back( output.push_back(
value_type(ptr + index, ptr + index + size) value_type(ptr + index, ptr + index + size)
); );
index += size; index += size;
} }
if(index != total_sz) if (index != total_sz) {
throw malformed_option(); throw malformed_option();
}
return output; return output;
} }
}
} } // Internals
} // Tins
#endif // TINS_DHCPV6_H #endif // TINS_DHCPV6_H

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -41,6 +41,12 @@
#include "endianness.h" #include "endianness.h"
namespace Tins { namespace Tins {
namespace Memory {
class InputMemoryStream;
} // Memory
class IPv4Address; class IPv4Address;
class IPv6Address; class IPv6Address;
@@ -69,7 +75,7 @@ namespace Tins {
* } * }
* \endcode * \endcode
*/ */
class DNS : public PDU { class TINS_API DNS : public PDU {
public: public:
/** /**
* \brief This PDU's flag. * \brief This PDU's flag.
@@ -151,7 +157,7 @@ namespace Tins {
/** /**
* \brief Struct that represent DNS queries. * \brief Struct that represent DNS queries.
*/ */
class Query { class query {
public: public:
/** /**
* \brief Constructs a DNS query. * \brief Constructs a DNS query.
@@ -160,13 +166,13 @@ namespace Tins {
* \param tp The query type. * \param tp The query type.
* \param cl The query class. * \param cl The query class.
*/ */
Query(const std::string &nm, QueryType tp, QueryClass cl) query(const std::string& nm, QueryType tp, QueryClass cl)
: name_(nm), type_(tp), qclass_(cl) {} : name_(nm), type_(tp), qclass_(cl) {}
/** /**
* \brief Default constructs this Query. * \brief Default constructs this Query.
*/ */
Query() : type_(), qclass_() {} query() : type_(), qclass_() {}
/** /**
* \brief Setter for the name field. * \brief Setter for the name field.
@@ -182,7 +188,19 @@ namespace Tins {
* *
* \param tp The query type to be set. * \param tp The query type to be set.
*/ */
void type(QueryType tp) { void query_type(QueryType tp) {
type_ = tp;
}
/**
* \brief Setter for the query type field.
*
* This method is deprecated. Use query::query_type
*
* \deprecated
* \sa query::query_type
*/
TINS_DEPRECATED(void type(QueryType tp)) {
type_ = tp; type_ = tp;
} }
@@ -198,27 +216,210 @@ namespace Tins {
/** /**
* \brief Getter for the name field. * \brief Getter for the name field.
*/ */
const std::string &dname() const { return name_; } const std::string& dname() const {
return name_;
}
/** /**
* \brief Getter for the query type field. * \brief Getter for the query type field.
*/ */
QueryType type() const { return type_; } QueryType query_type() const {
return type_;
}
/**
* \brief Getter for the query type field.
*
* This method is deprecated. Use query::query_type
*
* \deprecated
* \sa query::query_type
*/
TINS_DEPRECATED(QueryType type() const) {
return type_;
}
/** /**
* \brief Getter for the query class field. * \brief Getter for the query class field.
*/ */
QueryClass query_class() const { return qclass_; } QueryClass query_class() const {
return qclass_;
}
private: private:
std::string name_; std::string name_;
QueryType type_; QueryType type_;
QueryClass qclass_; QueryClass qclass_;
}; };
class resource;
/** /**
* \brief Struct that represent DNS resource records. * \brief Class that represents a Start Of Authority record
*/ */
class Resource { class soa_record {
public:
/**
* \brief Default constructor
*/
soa_record();
/**
* \brief Constructs a SOA record from a DNS::resource
* \param resource The resource from which to construct this record
*/
soa_record(const DNS::resource& resource);
/**
* \brief Constructs a SOA record from a buffer
* \param buffer The buffer from which to construct this SOA record
* \param total_sz The size of the buffer
*/
soa_record(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Constructs a SOA record
*
* \param mname The primary source name
* \param rname The responsible person name
* \param serial The serial number
* \param refresh The refresh value
* \param retry The retry value
* \param expire The expire value
* \param minimum_ttl The minimum TTL value
*/
soa_record(const std::string& mname,
const std::string& rname,
uint32_t serial,
uint32_t refresh,
uint32_t retry,
uint32_t expire,
uint32_t minimum_ttl);
/**
* \brief Getter for the primary source name field
*
* The returned domain name is already decoded.
*
* \return mname The primary source name field
*/
const std::string& mname() const {
return mname_;
}
/**
* \brief Getter for the responsible person name field
*
* The returned domain name is already decoded.
*
* \return mname The responsible person name field
*/
const std::string& rname() const {
return rname_;
}
/**
* \brief Getter for the serial number field
* \return The serial number field
*/
uint32_t serial() const {
return serial_;
}
/**
* \brief Getter for the refresh field
* \return The refresh field
*/
uint32_t refresh() const {
return refresh_;
}
/**
* \brief Getter for the retry field
* \return The retry field
*/
uint32_t retry() const {
return retry_;
}
/**
* \brief Getter for the expire field
* \return The expire field
*/
uint32_t expire() const {
return expire_;
}
/**
* \brief Getter for the minimum TTL field
* \return The minimum TTL field
*/
uint32_t minimum_ttl() const {
return minimum_ttl_;
}
/**
* \brief Getter for the primary source name field
* \param value The new primary source name field value
*/
void mname(const std::string& value);
/**
* \brief Getter for the responsible person name field
* \param value The new responsible person name field value
*/
void rname(const std::string& value);
/**
* \brief Getter for the serial number field
* \param value The new serial number field value
*/
void serial(uint32_t value);
/**
* \brief Getter for the refresh field
* \param value The new refresh field value
*/
void refresh(uint32_t value);
/**
* \brief Getter for the retry field
* \param value The new retry field value
*/
void retry(uint32_t value);
/**
* \brief Getter for the expire field
* \param value The new expire field value
*/
void expire(uint32_t value);
/**
* \brief Getter for the minimum TTL field
* \param value The new minimum TTL field value
*/
void minimum_ttl(uint32_t value);
/**
* \brief Serialize this SOA record
* \return The serialized SOA record
*/
PDU::serialization_type serialize() const;
private:
void init(const uint8_t* buffer, uint32_t total_sz);
std::string mname_;
std::string rname_;
uint32_t serial_;
uint32_t refresh_;
uint32_t retry_;
uint32_t expire_;
uint32_t minimum_ttl_;
};
/**
* \brief Class that represent DNS resource records.
*/
class resource {
public: public:
/** /**
* Constructs a Resource object. * Constructs a Resource object.
@@ -230,11 +431,16 @@ namespace Tins {
* \param rclass The class of this record. * \param rclass The class of this record.
* \param ttl The time-to-live of this record. * \param ttl The time-to-live of this record.
*/ */
Resource(const std::string &dname, const std::string &data, resource(const std::string& dname,
uint16_t type, uint16_t rclass, uint32_t ttl) const std::string& data,
: dname_(dname), data_(data), type_(type), qclass_(rclass), ttl_(ttl) {} uint16_t type,
uint16_t rclass,
uint32_t ttl,
uint16_t preference = 0)
: dname_(dname), data_(data), type_(type), qclass_(rclass),
ttl_(ttl), preference_(preference) {}
Resource() : type_(), qclass_(), ttl_() {} resource() : type_(), qclass_(), ttl_(), preference_() {}
/** /**
* \brief Getter for the domain name field. * \brief Getter for the domain name field.
@@ -242,27 +448,58 @@ namespace Tins {
* This returns the domain name for which this record * This returns the domain name for which this record
* provides an answer. * provides an answer.
*/ */
const std::string &dname() const { return dname_; } const std::string& dname() const {
return dname_;
}
/** /**
* Getter for the data field. * Getter for the data field.
*/ */
const std::string &data() const { return data_; } const std::string& data() const {
return data_;
}
/** /**
* Getter for the query type field. * Getter for the query type field.
*/ */
uint16_t type() const { return type_; } uint16_t query_type() const {
return type_;
}
/**
* \brief Getter for the query type field.
*
* This method is deprecated. Use resource::query_type
*
* \deprecated
* \sa resource::query_type
*/
TINS_DEPRECATED(uint16_t type() const) {
return type_;
}
/** /**
* Getter for the query class field. * Getter for the query class field.
*/ */
uint16_t query_class() const { return qclass_; } uint16_t query_class() const {
return qclass_;
}
/** /**
* Getter for the type field. * Getter for the time-to-live field.
*/ */
uint32_t ttl() const { return ttl_; } uint32_t ttl() const {
return ttl_;
}
/**
* \brief Getter for the preferece field.
*
* This field is only valid for MX resources.
*/
uint16_t preference() const {
return preference_;
}
/** /**
* Setter for the domain name field. * Setter for the domain name field.
@@ -288,14 +525,35 @@ namespace Tins {
} }
/** /**
* Setter for the type field. * \brief Sets the contents of this resource to the provided SOA record
* \param data The SOA record that will be stored in this resource
*/ */
void type(uint16_t data) { void data(const soa_record& data) {
serialization_type buffer = data.serialize();
data_.assign(buffer.begin(), buffer.end());
}
/**
* Setter for the query type field.
*/
void query_type(uint16_t data) {
type_ = data; type_ = data;
} }
/** /**
* Setter for the class field. * \brief Setter for the query type field.
*
* This method is deprecated. Use query::query_type
*
* \deprecated
* \sa resource::query_type
*/
TINS_DEPRECATED(void type(uint16_t data)) {
type_ = data;
}
/**
* Setter for the query class field.
*/ */
void query_class(uint16_t data) { void query_class(uint16_t data) {
qclass_ = data; qclass_ = data;
@@ -304,20 +562,41 @@ namespace Tins {
/** /**
* Setter for the time-to-live field. * Setter for the time-to-live field.
*/ */
void ttl(uint16_t data) { void ttl(uint32_t data) {
ttl_ = data; ttl_ = data;
} }
/**
* \brief Setter for the preference field.
*
* This field is only valid for MX resources.
*/
void preference(uint16_t data) {
preference_ = data;
}
private: private:
std::string dname_, data_; std::string dname_, data_;
uint16_t type_, qclass_; uint16_t type_, qclass_;
uint32_t ttl_; uint32_t ttl_;
uint16_t preference_;
}; };
typedef std::list<Query> queries_type; TINS_DEPRECATED(typedef query Query);
typedef std::list<Resource> resources_type; TINS_DEPRECATED(typedef resource Resource);
typedef std::list<query> queries_type;
typedef std::list<resource> resources_type;
typedef IPv4Address address_type; typedef IPv4Address address_type;
typedef IPv6Address address_v6_type; typedef IPv6Address address_v6_type;
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/** /**
* \brief Default constructor. * \brief Default constructor.
* *
@@ -344,7 +623,9 @@ namespace Tins {
* *
* \return uint16_t containing the value of the id field. * \return uint16_t containing the value of the id field.
*/ */
uint16_t id() const { return Endian::be_to_host(dns.id); } uint16_t id() const {
return Endian::be_to_host(header_.id);
}
/** /**
* \brief Setter for the query response field. * \brief Setter for the query response field.
@@ -352,14 +633,18 @@ namespace Tins {
* \return QRType containing the value of the query response * \return QRType containing the value of the query response
* field. * field.
*/ */
QRType type() const { return static_cast<QRType>(dns.qr); } QRType type() const {
return static_cast<QRType>(header_.qr);
}
/** /**
* \brief Setter for the opcode field. * \brief Setter for the opcode field.
* *
* \return uint8_t containing the value of the opcode field. * \return uint8_t containing the value of the opcode field.
*/ */
uint8_t opcode() const { return dns.opcode; } uint8_t opcode() const {
return header_.opcode;
}
/** /**
* \brief Setter for the authoritative answer field. * \brief Setter for the authoritative answer field.
@@ -367,14 +652,18 @@ namespace Tins {
* \return uint8_t containing the value of the authoritative * \return uint8_t containing the value of the authoritative
* answer field. * answer field.
*/ */
uint8_t authoritative_answer() const { return dns.aa; } uint8_t authoritative_answer() const {
return header_.aa;
}
/** /**
* \brief Setter for the truncated field. * \brief Setter for the truncated field.
* *
* \return uint8_t containing the value of the truncated field. * \return uint8_t containing the value of the truncated field.
*/ */
uint8_t truncated() const { return dns.tc; } uint8_t truncated() const {
return header_.tc;
}
/** /**
* \brief Setter for the recursion desired field. * \brief Setter for the recursion desired field.
@@ -382,7 +671,9 @@ namespace Tins {
* \return uint8_t containing the value of the recursion * \return uint8_t containing the value of the recursion
* desired field. * desired field.
*/ */
uint8_t recursion_desired() const { return dns.rd; } uint8_t recursion_desired() const {
return header_.rd;
}
/** /**
* \brief Setter for the recursion available field. * \brief Setter for the recursion available field.
@@ -390,14 +681,18 @@ namespace Tins {
* \return uint8_t containing the value of the recursion * \return uint8_t containing the value of the recursion
* available field. * available field.
*/ */
uint8_t recursion_available() const { return dns.ra; } uint8_t recursion_available() const {
return header_.ra;
}
/** /**
* \brief Setter for the z desired field. * \brief Setter for the z desired field.
* *
* \return uint8_t containing the value of the z field. * \return uint8_t containing the value of the z field.
*/ */
uint8_t z() const { return dns.z; } uint8_t z() const {
return header_.z;
}
/** /**
* \brief Setter for the authenticated data field. * \brief Setter for the authenticated data field.
@@ -405,7 +700,9 @@ namespace Tins {
* \return uint8_t containing the value of the authenticated * \return uint8_t containing the value of the authenticated
* data field. * data field.
*/ */
uint8_t authenticated_data() const { return dns.ad; } uint8_t authenticated_data() const {
return header_.ad;
}
/** /**
* \brief Setter for the checking disabled field. * \brief Setter for the checking disabled field.
@@ -413,49 +710,63 @@ namespace Tins {
* \return uint8_t containing the value of the checking * \return uint8_t containing the value of the checking
* disabled field. * disabled field.
*/ */
uint8_t checking_disabled() const { return dns.cd; } uint8_t checking_disabled() const {
return header_.cd;
}
/** /**
* \brief Setter for the rcode field. * \brief Setter for the rcode field.
* *
* \return uint8_t containing the value of the rcode field. * \return uint8_t containing the value of the rcode field.
*/ */
uint8_t rcode() const { return dns.rcode; } uint8_t rcode() const {
return header_.rcode;
}
/** /**
* \brief Setter for the questions field. * \brief Setter for the questions field.
* *
* \return uint16_t containing the value of 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); } uint16_t questions_count() const {
return Endian::be_to_host(header_.questions);
}
/** /**
* \brief Setter for the answers field. * \brief Setter for the answers field.
* *
* \return uint16_t containing the value of 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); } uint16_t answers_count() const {
return Endian::be_to_host(header_.answers);
}
/** /**
* \brief Setter for the authority field. * \brief Setter for the authority field.
* *
* \return uint16_t containing the value of 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); } uint16_t authority_count() const {
return Endian::be_to_host(header_.authority);
}
/** /**
* \brief Setter for the additional field. * \brief Setter for the additional field.
* *
* \return uint16_t containing the value of 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); } uint16_t additional_count() const {
return Endian::be_to_host(header_.additional);
}
/** /**
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* *
* \return Returns the PDUType corresponding to the PDU. * \return Returns the PDUType corresponding to the PDU.
*/ */
PDUType pdu_type() const { return PDU::DNS; } PDUType pdu_type() const {
return pdu_flag;
}
/** /**
* \brief The header's size * \brief The header's size
@@ -553,28 +864,28 @@ namespace Tins {
* *
* \param query The query to be added. * \param query The query to be added.
*/ */
void add_query(const Query &query); void add_query(const query& query);
/** /**
* \brief Add an answer resource record. * \brief Add an answer resource record.
* *
* \param resource The resource to be added. * \param resource The resource to be added.
*/ */
void add_answer(const Resource &resource); void add_answer(const resource& resource);
/** /**
* \brief Add an authority resource record. * \brief Add an authority resource record.
* *
* \param resource The resource to be added. * \param resource The resource to be added.
*/ */
void add_authority(const Resource &resource); void add_authority(const resource& resource);
/** /**
* \brief Add an additional resource record. * \brief Add an additional resource record.
* *
* \param resource The resource to be added. * \param resource The resource to be added.
*/ */
void add_additional(const Resource &resource); void add_additional(const resource& resource);
/** /**
* \brief Getter for this PDU's DNS queries. * \brief Getter for this PDU's DNS queries.
@@ -622,7 +933,21 @@ namespace Tins {
static std::string encode_domain_name(const std::string& 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. * \brief Decodes a domain name
*
* This method processes an encoded domain name and returns the decoded
* version. This <b>can't handle</b> offset labels.
*
* For example, given the input "\x03www\x07example\x03com\x00",
* the output would be www.example.com".
*
* \param domain_name The domain name to decode.
* \return The decoded domain name.
*/
static std::string decode_domain_name(const std::string& domain_name);
/**
* \brief Check whether ptr points to a valid response for this PDU.
* *
* \sa PDU::matches_response * \sa PDU::matches_response
* \param ptr The pointer to the buffer. * \param ptr The pointer to the buffer.
@@ -637,8 +962,10 @@ namespace Tins {
return new DNS(*this); return new DNS(*this);
} }
private: private:
friend class soa_record;
TINS_BEGIN_PACK TINS_BEGIN_PACK
struct dnshdr { struct dns_header {
uint16_t id; uint16_t id;
#if TINS_IS_LITTLE_ENDIAN #if TINS_IS_LITTLE_ENDIAN
uint16_t uint16_t
@@ -669,25 +996,30 @@ namespace Tins {
authority, additional; authority, additional;
} TINS_END_PACK; } TINS_END_PACK;
typedef std::list<Query> QueriesType;
typedef std::vector<std::pair<uint32_t*, uint32_t> > sections_type; typedef std::vector<std::pair<uint32_t*, uint32_t> > sections_type;
const uint8_t* compose_name(const uint8_t *ptr, char *out_ptr) const; uint32_t compose_name(const uint8_t* ptr, char* out_ptr) const;
void convert_records(const uint8_t *ptr, const uint8_t *end, resources_type &res) const; void convert_records(const uint8_t* ptr,
const uint8_t* find_section_end(const uint8_t *ptr, const uint32_t num_records) const; const uint8_t* end,
const uint8_t* find_dname_end(const uint8_t *ptr) const; resources_type& res) const;
void update_records(uint32_t &section_start, uint32_t num_records, uint32_t threshold, uint32_t offset); void skip_to_section_end(Memory::InputMemoryStream& stream,
const uint32_t num_records) const;
void skip_to_dname_end(Memory::InputMemoryStream& stream) 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); uint8_t* update_dname(uint8_t* ptr, uint32_t threshold, uint32_t offset);
static void inline_convert_v4(uint32_t value, char* output); static void inline_convert_v4(uint32_t value, char* output);
static bool contains_dname(uint16_t type); static bool contains_dname(uint16_t type);
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent); void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
void add_record(const Resource &resource, const sections_type &sections); void add_record(const resource& resource, const sections_type& sections);
dnshdr dns; dns_header header_;
byte_array records_data; byte_array records_data_;
uint32_t answers_idx, authority_idx, additional_idx; uint32_t answers_idx_, authority_idx_, additional_idx_;
}; };
}
} // Tins
#endif // TINS_DNS_H #endif // TINS_DNS_H

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -29,7 +29,7 @@
#include "config.h" #include "config.h"
#if !defined(TINS_DOT_11) && defined(HAVE_DOT11) #if !defined(TINS_DOT_11) && defined(TINS_HAVE_DOT11)
#define TINS_DOT_11 #define TINS_DOT_11
#include "dot11/dot11_base.h" #include "dot11/dot11_base.h"

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -29,17 +29,18 @@
#include "../config.h" #include "../config.h"
#if !defined(TINS_DOT11_DOT11_ASSOC_H) && defined(HAVE_DOT11) #if !defined(TINS_DOT11_DOT11_ASSOC_H) && defined(TINS_HAVE_DOT11)
#define TINS_DOT11_DOT11_ASSOC_H #define TINS_DOT11_DOT11_ASSOC_H
#include "../dot11/dot11_mgmt.h" #include "../dot11/dot11_mgmt.h"
#include "../macros.h"
namespace Tins { namespace Tins {
/** /**
* \brief Class representing a Disassociation frame in the IEEE 802.11 Protocol. * \brief Class representing a Disassociation frame in the IEEE 802.11 Protocol.
* *
*/ */
class Dot11Disassoc : public Dot11ManagementFrame { class TINS_API Dot11Disassoc : public Dot11ManagementFrame {
public: public:
/** /**
* \brief This PDU's flag. * \brief This PDU's flag.
@@ -79,7 +80,9 @@ public:
* *
* \return The stored reason code. * \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. * \brief Setter for the reason code field.
@@ -100,10 +103,12 @@ public:
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* \sa PDU::pdu_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 * \param flag The flag to match
* \sa PDU::matches_flag * \sa PDU::matches_flag
*/ */
@@ -120,20 +125,20 @@ public:
return new Dot11Disassoc(*this); return new Dot11Disassoc(*this);
} }
private: private:
struct DisassocBody { struct dot11_disassoc_body {
uint16_t reason_code; 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. * \brief Class representing an Association Request frame in the IEEE 802.11 Protocol.
* *
*/ */
class Dot11AssocRequest : public Dot11ManagementFrame { class TINS_API Dot11AssocRequest : public Dot11ManagementFrame {
public: public:
/** /**
* \brief This PDU's flag. * \brief This PDU's flag.
@@ -174,7 +179,9 @@ public:
* \return A constant refereence to the stored Capabilities * \return A constant refereence to the stored Capabilities
* Information field. * Information field.
*/ */
const capability_information& capabilities() const { return _body.capability;} const capability_information& capabilities() const {
return body_.capability;
}
/** /**
* \brief Getter for the Capabilities Information. * \brief Getter for the Capabilities Information.
@@ -182,14 +189,18 @@ public:
* \return A refereence to the stored Capabilities Information * \return A refereence to the stored Capabilities Information
* field. * field.
*/ */
capability_information& capabilities() { return _body.capability;} capability_information& capabilities() {
return body_.capability;
}
/** /**
* \brief Getter for the listen interval field. * \brief Getter for the listen interval field.
* *
* \return The stored 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. * \brief Setter for the listen interval field.
@@ -210,10 +221,12 @@ public:
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* \sa PDU::pdu_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 * \param flag The flag to match
* \sa PDU::matches_flag * \sa PDU::matches_flag
*/ */
@@ -230,21 +243,21 @@ public:
return new Dot11AssocRequest(*this); return new Dot11AssocRequest(*this);
} }
private: private:
struct AssocReqBody { struct dot11_assoc_request_body {
capability_information capability; capability_information capability;
uint16_t listen_interval; 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. * \brief Class representing an Association Response frame in the IEEE 802.11 Protocol.
* *
*/ */
class Dot11AssocResponse : public Dot11ManagementFrame { class TINS_API Dot11AssocResponse : public Dot11ManagementFrame {
public: public:
/** /**
* \brief This PDU's flag. * \brief This PDU's flag.
@@ -285,7 +298,9 @@ public:
* \return A constant reference to the stored Capabilities * \return A constant reference to the stored Capabilities
* Information field. * 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. * \brief Getter for the Capabilities Information field.
@@ -293,21 +308,27 @@ public:
* \return A reference to the stored Capabilities * \return A reference to the stored Capabilities
* Information field. * Information field.
*/ */
capability_information& capabilities() { return _body.capability;} capability_information& capabilities() {
return body_.capability;
}
/** /**
* \brief Getter for the status code field. * \brief Getter for the status code field.
* *
* \return The stored status code. * \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. * \brief Getter for the AID field.
* *
* \return The stored 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. * \brief Setter for the status code.
@@ -335,10 +356,12 @@ public:
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* \sa PDU::pdu_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 * \param flag The flag to match
* \sa PDU::matches_flag * \sa PDU::matches_flag
*/ */
@@ -355,22 +378,22 @@ public:
return new Dot11AssocResponse(*this); return new Dot11AssocResponse(*this);
} }
private: private:
struct AssocRespBody { struct dot11_assoc_response_body {
capability_information capability; capability_information capability;
uint16_t status_code; uint16_t status_code;
uint16_t aid; 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. * \brief Class representing an ReAssociation Request frame in the IEEE 802.11 Protocol.
* *
*/ */
class Dot11ReAssocRequest : public Dot11ManagementFrame { class TINS_API Dot11ReAssocRequest : public Dot11ManagementFrame {
public: public:
/** /**
* \brief This PDU's flag. * \brief This PDU's flag.
@@ -411,7 +434,9 @@ public:
* \return A constant reference to the stored Capabilities * \return A constant reference to the stored Capabilities
* Information field. * Information field.
*/ */
const capability_information& capabilities() const { return _body.capability;} const capability_information& capabilities() const {
return body_.capability;
}
/** /**
* \brief Getter for the Capabilities Information. * \brief Getter for the Capabilities Information.
@@ -419,21 +444,27 @@ public:
* \return A reference to the stored Capabilities Information * \return A reference to the stored Capabilities Information
* field. * field.
*/ */
capability_information& capabilities() { return _body.capability;} capability_information& capabilities() {
return body_.capability;
}
/** /**
* \brief Getter for the listen interval field. * \brief Getter for the listen interval field.
* *
* \return The stored listen interval. * \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. * \brief Getter for the current ap field.
* *
* \return The current ap. * \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. * \brief Setter for the listen interval field.
@@ -461,10 +492,12 @@ public:
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* \sa PDU::pdu_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 * \param flag The flag to match
* \sa PDU::matches_flag * \sa PDU::matches_flag
*/ */
@@ -481,22 +514,22 @@ public:
return new Dot11ReAssocRequest(*this); return new Dot11ReAssocRequest(*this);
} }
private: private:
struct ReAssocReqBody { struct dot11_reassoc_request_body {
capability_information capability; capability_information capability;
uint16_t listen_interval; uint16_t listen_interval;
uint8_t current_ap[address_type::address_size]; 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. * \brief IEEE 802.11 ReAssociation Response frame.
* *
*/ */
class Dot11ReAssocResponse : public Dot11ManagementFrame { class TINS_API Dot11ReAssocResponse : public Dot11ManagementFrame {
public: public:
/** /**
* \brief This PDU's flag. * \brief This PDU's flag.
@@ -537,7 +570,9 @@ public:
* \return A constant reference to the stored Capabilities * \return A constant reference to the stored Capabilities
* Information field. * Information field.
*/ */
const capability_information& capabilities() const { return _body.capability;} const capability_information& capabilities() const {
return body_.capability;
}
/** /**
* \brief Getter for the Capabilities Information. * \brief Getter for the Capabilities Information.
@@ -545,21 +580,27 @@ public:
* \return A reference to the stored Capabilities Information * \return A reference to the stored Capabilities Information
* field. * field.
*/ */
capability_information& capabilities() { return _body.capability;} capability_information& capabilities() {
return body_.capability;
}
/** /**
* \brief Getter for the status code field. * \brief Getter for the status code field.
* *
* \return The stored status code. * \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. * \brief Getter for the AID field.
* *
* \return The stored AID field value. * \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. * \brief Setter for the status code field.
@@ -587,10 +628,12 @@ public:
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* \sa PDU::pdu_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 * \param flag The flag to match
* \sa PDU::matches_flag * \sa PDU::matches_flag
*/ */
@@ -607,16 +650,17 @@ public:
return new Dot11ReAssocResponse(*this); return new Dot11ReAssocResponse(*this);
} }
private: private:
struct ReAssocRespBody { struct dot11_reassoc_response_body {
capability_information capability; capability_information capability;
uint16_t status_code; uint16_t status_code;
uint16_t aid; 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 } // namespace Tins
#endif // TINS_DOT11_DOT11_ASSOC_H #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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -29,16 +29,17 @@
#include "../config.h" #include "../config.h"
#if !defined(TINS_DOT11_DOT11_AUTH_H) && defined(HAVE_DOT11) #if !defined(TINS_DOT11_DOT11_AUTH_H) && defined(TINS_HAVE_DOT11)
#define TINS_DOT11_DOT11_AUTH_H #define TINS_DOT11_DOT11_AUTH_H
#include "../dot11/dot11_mgmt.h" #include "../dot11/dot11_mgmt.h"
#include "../macros.h"
namespace Tins { namespace Tins {
/** /**
* \brief IEEE 802.11 Authentication Request frame. * \brief IEEE 802.11 Authentication Request frame.
*/ */
class Dot11Authentication : public Dot11ManagementFrame { class TINS_API Dot11Authentication : public Dot11ManagementFrame {
public: public:
/** /**
* \brief This PDU's flag. * \brief This PDU's flag.
@@ -78,21 +79,26 @@ public:
* *
* \return The stored authentication algorithm number. * \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. * \brief Getter for the Authetication Sequence Number field.
* *
* \return The stored authentication sequence number. * \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. * \brief Getter for the status code field.
* *
* \return The stored status code. * \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. * \brief Setter for the Authetication Algorithm Number field.
@@ -129,10 +135,12 @@ public:
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* \sa PDU::pdu_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 * \param flag The flag to match
* \sa PDU::matches_flag * \sa PDU::matches_flag
*/ */
@@ -149,23 +157,22 @@ public:
return new Dot11Authentication(*this); return new Dot11Authentication(*this);
} }
private: private:
struct AuthBody { struct dot11_auth_body {
uint16_t auth_algorithm; uint16_t auth_algorithm;
uint16_t auth_seq_number; uint16_t auth_seq_number;
uint16_t status_code; uint16_t status_code;
}; };
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz); void write_fixed_parameters(Memory::OutputMemoryStream& stream);
AuthBody _body;
dot11_auth_body body_;
}; };
/** /**
* \brief IEEE 802.11 Deauthentication frame. * \brief IEEE 802.11 Deauthentication frame.
* *
*/ */
class Dot11Deauthentication : public Dot11ManagementFrame { class TINS_API Dot11Deauthentication : public Dot11ManagementFrame {
public: public:
/** /**
* \brief This PDU's flag. * \brief This PDU's flag.
@@ -205,7 +212,9 @@ public:
* *
* \return The reason code to be set. * \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. * \brief Setter for the reason code field.
@@ -226,10 +235,12 @@ public:
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* \sa PDU::pdu_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 * \param flag The flag to match
* \sa PDU::matches_flag * \sa PDU::matches_flag
*/ */
@@ -246,15 +257,15 @@ public:
return new Dot11Deauthentication(*this); return new Dot11Deauthentication(*this);
} }
private: private:
struct DeauthBody { struct dot11_deauth_body {
uint16_t reason_code; 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 } // namespace Tins
#endif // TINS_DOT11_DOT11_AUTH_H #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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -29,7 +29,7 @@
#include "../config.h" #include "../config.h"
#if !defined(TINS_DOT11_DOT11_H) && defined(HAVE_DOT11) #if !defined(TINS_DOT11_DOT11_H) && defined(TINS_HAVE_DOT11)
#define TINS_DOT11_DOT11_H #define TINS_DOT11_DOT11_H
#include <list> #include <list>
@@ -42,12 +42,17 @@
#include "../macros.h" #include "../macros.h"
namespace Tins { namespace Tins {
namespace Memory {
class InputMemoryStream;
class OutputMemoryStream;
} // Memory
class RSNInformation; class RSNInformation;
/** /**
* \brief Class representing an 802.11 frame. * \brief Class representing an 802.11 frame.
*/ */
class Dot11 : public PDU { class TINS_API Dot11 : public PDU {
public: public:
/** /**
* The type used to store hardware addresses. * The type used to store hardware addresses.
@@ -208,84 +213,108 @@ public:
* *
* \return The stored 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. * \brief Getter for the Type field.
* *
* \return The stored 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. * \brief Getter for the Subtype field.
* *
* \return The stored 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. * \brief Getter for the To-DS field.
* *
* \return The stored 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. * \brief Getter for the From-DS field.
* *
* \return The stored 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. * \brief Getter for the More-Frag field.
* *
* \return The stored 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. * \brief Getter for the Retry field.
* *
* \return The stored 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. * \brief Getter for the Power-Management field.
* *
* \return The stored 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. * \brief Getter for the WEP field.
* *
* \return The stored 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. * \brief Getter for the Order field.
* *
* \return The stored 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. * \brief Getter for the Duration-ID field.
* *
* \return The stored 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. * \brief Getter for the first address.
* *
* \return The stored first address. * \return The stored first address.
*/ */
address_type addr1() const { return _header.addr1; } address_type addr1() const {
return header_.addr1;
}
// Setters // Setters
@@ -382,12 +411,12 @@ public:
*/ */
uint32_t header_size() const; uint32_t header_size() const;
#ifndef WIN32 #ifndef _WIN32
/** /**
* \sa PDU::send() * \sa PDU::send()
*/ */
void send(PacketSender& sender, const NetworkInterface& iface); void send(PacketSender& sender, const NetworkInterface& iface);
#endif // WIN32 #endif // _WIN32
/** /**
* \brief Adds a new option to this Dot11 PDU. * \brief Adds a new option to this Dot11 PDU.
@@ -405,25 +434,38 @@ public:
*/ */
void add_option(option &&opt) { void add_option(option &&opt) {
internal_add_option(opt); internal_add_option(opt);
_options.push_back(std::move(opt)); options_.push_back(std::move(opt));
} }
#endif #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. * \brief Looks up a tagged option in the option list.
* *
* The returned pointer <b>must not</b> be free'd. * 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. * \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. * \brief Getter for the PDU's type.
* \sa PDU::pdu_type * \sa PDU::pdu_type
*/ */
PDUType pdu_type() const { return pdu_flag; } PDUType pdu_type() const {
return pdu_flag;
}
/** /**
* \sa PDU::clone * \sa PDU::clone
@@ -433,7 +475,7 @@ public:
} }
/** /**
* \brief Check wether this PDU matches the specified flag. * \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match * \param flag The flag to match
* \sa PDU::matches_flag * \sa PDU::matches_flag
*/ */
@@ -446,7 +488,9 @@ public:
* *
* \return The options list. * \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. * \brief Allocates an Dot11 PDU from a buffer.
@@ -464,16 +508,16 @@ public:
*/ */
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: protected:
virtual uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz) { return 0; } virtual void write_ext_header(Memory::OutputMemoryStream& stream) { }
virtual uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) { return 0; } virtual void write_fixed_parameters(Memory::OutputMemoryStream& stream) { }
void parse_tagged_parameters(const uint8_t *buffer, uint32_t total_sz); void parse_tagged_parameters(Memory::InputMemoryStream& stream);
void add_tagged_option(OptionTypes opt, uint8_t len, const uint8_t* val); void add_tagged_option(OptionTypes opt, uint8_t len, const uint8_t* val);
protected: protected:
/** /**
* Struct that represents the 802.11 header * Struct that represents the 802.11 header
*/ */
TINS_BEGIN_PACK TINS_BEGIN_PACK
struct ieee80211_header { struct dot11_header {
TINS_BEGIN_PACK TINS_BEGIN_PACK
struct { struct {
#if TINS_IS_LITTLE_ENDIAN #if TINS_IS_LITTLE_ENDIAN
@@ -507,16 +551,19 @@ protected:
} TINS_END_PACK; } TINS_END_PACK;
private: private:
Dot11(const ieee80211_header *header_ptr); Dot11(const dot11_header* header_ptr);
void internal_add_option(const option& opt); void internal_add_option(const option& opt);
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);
options_type::const_iterator search_option_iterator(OptionTypes type) const;
options_type::iterator search_option_iterator(OptionTypes type);
ieee80211_header _header; dot11_header header_;
uint32_t _options_size; uint32_t options_size_;
options_type _options; options_type options_;
}; };
}
} // Tins
#endif // TINS_DOT11_DOT11_H #endif // TINS_DOT11_DOT11_H

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -29,17 +29,19 @@
#include "../config.h" #include "../config.h"
#if !defined(TINS_DOT11_DOT11_BEACON_H) && defined(HAVE_DOT11) #if !defined(TINS_DOT11_DOT11_BEACON_H) && defined(TINS_HAVE_DOT11)
#define TINS_DOT11_DOT11_BEACON_H #define TINS_DOT11_DOT11_BEACON_H
#include "../dot11/dot11_mgmt.h" #include "../dot11/dot11_mgmt.h"
#include "../macros.h"
namespace Tins { namespace Tins {
/** /**
* \brief Class representing an 802.11 Beacon. * \brief Represents an IEEE 802.11 Beacon.
* *
*/ */
class Dot11Beacon : public Dot11ManagementFrame { class TINS_API Dot11Beacon : public Dot11ManagementFrame {
public: public:
/** /**
* \brief This PDU's flag. * \brief This PDU's flag.
@@ -79,14 +81,18 @@ namespace Tins {
* *
* \return The stored timestamp value. * \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. * \brief Getter for the interval field.
* *
* \return The stored interval value. * \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 structure. * \brief Getter for the Capabilities Information structure.
@@ -94,7 +100,9 @@ namespace Tins {
* \return A constant refereence to the stored Capabilities * \return A constant refereence to the stored Capabilities
* Information field. * Information field.
*/ */
const capability_information& capabilities() const { return _body.capability; } const capability_information& capabilities() const {
return body_.capability;
}
/** /**
* \brief Getter for the Capabilities Information. * \brief Getter for the Capabilities Information.
@@ -102,7 +110,9 @@ namespace Tins {
* \return A refereence to the stored Capabilities Information * \return A refereence to the stored Capabilities Information
* field. * field.
*/ */
capability_information& capabilities() { return _body.capability; } capability_information& capabilities() {
return body_.capability;
}
/** /**
* \brief Setter for the timestamp field. * \brief Setter for the timestamp field.
@@ -127,7 +137,7 @@ namespace Tins {
uint32_t header_size() const; uint32_t header_size() const;
/** /**
* \brief Check wether this PDU matches the specified flag. * \brief Check whether this PDU matches the specified flag.
* \param flag The flag to match * \param flag The flag to match
* \sa PDU::matches_flag * \sa PDU::matches_flag
*/ */
@@ -148,19 +158,22 @@ namespace Tins {
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* \sa PDU::pdu_type * \sa PDU::pdu_type
*/ */
PDUType pdu_type() const { return pdu_flag; } PDUType pdu_type() const {
return pdu_flag;
}
private: private:
TINS_BEGIN_PACK TINS_BEGIN_PACK
struct BeaconBody { struct dot11_beacon_body {
uint64_t timestamp; uint64_t timestamp;
uint16_t interval; uint16_t interval;
capability_information capability; capability_information capability;
} TINS_END_PACK; } TINS_END_PACK;
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz); void write_fixed_parameters(Memory::OutputMemoryStream& stream);
BeaconBody _body; dot11_beacon_body body_;
}; };
} // namespace Tins } // namespace Tins
#endif // TINS_DOT11_DOT11_BEACON_H #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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -29,17 +29,18 @@
#include "../config.h" #include "../config.h"
#if !defined(TINS_DOT11_DOT11_CONTROL_H) && defined(HAVE_DOT11) #if !defined(TINS_DOT11_DOT11_CONTROL_H) && defined(TINS_HAVE_DOT11)
#define TINS_DOT11_DOT11_CONTROL_H #define TINS_DOT11_DOT11_CONTROL_H
#include "../dot11/dot11_base.h" #include "../dot11/dot11_base.h"
#include "../macros.h"
namespace Tins { 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: public:
/** /**
* \brief This PDU's flag. * \brief This PDU's flag.
@@ -76,15 +77,17 @@ public:
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* \sa PDU::pdu_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 * \param flag The flag to match
* \sa PDU::matches_flag * \sa PDU::matches_flag
*/ */
bool matches_flag(PDUType flag) const { bool matches_flag(PDUType flag) const {
return flag == PDU::DOT11_CONTROL || Dot11::matches_flag(flag); return flag == pdu_flag || Dot11::matches_flag(flag);
} }
}; };
@@ -92,12 +95,14 @@ public:
* \brief Class that represents an abstraction of the 802.11 control frames * \brief Class that represents an abstraction of the 802.11 control frames
* that contain a target address. * that contain a target address.
*/ */
class Dot11ControlTA : public Dot11Control { class TINS_API Dot11ControlTA : public Dot11Control {
public: public:
/** /**
* \brief Getter for the target address field. * \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. * \brief Setter for the target address field.
@@ -144,18 +149,20 @@ protected:
/** /**
* \brief Getter for the control ta additional fields size. * \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: private:
address_type _taddr; address_type taddr_;
}; };
/** /**
* \brief IEEE 802.11 RTS frame. * \brief IEEE 802.11 RTS frame.
*/ */
class Dot11RTS : public Dot11ControlTA { class TINS_API Dot11RTS : public Dot11ControlTA {
public: public:
/** /**
* \brief This PDU's flag. * \brief This PDU's flag.
@@ -202,10 +209,12 @@ public:
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* \sa PDU::pdu_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 * \param flag The flag to match
* \sa PDU::matches_flag * \sa PDU::matches_flag
*/ */
@@ -214,7 +223,7 @@ public:
} }
}; };
class Dot11PSPoll : public Dot11ControlTA { class TINS_API Dot11PSPoll : public Dot11ControlTA {
public: public:
/** /**
* \brief This PDU's flag. * \brief This PDU's flag.
@@ -262,10 +271,12 @@ public:
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* \sa PDU::pdu_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 * \param flag The flag to match
* \sa PDU::matches_flag * \sa PDU::matches_flag
*/ */
@@ -274,7 +285,7 @@ public:
} }
}; };
class Dot11CFEnd : public Dot11ControlTA { class TINS_API Dot11CFEnd : public Dot11ControlTA {
public: public:
/** /**
* \brief This PDU's flag. * \brief This PDU's flag.
@@ -322,10 +333,12 @@ public:
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* \sa PDU::pdu_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 * \param flag The flag to match
* \sa PDU::matches_flag * \sa PDU::matches_flag
*/ */
@@ -334,7 +347,7 @@ public:
} }
}; };
class Dot11EndCFAck : public Dot11ControlTA { class TINS_API Dot11EndCFAck : public Dot11ControlTA {
public: public:
/** /**
* \brief This PDU's flag. * \brief This PDU's flag.
@@ -382,10 +395,12 @@ public:
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* \sa PDU::pdu_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 * \param flag The flag to match
* \sa PDU::matches_flag * \sa PDU::matches_flag
*/ */
@@ -394,7 +409,7 @@ public:
} }
}; };
class Dot11Ack : public Dot11Control { class TINS_API Dot11Ack : public Dot11Control {
public: public:
/** /**
* \brief This PDU's flag. * \brief This PDU's flag.
@@ -440,10 +455,12 @@ public:
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* \sa PDU::pdu_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 * \param flag The flag to match
* \sa PDU::matches_flag * \sa PDU::matches_flag
*/ */
@@ -455,7 +472,7 @@ public:
/** /**
* \brief Class that represents an 802.11 Block Ack Request PDU. * \brief Class that represents an 802.11 Block Ack Request PDU.
*/ */
class Dot11BlockAckRequest : public Dot11ControlTA { class TINS_API Dot11BlockAckRequest : public Dot11ControlTA {
public: public:
/** /**
* \brief This PDU's flag. * \brief This PDU's flag.
@@ -498,9 +515,9 @@ public:
*/ */
small_uint<4> bar_control() const { small_uint<4> bar_control() const {
#if TINS_IS_LITTLE_ENDIAN #if TINS_IS_LITTLE_ENDIAN
return _bar_control & 0xf; return bar_control_ & 0xf;
#else #else
return (_bar_control >> 8) & 0xf; return (bar_control_ >> 8) & 0xf;
#endif #endif
} }
@@ -510,9 +527,9 @@ public:
*/ */
small_uint<12> start_sequence() const { small_uint<12> start_sequence() const {
#if TINS_IS_LITTLE_ENDIAN #if TINS_IS_LITTLE_ENDIAN
return (_start_sequence >> 4) & 0xfff; return (start_sequence_ >> 4) & 0xfff;
#else #else
return (Endian::le_to_host<uint16_t>(_start_sequence) >> 4) & 0xfff; return (Endian::le_to_host<uint16_t>(start_sequence_) >> 4) & 0xfff;
#endif #endif
} }
@@ -522,9 +539,9 @@ public:
*/ */
small_uint<4> fragment_number() const { small_uint<4> fragment_number() const {
#if TINS_IS_LITTLE_ENDIAN #if TINS_IS_LITTLE_ENDIAN
return _start_sequence & 0xf; return start_sequence_ & 0xf;
#else #else
return (_start_sequence >> 8) & 0xf; return (start_sequence_ >> 8) & 0xf;
#endif #endif
} }
@@ -569,10 +586,12 @@ public:
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* \sa PDU::pdu_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 * \param flag The flag to match
* \sa PDU::matches_flag * \sa PDU::matches_flag
*/ */
@@ -580,18 +599,16 @@ public:
return flag == pdu_flag || Dot11Control::matches_flag(flag); return flag == pdu_flag || Dot11Control::matches_flag(flag);
} }
protected: protected:
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz); void write_ext_header(Memory::OutputMemoryStream& stream);
private: 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. * \brief Class that represents an 802.11 block ack frame.
*/ */
class Dot11BlockAck : public Dot11ControlTA { class TINS_API Dot11BlockAck : public Dot11ControlTA {
public: public:
/** /**
* \brief This PDU's flag. * \brief This PDU's flag.
@@ -639,9 +656,9 @@ public:
*/ */
small_uint<4> bar_control() const { small_uint<4> bar_control() const {
#if TINS_IS_LITTLE_ENDIAN #if TINS_IS_LITTLE_ENDIAN
return _bar_control & 0xf; return bar_control_ & 0xf;
#else #else
return (_bar_control >> 8) & 0xf; return (bar_control_ >> 8) & 0xf;
#endif #endif
} }
@@ -651,9 +668,9 @@ public:
*/ */
small_uint<12> start_sequence() const { small_uint<12> start_sequence() const {
#if TINS_IS_LITTLE_ENDIAN #if TINS_IS_LITTLE_ENDIAN
return (_start_sequence >> 4) & 0xfff; return (start_sequence_ >> 4) & 0xfff;
#else #else
return (Endian::le_to_host<uint16_t>(_start_sequence) >> 4) & 0xfff; return (Endian::le_to_host<uint16_t>(start_sequence_) >> 4) & 0xfff;
#endif #endif
} }
@@ -663,9 +680,9 @@ public:
*/ */
small_uint<4> fragment_number() const { small_uint<4> fragment_number() const {
#if TINS_IS_LITTLE_ENDIAN #if TINS_IS_LITTLE_ENDIAN
return _start_sequence & 0xf; return start_sequence_ & 0xf;
#else #else
return (_start_sequence >> 8) & 0xf; return (start_sequence_ >> 8) & 0xf;
#endif #endif
} }
@@ -704,7 +721,9 @@ public:
* *
* \return The bitmap field. * \return The bitmap field.
*/ */
const uint8_t *bitmap() const { return _bitmap; } const uint8_t* bitmap() const {
return bitmap_;
}
/** /**
* \brief Setter for the bitmap field. * \brief Setter for the bitmap field.
@@ -716,10 +735,12 @@ public:
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* \sa PDU::pdu_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 * \param flag The flag to match
* \sa PDU::matches_flag * \sa PDU::matches_flag
*/ */
@@ -736,11 +757,12 @@ public:
return new Dot11BlockAck(*this); return new Dot11BlockAck(*this);
} }
private: private:
void init_block_ack(); void write_ext_header(Memory::OutputMemoryStream& stream);
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
uint16_t _bar_control, _start_sequence; uint16_t bar_control_, start_sequence_;
uint8_t _bitmap[bitmap_size]; uint8_t bitmap_[bitmap_size];
}; };
} // namespace Tins } // namespace Tins
#endif // TINS_DOT11_DOT11_CONTROL_H #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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -29,13 +29,18 @@
#include "../config.h" #include "../config.h"
#if !defined(TINS_DOT11_DOT11_DATA_H) && defined(HAVE_DOT11) #if !defined(TINS_DOT11_DOT11_DATA_H) && defined(TINS_HAVE_DOT11)
#define TINS_DOT11_DOT11_DATA_H #define TINS_DOT11_DOT11_DATA_H
#include "../dot11/dot11_base.h" #include "../dot11/dot11_base.h"
#include "../macros.h"
namespace Tins { namespace Tins {
class Dot11Data : public Dot11 {
/**
* \brief Represents an IEEE 802.11 data frame
*/
class TINS_API Dot11Data : public Dot11 {
public: public:
/** /**
* \brief This PDU's flag. * \brief This PDU's flag.
@@ -75,14 +80,18 @@ public:
* *
* \return The stored 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. * \brief Getter for the third address.
* *
* \return The stored 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. * \brief Getter for the fragment number field.
@@ -91,9 +100,9 @@ public:
*/ */
small_uint<4> frag_num() const { small_uint<4> frag_num() const {
#if TINS_IS_LITTLE_ENDIAN #if TINS_IS_LITTLE_ENDIAN
return _ext_header.frag_seq & 0xf; return ext_header_.frag_seq & 0xf;
#else #else
return (_ext_header.frag_seq >> 8) & 0xf; return (ext_header_.frag_seq >> 8) & 0xf;
#endif #endif
} }
@@ -104,9 +113,9 @@ public:
*/ */
small_uint<12> seq_num() const { small_uint<12> seq_num() const {
#if TINS_IS_LITTLE_ENDIAN #if TINS_IS_LITTLE_ENDIAN
return (_ext_header.frag_seq >> 4) & 0xfff; return (ext_header_.frag_seq >> 4) & 0xfff;
#else #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 #endif
} }
@@ -115,7 +124,9 @@ public:
* *
* \return The fourth address. * \return The fourth address.
*/ */
address_type addr4() const { return _addr4; } address_type addr4() const {
return addr4_;
}
/** /**
* \brief Setter for the second address. * \brief Setter for the second address.
@@ -161,10 +172,12 @@ public:
* If FromDS == ToDS == 1, the return value is not defined. * If FromDS == ToDS == 1, the return value is not defined.
*/ */
address_type src_addr() const { address_type src_addr() const {
if(!from_ds() && !to_ds()) if (!from_ds() && !to_ds()) {
return addr2(); return addr2();
if(!from_ds() && to_ds()) }
if (!from_ds() && to_ds()) {
return addr2(); return addr2();
}
return addr3(); return addr3();
} }
@@ -177,10 +190,12 @@ public:
* If FromDS == ToDS == 1, the return value is not defined. * If FromDS == ToDS == 1, the return value is not defined.
*/ */
address_type dst_addr() const { address_type dst_addr() const {
if(!from_ds() && !to_ds()) if (!from_ds() && !to_ds()) {
return addr1(); return addr1();
if(!from_ds() && to_ds()) }
if (!from_ds() && to_ds()) {
return addr3(); return addr3();
}
return addr1(); return addr1();
} }
@@ -193,10 +208,12 @@ public:
* If FromDS == ToDS == 1, the return value is not defined. * If FromDS == ToDS == 1, the return value is not defined.
*/ */
address_type bssid_addr() const { address_type bssid_addr() const {
if(!from_ds() && !to_ds()) if (!from_ds() && !to_ds()) {
return addr3(); return addr3();
if(!from_ds() && to_ds()) }
if (!from_ds() && to_ds()) {
return addr1(); return addr1();
}
return addr2(); return addr2();
} }
@@ -212,10 +229,12 @@ public:
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* \sa PDU::pdu_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 * \param flag The flag to match
* \sa PDU::matches_flag * \sa PDU::matches_flag
*/ */
@@ -233,7 +252,7 @@ public:
} }
protected: protected:
TINS_BEGIN_PACK TINS_BEGIN_PACK
struct ExtendedHeader { struct dot11_extended_header {
uint8_t addr2[address_type::address_size]; uint8_t addr2[address_type::address_size];
uint8_t addr3[address_type::address_size]; uint8_t addr3[address_type::address_size];
uint16_t frag_seq; uint16_t frag_seq;
@@ -243,18 +262,13 @@ protected:
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 init(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 data_frame_size() {
return Dot11::header_size() + sizeof(_ext_header) +
((from_ds() && to_ds()) ? _addr4.size() : 0);
}
private: private:
ExtendedHeader _ext_header; dot11_extended_header ext_header_;
address_type _addr4; address_type addr4_;
}; };
class Dot11QoSData : public Dot11Data { class TINS_API Dot11QoSData : public Dot11Data {
public: public:
/** /**
* \brief This PDU's flag. * \brief This PDU's flag.
@@ -294,7 +308,9 @@ public:
* *
* \return The stored QOS Control field value. * \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. * \brief Setter for the QOS Control field.
@@ -324,21 +340,22 @@ public:
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* \sa PDU::pdu_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 * \param flag The flag to match
* \sa PDU::matches_flag * \sa PDU::matches_flag
*/ */
bool matches_flag(PDUType flag) const { 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: 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -29,19 +29,20 @@
#include "../config.h" #include "../config.h"
#if !defined(TINS_DOT11_DOT11_MGMT_H) && defined(HAVE_DOT11) #if !defined(TINS_DOT11_DOT11_MGMT_H) && defined(TINS_HAVE_DOT11)
#define TINS_DOT11_DOT11_MGMT_H #define TINS_DOT11_DOT11_MGMT_H
#include <vector> #include <vector>
#include <utility> #include <utility>
#include "../dot11/dot11_base.h" #include "../dot11/dot11_base.h"
#include "../macros.h"
namespace Tins { 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: public:
/** /**
* The supported rates container type. * The supported rates container type.
@@ -53,6 +54,11 @@ public:
*/ */
typedef std::vector<std::pair<uint8_t, uint8_t> > channels_type; 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. * The requested information container type.
*/ */
@@ -63,6 +69,12 @@ public:
*/ */
static const PDU::PDUType pdu_flag = PDU::DOT11_MANAGEMENT; 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 { enum ReasonCodes {
UNSPECIFIED = 1, UNSPECIFIED = 1,
PREV_AUTH_NOT_VALID = 2, PREV_AUTH_NOT_VALID = 2,
@@ -98,6 +110,21 @@ public:
PEER_STA_NOT_SUPPORT_CIPHER = 45 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. * Represents the IEEE 802.11 frames' capability information.
*/ */
@@ -105,39 +132,39 @@ public:
class capability_information { class capability_information {
private: private:
#if TINS_IS_LITTLE_ENDIAN #if TINS_IS_LITTLE_ENDIAN
uint16_t _ess:1, uint16_t ess_:1,
_ibss:1, ibss_:1,
_cf_poll:1, cf_poll_:1,
_cf_poll_req:1, cf_poll_req_:1,
_privacy:1, privacy_:1,
_short_preamble:1, short_preamble_:1,
_pbcc:1, pbcc_:1,
_channel_agility:1, channel_agility_:1,
_spectrum_mgmt:1, spectrum_mgmt_:1,
_qos:1, qos_:1,
_sst:1, sst_:1,
_apsd:1, apsd_:1,
_reserved:1, radio_measurement_:1,
_dsss_ofdm:1, dsss_ofdm_:1,
_delayed_block_ack:1, delayed_block_ack_:1,
_immediate_block_ack:1; immediate_block_ack_:1;
#elif TINS_IS_BIG_ENDIAN #elif TINS_IS_BIG_ENDIAN
uint16_t _channel_agility:1, uint16_t channel_agility_:1,
_pbcc:1, pbcc_:1,
_short_preamble:1, short_preamble_:1,
_privacy:1, privacy_:1,
_cf_poll_req:1, cf_poll_req_:1,
_cf_poll:1, cf_poll_:1,
_ibss:1, ibss_:1,
_ess:1, ess_:1,
_immediate_block_ack:1, immediate_block_ack_:1,
_delayed_block_ack:1, delayed_block_ack_:1,
_dsss_ofdm:1, dsss_ofdm_:1,
_reserved:1, radio_measurement_:1,
_apsd:1, apsd_:1,
_sst:1, sst_:1,
_qos:1, qos_:1,
_spectrum_mgmt:1; spectrum_mgmt_:1;
#endif #endif
public: public:
/** /**
@@ -145,225 +172,288 @@ public:
* *
* \return Bool indicating the flag's value. * \return Bool indicating the flag's value.
*/ */
bool ess() const { return _ess; } bool ess() const {
return ess_;
}
/** /**
* \brief Getter for the ibss flag. * \brief Getter for the ibss flag.
* *
* \return Bool indicating the flag's value. * \return Bool indicating the flag's value.
*/ */
bool ibss() const { return _ibss; } bool ibss() const {
return ibss_;
}
/** /**
* \brief Getter for the cf_poll flag. * \brief Getter for the cf_poll flag.
* *
* \return Bool indicating the flag's value. * \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. * \brief Getter for the cf_poll_req flag.
* *
* \return Bool indicating the flag's value. * \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. * \brief Getter for the privacy flag.
* *
* \return Bool indicating the flag's value. * \return Bool indicating the flag's value.
*/ */
bool privacy() const { return _privacy; } bool privacy() const {
return privacy_;
}
/** /**
* \brief Getter for the short_preamble flag. * \brief Getter for the short_preamble flag.
* *
* \return Bool indicating the flag's value. * \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. * \brief Getter for the pbcc flag.
* *
* \return Bool indicating the flag's value. * \return Bool indicating the flag's value.
*/ */
bool pbcc() const { return _pbcc; } bool pbcc() const {
return pbcc_;
}
/** /**
* \brief Getter for the channel_agility flag. * \brief Getter for the channel_agility flag.
* *
* \return Bool indicating the flag's value. * \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. * \brief Getter for the spectrum_mgmt flag.
* *
* \return Bool indicating the flag's value. * \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. * \brief Getter for the qos flag.
* *
* \return Bool indicating the flag's value. * \return Bool indicating the flag's value.
*/ */
bool qos() const { return _qos; } bool qos() const {
return qos_;
}
/** /**
* \brief Getter for the sst flag. * \brief Getter for the sst flag.
* *
* \return Bool indicating the flag's value. * \return Bool indicating the flag's value.
*/ */
bool sst() const { return _sst; } bool sst() const {
return sst_;
}
/** /**
* \brief Getter for the apsd flag. * \brief Getter for the apsd flag.
* *
* \return Bool indicating the flag's value. * \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. * \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. * \brief Getter for the dsss_ofdm flag.
* *
* \return Bool indicating the flag's value. * \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. * \brief Getter for the delayed_block_ack flag.
* *
* \return Bool indicating the flag's value. * \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. * \brief Getter for the immediate_block_ack flag.
* *
* \return Bool indicating the flag's value. * \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. * \brief Setter for the ess flag.
* *
* \param new_value bool indicating the flag's new value. * \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. * \brief Setter for the ibss flag.
* *
* \param new_value bool indicating the flag's new value. * \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. * \brief Setter for the cf_poll flag.
* *
* \param new_value bool indicating the flag's new value. * \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. * \brief Setter for the cf_poll_req flag.
* *
* \param new_value bool indicating the flag's new value. * \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. * \brief Setter for the privacy flag.
* *
* \param new_value bool indicating the flag's new value. * \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. * \brief Setter for the short_preamble flag.
* *
* \param new_value bool indicating the flag's new value. * \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. * \brief Setter for the pbcc flag.
* *
* \param new_value bool indicating the flag's new value. * \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. * \brief Setter for the channel_agility flag.
* *
* \param new_value bool indicating the flag's new value. * \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. * \brief Setter for the spectrum_mgmt flag.
* *
* \param new_value bool indicating the flag's new value. * \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. * \brief Setter for the qos flag.
* *
* \param new_value bool indicating the flag's new value. * \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. * \brief Setter for the sst flag.
* *
* \param new_value bool indicating the flag's new value. * \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. * \brief Setter for the apsd flag.
* *
* \param new_value bool indicating the flag's new value. * \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. * \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. * \brief Setter for the dsss_ofdm flag.
* *
* \param new_value bool indicating the flag's new value. * \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. * \brief Setter for the delayed_block_ack flag.
* *
* \param new_value bool indicating the flag's new value. * \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. * \brief Setter for the immediate_block_ack flag.
* *
* \param new_value bool indicating the flag's new value. * \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; } TINS_END_PACK;
/** /**
@@ -375,8 +465,10 @@ public:
fh_params_set() {} fh_params_set() {}
fh_params_set(uint16_t dwell_time, uint8_t hop_set, fh_params_set(uint16_t dwell_time,
uint8_t hop_pattern, uint8_t hop_index) uint8_t hop_set,
uint8_t hop_pattern,
uint8_t hop_index)
: dwell_time(dwell_time), hop_set(hop_set), : dwell_time(dwell_time), hop_set(hop_set),
hop_pattern(hop_pattern), hop_index(hop_index) {} hop_pattern(hop_pattern), hop_index(hop_index) {}
@@ -392,8 +484,10 @@ public:
cf_params_set() {} cf_params_set() {}
cf_params_set(uint8_t cfp_count, uint8_t cfp_period, cf_params_set(uint8_t cfp_count,
uint16_t cfp_max_duration, uint16_t cfp_dur_remaining) uint8_t cfp_period,
uint16_t cfp_max_duration,
uint16_t cfp_dur_remaining)
: cfp_count(cfp_count), cfp_period(cfp_period), : cfp_count(cfp_count), cfp_period(cfp_period),
cfp_max_duration(cfp_max_duration), cfp_max_duration(cfp_max_duration),
cfp_dur_remaining(cfp_dur_remaining) {} cfp_dur_remaining(cfp_dur_remaining) {}
@@ -409,14 +503,15 @@ public:
address_type dfs_owner; address_type dfs_owner;
uint8_t recovery_interval; uint8_t recovery_interval;
channels_type channel_map; channel_map_type channel_map;
ibss_dfs_params() {} ibss_dfs_params() {}
ibss_dfs_params(const address_type& addr, ibss_dfs_params(const address_type& addr,
uint8_t recovery_interval, const channels_type &channels) uint8_t recovery_interval,
const channel_map_type& channel_map)
: dfs_owner(addr), recovery_interval(recovery_interval), : 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,8 +528,10 @@ public:
country_params() {} country_params() {}
country_params(const std::string &country, const byte_array &first, country_params(const std::string& country,
const byte_array &number, const byte_array &max) const byte_array& first,
const byte_array& number,
const byte_array& max)
: country(country), first_channel(first), number_channels(number), : country(country), first_channel(first), number_channels(number),
max_transmit_power(max) {} max_transmit_power(max) {}
@@ -452,8 +549,11 @@ public:
fh_pattern_type() {} fh_pattern_type() {}
fh_pattern_type(uint8_t flag, uint8_t sets, uint8_t modulus, fh_pattern_type(uint8_t flag,
uint8_t offset, const byte_array& table) uint8_t sets,
uint8_t modulus,
uint8_t offset,
const byte_array& table)
: flag(flag), number_of_sets(sets), modulus(modulus), : flag(flag), number_of_sets(sets), modulus(modulus),
offset(offset), random_table(table) {} offset(offset), random_table(table) {}
@@ -468,7 +568,9 @@ public:
channel_switch_type() {} 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) { } : 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,7 +585,9 @@ public:
quiet_type() {} quiet_type() {}
quiet_type(uint8_t count, uint8_t period, uint16_t duration, quiet_type(uint8_t count,
uint8_t period,
uint16_t duration,
uint16_t offset) uint16_t offset)
: quiet_count(count), quiet_period(period), : quiet_count(count), quiet_period(period),
quiet_duration(duration), quiet_offset(offset) {} quiet_duration(duration), quiet_offset(offset) {}
@@ -501,8 +605,7 @@ public:
bss_load_type() {} bss_load_type() {}
bss_load_type(uint16_t count, uint8_t utilization, bss_load_type(uint16_t count, uint8_t utilization, uint16_t capacity)
uint16_t capacity)
: station_count(count), available_capacity(capacity), : station_count(count), available_capacity(capacity),
channel_utilization(utilization) {} channel_utilization(utilization) {}
@@ -518,7 +621,9 @@ public:
tim_type() {} tim_type() {}
tim_type(uint8_t count, uint8_t period, uint8_t control, tim_type(uint8_t count,
uint8_t period,
uint8_t control,
const byte_array& bitmap) const byte_array& bitmap)
: dtim_count(count), dtim_period(period), bitmap_control(control), : dtim_count(count), dtim_period(period), bitmap_control(control),
partial_virtual_bitmap(bitmap) {} partial_virtual_bitmap(bitmap) {}
@@ -552,14 +657,18 @@ public:
* *
* \return address_type containing the second address. * \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. * \brief Getter for the third address.
* *
* \return address_type containing 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. * \brief Getter for the fragment number.
@@ -568,9 +677,9 @@ public:
*/ */
small_uint<4> frag_num() const { small_uint<4> frag_num() const {
#if TINS_IS_LITTLE_ENDIAN #if TINS_IS_LITTLE_ENDIAN
return _ext_header.frag_seq & 0xf; return ext_header_.frag_seq & 0xf;
#else #else
return (_ext_header.frag_seq >> 8) & 0xf; return (ext_header_.frag_seq >> 8) & 0xf;
#endif #endif
} }
@@ -581,9 +690,9 @@ public:
*/ */
small_uint<12> seq_num() const { small_uint<12> seq_num() const {
#if TINS_IS_LITTLE_ENDIAN #if TINS_IS_LITTLE_ENDIAN
return (_ext_header.frag_seq >> 4) & 0xfff; return (ext_header_.frag_seq >> 4) & 0xfff;
#else #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 #endif
} }
@@ -592,7 +701,9 @@ public:
* *
* \return The stored fourth address. * \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. * \brief Setter for the second address.
@@ -834,7 +945,7 @@ public:
* *
* \return std::string containing the ssid. * \return std::string containing the ssid.
*/ */
RSNInformation rsn_information(); RSNInformation rsn_information() const;
/** /**
* \brief Helper method to search for this PDU's SSID. * \brief Helper method to search for this PDU's SSID.
@@ -1096,10 +1207,12 @@ public:
* *
* \sa PDU::pdu_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 * \param flag The flag to match
* \sa PDU::matches_flag * \sa PDU::matches_flag
*/ */
@@ -1108,7 +1221,7 @@ public:
} }
protected: protected:
TINS_BEGIN_PACK TINS_BEGIN_PACK
struct ExtendedHeader { struct dot11_extended_header {
uint8_t addr2[address_type::address_size]; uint8_t addr2[address_type::address_size];
uint8_t addr3[address_type::address_size]; uint8_t addr3[address_type::address_size];
uint16_t frag_seq; uint16_t frag_seq;
@@ -1134,27 +1247,28 @@ protected:
*/ */
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() { uint32_t management_frame_size() {
return sizeof(ieee80211_header) + sizeof(_ext_header) + return Dot11ManagementFrame::header_size();
((from_ds() && to_ds()) ? address_type::address_size : 0);
} }
private: private:
static uint8_t *serialize_rates(const rates_type &rates); static std::vector<uint8_t> serialize_rates(const rates_type& rates);
static rates_type deserialize_rates(const option* option); static rates_type deserialize_rates(const option* option);
template<typename T> template<typename T>
T search_and_convert(OptionTypes opt_type) const { T search_and_convert(OptionTypes opt_type) const {
const option* opt = search_option(opt_type); const option* opt = search_option(opt_type);
if(!opt) if (!opt) {
throw option_not_found(); throw option_not_found();
}
return opt->to<T>(); return opt->to<T>();
} }
ExtendedHeader _ext_header; dot11_extended_header ext_header_;
address_type _addr4; address_type addr4_;
}; };
} // namespace Tins } // namespace Tins
#endif // TINS_DOT11_DOT11_MGMT_H #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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -29,18 +29,19 @@
#include "../config.h" #include "../config.h"
#if !defined(TINS_DOT11_DOT11_PROBE_H) && defined(HAVE_DOT11) #if !defined(TINS_DOT11_DOT11_PROBE_H) && defined(TINS_HAVE_DOT11)
#define TINS_DOT11_DOT11_PROBE_H #define TINS_DOT11_DOT11_PROBE_H
#include "../dot11/dot11_mgmt.h" #include "../dot11/dot11_mgmt.h"
#include "../macros.h"
namespace Tins { namespace Tins {
/** /**
* \brief Class representing an Probe Request frame in the IEEE 802.11 Protocol. * \brief Class representing an Probe Request frame in the IEEE 802.11 Protocol.
* *
*/ */
class Dot11ProbeRequest : public Dot11ManagementFrame { class TINS_API Dot11ProbeRequest : public Dot11ManagementFrame {
public: public:
/** /**
* \brief This PDU's flag. * \brief This PDU's flag.
@@ -79,10 +80,12 @@ public:
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* \sa PDU::pdu_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 * \param flag The flag to match
* \sa PDU::matches_flag * \sa PDU::matches_flag
*/ */
@@ -105,7 +108,7 @@ public:
* \brief Class representing an Probe Response frame in the IEEE 802.11 Protocol. * \brief Class representing an Probe Response frame in the IEEE 802.11 Protocol.
* *
*/ */
class Dot11ProbeResponse : public Dot11ManagementFrame { class TINS_API Dot11ProbeResponse : public Dot11ManagementFrame {
public: public:
/** /**
* \brief This PDU's flag. * \brief This PDU's flag.
@@ -145,14 +148,18 @@ public:
* *
* \return The stored timestamp value. * \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. * \brief Getter for the interval field.
* *
* \return The stored interval value. * \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. * \brief Getter for the Capabilities Information.
@@ -160,7 +167,9 @@ public:
* \return A constant reference to the stored Capabilities * \return A constant reference to the stored Capabilities
* Information field. * Information field.
*/ */
const capability_information& capabilities() const { return _body.capability;} const capability_information& capabilities() const {
return body_.capability;
}
/** /**
* \brief Getter for the Capabilities Information. * \brief Getter for the Capabilities Information.
@@ -168,7 +177,9 @@ public:
* \return A reference to the stored Capabilities Information * \return A reference to the stored Capabilities Information
* field. * field.
*/ */
capability_information& capabilities() { return _body.capability;} capability_information& capabilities() {
return body_.capability;
}
/** /**
* \brief Setter for the timestamp field. * \brief Setter for the timestamp field.
@@ -208,26 +219,26 @@ public:
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 * \param flag The flag to match
* \sa PDU::matches_flag * \sa PDU::matches_flag
*/ */
bool matches_flag(PDUType flag) const { bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag); return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
} }
protected:
private: private:
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
TINS_BEGIN_PACK TINS_BEGIN_PACK
struct ProbeResp { struct dot11_probe_response_header {
uint64_t timestamp; uint64_t timestamp;
uint16_t interval; uint16_t interval;
capability_information capability; capability_information capability;
} TINS_END_PACK; } TINS_END_PACK;
ProbeResp _body; dot11_probe_response_header body_;
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
}; };
} // namespace Tins } // namespace Tins
#endif // TINS_DOT11_DOT11_PROBE_H #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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -31,21 +31,31 @@
#define TINS_DOT1Q_H #define TINS_DOT1Q_H
#include "pdu.h" #include "pdu.h"
#include "macros.h"
#include "endianness.h" #include "endianness.h"
#include "small_uint.h" #include "small_uint.h"
namespace Tins { namespace Tins {
/** /**
* \class Dot1Q * \class Dot1Q
* Represents an IEEE 802.1q PDU. * Represents an IEEE 802.1q PDU.
*/ */
class Dot1Q : public PDU { class TINS_API Dot1Q : public PDU {
public: public:
/** /**
* This PDU's flag. * This PDU's flag.
*/ */
static const PDU::PDUType pdu_flag = PDU::DOT1Q; static const PDU::PDUType pdu_flag = PDU::DOT1Q;
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/** /**
* Default constructor * Default constructor
*/ */
@@ -71,7 +81,7 @@ public:
/** /**
* \brief Returns the header size. * \brief Returns the header size.
* *
* This metod overrides PDU::header_size. \sa PDU::header_size * This method overrides PDU::header_size. \sa PDU::header_size
*/ */
uint32_t header_size() const; uint32_t header_size() const;
@@ -86,7 +96,7 @@ public:
* \return The stored priority field value. * \return The stored priority field value.
*/ */
small_uint<3> priority() const { small_uint<3> priority() const {
return _header.priority; return header_.priority;
} }
/** /**
@@ -94,7 +104,7 @@ public:
* \return The stored CFI field value. * \return The stored CFI field value.
*/ */
small_uint<1> cfi() const { small_uint<1> cfi() const {
return _header.cfi; return header_.cfi;
} }
/** /**
@@ -103,9 +113,9 @@ public:
*/ */
small_uint<12> id() const { small_uint<12> id() const {
#if TINS_IS_LITTLE_ENDIAN #if TINS_IS_LITTLE_ENDIAN
return _header.idL | (_header.idH << 8); return header_.idL | (header_.idH << 8);
#else #else
return _header.id; return header_.id;
#endif #endif
} }
@@ -114,14 +124,16 @@ public:
* \return The stored type field value. * \return The stored type field value.
*/ */
uint16_t payload_type() const { 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. * \brief Getter for the PDU's type.
* \sa PDU::pdu_type * \sa PDU::pdu_type
*/ */
PDUType pdu_type() const { return pdu_flag; } PDUType pdu_type() const {
return pdu_flag;
}
/** /**
* \sa PDU::clone * \sa PDU::clone
@@ -135,7 +147,7 @@ public:
* appended at the end of this packet. * appended at the end of this packet.
*/ */
bool append_padding() const { bool append_padding() const {
return _append_padding; return append_padding_;
} }
// Setters // Setters
@@ -177,7 +189,7 @@ public:
void append_padding(bool value); 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 * \sa PDU::matches_response
* \param ptr The pointer to the buffer. * \param ptr The pointer to the buffer.
@@ -188,7 +200,7 @@ 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 TINS_BEGIN_PACK
struct dot1q_hdr { struct dot1q_header {
#if TINS_IS_BIG_ENDIAN #if TINS_IS_BIG_ENDIAN
uint16_t priority:3, uint16_t priority:3,
cfi:1, cfi:1,
@@ -203,10 +215,10 @@ private:
#endif #endif
} TINS_END_PACK; } TINS_END_PACK;
static uint16_t get_id(const dot1q_hdr *hdr); static uint16_t get_id(const dot1q_header* hdr);
dot1q_hdr _header; dot1q_header header_;
bool _append_padding; bool append_padding_;
}; };
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -33,6 +33,7 @@
#include <stdint.h> #include <stdint.h>
#include "macros.h" #include "macros.h"
#include "pdu.h" #include "pdu.h"
#include "config.h"
#include "endianness.h" #include "endianness.h"
#include "hw_address.h" #include "hw_address.h"
@@ -42,7 +43,7 @@ namespace Tins {
* \class Dot3 * \class Dot3
* \brief Class representing an IEEE 802.3 PDU. * \brief Class representing an IEEE 802.3 PDU.
*/ */
class Dot3 : public PDU { class TINS_API Dot3 : public PDU {
public: public:
/** /**
* \brief The address type. * \brief The address type.
@@ -59,6 +60,14 @@ namespace Tins {
*/ */
static const address_type BROADCAST; static const address_type BROADCAST;
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/** /**
* \brief Constructor for creating an Dot3 PDU * \brief Constructor for creating an Dot3 PDU
* *
@@ -90,45 +99,52 @@ namespace Tins {
* *
* \return The destination hardware address. * \return The destination hardware address.
*/ */
address_type dst_addr() const { return _eth.dst_mac; } address_type dst_addr() const {
return header_.dst_mac;
}
/** /**
* \brief Getter for the source hardware address. * \brief Getter for the source hardware address.
* *
* \return The source hardware address. * \return The source hardware address.
*/ */
address_type src_addr() const { return _eth.src_mac; } address_type src_addr() const {
return header_.src_mac;
}
/** /**
* \brief Getter for the length field. * \brief Getter for the length field.
* \return The length field value. * \return The length field value.
*/ */
uint16_t length() const { return Endian::be_to_host(_eth.length); }; uint16_t length() const {
return Endian::be_to_host(header_.length);
}
/* Setters */ /* Setters */
/** /**
* \brief Setter for the destination hardware address. * \brief Setter for the destination hardware address.
* *
* \param new_dst_mac The new destination hardware address. * \param address The new destination hardware address.
*/ */
void dst_addr(const address_type &new_dst_mac); void dst_addr(const address_type& address);
/** /**
* \brief Setter for the source hardware address. * \brief Setter for the source hardware address.
* *
* \param new_src_mac The new source hardware address. * \param address The new source hardware address.
*/ */
void src_addr(const address_type &new_src_mac); void src_addr(const address_type& address);
/** /**
* \brief Setter for the length field. * \brief Setter for the length field.
* *
* \param new_length uint16_t with the new value of the length field. * \param value The new value for the length field
*/ */
void length(uint16_t new_length); void length(uint16_t value);
// Virtual methods
/* Virtual methods */
/** /**
* \brief Returns the Dot3 frame's header length. * \brief Returns the Dot3 frame's header length.
* *
@@ -137,15 +153,15 @@ namespace Tins {
*/ */
uint32_t header_size() const; uint32_t header_size() const;
#ifndef WIN32 #if !defined(_WIN32) || defined(TINS_HAVE_PACKET_SENDER_PCAP_SENDPACKET)
/** /**
* \sa PDU::send() * \sa PDU::send()
*/ */
void send(PacketSender& sender, const NetworkInterface& iface); void send(PacketSender& sender, const NetworkInterface& iface);
#endif // WIN32 #endif // !_WIN32 || TINS_HAVE_PACKET_SENDER_PCAP_SENDPACKET
/** /**
* \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 * \sa PDU::matches_response
* \param ptr The pointer to the buffer. * \param ptr The pointer to the buffer.
@@ -153,12 +169,12 @@ namespace Tins {
*/ */
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const; bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
#ifndef WIN32 #ifndef _WIN32
/** /**
* \sa PDU::recv_response * \sa PDU::recv_response
*/ */
PDU* recv_response(PacketSender& sender, const NetworkInterface& iface); PDU* recv_response(PacketSender& sender, const NetworkInterface& iface);
#endif // WIN32 #endif // _WIN32
/** /**
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
@@ -177,7 +193,7 @@ namespace Tins {
* Struct that represents the Ethernet II header * Struct that represents the Ethernet II header
*/ */
TINS_BEGIN_PACK TINS_BEGIN_PACK
struct ethhdr { struct dot3_header {
uint8_t dst_mac[address_type::address_size]; uint8_t dst_mac[address_type::address_size];
uint8_t src_mac[address_type::address_size]; uint8_t src_mac[address_type::address_size];
uint16_t length; uint16_t length;
@@ -185,10 +201,9 @@ namespace Tins {
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);
dot3_header header_;
ethhdr _eth;
}; };
}
} // Tins
#endif // TINS_DOT3_H #endif // TINS_DOT3_H

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -36,8 +36,12 @@
#include "small_uint.h" #include "small_uint.h"
#include "endianness.h" #include "endianness.h"
namespace Tins { namespace Tins {
namespace Memory {
class OutputMemoryStream;
} // Memory
/** \cond /** \cond
* Forward declaration. Avoid header inclusion. * Forward declaration. Avoid header inclusion.
@@ -49,7 +53,7 @@ namespace Tins {
* \class EAPOL * \class EAPOL
* \brief Represents the EAP encapsulation over LAN. * \brief Represents the EAP encapsulation over LAN.
*/ */
class EAPOL : public PDU { class TINS_API EAPOL : public PDU {
public: public:
/** /**
* \brief This PDU's flag. * \brief This PDU's flag.
@@ -65,6 +69,14 @@ namespace Tins {
EAPOL_WPA = 254 EAPOL_WPA = 254
}; };
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/** /**
* \brief Static method to instantiate the correct EAPOL subclass * \brief Static method to instantiate the correct EAPOL subclass
* based on a raw buffer. * based on a raw buffer.
@@ -85,51 +97,59 @@ namespace Tins {
* \brief Getter for the version field. * \brief Getter for the version field.
* \return The version field. * \return The version field.
*/ */
uint8_t version() const { return _header.version; } uint8_t version() const {
return header_.version;
}
/** /**
* \brief Getter for the packet type field. * \brief Getter for the packet type field.
* \return The packet type field. * \return The packet type field.
*/ */
uint8_t packet_type() const { return _header.packet_type; } uint8_t packet_type() const {
return header_.packet_type;
}
/** /**
* \brief Getter for the length field. * \brief Getter for the length field.
* \return The length field. * \return The length field.
*/ */
uint16_t length() const { return Endian::be_to_host(_header.length); } uint16_t length() const {
return Endian::be_to_host(header_.length);
}
/** /**
* \brief Getter for the type field. * \brief Getter for the type field.
* \return The type field. * \return The type field.
*/ */
uint8_t type() const { return _header.type; } uint8_t type() const {
return header_.type;
}
/* Setters */ /* Setters */
/** /**
* \brief Sets the version field. * \brief Sets the version field.
* \param new_version The new version to be set. * \param value The new version to be set.
*/ */
void version(uint8_t new_version); void version(uint8_t value);
/** /**
* \brief Sets the packet type field. * \brief Sets the packet type field.
* \param new_ptype The new packet type to be set. * \param value The new packet type to be set.
*/ */
void packet_type(uint8_t new_ptype); void packet_type(uint8_t value);
/** /**
* \brief Sets the length field. * \brief Sets the length field.
* \param new_length The new length to be set. * \param value The new length to be set.
*/ */
void length(uint16_t new_length); void length(uint16_t value);
/** /**
* \brief Sets the type field. * \brief Sets the type field.
* \param new_type The new type to be set. * \param value The new type to be set.
*/ */
void type(uint8_t new_type); void type(uint8_t value);
/** /**
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
@@ -150,7 +170,7 @@ namespace Tins {
EAPOL(const uint8_t* buffer, uint32_t total_sz); EAPOL(const uint8_t* buffer, uint32_t total_sz);
TINS_BEGIN_PACK TINS_BEGIN_PACK
struct eapolhdr { struct eapol_header {
uint8_t version, packet_type; uint8_t version, packet_type;
uint16_t length; uint16_t length;
uint8_t type; uint8_t type;
@@ -163,7 +183,7 @@ namespace Tins {
* \param buffer The pointer in which to save the serialization. * \param buffer The pointer in which to save the serialization.
* \param total_sz The total size of the buffer. * \param total_sz The total size of the buffer.
*/ */
virtual void write_body(uint8_t *buffer, uint32_t total_sz) = 0; virtual void write_body(Memory::OutputMemoryStream& stream) = 0;
private: private:
/** /**
* \brief Serialices this EAPOL PDU. * \brief Serialices this EAPOL PDU.
@@ -173,7 +193,7 @@ namespace Tins {
*/ */
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);
eapolhdr _header; eapol_header header_;
}; };
@@ -181,7 +201,7 @@ namespace Tins {
/** /**
* \brief Class that represents the RC4 EAPOL PDU. * \brief Class that represents the RC4 EAPOL PDU.
*/ */
class RC4EAPOL : public EAPOL { class TINS_API RC4EAPOL : public EAPOL {
public: public:
/** /**
* The type used to store the key. * The type used to store the key.
@@ -225,94 +245,108 @@ namespace Tins {
* \brief Getter for the key length field. * \brief Getter for the key length field.
* \return The key length field. * \return The key length field.
*/ */
uint16_t key_length() const { return Endian::be_to_host(_header.key_length); } uint16_t key_length() const {
return Endian::be_to_host(header_.key_length);
}
/** /**
* \brief Getter for the replay counter field. * \brief Getter for the replay counter field.
* \return The replay counter field. * \return The replay counter field.
*/ */
uint64_t replay_counter() const { return Endian::be_to_host(_header.replay_counter); } uint64_t replay_counter() const {
return Endian::be_to_host(header_.replay_counter);
}
/** /**
* \brief Getter for the key IV field. * \brief Getter for the key IV field.
* \return The key IV field. * \return The key IV field.
*/ */
const uint8_t *key_iv() const { return _header.key_iv; } const uint8_t* key_iv() const {
return header_.key_iv;
}
/** /**
* \brief Getter for the key flag field. * \brief Getter for the key flag field.
* \return The key flag field. * \return The key flag field.
*/ */
small_uint<1> key_flag() const { return _header.key_flag; } small_uint<1> key_flag() const {
return header_.key_flag;
}
/** /**
* \brief Getter for the key index field. * \brief Getter for the key index field.
* \return The key index field. * \return The key index field.
*/ */
small_uint<7> key_index() const { return _header.key_index; } small_uint<7> key_index() const {
return header_.key_index;
}
/** /**
* \brief Getter for the key signature field. * \brief Getter for the key signature field.
* \return The key signature field. * \return The key signature field.
*/ */
const uint8_t *key_sign() const { return _header.key_sign; } const uint8_t* key_sign() const {
return header_.key_sign;
}
/** /**
* \brief Getter for the key field. * \brief Getter for the key field.
* \return The key field. * \return The key field.
*/ */
const key_type &key() const { return _key; } const key_type& key() const {
return key_;
}
/* Setters */ /* Setters */
/** /**
* \brief Sets the key length field. * \brief Sets the key length field.
* \param new_key_length The new key length to be set. * \param value The new key length to be set.
*/ */
void key_length(uint16_t new_key_length); void key_length(uint16_t value);
/** /**
* \brief Sets the replay counter field. * \brief Sets the replay counter field.
* \param new_replay_counter The new replay counter to be set. * \param value The new replay counter to be set.
*/ */
void replay_counter(uint64_t new_replay_counter); void replay_counter(uint64_t value);
/** /**
* \brief Sets the key IV field. * \brief Sets the key IV field.
* \param new_key_iv The new key IV to be set. * \param value The new key IV to be set.
*/ */
void key_iv(const uint8_t *new_key_iv); void key_iv(const uint8_t* value);
/** /**
* \brief Sets the key flag field. * \brief Sets the key flag field.
* \param new_key_flag The new key flag to be set. * \param value The new key flag to be set.
*/ */
void key_flag(small_uint<1> new_key_flag); void key_flag(small_uint<1> value);
/** /**
* \brief Sets the key index field. * \brief Sets the key index field.
* \param new_key_index The new key index to be set. * \param value The new key index to be set.
*/ */
void key_index(small_uint<7> new_key_index); void key_index(small_uint<7> value);
/** /**
* \brief Sets the key signature field. * \brief Sets the key signature field.
* \param new_key_sign The new key signature to be set. * \param value The new key signature to be set.
*/ */
void key_sign(const uint8_t *new_key_sign); void key_sign(const uint8_t* value);
/** /**
* \brief Sets the key field. * \brief Sets the key field.
* \param new_key The new key to be set. * \param value The new key to be set.
*/ */
void key(const key_type &new_key); void key(const key_type& value);
/* Virtual method override. */ /* Virtual method override. */
/** /**
* \brief Returns the header size. * \brief Returns the header size.
* *
* This metod overrides PDU::header_size. This size includes the * This method overrides PDU::header_size. This size includes the
* payload and options size. * payload and options size.
* *
* \sa PDU::header_size * \sa PDU::header_size
@@ -323,15 +357,17 @@ namespace Tins {
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* \return Returns the PDUType corresponding to the PDU. * \return Returns the PDUType corresponding to the PDU.
*/ */
PDUType pdu_type() const { return PDU::RC4EAPOL; } 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 * \param flag The flag to match
* \sa PDU::matches_flag * \sa PDU::matches_flag
*/ */
bool matches_flag(PDUType flag) const { bool matches_flag(PDUType flag) const {
return flag == PDU::RC4EAPOL || EAPOL::matches_flag(flag); return flag == pdu_flag || EAPOL::matches_flag(flag);
} }
/** /**
@@ -344,7 +380,7 @@ namespace Tins {
} }
private: private:
TINS_BEGIN_PACK TINS_BEGIN_PACK
struct rc4hdr { struct rc4_eapol_header {
uint16_t key_length; uint16_t key_length;
uint64_t replay_counter; uint64_t replay_counter;
uint8_t key_iv[key_iv_size]; uint8_t key_iv[key_iv_size];
@@ -353,18 +389,18 @@ namespace Tins {
uint8_t key_sign[16]; uint8_t key_sign[16];
} TINS_END_PACK; } TINS_END_PACK;
void write_body(uint8_t *buffer, uint32_t total_sz); void write_body(Memory::OutputMemoryStream& stream);
key_type _key; key_type key_;
rc4hdr _header; rc4_eapol_header header_;
}; };
/** /**
* \brief Class that represents the RSN EAPOL PDU. * \brief Class that represents the RSN EAPOL PDU.
*/ */
class RSNEAPOL : public EAPOL { class TINS_API RSNEAPOL : public EAPOL {
public: public:
/** /**
* The type used to store the key. * The type used to store the key.
@@ -423,121 +459,159 @@ namespace Tins {
* \brief Getter for the key length field. * \brief Getter for the key length field.
* \return The key length field. * \return The key length field.
*/ */
uint16_t key_length() const { return Endian::be_to_host(_header.key_length); } uint16_t key_length() const {
return Endian::be_to_host(header_.key_length);
}
/** /**
* \brief Getter for the replay counter field. * \brief Getter for the replay counter field.
* \return The replay counter field. * \return The replay counter field.
*/ */
uint64_t replay_counter() const { return Endian::be_to_host(_header.replay_counter); } uint64_t replay_counter() const {
return Endian::be_to_host(header_.replay_counter);
}
/** /**
* \brief Getter for the key IV field. * \brief Getter for the key IV field.
* \return The key IV field. * \return The key IV field.
*/ */
const uint8_t *key_iv() const { return _header.key_iv; } const uint8_t* key_iv() const {
return header_.key_iv;
}
/** /**
* \brief Getter for the nonce field. * \brief Getter for the nonce field.
* \return The nonce field. * \return The nonce field.
*/ */
const uint8_t *nonce() const { return _header.nonce; } const uint8_t* nonce() const {
return header_.nonce;
}
/** /**
* \brief Getter for the rsc field. * \brief Getter for the rsc field.
* \return The rsc field. * \return The rsc field.
*/ */
const uint8_t *rsc() const { return _header.rsc; } const uint8_t* rsc() const {
return header_.rsc;
}
/** /**
* \brief Getter for the id field. * \brief Getter for the id field.
* \return The id field. * \return The id field.
*/ */
const uint8_t *id() const { return _header.id; } const uint8_t* id() const {
return header_.id;
}
/** /**
* \brief Getter for the mic field. * \brief Getter for the mic field.
* \return The mic field. * \return The mic field.
*/ */
const uint8_t *mic() const { return _header.mic; } const uint8_t* mic() const {
return header_.mic;
}
/** /**
* \brief Getter for the wpa length field. * \brief Getter for the wpa length field.
* \return The wpa length field. * \return The wpa length field.
*/ */
uint16_t wpa_length() const { return Endian::be_to_host(_header.wpa_length); } uint16_t wpa_length() const {
return Endian::be_to_host(header_.wpa_length);
}
/** /**
* \brief Getter for the key field. * \brief Getter for the key field.
* \return The key field. * \return The key field.
*/ */
const key_type &key() const { return _key; } const key_type& key() const {
return key_;
}
/** /**
* \brief Getter for the key mic field. * \brief Getter for the key mic field.
* \return 1 if this EAPOL PDU contains a valid MIC, 0 otherwise. * \return 1 if this EAPOL PDU contains a valid MIC, 0 otherwise.
*/ */
small_uint<1> key_mic() const { return _header.key_mic; }; small_uint<1> key_mic() const {
return header_.key_mic;
}
/** /**
* \brief Getter for the secure field. * \brief Getter for the secure field.
* \return The secure field. * \return The secure field.
*/ */
small_uint<1> secure() const { return _header.secure; }; small_uint<1> secure() const {
return header_.secure;
}
/** /**
* \brief Getter for the error field. * \brief Getter for the error field.
* \return The error field. * \return The error field.
*/ */
small_uint<1> error() const { return _header.error; }; small_uint<1> error() const {
return header_.error;
}
/** /**
* \brief Getter for the request field. * \brief Getter for the request field.
* \return The request field. * \return The request field.
*/ */
small_uint<1> request() const { return _header.request; }; small_uint<1> request() const {
return header_.request;
}
/** /**
* \brief Getter for the encrypted field. * \brief Getter for the encrypted field.
* \return The encrypted field. * \return The encrypted field.
*/ */
small_uint<1> encrypted() const { return _header.encrypted; }; small_uint<1> encrypted() const {
return header_.encrypted;
}
/** /**
* \brief Getter for the key descriptor field. * \brief Getter for the key descriptor field.
* \return The key descriptor field. * \return The key descriptor field.
*/ */
small_uint<3> key_descriptor() const { return _header.key_descriptor; }; small_uint<3> key_descriptor() const {
return header_.key_descriptor;
}
/** /**
* \brief Getter for the key type field. * \brief Getter for the key type field.
* *
* \return 1 if this is a pairwise key, 0 otherwise. * \return 1 if this is a pairwise key, 0 otherwise.
*/ */
small_uint<1> key_t() const { return _header.key_t; }; small_uint<1> key_t() const {
return header_.key_t;
}
/** /**
* \brief Getter for the key_index field. * \brief Getter for the key_index field.
* \return The key_index field. * \return The key_index field.
*/ */
small_uint<2> key_index() const { return _header.key_index; }; small_uint<2> key_index() const {
return header_.key_index;
}
/** /**
* \brief Getter for the install field. * \brief Getter for the install field.
* \return The install field. * \return The install field.
*/ */
small_uint<1> install() const { return _header.install; }; small_uint<1> install() const {
return header_.install;
}
/** /**
* \brief Getter for the key_ack field. * \brief Getter for the key_ack field.
* \return The key_ack field. * \return The key_ack field.
*/ */
small_uint<1> key_ack() const { return _header.key_ack; }; small_uint<1> key_ack() const {
return header_.key_ack;
}
/** /**
* \brief Returns the header size. * \brief Returns the header size.
* *
* This metod overrides PDU::header_size. This size includes the * This method overrides PDU::header_size. This size includes the
* payload and options size. * payload and options size.
* *
* \sa PDU::header_size * \sa PDU::header_size
@@ -548,137 +622,153 @@ namespace Tins {
/** /**
* \brief Sets the key length field. * \brief Sets the key length field.
* \param new_key_length The new key length to be set. * \param value The new key length to be set.
*/ */
void key_length(uint16_t new_key_length); void key_length(uint16_t value);
/** /**
* \brief Sets the replay counter field. * \brief Sets the replay counter field.
* \param new_replay_counter The new replay counter to be set. * \param value The new replay counter to be set.
*/ */
void replay_counter(uint64_t new_replay_counter); void replay_counter(uint64_t value);
/** /**
* \brief Sets the key IV field. * \brief Sets the key IV field.
* \param new_key_iv The new key IV to be set. *
* 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 *new_key_iv); void key_iv(const uint8_t* ptr);
/** /**
* \brief Sets the nonce field. * \brief Sets the nonce field.
* *
* This method sets the nonce field. This field is 32 bytes long, * The pointer has to contain at least nonce_size bytes. The pointer's contents
* therefore the input buffer should be at least that length. * will be copied.
* \param new_nonce The new nonce to be set. *
* \param ptr The new nonce to be set.
*/ */
void nonce(const uint8_t *new_nonce); void nonce(const uint8_t* ptr);
/** /**
* \brief Sets the rsc field. * \brief Sets the rsc field.
* \param new_rsc The new rsc to be set. *
* 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 *new_rsc); void rsc(const uint8_t* ptr);
/** /**
* \brief Sets the id field. * \brief Sets the id field.
* \param new_id The new id to be set. *
* 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 *new_id); void id(const uint8_t* ptr);
/** /**
* \brief Sets the mic field. * \brief Sets the mic field.
* *
* This method sets the mic field. This field is 16 bytes long, * The pointer has to contain at least mic_size bytes. The pointer's contents
* therefore the input buffer should be at least that length. * will be copied.
* \param new_mic The new mic to be set. *
* \param ptr The new mic to be set.
*/ */
void mic(const uint8_t *new_mic); void mic(const uint8_t* ptr);
/** /**
* \brief Sets the wpa length field. * \brief Sets the wpa length field.
* \param new_wpa_length The new wpa length to be set. * \param length The new wpa length to be set.
*/ */
void wpa_length(uint16_t new_wpa_length); void wpa_length(uint16_t length);
/** /**
* \brief Sets the key field. * \brief Sets the key field.
* \param new_key The new key to be set. * \param value The new key to be set.
*/ */
void key(const key_type &new_key); void key(const key_type& value);
/** /**
* \brief Setter for the key_mic field. * \brief Setter for the key_mic field.
* \param new_key_mic The new to be set. * \param value The new to be set.
*/ */
void key_mic(small_uint<1> new_key_mic); void key_mic(small_uint<1> value);
/** /**
* \brief Setter for the secure field. * \brief Setter for the secure field.
* \param new_secure The new to be set. * \param value The new to be set.
*/ */
void secure(small_uint<1> new_secure); void secure(small_uint<1> value);
/** /**
* \brief Setter for the error field. * \brief Setter for the error field.
* \param new_error The new to be set. * \param flag The new to be set.
*/ */
void error(small_uint<1> new_error); void error(small_uint<1> flag);
/** /**
* \brief Setter for the request field. * \brief Setter for the request field.
* \param new_request The new to be set. * \param flag The new to be set.
*/ */
void request(small_uint<1> new_request); void request(small_uint<1> flag);
/** /**
* \brief Setter for the encrypted field. * \brief Setter for the encrypted field.
* \param new_encrypted The new to be set. * \param flag The new to be set.
*/ */
void encrypted(small_uint<1 > new_encrypted); void encrypted(small_uint<1 > flag);
/** /**
* \brief Setter for the key_descriptor field. * \brief Setter for the key_descriptor field.
* \param new_key_descriptor The new to be set. * \param value The new to be set.
*/ */
void key_descriptor(small_uint<3> new_key_descriptor); void key_descriptor(small_uint<3> value);
/** /**
* \brief Setter for the key_t field. * \brief Setter for the key_t field.
* \param new_key_t The new to be set. * \param flag The new to be set.
*/ */
void key_t(small_uint<1> new_key_t); void key_t(small_uint<1> flag);
/** /**
* \brief Setter for the key_index field. * \brief Setter for the key_index field.
* \param new_key_index The new to be set. * \param value The new to be set.
*/ */
void key_index(small_uint<2> new_key_index); void key_index(small_uint<2> value);
/** /**
* \brief Setter for the install field. * \brief Setter for the install field.
* \param new_install The new to be set. * \param flag The new to be set.
*/ */
void install(small_uint<1> new_install); void install(small_uint<1> flag);
/** /**
* \brief Setter for the key_ack field. * \brief Setter for the key_ack field.
* \param new_key_ack The new to be set. * \param flag The new to be set.
*/ */
void key_ack(small_uint<1> new_key_ack); void key_ack(small_uint<1> flag);
/** /**
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* \return Returns the PDUType corresponding to the PDU. * \return Returns the PDUType corresponding to the PDU.
*/ */
PDUType pdu_type() const { return PDU::RSNEAPOL; } 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 * \param flag The flag to match
* \sa PDU::matches_flag * \sa PDU::matches_flag
*/ */
bool matches_flag(PDUType flag) const { bool matches_flag(PDUType flag) const {
return flag == PDU::RSNEAPOL || EAPOL::matches_flag(flag); return flag == pdu_flag || EAPOL::matches_flag(flag);
} }
/** /**
@@ -691,7 +781,7 @@ namespace Tins {
} }
private: private:
TINS_BEGIN_PACK TINS_BEGIN_PACK
struct rsnhdr { struct rsn_eapol_header {
#if TINS_IS_LITTLE_ENDIAN #if TINS_IS_LITTLE_ENDIAN
uint16_t key_mic:1, uint16_t key_mic:1,
secure:1, secure:1,
@@ -731,12 +821,13 @@ namespace Tins {
#endif #endif
} TINS_END_PACK; } TINS_END_PACK;
void write_body(uint8_t *buffer, uint32_t total_sz); void write_body(Memory::OutputMemoryStream& stream);
rsnhdr _header; rsn_eapol_header header_;
key_type _key; key_type key_;
}; };
}
} // Tins
#endif // TINS_EAPOL_H #endif // TINS_EAPOL_H

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -41,7 +41,8 @@
#include <sys/endian.h> #include <sys/endian.h>
#define TINS_IS_LITTLE_ENDIAN (_BYTE_ORDER == _LITTLE_ENDIAN) #define TINS_IS_LITTLE_ENDIAN (_BYTE_ORDER == _LITTLE_ENDIAN)
#define TINS_IS_BIG_ENDIAN (_BYTE_ORDER == _BIG_ENDIAN) #define TINS_IS_BIG_ENDIAN (_BYTE_ORDER == _BIG_ENDIAN)
#elif defined(WIN32) #elif defined(_WIN32)
#include <cstdlib>
// Assume windows == little endian. fixme later // Assume windows == little endian. fixme later
#define TINS_IS_LITTLE_ENDIAN 1 #define TINS_IS_LITTLE_ENDIAN 1
#define TINS_IS_BIG_ENDIAN 0 #define TINS_IS_BIG_ENDIAN 0
@@ -51,10 +52,22 @@
#define TINS_IS_BIG_ENDIAN (__BYTE_ORDER == __BIG_ENDIAN) #define TINS_IS_BIG_ENDIAN (__BYTE_ORDER == __BIG_ENDIAN)
#endif #endif
// Define macros to swap bytes using compiler intrinsics when possible
#if defined(_MSC_VER)
#define TINS_BYTE_SWAP_16(data) _byteswap_ushort(data)
#define TINS_BYTE_SWAP_32(data) _byteswap_ulong(data)
#define TINS_BYTE_SWAP_64(data) _byteswap_uint64(data)
#elif defined(TINS_HAVE_GCC_BUILTIN_SWAP)
#define TINS_BYTE_SWAP_16(data) __builtin_bswap16(data)
#define TINS_BYTE_SWAP_32(data) __builtin_bswap32(data)
#define TINS_BYTE_SWAP_64(data) __builtin_bswap64(data)
#else
#define TINS_NO_BYTE_SWAP_INTRINSICS
#endif
namespace Tins { namespace Tins {
namespace Endian { namespace Endian {
/** /**
* \brief "Changes" a 8-bit integral value's endianess. This is an * \brief "Changes" a 8-bit integral value's endianess. This is an
* identity function. * identity function.
@@ -71,7 +84,11 @@ namespace Endian {
* \param data The data to convert. * \param data The data to convert.
*/ */
inline uint16_t do_change_endian(uint16_t data) { inline uint16_t do_change_endian(uint16_t data) {
#ifdef TINS_NO_BYTE_SWAP_INTRINSICS
return ((data & 0xff00) >> 8) | ((data & 0x00ff) << 8); return ((data & 0xff00) >> 8) | ((data & 0x00ff) << 8);
#else
return TINS_BYTE_SWAP_16(data);
#endif
} }
/** /**
@@ -80,8 +97,12 @@ namespace Endian {
* \param data The data to convert. * \param data The data to convert.
*/ */
inline uint32_t do_change_endian(uint32_t data) { inline uint32_t do_change_endian(uint32_t data) {
#ifdef TINS_NO_BYTE_SWAP_INTRINSICS
return (((data & 0xff000000) >> 24) | ((data & 0x00ff0000) >> 8) | return (((data & 0xff000000) >> 24) | ((data & 0x00ff0000) >> 8) |
((data & 0x0000ff00) << 8) | ((data & 0x000000ff) << 24)); ((data & 0x0000ff00) << 8) | ((data & 0x000000ff) << 24));
#else
return TINS_BYTE_SWAP_32(data);
#endif
} }
/** /**
@@ -90,8 +111,12 @@ namespace Endian {
* \param data The data to convert. * \param data The data to convert.
*/ */
inline uint64_t do_change_endian(uint64_t data) { inline uint64_t do_change_endian(uint64_t data) {
#ifdef TINS_NO_BYTE_SWAP_INTRINSICS
return (((uint64_t)(do_change_endian((uint32_t)(data & 0xffffffff))) << 32) | return (((uint64_t)(do_change_endian((uint32_t)(data & 0xffffffff))) << 32) |
(do_change_endian(((uint32_t)(data >> 32))))); (do_change_endian(((uint32_t)(data >> 32)))));
#else
return TINS_BYTE_SWAP_64(data);
#endif
} }
/** /**
@@ -112,23 +137,19 @@ namespace Endian {
template<> template<>
struct conversion_dispatcher<sizeof(uint8_t)> struct conversion_dispatcher<sizeof(uint8_t)>
: public conversion_dispatch_helper<uint8_t> : public conversion_dispatch_helper<uint8_t> { };
{ };
template<> template<>
struct conversion_dispatcher<sizeof(uint16_t)> struct conversion_dispatcher<sizeof(uint16_t)>
: public conversion_dispatch_helper<uint16_t> : public conversion_dispatch_helper<uint16_t> { };
{ };
template<> template<>
struct conversion_dispatcher<sizeof(uint32_t)> struct conversion_dispatcher<sizeof(uint32_t)>
: public conversion_dispatch_helper<uint32_t> : public conversion_dispatch_helper<uint32_t> { };
{ };
template<> template<>
struct conversion_dispatcher<sizeof(uint64_t)> struct conversion_dispatcher<sizeof(uint64_t)>
: public conversion_dispatch_helper<uint64_t> : public conversion_dispatch_helper<uint64_t> { };
{ };
/** /**
* \endcond * \endcond
@@ -231,7 +252,8 @@ namespace Endian {
return change_endian(data); return change_endian(data);
} }
#endif #endif
}
} } // Endian
} // Tins
#endif // TINS_ENDIANNESS_H #endif // TINS_ENDIANNESS_H

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -33,6 +33,7 @@
#include <stdint.h> #include <stdint.h>
#include "macros.h" #include "macros.h"
#include "pdu.h" #include "pdu.h"
#include "config.h"
#include "endianness.h" #include "endianness.h"
#include "hw_address.h" #include "hw_address.h"
@@ -42,7 +43,7 @@ namespace Tins {
* \class EthernetII * \class EthernetII
* \brief Represents an Ethernet II PDU. * \brief Represents an Ethernet II PDU.
*/ */
class EthernetII : public PDU { class TINS_API EthernetII : public PDU {
public: public:
/** /**
* \brief The hardware address type. * \brief The hardware address type.
@@ -59,6 +60,14 @@ namespace Tins {
*/ */
static const address_type BROADCAST; static const address_type BROADCAST;
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/** /**
* \brief Constructs an ethernet II PDU. * \brief Constructs an ethernet II PDU.
* *
@@ -90,20 +99,26 @@ namespace Tins {
* \return address_type containing the destination hardware * \return address_type containing the destination hardware
* address. * address.
*/ */
address_type dst_addr() const { return _eth.dst_mac; } address_type dst_addr() const {
return header_.dst_mac;
}
/** /**
* \brief Getter for the source's hardware address. * \brief Getter for the source's hardware address.
* *
* \return address_type containing the source hardware address. * \return address_type containing the source hardware address.
*/ */
address_type src_addr() const { return _eth.src_mac; } address_type src_addr() const {
return header_.src_mac;
}
/** /**
* \brief Getter for the payload_type * \brief Getter for the payload_type
* \return The payload type. * \return The payload type.
*/ */
uint16_t payload_type() const { return Endian::be_to_host(_eth.payload_type); }; uint16_t payload_type() const {
return Endian::be_to_host(header_.payload_type);
}
/* Setters */ /* Setters */
@@ -145,16 +160,13 @@ namespace Tins {
*/ */
uint32_t trailer_size() const; uint32_t trailer_size() const;
// Windows does not support sending L2 PDUs.
#ifndef WIN32
/** /**
* \sa PDU::send() * \sa PDU::send()
*/ */
void send(PacketSender& sender, const NetworkInterface& iface); void send(PacketSender& sender, const NetworkInterface& iface);
#endif // WIN32
/** /**
* \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 * \sa PDU::matches_response
* \param ptr The pointer to the buffer. * \param ptr The pointer to the buffer.
@@ -162,20 +174,22 @@ namespace Tins {
*/ */
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const; bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
#ifndef WIN32 #ifndef _WIN32
/** /**
* \brief Receives a matching response for this packet. * \brief Receives a matching response for this packet.
* *
* \sa PDU::recv_response * \sa PDU::recv_response
*/ */
PDU* recv_response(PacketSender& sender, const NetworkInterface& iface); PDU* recv_response(PacketSender& sender, const NetworkInterface& iface);
#endif // WIN32 #endif // _WIN32
/** /**
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* \sa PDU::pdu_type * \sa PDU::pdu_type
*/ */
PDUType pdu_type() const { return PDU::ETHERNET_II; } PDUType pdu_type() const {
return pdu_flag;
}
/** /**
* \sa PDU::clone * \sa PDU::clone
@@ -188,7 +202,7 @@ namespace Tins {
* Struct that represents the Ethernet II header * Struct that represents the Ethernet II header
*/ */
TINS_BEGIN_PACK TINS_BEGIN_PACK
struct ethhdr { struct ethernet_header {
uint8_t dst_mac[address_type::address_size]; uint8_t dst_mac[address_type::address_size];
uint8_t src_mac[address_type::address_size]; uint8_t src_mac[address_type::address_size];
uint16_t payload_type; uint16_t payload_type;
@@ -196,10 +210,9 @@ namespace Tins {
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);
ethhdr _eth; ethernet_header header_;
}; };
} } // Tins
#endif // TINS_ETHERNET_II_H #endif // TINS_ETHERNET_II_H

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -34,14 +34,24 @@
#include <stdexcept> #include <stdexcept>
namespace Tins { 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. * \brief Exception thrown when an option is not found.
*/ */
class option_not_found : public std::runtime_error { class option_not_found : public exception_base {
public: public:
option_not_found()
: std::runtime_error(std::string()) { }
// try to avoid allocations by doing this. // try to avoid allocations by doing this.
const char* what() const throw() { const char* what() const throw() {
return "Option not found"; return "Option not found";
@@ -51,24 +61,28 @@ public:
/** /**
* \brief Exception thrown when a malformed packet is parsed. * \brief Exception thrown when a malformed packet is parsed.
*/ */
class malformed_packet : public std::runtime_error { class malformed_packet : public exception_base {
public: public:
malformed_packet()
: std::runtime_error(std::string()) { }
const char* what() const throw() { const char* what() const throw() {
return "Malformed packet"; 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. * \brief Exception thrown when a PDU is not found when using PDU::rfind_pdu.
*/ */
class pdu_not_found : public std::runtime_error { class pdu_not_found : public exception_base {
public: public:
pdu_not_found()
: std::runtime_error(std::string()) { }
const char* what() const throw() { const char* what() const throw() {
return "PDU not found"; return "PDU not found";
} }
@@ -78,23 +92,29 @@ public:
* \brief Exception thrown when PDU::send requires a valid interface, * \brief Exception thrown when PDU::send requires a valid interface,
* but an invalid is used. * but an invalid is used.
*/ */
class invalid_interface : public std::runtime_error { class invalid_interface : public exception_base {
public: public:
invalid_interface()
: std::runtime_error(std::string()) { }
const char* what() const throw() { const char* what() const throw() {
return "Invalid interface"; 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. * \brief Exception thrown when a field is not present in frame.
*/ */
class field_not_present : public std::runtime_error { class field_not_present : public exception_base {
public: public:
field_not_present()
: std::runtime_error(std::string()) { }
const char* what() const throw() { const char* what() const throw() {
return "Field not present"; return "Field not present";
} }
@@ -103,35 +123,35 @@ public:
/** /**
* \brief Exception thrown when PacketSender fails to open a socket. * \brief Exception thrown when PacketSender fails to open a socket.
*/ */
class socket_open_error : public std::runtime_error { class socket_open_error : public exception_base {
public: public:
socket_open_error(const std::string& msg) socket_open_error(const std::string& msg)
: std::runtime_error(msg) { } : exception_base(msg) { }
}; };
/** /**
* \brief Exception thrown when PacketSender fails to close a socket. * \brief Exception thrown when PacketSender fails to close a socket.
*/ */
class socket_close_error : public std::runtime_error { class socket_close_error : exception_base {
public: public:
socket_close_error(const std::string& msg) socket_close_error(const std::string& msg)
: std::runtime_error(msg) { } : exception_base(msg) { }
}; };
/** /**
* \brief Exception thrown when PacketSender fails to write on a socket. * \brief Exception thrown when PacketSender fails to write on a socket.
*/ */
class socket_write_error : public std::runtime_error { class socket_write_error : public exception_base {
public: public:
socket_write_error(const std::string& msg) socket_write_error(const std::string& msg)
: std::runtime_error(msg) { } : exception_base(msg) { }
}; };
/** /**
* \brief Exception thrown when an invalid socket type is provided * \brief Exception thrown when an invalid socket type is provided
* to PacketSender. * to PacketSender.
*/ */
class invalid_socket_type : public std::exception { class invalid_socket_type : public exception_base {
public: public:
const char* what() const throw() { const char* what() const throw() {
return "The provided socket type is invalid"; return "The provided socket type is invalid";
@@ -142,7 +162,7 @@ public:
* \brief Exception thrown when an unkown link layer PDU type is * \brief Exception thrown when an unkown link layer PDU type is
* found while sniffing. * found while sniffing.
*/ */
class unknown_link_type : public std::exception { class unknown_link_type : public exception_base {
public: public:
const char* what() const throw() { const char* what() const throw() {
return "The sniffed link layer PDU type is unknown"; return "The sniffed link layer PDU type is unknown";
@@ -152,7 +172,7 @@ public:
/** /**
* \brief Exception thrown when a malformed option is found. * \brief Exception thrown when a malformed option is found.
*/ */
class malformed_option : public std::exception { class malformed_option : public exception_base {
public: public:
const char* what() const throw() { const char* what() const throw() {
return "Malformed option"; return "Malformed option";
@@ -162,7 +182,7 @@ public:
/** /**
* \brief Exception thrown when a call to tins_cast fails. * \brief Exception thrown when a call to tins_cast fails.
*/ */
class bad_tins_cast : public std::exception { class bad_tins_cast : public exception_base {
public: public:
const char* what() const throw() { const char* what() const throw() {
return "Bad Tins cast"; return "Bad Tins cast";
@@ -173,13 +193,141 @@ public:
* \brief Exception thrown when sniffing a protocol that * \brief Exception thrown when sniffing a protocol that
* has been disabled at compile time. * has been disabled at compile time.
*/ */
class protocol_disabled : public std::exception { class protocol_disabled : public exception_base {
public: public:
const char* what() const throw() { const char* what() const throw() {
return "Protocol disabled"; return "Protocol disabled";
} }
}; };
/**
* \brief Exception thrown when a feature has been disabled
* at compile time.
*/
class feature_disabled : public exception_base {
public:
const char* what() const throw() {
return "Feature disabled";
}
};
/**
* \brief Exception thrown when a payload is too large to fit
* into a PDUOption.
*/
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";
}
};
/**
* \brief Exception thrown when a stream is not found
*/
class stream_not_found : public exception_base {
public:
const char* what() const throw() {
return "Stream not found";
}
};
/**
* \brief Exception thrown when a required callback for an object is not set
*/
class callback_not_set : public exception_base {
public:
const char* what() const throw() {
return "Callback not set";
}
};
/**
* \brief Exception thrown when an invalid packet is provided to some function
*/
class invalid_packet : public exception_base {
public:
const char* what() const throw() {
return "Invalid packet";
}
};
namespace Crypto {
namespace WPA2 {
/**
* \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 } // Tins
#endif // TINS_EXCEPTIONS_H #endif // TINS_EXCEPTIONS_H

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -29,17 +29,18 @@
#include "config.h" #include "config.h"
#if !defined(TINS_HANDSHAKE_CAPTURER_H) && defined(HAVE_DOT11) #if !defined(TINS_HANDSHAKE_CAPTURER_H) && defined(TINS_HAVE_DOT11)
#define TINS_HANDSHAKE_CAPTURER_H #define TINS_HANDSHAKE_CAPTURER_H
#include <vector> #include <vector>
#include <map> #include <map>
#include <utility> #include <utility>
#include "hw_address.h" #include "hw_address.h"
#include "macros.h"
#include "eapol.h" #include "eapol.h"
// .h
namespace Tins { namespace Tins {
/** /**
* \brief Generic EAPOL handshake. * \brief Generic EAPOL handshake.
* *
@@ -66,11 +67,10 @@ namespace Tins {
* in the handshake. * in the handshake.
*/ */
EAPOLHandshake(const address_type& client_address, EAPOLHandshake(const address_type& client_address,
const address_type &supplicant_address, const container_type &cont) const address_type& supplicant_address,
const container_type& cont)
: cl_address_(client_address), suppl_address_(supplicant_address), : cl_address_(client_address), suppl_address_(supplicant_address),
handshake_(cont) handshake_(cont) {
{
} }
/** /**
@@ -106,7 +106,7 @@ namespace Tins {
/** /**
* Captures 802.1X RSN handshakes. * Captures 802.1X RSN handshakes.
*/ */
class RSNHandshakeCapturer { class TINS_API RSNHandshakeCapturer {
public: public:
/** /**
* The type of handshakes that will be captured. * The type of handshakes that will be captured.
@@ -164,6 +164,7 @@ namespace Tins {
handshake_map handshakes_; handshake_map handshakes_;
handshakes_type completed_handshakes_; handshakes_type completed_handshakes_;
}; };
}
} // Tins
#endif // TINS_HANDSHAKE_CAPTURER_H #endif // TINS_HANDSHAKE_CAPTURER_H

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,7 @@
#include "cxxstd.h" #include "cxxstd.h"
namespace Tins { namespace Tins {
/** /**
* \class HWAddress * \class HWAddress
* \brief Represents a hardware address. * \brief Represents a hardware address.
@@ -107,11 +108,13 @@ public:
* \param ptr The pointer from which to construct this address. * \param ptr The pointer from which to construct this address.
*/ */
HWAddress(const storage_type* ptr = 0) { HWAddress(const storage_type* ptr = 0) {
if(ptr) if (ptr) {
std::copy(ptr, ptr + address_size, buffer); std::copy(ptr, ptr + address_size, buffer_);
else }
else {
std::fill(begin(), end(), storage_type()); std::fill(begin(), end(), storage_type());
} }
}
/** /**
* \brief Constructs an address from a hex-notation address. * \brief Constructs an address from a hex-notation address.
@@ -125,7 +128,7 @@ public:
* \param address The hex-notation address to be parsed. * \param address The hex-notation address to be parsed.
*/ */
HWAddress(const std::string& address) { HWAddress(const std::string& address) {
convert(address, buffer); convert(address, buffer_);
} }
/** /**
@@ -143,7 +146,7 @@ public:
*/ */
template<size_t i> template<size_t i>
HWAddress(const char (&address)[i]) { HWAddress(const char (&address)[i]) {
convert(address, buffer); convert(address, buffer_);
} }
/** /**
@@ -181,7 +184,7 @@ public:
* \return iterator. * \return iterator.
*/ */
iterator begin() { iterator begin() {
return buffer; return buffer_;
} }
/** /**
@@ -191,7 +194,7 @@ public:
* \return const_iterator. * \return const_iterator.
*/ */
const_iterator begin() const { const_iterator begin() const {
return buffer; return buffer_;
} }
/** /**
@@ -201,7 +204,7 @@ public:
* \return iterator. * \return iterator.
*/ */
iterator end() { iterator end() {
return buffer + address_size; return buffer_ + address_size;
} }
/** /**
@@ -211,7 +214,7 @@ public:
* \return const_iterator. * \return const_iterator.
*/ */
const_iterator end() const { const_iterator end() const {
return buffer + address_size; return buffer_ + address_size;
} }
/** /**
@@ -267,7 +270,7 @@ public:
* \brief Indicates whether this is a multicast address. * \brief Indicates whether this is a multicast address.
*/ */
bool is_multicast() const { bool is_multicast() const {
return (buffer[0] & 0x01); return (*begin() & 0x01);
} }
/** /**
@@ -294,7 +297,7 @@ public:
* \param i The element to retrieve. * \param i The element to retrieve.
*/ */
storage_type operator[](size_t i) const { storage_type operator[](size_t i) const {
return buffer[i]; return begin()[i];
} }
/** /**
@@ -311,7 +314,7 @@ public:
std::ostream_iterator<std::string>(os, ":"), std::ostream_iterator<std::string>(os, ":"),
&HWAddress::storage_to_string &HWAddress::storage_to_string
); );
return os << storage_to_string(addr.buffer[HWAddress::address_size-1]); return os << storage_to_string(addr.begin()[HWAddress::address_size - 1]);
} }
/** /**
@@ -325,35 +328,47 @@ public:
* But since some PDUs return a HWAddress<> by value, this function * But since some PDUs return a HWAddress<> by value, this function
* can be used to avoid temporaries. * 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 * \return OutputIterator pointing to one-past the last position
* written. * written.
*/ */
template<typename OutputIterator> template<typename OutputIterator>
OutputIterator copy(OutputIterator iter) const { OutputIterator copy(OutputIterator output) const {
return std::copy(begin(), end(), iter); for (const_iterator iter = begin(); iter != end(); ++iter) {
*output++ = *iter;
}
return output;
} }
private: private:
template<typename OutputIterator> 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) { static std::string storage_to_string(storage_type element) {
std::ostringstream oss; std::ostringstream oss;
oss << std::hex; oss << std::hex;
if(element < 0x10) if (element < 0x10) {
oss << '0'; oss << '0';
}
oss << (unsigned)element; oss << (unsigned)element;
return oss.str(); return oss.str();
} }
storage_type buffer[n]; storage_type buffer_[n];
}; };
template<size_t n, typename Storage> template<size_t n, typename Storage>
template<typename OutputIterator> template<typename OutputIterator>
void HWAddress<n, Storage>::convert(const std::string& hw_addr, void HWAddress<n, Storage>::convert(const std::string& hw_addr,
OutputIterator output) OutputIterator output) {
{
unsigned i(0); unsigned i(0);
size_t count(0); size_t count(0);
storage_type tmp; storage_type tmp;
@@ -361,44 +376,56 @@ void HWAddress<n, Storage>::convert(const std::string &hw_addr,
const unsigned end = i+2; const unsigned end = i+2;
tmp = storage_type(); tmp = storage_type();
while (i < end) { while (i < end) {
if(hw_addr[i] >= 'a' && hw_addr[i] <= 'f') if (hw_addr[i] >= 'a' && hw_addr[i] <= 'f') {
tmp = (tmp << 4) | (hw_addr[i] - 'a' + 10); 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); 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'); tmp = (tmp << 4) | (hw_addr[i] - '0');
else if(hw_addr[i] == ':') }
else if (hw_addr[i] == ':') {
break; break;
else }
else {
throw std::runtime_error("Invalid byte found"); throw std::runtime_error("Invalid byte found");
}
i++; i++;
} }
*(output++) = tmp; *(output++) = tmp;
count++; count++;
if (i < hw_addr.size()) { if (i < hw_addr.size()) {
if(hw_addr[i] == ':') if (hw_addr[i] == ':') {
i++; i++;
else }
else {
throw std::runtime_error("Invalid separator"); throw std::runtime_error("Invalid separator");
} }
} }
}
while (count++ < n) { while (count++ < n) {
*(output++) = storage_type(); *(output++) = storage_type();
} }
} }
template<size_t n, typename Storage> 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 } // namespace Tins
#if TINS_IS_CXX11 #if TINS_IS_CXX11
namespace std namespace std {
{
// Specialization of std::hash for HWAddress
template<size_t n> template<size_t n>
struct hash<Tins::HWAddress<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()); return std::hash<std::string>()(addr.to_string());
} }
}; };
} // namespace std } // namespace std
#endif #endif // TINS_IS_CXX11
#endif // TINS_HWADDRESS_H #endif // TINS_HWADDRESS_H

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -32,7 +32,7 @@
// Windows likes to define macros with not-so-common-names, which break // Windows likes to define macros with not-so-common-names, which break
// this code // this code
#ifdef WIN32 #ifdef _WIN32
#ifdef TIMESTAMP_REQUEST #ifdef TIMESTAMP_REQUEST
#undef TIMESTAMP_REQUEST #undef TIMESTAMP_REQUEST
#endif // TIMESTAMP_REQUEST #endif // TIMESTAMP_REQUEST
@@ -40,14 +40,20 @@
#ifdef TIMESTAMP_REPLY #ifdef TIMESTAMP_REPLY
#undef TIMESTAMP_REPLY #undef TIMESTAMP_REPLY
#endif // TIMESTAMP_REPLY #endif // TIMESTAMP_REPLY
#endif // WIN32 #endif // _WIN32
#include "macros.h" #include "macros.h"
#include "pdu.h" #include "pdu.h"
#include "endianness.h" #include "endianness.h"
#include "ip_address.h" #include "ip_address.h"
#include "icmp_extension.h"
namespace Tins { namespace Tins {
namespace Memory {
class InputMemoryStream;
} // Memory
/** /**
* \class ICMP * \class ICMP
@@ -56,7 +62,7 @@ namespace Tins {
* ICMP is the representation of the ICMP PDU. Instances of this class * ICMP is the representation of the ICMP PDU. Instances of this class
* must be sent over a level 3 PDU, this will otherwise fail. * must be sent over a level 3 PDU, this will otherwise fail.
*/ */
class ICMP : public PDU { class TINS_API ICMP : public PDU {
public: public:
/** /**
* \brief This PDU's flag. * \brief This PDU's flag.
@@ -86,6 +92,14 @@ namespace Tins {
ADDRESS_MASK_REPLY = 18 ADDRESS_MASK_REPLY = 18
}; };
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/** /**
* \brief Creates an instance of ICMP. * \brief Creates an instance of ICMP.
* *
@@ -232,7 +246,7 @@ namespace Tins {
/** /**
* \brief Sets parameter problem flag for this PDU. * \brief Sets parameter problem flag for this PDU.
* *
* \param set_pointer Indicates wether a pointer to the bad octet * \param set_pointer Indicates whether a pointer to the bad octet
* is provided. * is provided.
* \param bad_octet Identifies the octet in which the error was * \param bad_octet Identifies the octet in which the error was
* detected. If set_pointer == false, it is ignored. * detected. If set_pointer == false, it is ignored.
@@ -258,35 +272,45 @@ namespace Tins {
* *
* \return The type flag for this ICMP PDU. * \return The type flag for this ICMP PDU.
*/ */
Flags type() const { return (Flags)_icmp.type; } Flags type() const {
return (Flags)header_.type;
}
/** /**
* \brief Getter for the ICMP code flag. * \brief Getter for the ICMP code flag.
* *
* \return The code flag for this ICMP PDU. * \return The code flag for this ICMP PDU.
*/ */
uint8_t code() const { return _icmp.code; } uint8_t code() const {
return header_.code;
}
/** /**
* \brief Getter for the checksum field. * \brief Getter for the checksum field.
* *
* \return Returns the checksum as an unit16_t. * \return Returns the checksum as an unit16_t.
*/ */
uint16_t checksum() const { return Endian::be_to_host(_icmp.check); } uint16_t checksum() const {
return Endian::be_to_host(header_.check);
}
/** /**
* \brief Getter for the echo id. * \brief Getter for the echo id.
* *
* \return Returns the echo id. * \return Returns the echo id.
*/ */
uint16_t id() const { return Endian::be_to_host(_icmp.un.echo.id); } uint16_t id() const {
return Endian::be_to_host(header_.un.echo.id);
}
/** /**
* \brief Getter for the echo sequence number. * \brief Getter for the echo sequence number.
* *
* \return Returns the echo sequence number. * \return Returns the echo sequence number.
*/ */
uint16_t sequence() const { return Endian::be_to_host(_icmp.un.echo.sequence); } uint16_t sequence() const {
return Endian::be_to_host(header_.un.echo.sequence);
}
/** /**
* \brief Getter for the gateway field. * \brief Getter for the gateway field.
@@ -294,7 +318,7 @@ namespace Tins {
* \return Returns the gateway field value. * \return Returns the gateway field value.
*/ */
address_type gateway() const { address_type gateway() const {
return address_type(Endian::be_to_host(_icmp.un.gateway)); return address_type(Endian::be_to_host(header_.un.gateway));
} }
/** /**
@@ -302,35 +326,54 @@ namespace Tins {
* *
* \return Returns the pointer field value. * \return Returns the pointer field value.
*/ */
uint8_t pointer() const { return this->_icmp.un.pointer; } 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. * \brief Getter for the mtu field.
* *
* \return Returns the mtu field value. * \return Returns the mtu field value.
*/ */
uint16_t mtu() const { return Endian::be_to_host(_icmp.un.frag.mtu); } uint16_t mtu() const {
return Endian::be_to_host(header_.un.frag.mtu);
}
/** /**
* \brief Getter for the original timestamp field. * \brief Getter for the original timestamp field.
* *
* \return Returns the original timestamp value. * \return Returns the original timestamp value.
*/ */
uint32_t original_timestamp() const { return Endian::be_to_host(_orig_timestamp_or_address_mask); } uint32_t original_timestamp() const {
return Endian::be_to_host(orig_timestamp_or_address_mask_);
}
/** /**
* \brief Getter for the receive timestamp field. * \brief Getter for the receive timestamp field.
* *
* \return Returns the receive timestamp value. * \return Returns the receive timestamp value.
*/ */
uint32_t receive_timestamp() const { return Endian::be_to_host(_recv_timestamp); } uint32_t receive_timestamp() const {
return Endian::be_to_host(recv_timestamp_);
}
/** /**
* \brief Getter for the transmit timestamp field. * \brief Getter for the transmit timestamp field.
* *
* \return Returns the transmit timestamp value. * \return Returns the transmit timestamp value.
*/ */
uint32_t transmit_timestamp() const { return Endian::be_to_host(_trans_timestamp); } uint32_t transmit_timestamp() const {
return Endian::be_to_host(trans_timestamp_);
}
/** /**
* \brief Getter for the address mask field. * \brief Getter for the address mask field.
@@ -338,19 +381,30 @@ namespace Tins {
* \return Returns the address mask value. * \return Returns the address mask value.
*/ */
address_type address_mask() const { address_type address_mask() const {
return address_type(Endian::be_to_host(_orig_timestamp_or_address_mask)); return address_type(Endian::be_to_host(orig_timestamp_or_address_mask_));
} }
/** /**
* \brief Returns the header size. * \brief Returns the header size.
* *
* This metod overrides PDU::header_size. This size includes the * This method overrides PDU::header_size. This size includes the
* payload and options size. \sa PDU::header_size * payload and options size.
*
* \sa PDU::header_size
*/ */
uint32_t header_size() const; uint32_t header_size() const;
/** /**
* \brief Check wether ptr points to a valid response for this PDU. * \brief Returns the trailer size.
*
* This method overrides PDU::trailer_size. This size will hold the extensions size
*
* \sa PDU::header_size
*/
uint32_t trailer_size() const;
/**
* \brief Check whether ptr points to a valid response for this PDU.
* *
* \sa PDU::matches_response * \sa PDU::matches_response
* \param ptr The pointer to the buffer. * \param ptr The pointer to the buffer.
@@ -358,12 +412,56 @@ namespace Tins {
*/ */
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 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. * \brief Getter for the PDU's type.
* *
* \sa PDU::pdu_type * \sa PDU::pdu_type
*/ */
PDUType pdu_type() const { return PDU::ICMP; } PDUType pdu_type() const {
return pdu_flag;
}
/** /**
* \sa PDU::clone * \sa PDU::clone
@@ -373,7 +471,7 @@ namespace Tins {
} }
private: private:
TINS_BEGIN_PACK TINS_BEGIN_PACK
struct icmphdr { struct icmp_header {
uint8_t type; uint8_t type;
uint8_t code; uint8_t code;
uint16_t check; uint16_t check;
@@ -387,7 +485,11 @@ namespace Tins {
uint16_t unused; uint16_t unused;
uint16_t mtu; uint16_t mtu;
} frag; } frag;
struct {
uint8_t pointer; uint8_t pointer;
uint8_t length;
uint16_t unused;
} rfc4884;
} un; } un;
} TINS_END_PACK; } TINS_END_PACK;
@@ -400,9 +502,15 @@ namespace Tins {
*/ */
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);
icmphdr _icmp; uint32_t get_adjusted_inner_pdu_size() const;
uint32_t _orig_timestamp_or_address_mask, _recv_timestamp, _trans_timestamp; 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 #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

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -40,14 +40,22 @@
#include "small_uint.h" #include "small_uint.h"
#include "hw_address.h" #include "hw_address.h"
#include "small_uint.h" #include "small_uint.h"
#include "icmp_extension.h"
#include "cxxstd.h" #include "cxxstd.h"
namespace Tins { namespace Tins {
namespace Memory {
class InputMemoryStream;
class OutputMemoryStream;
} // memory
/** /**
* \class ICMPv6 * \class ICMPv6
* \brief Represents an ICMPv6 PDU. * \brief Represents an ICMPv6 PDU.
*/ */
class ICMPv6 : public PDU { class TINS_API ICMPv6 : public PDU {
public: public:
/** /**
* \brief This PDU's flag. * \brief This PDU's flag.
@@ -72,14 +80,20 @@ public:
NEIGHBOUR_SOLICIT = 135, NEIGHBOUR_SOLICIT = 135,
NEIGHBOUR_ADVERT = 136, NEIGHBOUR_ADVERT = 136,
REDIRECT = 137, REDIRECT = 137,
ROUTER_RENUMBER = 137, ROUTER_RENUMBER = 138,
NI_QUERY = 139, NI_QUERY = 139,
NI_REPLY = 140, NI_REPLY = 140,
MLD2_REPORT = 143, MLD2_REPORT = 143,
DHAAD_REQUEST = 144, DHAAD_REQUEST = 144,
DHAAD_REPLY = 145, DHAAD_REPLY = 145,
MOBILE_PREFIX_SOL = 146, MOBILE_PREFIX_SOLICIT = 146,
MOBILE_PREFIX_ADV = 147 MOBILE_PREFIX_ADVERT = 147,
CERT_PATH_SOLICIT = 148,
CERT_PATH_ADVERT = 149,
MULTICAST_ROUTER_ADVERT = 151,
MULTICAST_ROUTER_SOLICIT = 152,
MULTICAST_ROUTER_TERMINATE = 153,
RPL_CONTROL_MSG = 155
}; };
/** /**
@@ -159,8 +173,7 @@ public:
addresses_type addresses; addresses_type addresses;
addr_list_type(const addresses_type& addresses = addresses_type()) addr_list_type(const addresses_type& addresses = addresses_type())
: addresses(addresses) : addresses(addresses) {
{
std::fill(reserved, reserved + sizeof(reserved), 0); std::fill(reserved, reserved + sizeof(reserved), 0);
} }
@@ -186,8 +199,7 @@ public:
uint8_t reserved[4]; uint8_t reserved[4];
naack_type(uint8_t code = 0, uint8_t status = 0) naack_type(uint8_t code = 0, uint8_t status = 0)
: code(code), status(status) : code(code), status(status) {
{
std::fill(reserved, reserved + 4, 0); std::fill(reserved, reserved + 4, 0);
} }
@@ -211,8 +223,7 @@ public:
*/ */
lladdr_type(uint8_t option_code = 0, lladdr_type(uint8_t option_code = 0,
const address_type& address = address_type()) const address_type& address = address_type())
: option_code(option_code), address(address) : option_code(option_code), address(address) {
{
} }
@@ -225,10 +236,8 @@ public:
* \param option_code The option code. * \param option_code The option code.
* \param address The address to be stored. * \param address The address to be stored.
*/ */
lladdr_type(uint8_t option_code, lladdr_type(uint8_t option_code, const hwaddress_type& address)
const hwaddress_type &address) : option_code(option_code), address(address.begin(), address.end()) {
: option_code(option_code), address(address.begin(), address.end())
{
} }
@@ -246,12 +255,14 @@ public:
reserved2; reserved2;
ipaddress_type prefix; ipaddress_type prefix;
prefix_info_type(uint8_t prefix_len=0, small_uint<1> A=0, small_uint<1> L=0, prefix_info_type(uint8_t prefix_len = 0,
uint32_t valid_lifetime=0, uint32_t preferred_lifetime=0, small_uint<1> A = 0,
small_uint<1> L = 0,
uint32_t valid_lifetime = 0,
uint32_t preferred_lifetime = 0,
const ipaddress_type& prefix = ipaddress_type()) const ipaddress_type& prefix = ipaddress_type())
: prefix_len(prefix_len), A(A), L(L), : prefix_len(prefix_len), A(A), L(L), valid_lifetime(valid_lifetime),
valid_lifetime(valid_lifetime), preferred_lifetime(preferred_lifetime), preferred_lifetime(preferred_lifetime), prefix(prefix) { }
prefix(prefix) { }
static prefix_info_type from_option(const option& opt); static prefix_info_type from_option(const option& opt);
}; };
@@ -285,8 +296,7 @@ public:
*/ */
template <typename RAIterator, typename ForwardIterator> template <typename RAIterator, typename ForwardIterator>
rsa_sign_type(RAIterator hash, ForwardIterator start, ForwardIterator end) rsa_sign_type(RAIterator hash, ForwardIterator start, ForwardIterator end)
: signature(start, end) : signature(start, end) {
{
std::copy(hash, hash + sizeof(key_hash), key_hash); std::copy(hash, hash + sizeof(key_hash), key_hash);
} }
@@ -304,8 +314,7 @@ public:
*/ */
template <typename RAIterator> template <typename RAIterator>
rsa_sign_type(RAIterator hash, const signature_type& sign) rsa_sign_type(RAIterator hash, const signature_type& sign)
: signature(sign) : signature(sign) {
{
std::copy(hash, hash + sizeof(key_hash), key_hash); std::copy(hash, hash + sizeof(key_hash), key_hash);
} }
@@ -314,8 +323,7 @@ public:
* *
* The key_hash member will be 0-initialized. * The key_hash member will be 0-initialized.
*/ */
rsa_sign_type() rsa_sign_type() {
{
std::fill(key_hash, key_hash + sizeof(key_hash), 0); std::fill(key_hash, key_hash + sizeof(key_hash), 0);
} }
@@ -329,7 +337,8 @@ public:
uint8_t option_code, prefix_len; uint8_t option_code, prefix_len;
ipaddress_type address; ipaddress_type address;
ip_prefix_type(uint8_t option_code = 0, uint8_t prefix_len = 0, ip_prefix_type(uint8_t option_code = 0,
uint8_t prefix_len = 0,
const ipaddress_type& address = ipaddress_type()) const ipaddress_type& address = ipaddress_type())
: option_code(option_code), prefix_len(prefix_len), address(address) : option_code(option_code), prefix_len(prefix_len), address(address)
{} {}
@@ -346,8 +355,10 @@ public:
uint32_t valid_lifetime; uint32_t valid_lifetime;
ipaddress_type address; ipaddress_type address;
map_type(small_uint<4> dist = 0, small_uint<4> pref = 0, map_type(small_uint<4> dist = 0,
small_uint<1> r = 0, uint32_t valid_lifetime = 0, small_uint<4> pref = 0,
small_uint<1> r = 0,
uint32_t valid_lifetime = 0,
const ipaddress_type& address = ipaddress_type()) const ipaddress_type& address = ipaddress_type())
: dist(dist), pref(pref), r(r), valid_lifetime(valid_lifetime), : dist(dist), pref(pref), r(r), valid_lifetime(valid_lifetime),
address(address) { } address(address) { }
@@ -366,8 +377,10 @@ public:
uint32_t route_lifetime; uint32_t route_lifetime;
prefix_type prefix; prefix_type prefix;
route_info_type(uint8_t prefix_len = 0, small_uint<2> pref = 0, route_info_type(uint8_t prefix_len = 0,
uint32_t route_lifetime = 0, const prefix_type &prefix = prefix_type()) small_uint<2> pref = 0,
uint32_t route_lifetime = 0,
const prefix_type& prefix = prefix_type())
: prefix_len(prefix_len), pref(pref), route_lifetime(route_lifetime), : prefix_len(prefix_len), pref(pref), route_lifetime(route_lifetime),
prefix(prefix) { } prefix(prefix) { }
@@ -412,7 +425,8 @@ public:
struct handover_key_reply_type : handover_key_req_type { struct handover_key_reply_type : handover_key_req_type {
uint16_t lifetime; uint16_t lifetime;
handover_key_reply_type(uint16_t lifetime = 0, small_uint<4> AT = 0, handover_key_reply_type(uint16_t lifetime = 0,
small_uint<4> AT = 0,
const key_type& key = key_type()) const key_type& key = key_type())
: handover_key_req_type(AT, key), lifetime(lifetime) { } : handover_key_req_type(AT, key), lifetime(lifetime) { }
@@ -475,8 +489,7 @@ public:
uint64_t timestamp; uint64_t timestamp;
timestamp_type(uint64_t timestamp = 0) timestamp_type(uint64_t timestamp = 0)
: timestamp(timestamp) : timestamp(timestamp) {
{
std::fill(reserved, reserved + sizeof(reserved), 0); std::fill(reserved, reserved + sizeof(reserved), 0);
} }
@@ -491,8 +504,7 @@ public:
uint32_t reserved2; uint32_t reserved2;
shortcut_limit_type(uint8_t limit = 0) shortcut_limit_type(uint8_t limit = 0)
: limit(limit), reserved1(), reserved2() : limit(limit), reserved1(), reserved2() {
{
} }
@@ -507,14 +519,43 @@ public:
uint32_t interval; uint32_t interval;
new_advert_interval_type(uint32_t interval = 0) new_advert_interval_type(uint32_t interval = 0)
: reserved(), interval(interval) : reserved(), interval(interval) {
{
} }
static new_advert_interval_type from_option(const option& opt); static new_advert_interval_type from_option(const option& opt);
}; };
/**
* The type used to represent a multicast address record
*/
struct multicast_address_record {
typedef std::vector<ipaddress_type> sources_type;
typedef std::vector<uint8_t> aux_data_type;
multicast_address_record(uint8_t type = 0) : type(type) { }
multicast_address_record(const uint8_t* buffer, uint32_t total_sz);
void serialize(uint8_t* buffer, uint32_t total_sz) const;
uint32_t size() const;
uint8_t type;
ipaddress_type multicast_address;
sources_type sources;
aux_data_type aux_data;
};
/*
* The type used to store all multicast address records in a packet
*/
typedef std::list<multicast_address_record> multicast_address_records_list;
/*
* The type used to store all source address (from Multicast
* Listener Query messages) in a packet
*/
typedef std::list<ipaddress_type> sources_list;
/** /**
* \brief Constructs an ICMPv6 object. * \brief Constructs an ICMPv6 object.
* *
@@ -545,7 +586,7 @@ public:
* \return The stored type field value. * \return The stored type field value.
*/ */
Types type() const { Types type() const {
return static_cast<Types>(_header.type); return static_cast<Types>(header_.type);
} }
/** /**
@@ -553,7 +594,7 @@ public:
* \return The stored code field value. * \return The stored code field value.
*/ */
uint8_t code() const { uint8_t code() const {
return _header.code; return header_.code;
} }
/** /**
@@ -561,7 +602,7 @@ public:
* \return The stored cksum field value. * \return The stored cksum field value.
*/ */
uint16_t checksum() const { uint16_t checksum() const {
return Endian::be_to_host(_header.cksum); return Endian::be_to_host(header_.cksum);
} }
/** /**
@@ -569,7 +610,7 @@ public:
* \return The stored identifier field value. * \return The stored identifier field value.
*/ */
uint16_t identifier() const { uint16_t identifier() const {
return Endian::be_to_host(_header.u_echo.identifier); return Endian::be_to_host(header_.u_echo.identifier);
} }
/** /**
@@ -577,7 +618,7 @@ public:
* \return The stored sequence field value. * \return The stored sequence field value.
*/ */
uint16_t sequence() const { uint16_t sequence() const {
return Endian::be_to_host(_header.u_echo.sequence); return Endian::be_to_host(header_.u_echo.sequence);
} }
/** /**
@@ -585,7 +626,7 @@ public:
* \return The stored override field value. * \return The stored override field value.
*/ */
small_uint<1> override() const { small_uint<1> override() const {
return _header.u_nd_advt.override; return header_.u_nd_advt.override;
} }
/** /**
@@ -593,7 +634,7 @@ public:
* \return The stored solicited field value. * \return The stored solicited field value.
*/ */
small_uint<1> solicited() const { small_uint<1> solicited() const {
return _header.u_nd_advt.solicited; return header_.u_nd_advt.solicited;
} }
/** /**
@@ -601,15 +642,23 @@ public:
* \return The stored router field value. * \return The stored router field value.
*/ */
small_uint<1> router() const { small_uint<1> router() const {
return _header.u_nd_advt.router; return header_.u_nd_advt.router;
} }
/** /**
* \brief Getter for the hop_limit field. * \brief Getter for the hop limit field.
* \return The stored hop_limit field value. * \return The stored hop limit field value.
*/ */
uint8_t hop_limit() const { uint8_t hop_limit() const {
return _header.u_nd_ra.hop_limit; return header_.u_nd_ra.hop_limit;
}
/**
* \brief Getter for the maximum response code field.
* \return The stored maximum response code field value.
*/
uint16_t maximum_response_code() const {
return Endian::be_to_host(header_.u_echo.identifier);
} }
/** /**
@@ -617,7 +666,7 @@ public:
* \return The stored router_pref field value. * \return The stored router_pref field value.
*/ */
small_uint<2> router_pref() const { small_uint<2> router_pref() const {
return _header.u_nd_ra.router_pref; return header_.u_nd_ra.router_pref;
} }
/** /**
@@ -625,7 +674,7 @@ public:
* \return The stored home_agent field value. * \return The stored home_agent field value.
*/ */
small_uint<1> home_agent() const { small_uint<1> home_agent() const {
return _header.u_nd_ra.home_agent; return header_.u_nd_ra.home_agent;
} }
/** /**
@@ -633,7 +682,7 @@ public:
* \return The stored other field value. * \return The stored other field value.
*/ */
small_uint<1> other() const { small_uint<1> other() const {
return _header.u_nd_ra.other; return header_.u_nd_ra.other;
} }
/** /**
@@ -641,7 +690,7 @@ public:
* \return The stored managed field value. * \return The stored managed field value.
*/ */
small_uint<1> managed() const { small_uint<1> managed() const {
return _header.u_nd_ra.managed; return header_.u_nd_ra.managed;
} }
/** /**
@@ -649,7 +698,7 @@ public:
* \return The stored router_lifetime field value. * \return The stored router_lifetime field value.
*/ */
uint16_t router_lifetime() const { uint16_t router_lifetime() const {
return Endian::be_to_host(_header.u_nd_ra.router_lifetime); return Endian::be_to_host(header_.u_nd_ra.router_lifetime);
} }
/** /**
@@ -657,7 +706,7 @@ public:
* \return The stored reachable_time field value. * \return The stored reachable_time field value.
*/ */
uint32_t reachable_time() const { uint32_t reachable_time() const {
return Endian::be_to_host(reach_time); return Endian::be_to_host(reach_time_);
} }
/** /**
@@ -665,7 +714,7 @@ public:
* \return The stored retransmit_timer field value. * \return The stored retransmit_timer field value.
*/ */
uint32_t retransmit_timer() const { uint32_t retransmit_timer() const {
return Endian::be_to_host(retrans_timer); return Endian::be_to_host(retrans_timer_);
} }
/** /**
@@ -673,7 +722,7 @@ public:
* \return The stored target address field value. * \return The stored target address field value.
*/ */
const ipaddress_type& target_addr() const { const ipaddress_type& target_addr() const {
return _target_address; return target_address_;
} }
/** /**
@@ -681,7 +730,18 @@ public:
* \return The stored destination address field value. * \return The stored destination address field value.
*/ */
const ipaddress_type& dest_addr() const { const ipaddress_type& dest_addr() const {
return _dest_address; return dest_address_;
}
/**
* \brief Getter for the multicast address field.
*
* Note that this field is only valid for Multicast Listener Query
* Message packets
* \return The stored multicast address field value.
*/
const ipaddress_type& multicast_addr() const {
return multicast_address_;
} }
/** /**
@@ -689,7 +749,63 @@ public:
* \return The stored options. * \return The stored options.
*/ */
const options_type& options() const { const options_type& options() const {
return _options; return options_;
}
/**
* \brief Getter for the length field.
*
* \return Returns the length field value.
*/
uint8_t length() const {
return header_.rfc4884.length;
}
/**
* \brief Getter for the multicast address records field
*/
const multicast_address_records_list& multicast_address_records() const {
return multicast_records_;
}
/**
* \brief Getter for the multicast address records field.
*
* Note that this field is only valid for Multicast Listener Query Message
* packets
*/
const sources_list& sources() const {
return sources_;
}
/**
* \brief Getter for the Suppress Router-Side Processing field.
*
* Note that this field is only valid for Multicast Listener Query Message
* packets
*/
small_uint<1> supress() const {
return mlqm_.supress;
}
/**
* \brief Getter for the Querier's Robustnes Variable field.
*
* Note that this field is only valid for Multicast Listener Query Message
* packets
*/
small_uint<3> qrv() const {
return mlqm_.qrv;
}
/**
* \brief Getter for the Querier's Query Interval Code field.
*
* Note that this field is only valid for Multicast Listener Query Message
* packets
*/
uint8_t qqic() const {
return mlqm_.qqic;
} }
// Setters // Setters
@@ -748,6 +864,12 @@ public:
*/ */
void hop_limit(uint8_t new_hop_limit); void hop_limit(uint8_t new_hop_limit);
/**
* \brief Setter for the maximum response code field.
* \param new_hop_limit The new maximum response code field value.
*/
void maximum_response_code(uint16_t maximum_response_code);
/** /**
* \brief Setter for the router_pref field. * \brief Setter for the router_pref field.
* \param new_router_pref The new router_pref field value. * \param new_router_pref The new router_pref field value.
@@ -790,6 +912,15 @@ public:
*/ */
void dest_addr(const ipaddress_type& new_dest_addr); void dest_addr(const ipaddress_type& new_dest_addr);
/**
* \brief Setter for the multicast address field.
*
* Note that this field is only valid if the type is MGM_QUERY
*
* \param new_multicast_addr The new multicast address field value.
*/
void multicast_addr(const ipaddress_type& new_multicast_addr);
/** /**
* \brief Setter for the reachable_time field. * \brief Setter for the reachable_time field.
* \param new_reachable_time The new reachable_time field value. * \param new_reachable_time The new reachable_time field value.
@@ -802,6 +933,41 @@ public:
*/ */
void retransmit_timer(uint32_t new_retrans_timer); void retransmit_timer(uint32_t new_retrans_timer);
/**
* \brief Setter for the multicast address records field.
*
* This field is only valid if the type of this PDU is MLD2_REPORT
*/
void multicast_address_records(const multicast_address_records_list& records);
/**
* \brief Setter for the sources field.
*
* This field is only valid if the type of this PDU is MGM_QUERY
*/
void sources(const sources_list& new_sources);
/**
* \brief Setter for the supress field.
*
* This field is only valid if the type of this PDU is MGM_QUERY
*/
void supress(small_uint<1> value);
/**
* \brief Setter for the Querier's Robustness Variable field.
*
* This field is only valid if the type of this PDU is MGM_QUERY
*/
void qrv(small_uint<3> value);
/**
* \brief Setter for the Querier's Query Interval Code field.
*
* This field is only valid if the type of this PDU is MGM_QUERY
*/
void qqic(uint8_t value);
/** /**
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* *
@@ -849,20 +1015,82 @@ public:
*/ */
void add_option(option &&option) { void add_option(option &&option) {
internal_add_option(option); internal_add_option(option);
_options.push_back(std::move(option)); options_.push_back(std::move(option));
} }
#endif #endif
/**
* \brief Removes an ICMPv6 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 Returns the header size. * \brief Returns the header size.
* *
* This metod overrides PDU::header_size. This size includes the * This method overrides PDU::header_size. This size includes the
* payload and options size. \sa PDU::header_size * payload and options size. \sa PDU::header_size
*/ */
uint32_t header_size() const; uint32_t header_size() const;
/** /**
* \brief Check wether ptr points to a valid response for this PDU. * \brief Returns the trailer size.
*
* This method overrides PDU::trailer_size. This size will hold the extensions size
*
* \sa PDU::header_size
*/
uint32_t trailer_size() const;
/**
* \brief 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 Check whether ptr points to a valid response for this PDU.
* *
* \sa PDU::matches_response * \sa PDU::matches_response
* \param ptr The pointer to the buffer. * \param ptr The pointer to the buffer.
@@ -877,9 +1105,9 @@ public:
* Deleting the returned pointer will result in <b>undefined * Deleting the returned pointer will result in <b>undefined
* behaviour</b>. * 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;
/** /**
* \sa PDU::clone * \sa PDU::clone
@@ -1258,7 +1486,7 @@ public:
dns_search_list_type dns_search_list() const; dns_search_list_type dns_search_list() const;
private: private:
TINS_BEGIN_PACK TINS_BEGIN_PACK
struct icmp6hdr { struct icmp6_header {
uint8_t type; uint8_t type;
uint8_t code; uint8_t code;
uint16_t cksum; uint16_t cksum;
@@ -1299,40 +1527,71 @@ private:
#endif #endif
uint16_t router_lifetime; uint16_t router_lifetime;
} u_nd_ra; } u_nd_ra;
struct {
uint8_t length;
uint8_t unused[3];
} rfc4884;
// Multicast Listener Report Message (mld2)
struct {
uint16_t reserved;
uint16_t record_count;
} mlrm2;
}; };
} TINS_END_PACK; } TINS_END_PACK;
TINS_BEGIN_PACK
struct multicast_listener_query_message_fields {
uint8_t reserved:4,
supress:1,
qrv:3;
uint8_t qqic;
} TINS_END_PACK;
void internal_add_option(const option& option); void internal_add_option(const option& option);
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);
bool has_options() const; bool has_options() const;
uint8_t *write_option(const option &opt, uint8_t *buffer); void write_option(const option& opt, Memory::OutputMemoryStream& stream);
void parse_options(const uint8_t *&buffer, uint32_t &total_sz); void parse_options(Memory::InputMemoryStream& stream);
void add_addr_list(uint8_t type, const addr_list_type& value); void add_addr_list(uint8_t type, const addr_list_type& value);
addr_list_type search_addr_list(OptionTypes type) const; addr_list_type search_addr_list(OptionTypes type) const;
options_type::const_iterator search_option_iterator(OptionTypes type) const;
options_type::iterator search_option_iterator(OptionTypes type);
void try_parse_extensions(Memory::InputMemoryStream& stream);
bool are_extensions_allowed() const;
uint32_t get_adjusted_inner_pdu_size() const;
uint8_t get_option_padding(uint32_t data_size);
template <template <typename> class Functor> template <template <typename> class Functor>
const option* safe_search_option(OptionTypes opt, uint32_t size) const { const option* safe_search_option(OptionTypes opt, uint32_t size) const {
const option* option = search_option(opt); const option* option = search_option(opt);
if(!option || Functor<uint32_t>()(option->data_size(), size)) if (!option || Functor<uint32_t>()(option->data_size(), size)) {
throw option_not_found(); throw option_not_found();
}
return option; return option;
} }
template <typename T> template <typename T>
T search_and_convert(OptionTypes type) const { T search_and_convert(OptionTypes type) const {
const option* opt = search_option(type); const option* opt = search_option(type);
if(!opt) if (!opt) {
throw option_not_found(); throw option_not_found();
}
return opt->to<T>(); return opt->to<T>();
} }
icmp6hdr _header; icmp6_header header_;
ipaddress_type _target_address, _dest_address; ipaddress_type target_address_;
options_type _options; ipaddress_type dest_address_;
uint32_t _options_size; ipaddress_type multicast_address_;
uint32_t reach_time, retrans_timer; options_type options_;
uint32_t options_size_;
uint32_t reach_time_, retrans_timer_;
multicast_address_records_list multicast_records_;
multicast_listener_query_message_fields mlqm_;
sources_list sources_;
ICMPExtensionsStructure extensions_;
}; };
}
} // Tins
#endif // TINS_ICMPV6_H #endif // TINS_ICMPV6_H

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -45,10 +45,16 @@
* \cond * \cond
*/ */
namespace Tins { namespace Tins {
namespace Memory {
class InputMemoryStream;
} // Memory
class IPv4Address; class IPv4Address;
class IPv6Address; class IPv6Address;
class ICMPExtensionsStructure;
namespace Internals { namespace Internals {
template<size_t n> template<size_t n>
class byte_array { class byte_array {
public: public:
@@ -122,7 +128,13 @@ PDU *pdu_from_dlt_flag(int flag, const uint8_t *buffer,
PDU* pdu_from_flag(PDU::PDUType type, const uint8_t* buffer, uint32_t size); 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::Ethernet::e pdu_flag_to_ether_type(PDU::PDUType flag);
PDU::PDUType ether_type_to_pdu_flag(Constants::Ethernet::e flag);
Constants::IP::e pdu_flag_to_ip_type(PDU::PDUType flag); Constants::IP::e pdu_flag_to_ip_type(PDU::PDUType flag);
PDU::PDUType ip_type_to_pdu_flag(Constants::IP::e flag);
uint32_t get_padded_icmp_inner_pdu_size(const PDU* inner_pdu, uint32_t pad_alignment);
void try_parse_icmp_extensions(Memory::InputMemoryStream& stream,
uint32_t payload_length, ICMPExtensionsStructure& extensions);
template<typename T> template<typename T>
bool increment_buffer(T& addr) { bool increment_buffer(T& addr) {
@@ -132,8 +144,9 @@ bool increment_buffer(T &addr) {
--it; --it;
} }
// reached end // reached end
if(it < addr.begin()) if (it < addr.begin()) {
return true; return true;
}
(*it)++; (*it)++;
return false; return false;
} }
@@ -146,8 +159,9 @@ bool decrement_buffer(T &addr) {
--it; --it;
} }
// reached end // reached end
if(it < addr.begin()) if (it < addr.begin()) {
return true; return true;
}
(*it)--; (*it)--;
return false; return false;
} }
@@ -165,6 +179,9 @@ bool decrement(HWAddress<n> &addr) {
return decrement_buffer(addr); return decrement_buffer(addr);
} }
// Compares sequence numbers as defined by RFC 1982.
int seq_compare(uint32_t seq1, uint32_t seq2);
IPv4Address last_address_from_mask(IPv4Address addr, IPv4Address mask); 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> template<size_t n>
@@ -205,33 +222,31 @@ struct is_unsigned_integral<uint64_t> {
static const bool value = true; static const bool value = true;
}; };
#if TINS_IS_CXX11 #if TINS_IS_CXX11 && !defined(_MSC_VER)
// Part of C++14 standard library
template<bool B, class T = void>
using enable_if_t = typename std::enable_if<B,T>::type;
// Template metaprogramming trait to determine if a functor can accept another parameter as an argument // Template metaprogramming trait to determine if a functor can accept another parameter as an argument
template <class T, class P, class=void> template <typename T, typename P, typename=void>
struct accepts_type : std::false_type { }; struct accepts_type : std::false_type { };
template <class T, class P> template <typename T, typename P>
struct accepts_type<T, P, enable_if_t< struct accepts_type<T, P,
typename std::enable_if<
std::is_same< decltype( std::declval<T>()(std::declval<P>()) ), bool>::value std::is_same< decltype( std::declval<T>()(std::declval<P>()) ), bool>::value
>> : std::true_type { }; >::type
> : std::true_type { };
// use enable_if to invoke the Packet&& version of the sniff_loop handler if possible - otherwise fail to old behavior // use enable_if to invoke the Packet&& version of the sniff_loop handler if possible - otherwise fail to old behavior
template <class Functor, class Packet> template <typename Functor, typename Packet>
bool invoke_loop_cb(Functor& f, Packet& p, typename std::enable_if<accepts_type<Functor, Packet>::value, bool>::type* = 0) { bool invoke_loop_cb(Functor& f, Packet& p, typename std::enable_if<accepts_type<Functor, Packet>::value, bool>::type* = 0) {
return f(std::move(p)); return f(std::move(p));
} }
template <class Functor, class Packet> template <typename Functor, typename Packet>
bool invoke_loop_cb(Functor& f, Packet& p, typename std::enable_if<!accepts_type<Functor, Packet>::value && accepts_type<Functor, Packet&>::value, bool>::type* = 0) { bool invoke_loop_cb(Functor& f, Packet& p, typename std::enable_if<!accepts_type<Functor, Packet>::value && accepts_type<Functor, Packet&>::value, bool>::type* = 0) {
return f(p); return f(p);
} }
template <class Functor, class Packet> template <typename Functor, typename Packet>
bool invoke_loop_cb(Functor& f, Packet& p, typename std::enable_if<!accepts_type<Functor, Packet>::value && !accepts_type<Functor, Packet&>::value, bool>::type* = 0) { bool invoke_loop_cb(Functor& f, Packet& p, typename std::enable_if<!accepts_type<Functor, Packet>::value && !accepts_type<Functor, Packet&>::value, bool>::type* = 0) {
return f(*p.pdu()); return f(*p.pdu());
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,11 @@
#include "cxxstd.h" #include "cxxstd.h"
namespace Tins { namespace Tins {
namespace Memory {
class OutputMemoryStream;
} // Memory
/** /**
* \class IP * \class IP
@@ -48,8 +53,15 @@ namespace Tins {
* By default, IP PDUs are initialized, setting TTL to IP::DEFAULT_TTL, * 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 * 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. * 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 IP : public PDU { class TINS_API IP : public PDU {
public: public:
/** /**
* This PDU's flag. * This PDU's flag.
@@ -61,6 +73,15 @@ namespace Tins {
*/ */
typedef IPv4Address address_type; 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. * \brief Enum indicating the option's class.
* *
@@ -81,7 +102,7 @@ namespace Tins {
END = 0, END = 0,
NOOP = 1, NOOP = 1,
SEC = 2, SEC = 2,
LSSR = 3, LSRR = 3,
TIMESTAMP = 4, TIMESTAMP = 4,
EXTSEC = 5, EXTSEC = 5,
RR = 7, RR = 7,
@@ -180,11 +201,12 @@ namespace Tins {
uint16_t handling_restrictions; uint16_t handling_restrictions;
small_uint<24> transmission_control; small_uint<24> transmission_control;
security_type(uint16_t sec = 0, uint16_t comp = 0, security_type(uint16_t sec = 0,
uint16_t hand_res = 0, small_uint<24> tcc = 0) uint16_t comp = 0,
uint16_t hand_res = 0,
small_uint<24> tcc = 0)
: security(sec), compartments(comp), : security(sec), compartments(comp),
handling_restrictions(hand_res), transmission_control(tcc) handling_restrictions(hand_res), transmission_control(tcc) { }
{}
static security_type from_option(const option& opt); static security_type from_option(const option& opt);
}; };
@@ -198,8 +220,7 @@ namespace Tins {
uint8_t pointer; uint8_t pointer;
routes_type routes; routes_type routes;
generic_route_option_type(uint8_t ptr = 0, generic_route_option_type(uint8_t ptr = 0, routes_type rts = routes_type())
routes_type rts = routes_type())
: pointer(ptr), routes(rts) {} : pointer(ptr), routes(rts) {}
static generic_route_option_type from_option(const option& opt); static generic_route_option_type from_option(const option& opt);
@@ -225,6 +246,14 @@ namespace Tins {
*/ */
typedef std::list<option> options_type; typedef std::list<option> options_type;
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/** /**
* \brief Constructor for building the IP PDU. * \brief Constructor for building the IP PDU.
* *
@@ -258,14 +287,18 @@ namespace Tins {
* *
* \return The number of dwords the header occupies in an uin8_t. * \return The number of dwords the header occupies in an uin8_t.
*/ */
small_uint<4> head_len() const { return this->_ip.ihl; } small_uint<4> head_len() const {
return this->header_.ihl;
}
/** /**
* \brief Getter for the type of service field. * \brief Getter for the type of service field.
* *
* \return The this IP PDU's type of service. * \return The this IP PDU's type of service.
*/ */
uint8_t tos() const { return _ip.tos; } uint8_t tos() const {
return header_.tos;
}
/** /**
* \brief Getter for the total length field. * \brief Getter for the total length field.
@@ -273,7 +306,7 @@ namespace Tins {
* \return The total length of this IP PDU. * \return The total length of this IP PDU.
*/ */
uint16_t tot_len() const { uint16_t tot_len() const {
return Endian::be_to_host(_ip.tot_len); return Endian::be_to_host(header_.tot_len);
} }
/** /**
@@ -281,60 +314,104 @@ namespace Tins {
* *
* \return The id for this IP PDU. * \return The id for this IP PDU.
*/ */
uint16_t id() const { return Endian::be_to_host(_ip.id); } uint16_t id() const {
return Endian::be_to_host(header_.id);
}
/** /**
* \brief Getter for the fragment offset field. * \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. * \return The fragment offset for this IP PDU.
* \sa IP::fragment_offset
* \sa IP::flags
*/ */
uint16_t frag_off() const { return Endian::be_to_host(_ip.frag_off); } TINS_DEPRECATED(uint16_t frag_off() const) {
return Endian::be_to_host(header_.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(header_.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(header_.frag_off) >> 13);
}
/** /**
* \brief Getter for the time to live field. * \brief Getter for the time to live field.
* *
* \return The time to live for this IP PDU. * \return The time to live for this IP PDU.
*/ */
uint8_t ttl() const { return _ip.ttl; } uint8_t ttl() const {
return header_.ttl;
}
/** /**
* \brief Getter for the protocol field. * \brief Getter for the protocol field.
* *
* \return The protocol for this IP PDU. * \return The protocol for this IP PDU.
*/ */
uint8_t protocol() const { return _ip.protocol; } uint8_t protocol() const {
return header_.protocol;
}
/** /**
* \brief Getter for the checksum field. * \brief Getter for the checksum field.
* *
* \return The checksum for this IP PDU. * \return The checksum for this IP PDU.
*/ */
uint16_t checksum() const { return Endian::be_to_host(_ip.check); } uint16_t checksum() const {
return Endian::be_to_host(header_.check);
}
/** /**
* \brief Getter for the source address field. * \brief Getter for the source address field.
* *
* \return The source address for this IP PDU. * \return The source address for this IP PDU.
*/ */
address_type src_addr() const { return address_type(_ip.saddr); } address_type src_addr() const {
return address_type(header_.saddr);
}
/** /**
* \brief Getter for the destination address field. * \brief Getter for the destination address field.
* \return The destination address for this IP PDU. * \return The destination address for this IP PDU.
*/ */
address_type dst_addr() const { return address_type(_ip.daddr); } address_type dst_addr() const {
return address_type(header_.daddr);
}
/** /**
* \brief Getter for the version field. * \brief Getter for the version field.
* \return The version for this IP PDU. * \return The version for this IP PDU.
*/ */
small_uint<4> version() const { return _ip.version; } small_uint<4> version() const {
return header_.version;
}
/** /**
* \brief Getter for the IP options. * \brief Getter for the IP options.
* \return The stored options. * \return The stored options.
*/ */
const options_type &options() const { return _ip_options; } const options_type& options() const {
return ip_options_;
}
/* Setters */ /* Setters */
@@ -355,9 +432,32 @@ namespace Tins {
/** /**
* \brief Setter for the fragment offset field. * \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. * \param new_frag_off The new fragment offset.
* \sa IP::fragment_offset
* \sa IP::flags
*/ */
void frag_off(uint16_t new_frag_off); 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. * \brief Setter for the time to live field.
@@ -425,7 +525,7 @@ namespace Tins {
*/ */
void add_option(option &&opt) { void add_option(option &&opt) {
internal_add_option(opt); internal_add_option(opt);
_ip_options.push_back(std::move(opt)); ip_options_.push_back(std::move(opt));
} }
/** /**
@@ -438,11 +538,22 @@ namespace Tins {
*/ */
template<typename... Args> template<typename... Args>
void add_option(Args&&... args) { void add_option(Args&&... args) {
_ip_options.emplace_back(std::forward<Args>(args)...); ip_options_.emplace_back(std::forward<Args>(args)...);
internal_add_option(_ip_options.back()); internal_add_option(ip_options_.back());
} }
#endif #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. * \brief Searchs for an option that matchs the given flag.
* *
@@ -572,7 +683,7 @@ namespace Tins {
/** /**
* \brief Returns the header size. * \brief Returns the header size.
* *
* This metod overrides PDU::header_size. \sa PDU::header_size * This method overrides PDU::header_size. \sa PDU::header_size
*/ */
uint32_t header_size() const; uint32_t header_size() const;
@@ -582,7 +693,7 @@ namespace Tins {
void send(PacketSender& sender, const NetworkInterface &); void send(PacketSender& sender, const NetworkInterface &);
/** /**
* \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 * \sa PDU::matches_response
* \param ptr The pointer to the buffer. * \param ptr The pointer to the buffer.
@@ -609,7 +720,9 @@ namespace Tins {
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* \sa PDU::pdu_type * \sa PDU::pdu_type
*/ */
PDUType pdu_type() const { return PDU::IP; } PDUType pdu_type() const {
return pdu_flag;
}
/** /**
* \sa PDU::clone * \sa PDU::clone
@@ -621,7 +734,7 @@ namespace Tins {
static const uint8_t DEFAULT_TTL; static const uint8_t DEFAULT_TTL;
TINS_BEGIN_PACK TINS_BEGIN_PACK
struct iphdr { struct ip_header {
#if TINS_IS_LITTLE_ENDIAN #if TINS_IS_LITTLE_ENDIAN
uint8_t ihl:4, uint8_t ihl:4,
version:4; version:4;
@@ -638,10 +751,8 @@ namespace Tins {
uint16_t check; uint16_t check;
uint32_t saddr; uint32_t saddr;
uint32_t daddr; uint32_t daddr;
/*The options start here. */
} TINS_END_PACK; } TINS_END_PACK;
void head_len(small_uint<4> new_head_len); void head_len(small_uint<4> new_head_len);
void tot_len(uint16_t new_tot_len); void tot_len(uint16_t new_tot_len);
@@ -649,15 +760,19 @@ namespace Tins {
void internal_add_option(const option& option); void internal_add_option(const option& option);
void init_ip_fields(); void init_ip_fields();
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);
uint8_t* write_option(const option &opt, uint8_t* buffer); void write_option(const option& opt, Memory::OutputMemoryStream& stream);
void add_route_option(option_identifier id, const generic_route_option_type& data); void add_route_option(option_identifier id, const generic_route_option_type& data);
generic_route_option_type search_route_option(option_identifier id) const; generic_route_option_type search_route_option(option_identifier id) const;
void checksum(uint16_t new_check); 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();
iphdr _ip; ip_header header_;
uint16_t _options_size, _padded_options_size; uint16_t options_size_, padded_options_size_;
options_type _ip_options; options_type ip_options_;
}; };
}
} // Tins
#endif // TINS_IP_H #endif // TINS_IP_H

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -34,13 +34,14 @@
#include <iostream> #include <iostream>
#include <stdint.h> #include <stdint.h>
#include "cxxstd.h" #include "cxxstd.h"
#include "macros.h"
namespace Tins { namespace Tins {
/** /**
* \class IPv4Address * \class IPv4Address
* \brief Abstraction of an IPv4 address. * \brief Abstraction of an IPv4 address.
*/ */
class IPv4Address { class TINS_API IPv4Address {
public: public:
/** /**
* The address size. * The address size.
@@ -102,7 +103,7 @@ public:
* \return bool indicating whether this address equals rhs. * \return bool indicating whether this address equals rhs.
*/ */
bool operator==(const IPv4Address& rhs) const { bool operator==(const IPv4Address& rhs) const {
return ip_addr == rhs.ip_addr; return ip_addr_ == rhs.ip_addr_;
} }
/** /**
@@ -123,7 +124,7 @@ public:
* \return bool indicating whether this address is less-than rhs. * \return bool indicating whether this address is less-than rhs.
*/ */
bool operator< (const IPv4Address& rhs) const { bool operator< (const IPv4Address& rhs) const {
return ip_addr < rhs.ip_addr; return ip_addr_ < rhs.ip_addr_;
} }
/** /**
@@ -179,21 +180,23 @@ public:
private: private:
uint32_t ip_to_int(const char* ip); uint32_t ip_to_int(const char* ip);
uint32_t ip_addr; uint32_t ip_addr_;
}; };
} //namespace Tins
} // Tins
#if TINS_IS_CXX11 #if TINS_IS_CXX11
namespace std namespace std {
{
template<> template<>
struct hash<Tins::IPv4Address> { struct hash<Tins::IPv4Address> {
size_t operator()(const Tins::IPv4Address& addr) const { size_t operator()(const Tins::IPv4Address& addr) const {
return std::hash<uint32_t>()(addr); return std::hash<uint32_t>()(addr);
} }
}; };
} // namespace std
#endif
} // std
#endif // TINS_IS_CXX11
#endif // TINS_IPADDRESS_H #endif // TINS_IPADDRESS_H

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -33,9 +33,11 @@
#include <vector> #include <vector>
#include <map> #include <map>
#include "pdu.h" #include "pdu.h"
#include "macros.h"
#include "ip_address.h" #include "ip_address.h"
namespace Tins { namespace Tins {
/** /**
* \cond * \cond
*/ */
@@ -49,8 +51,7 @@ public:
template<typename T> template<typename T>
IPv4Fragment(T* pdu, uint16_t offset) IPv4Fragment(T* pdu, uint16_t offset)
: payload_(pdu->serialize()), offset_(offset) : payload_(pdu->serialize()), offset_(offset) {
{
} }
@@ -66,7 +67,7 @@ private:
uint16_t offset_; uint16_t offset_;
}; };
class IPv4Stream { class TINS_API IPv4Stream {
public: public:
IPv4Stream(); IPv4Stream();
@@ -79,10 +80,10 @@ private:
uint16_t extract_offset(const IP* ip); uint16_t extract_offset(const IP* ip);
bool extract_more_frag(const IP* ip); bool extract_more_frag(const IP* ip);
fragments_type fragments; fragments_type fragments_;
bool received_end; bool received_end_;
uint8_t transport_proto; uint8_t transport_proto_;
size_t received_size, total_size; size_t received_size_, total_size_;
}; };
} // namespace Internals } // namespace Internals
@@ -92,32 +93,61 @@ private:
/** /**
* \brief Reassembles fragmented IP packets. * \brief Reassembles fragmented IP packets.
*
* This class is fairly simple: just feed packets into it using IPv4Reassembler::process.
* If the return value is IPv4Reassembler::FRAGMENTED, then the packet is fragmented
* and we haven't yet seen the missing fragments, hence we can't reassemble it.
* If the function returns either IPv4Reassembler::NOT_FRAGMENTED (meaning the
* packet wasn't fragmented) or IPv4Reassembler::REASSEMBLED (meaning the packet was
* fragmented but it's now reassembled), then you can process the packet normally.
*
* Simple example:
*
* \code
* IPv4Reassembler reassembler;
* Sniffer sniffer = ...;
* sniffer.sniff_loop([&](PDU& pdu) {
* // Process it in any case, unless it's fragmented (and can't be reassembled yet)
* if (reassembler.process(pdu) != IPv4Reassembler::FRAGMENTED) {
* // Now actually process the packet
* process_packet(pdu);
* }
* });
* \endcode
*/ */
class IPv4Reassembler { class TINS_API IPv4Reassembler {
public: public:
/** /**
* The status of each processed packet. * The status of each processed packet.
*/ */
enum packet_status { enum PacketStatus {
NOT_FRAGMENTED, NOT_FRAGMENTED, ///< The given packet is not fragmented
FRAGMENTED, FRAGMENTED, ///< The given packet is fragmented and can't be reassembled yet
REASSEMBLED REASSEMBLED ///< The given packet was fragmented but is now reassembled
}; };
TINS_DEPRECATED(typedef PacketStatus packet_status);
/** /**
* The type used to represent the overlapped segment * The type used to represent the overlapped segment reassembly
* reassembly technique to be used. * technique to be used.
*/ */
enum overlapping_technique { enum OverlappingTechnique {
NONE NONE
}; };
/**
* Default constructor
*/
IPv4Reassembler();
/** /**
* Constructs an IPV4Reassembler. * Constructs an IPV4Reassembler.
*
* \param technique The technique to be used for reassembling * \param technique The technique to be used for reassembling
* overlapped fragments. * overlapped fragments.
*/ */
IPv4Reassembler(overlapping_technique technique = NONE); IPv4Reassembler(OverlappingTechnique technique);
/** /**
* \brief Processes a PDU and tries to reassemble it. * \brief Processes a PDU and tries to reassemble it.
@@ -133,7 +163,7 @@ public:
* fragmented or REASSEMBLED if the packet was fragmented * fragmented or REASSEMBLED if the packet was fragmented
* but has now been reassembled. * but has now been reassembled.
*/ */
packet_status process(PDU &pdu); PacketStatus process(PDU& pdu);
/** /**
* Removes all of the packets and data stored. * Removes all of the packets and data stored.
@@ -159,8 +189,8 @@ private:
key_type make_key(const IP* ip) const; key_type make_key(const IP* ip) const;
address_pair make_address_pair(IPv4Address addr1, IPv4Address addr2) const; address_pair make_address_pair(IPv4Address addr1, IPv4Address addr2) const;
streams_type streams; streams_type streams_;
overlapping_technique technique; OverlappingTechnique technique_;
}; };
/** /**
@@ -175,8 +205,7 @@ public:
* \param func The functor object. * \param func The functor object.
*/ */
IPv4ReassemblerProxy(Functor func) IPv4ReassemblerProxy(Functor func)
: functor_(func) : functor_(func) {
{
} }
@@ -190,13 +219,15 @@ public:
*/ */
bool operator()(PDU& pdu) { bool operator()(PDU& pdu) {
// Forward it unless it's fragmented. // Forward it unless it's fragmented.
if(reassembler.process(pdu) != IPv4Reassembler::FRAGMENTED) if (reassembler_.process(pdu) != IPv4Reassembler::FRAGMENTED) {
return functor_(pdu); return functor_(pdu);
else }
else {
return true; return true;
} }
}
private: private:
IPv4Reassembler reassembler; IPv4Reassembler reassembler_;
Functor functor_; Functor functor_;
}; };
@@ -210,7 +241,7 @@ template<typename Functor>
IPv4ReassemblerProxy<Functor> make_ipv4_reassembler_proxy(Functor func) { IPv4ReassemblerProxy<Functor> make_ipv4_reassembler_proxy(Functor func) {
return IPv4ReassemblerProxy<Functor>(func); return IPv4ReassemblerProxy<Functor>(func);
} }
}
} // Tins
#endif // TINS_IP_REASSEMBLER_H #endif // TINS_IP_REASSEMBLER_H

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -31,15 +31,17 @@
#define TINS_IPSEC_H #define TINS_IPSEC_H
#include "pdu.h" #include "pdu.h"
#include "macros.h"
#include "endianness.h" #include "endianness.h"
#include "small_uint.h" #include "small_uint.h"
namespace Tins { namespace Tins {
/** /**
* \class IPSecAH * \class IPSecAH
* \brief Represents an IPSec Authentication Header. * \brief Represents an IPSec Authentication Header.
*/ */
class IPSecAH : public PDU { class TINS_API IPSecAH : public PDU {
public: public:
/** /**
* This PDU's flag. * This PDU's flag.
@@ -74,7 +76,7 @@ public:
* \return The stored Next header field value. * \return The stored Next header field value.
*/ */
uint8_t next_header() const { uint8_t next_header() const {
return _header.next_header; return header_.next_header;
} }
/** /**
@@ -82,7 +84,7 @@ public:
* \return The stored Length field value. * \return The stored Length field value.
*/ */
uint8_t length() const { uint8_t length() const {
return _header.length; return header_.length;
} }
/** /**
@@ -90,7 +92,7 @@ public:
* \return The stored Security Parameters Index field value. * \return The stored Security Parameters Index field value.
*/ */
uint32_t spi() const { uint32_t spi() const {
return Endian::be_to_host(_header.spi); return Endian::be_to_host(header_.spi);
} }
/** /**
@@ -98,7 +100,7 @@ public:
* \return The stored Sequence number field value. * \return The stored Sequence number field value.
*/ */
uint32_t seq_number() const { uint32_t seq_number() const {
return Endian::be_to_host(_header.seq_number); return Endian::be_to_host(header_.seq_number);
} }
/** /**
@@ -106,7 +108,7 @@ public:
* \return The stored ICV field value. * \return The stored ICV field value.
*/ */
const byte_array& icv() const { const byte_array& icv() const {
return _icv; return icv_;
} }
// Setters // Setters
@@ -137,14 +139,14 @@ public:
/** /**
* \brief Setter for the ICV field. * \brief Setter for the ICV field.
* \param new_icv The new ICV field value. * \param newicv_ The new ICV field value.
*/ */
void icv(const byte_array &new_icv); void icv(const byte_array& newicv_);
/** /**
* \brief Returns the header size. * \brief Returns the header size.
* *
* This metod overrides PDU::header_size. \sa PDU::header_size * This method overrides PDU::header_size. \sa PDU::header_size
*/ */
uint32_t header_size() const; uint32_t header_size() const;
@@ -161,21 +163,21 @@ public:
return new IPSecAH(*this); return new IPSecAH(*this);
} }
private: private:
struct header { struct ipsec_header {
uint8_t next_header, length; uint8_t next_header, length;
uint32_t spi, seq_number; uint32_t spi, seq_number;
}; };
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU *); void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU *);
header _header; ipsec_header header_;
byte_array _icv; byte_array icv_;
}; };
/** /**
* \brief Represents an IPSec Authentication Header. * \brief Represents an IPSec Authentication Header.
*/ */
class IPSecESP : public PDU { class TINS_API IPSecESP : public PDU {
public: public:
/** /**
* This PDU's flag. * This PDU's flag.
@@ -207,7 +209,7 @@ public:
* \return The stored Security Parameters Index field value. * \return The stored Security Parameters Index field value.
*/ */
uint32_t spi() const { uint32_t spi() const {
return Endian::be_to_host(_header.spi); return Endian::be_to_host(header_.spi);
} }
/** /**
@@ -215,7 +217,7 @@ public:
* \return The stored Sequence number field value. * \return The stored Sequence number field value.
*/ */
uint32_t seq_number() const { uint32_t seq_number() const {
return Endian::be_to_host(_header.seq_number); return Endian::be_to_host(header_.seq_number);
} }
// Setters // Setters
@@ -235,7 +237,7 @@ public:
/** /**
* \brief Returns the header size. * \brief Returns the header size.
* *
* This metod overrides PDU::header_size. \sa PDU::header_size * This method overrides PDU::header_size. \sa PDU::header_size
*/ */
uint32_t header_size() const; uint32_t header_size() const;
@@ -252,13 +254,13 @@ public:
return new IPSecESP(*this); return new IPSecESP(*this);
} }
private: private:
struct header { struct ipsec_header {
uint32_t spi, seq_number; uint32_t spi, seq_number;
}; };
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU *); void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU *);
header _header; ipsec_header header_;
}; };
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -40,13 +40,19 @@
#include "ipv6_address.h" #include "ipv6_address.h"
namespace Tins { namespace Tins {
namespace Memory {
class OutputMemoryStream;
} // Memory
class PacketSender; class PacketSender;
/** /**
* \class IPv6 * \class IPv6
* Represents an IPv6 PDU. * Represents an IPv6 PDU.
*/ */
class IPv6 : public PDU { class TINS_API IPv6 : public PDU {
public: public:
/** /**
* This PDU's flag. * This PDU's flag.
@@ -83,6 +89,14 @@ public:
NO_NEXT_HEADER = 59 NO_NEXT_HEADER = 59
}; };
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/** /**
* \brief Constructs an IPv6 object. * \brief Constructs an IPv6 object.
* *
@@ -114,7 +128,7 @@ public:
* \return The stored version field value. * \return The stored version field value.
*/ */
small_uint<4> version() const { small_uint<4> version() const {
return _header.version; return header_.version;
} }
/** /**
@@ -123,10 +137,10 @@ public:
*/ */
uint8_t traffic_class() const { uint8_t traffic_class() const {
#if TINS_IS_LITTLE_ENDIAN #if TINS_IS_LITTLE_ENDIAN
return ((_header.traffic_class << 4) & 0xf0) | return ((header_.traffic_class << 4) & 0xf0) |
((_header.flow_label[0] >> 4) & 0x0f); ((header_.flow_label[0] >> 4) & 0x0f);
#else #else
return _header.traffic_class; return header_.traffic_class;
#endif #endif
} }
@@ -136,11 +150,11 @@ public:
*/ */
small_uint<20> flow_label() const { small_uint<20> flow_label() const {
#if TINS_IS_LITTLE_ENDIAN #if TINS_IS_LITTLE_ENDIAN
return ((_header.flow_label[0] & 0x0f) << 16) return ((header_.flow_label[0] & 0x0f) << 16)
| (_header.flow_label[1] << 8) | (header_.flow_label[1] << 8)
| (_header.flow_label[2]); | (header_.flow_label[2]);
#else #else
return _header.flow_label; return header_.flow_label;
#endif #endif
} }
@@ -149,7 +163,7 @@ public:
* \return The stored payload_length field value. * \return The stored payload_length field value.
*/ */
uint16_t payload_length() const { uint16_t payload_length() const {
return Endian::be_to_host(_header.payload_length); return Endian::be_to_host(header_.payload_length);
} }
/** /**
@@ -157,7 +171,7 @@ public:
* \return The stored next_header field value. * \return The stored next_header field value.
*/ */
uint8_t next_header() const { uint8_t next_header() const {
return _header.next_header; return header_.next_header;
} }
/** /**
@@ -165,7 +179,7 @@ public:
* \return The stored hop_limit field value. * \return The stored hop_limit field value.
*/ */
uint8_t hop_limit() const { uint8_t hop_limit() const {
return _header.hop_limit; return header_.hop_limit;
} }
/** /**
@@ -173,7 +187,7 @@ public:
* \return The stored src_addr field value. * \return The stored src_addr field value.
*/ */
address_type src_addr() const { address_type src_addr() const {
return _header.src_addr; return header_.src_addr;
} }
/** /**
@@ -181,7 +195,7 @@ public:
* \return The stored dst_addr field value. * \return The stored dst_addr field value.
*/ */
address_type dst_addr() const { address_type dst_addr() const {
return _header.dst_addr; return header_.dst_addr;
} }
/** /**
@@ -189,7 +203,7 @@ public:
* \return The stored headers. * \return The stored headers.
*/ */
const headers_type& headers() const { const headers_type& headers() const {
return ext_headers; return ext_headers_;
} }
// Setters // Setters
@@ -245,12 +259,12 @@ public:
/** /**
* \brief Returns the header size. * \brief Returns the header size.
* *
* This metod overrides PDU::header_size. \sa PDU::header_size * This method overrides PDU::header_size. \sa PDU::header_size
*/ */
uint32_t header_size() const; 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 * \sa PDU::matches_response
* \param ptr The pointer to the buffer. * \param ptr The pointer to the buffer.
@@ -299,7 +313,7 @@ public:
private: private:
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent); void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
void set_last_next_header(uint8_t value); void set_last_next_header(uint8_t value);
static uint8_t *write_header(const ext_header &header, uint8_t *buffer); static void write_header(const ext_header& header, Memory::OutputMemoryStream& stream);
static bool is_extension_header(uint8_t header_id); static bool is_extension_header(uint8_t header_id);
TINS_BEGIN_PACK TINS_BEGIN_PACK
@@ -322,9 +336,9 @@ private:
uint8_t src_addr[16], dst_addr[16]; uint8_t src_addr[16], dst_addr[16];
} TINS_END_PACK; } TINS_END_PACK;
ipv6_header _header; ipv6_header header_;
headers_type ext_headers; headers_type ext_headers_;
uint32_t headers_size; uint32_t headers_size_;
}; };
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -34,24 +34,15 @@
#include <stdexcept> #include <stdexcept>
#include <stdint.h> #include <stdint.h>
#include "cxxstd.h" #include "cxxstd.h"
#include "macros.h"
namespace Tins { namespace Tins {
/** /**
* Represents an IPv6 address. * Represents an IPv6 address.
*/ */
class IPv6Address { class TINS_API IPv6Address {
public: public:
/**
* The exception thrown when a malformed address is parsed.
*/
class malformed_address : public std::exception {
public:
const char *what() const throw() {
return "Malformed address";
}
};
static const size_t address_size = 16; static const size_t address_size = 16;
/** /**
@@ -104,21 +95,21 @@ public:
* Returns an iterator to the beginning of this address. * Returns an iterator to the beginning of this address.
*/ */
iterator begin() { iterator begin() {
return address; return address_;
} }
/** /**
* Returns a const iterator to the beginning of this address. * Returns a const iterator to the beginning of this address.
*/ */
const_iterator begin() const { const_iterator begin() const {
return address; return address_;
} }
/** /**
* Returns an iterator to the one-past-the-end element of this address. * Returns an iterator to the one-past-the-end element of this address.
*/ */
iterator end() { iterator end() {
return address + address_size; return address_ + address_size;
} }
/** /**
@@ -126,7 +117,7 @@ public:
* address. * address.
*/ */
const_iterator end() const { const_iterator end() const {
return address + address_size; return address_ + address_size;
} }
/** /**
@@ -137,7 +128,7 @@ public:
* \return bool indicating whether addresses are equal. * \return bool indicating whether addresses are equal.
*/ */
bool operator==(const IPv6Address& rhs) const { bool operator==(const IPv6Address& rhs) const {
return std::equal(begin(), end(), rhs.begin()); return std::equal(begin(), end(), rhs.address_);
} }
/** /**
@@ -211,20 +202,23 @@ public:
private: private:
void init(const char* addr); void init(const char* addr);
uint8_t address[address_size]; uint8_t address_[address_size];
}; };
} //namespace Tins
} // Tins
#if TINS_IS_CXX11 #if TINS_IS_CXX11
namespace std namespace std {
{
template<> template<>
struct hash<Tins::IPv6Address> { struct hash<Tins::IPv6Address> {
size_t operator()(const Tins::IPv6Address& addr) const { size_t operator()(const Tins::IPv6Address& addr) const {
return std::hash<std::string>()(addr.to_string()); return std::hash<std::string>()(addr.to_string());
} }
}; };
} // namespace std
#endif } // std
#endif // TINS_IS_CXX11
#endif // TINS_IPV6_ADDRESS #endif // TINS_IPV6_ADDRESS

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -35,6 +35,7 @@
#include <stdint.h> #include <stdint.h>
#include "macros.h" #include "macros.h"
#include "pdu.h" #include "pdu.h"
#include "macros.h"
#include "endianness.h" #include "endianness.h"
namespace Tins { namespace Tins {
@@ -45,7 +46,7 @@ namespace Tins {
* *
* This PDU follows the standard LLC frame described in the IEEE 802.2 specs. * This PDU follows the standard LLC frame described in the IEEE 802.2 specs.
*/ */
class LLC : public PDU { class TINS_API LLC : public PDU {
public: public:
/** /**
* \brief This PDU's flag. * \brief This PDU's flag.
@@ -192,7 +193,9 @@ namespace Tins {
* \param llc_type_class Value to set the llc_type_class field. * \param llc_type_class Value to set the llc_type_class field.
* \param receive_window XID sender's receive window size. * \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); void add_xid_information(uint8_t xid_id,
uint8_t llc_type_class,
uint8_t receive_window);
//TODO: Add Acknowledged connectionless information //TODO: Add Acknowledged connectionless information
@@ -202,31 +205,41 @@ namespace Tins {
* \brief Getter for the group destination bit. * \brief Getter for the group destination bit.
* \return Whether the group bit is set or not. * \return Whether the group bit is set or not.
*/ */
bool group() {return _header.dsap & 0x01; } bool group() {
return header_.dsap & 0x01;
}
/** /**
* \brief Getter for the dsap field. * \brief Getter for the dsap field.
* \return The dsap field value * \return The dsap field value
*/ */
uint8_t dsap() {return _header.dsap; } uint8_t dsap() {
return header_.dsap;
}
/** /**
* \brief Getter for the response bit. * \brief Getter for the response bit.
* \return Whether the response bit is set or not. * \return Whether the response bit is set or not.
*/ */
bool response() {return (_header.ssap & 0x01); } bool response() {
return (header_.ssap & 0x01);
}
/** /**
* \brief Getter for the ssap field. * \brief Getter for the ssap field.
* \return The ssap field. * \return The ssap field.
*/ */
uint8_t ssap() {return _header.ssap; } uint8_t ssap() {
return header_.ssap;
}
/** /**
* \brief Getter for the LLC frame format type. * \brief Getter for the LLC frame format type.
* \return The LLC frame format. * \return The LLC frame format.
*/ */
uint8_t type() {return _type; } uint8_t type() {
return type_;
}
/** /**
* \brief Getter for sender send sequence number. * \brief Getter for sender send sequence number.
@@ -279,8 +292,9 @@ namespace Tins {
* \return The supervisory function if format is SUPERVISORY else 0. * \return The supervisory function if format is SUPERVISORY else 0.
*/ */
uint8_t supervisory_function() { uint8_t supervisory_function() {
if (type() == SUPERVISORY) if (type() == SUPERVISORY) {
return control_field.super.supervisory_func; return control_field.super.supervisory_func;
}
return 0; return 0;
} }
@@ -290,8 +304,9 @@ namespace Tins {
* \return The modifier function if format is UNNUMBERED else 0. * \return The modifier function if format is UNNUMBERED else 0.
*/ */
uint8_t modifier_function() { uint8_t modifier_function() {
if (type() == UNNUMBERED) if (type() == UNNUMBERED) {
return (control_field.unnumbered.mod_func1 << 3) + control_field.unnumbered.mod_func2; return (control_field.unnumbered.mod_func1 << 3) + control_field.unnumbered.mod_func2;
}
return 0; return 0;
} }
@@ -307,7 +322,9 @@ namespace Tins {
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* \sa PDU::pdu_type * \sa PDU::pdu_type
*/ */
PDUType pdu_type() const { return pdu_flag; } PDUType pdu_type() const {
return pdu_flag;
}
/** /**
* \brief Delete all the information fields added. * \brief Delete all the information fields added.
@@ -383,21 +400,22 @@ namespace Tins {
#endif #endif
typedef std::vector<uint8_t> field_type; typedef std::vector<uint8_t> field_type;
typedef std::list<field_type> field_list;
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent); void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
llchdr _header; llchdr header_;
uint8_t control_field_length; uint8_t control_field_length_;
union { union {
info_control_field info; info_control_field info;
super_control_field super; super_control_field super;
un_control_field unnumbered; un_control_field unnumbered;
} control_field; } control_field;
Format _type; Format type_;
uint8_t information_field_length; uint8_t information_field_length_;
std::list<field_type> information_fields; field_list information_fields_;
}; };
} } // Tins
#endif // TINS_IEEE8022_H #endif // TINS_IEEE8022_H

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -34,7 +34,11 @@
#include "macros.h" #include "macros.h"
namespace Tins { namespace Tins {
class Loopback : public PDU {
/**
* \brief Represents a Loopback PDU
*/
class TINS_API Loopback : public PDU {
public: public:
/** /**
* This PDU's type. * This PDU's type.
@@ -67,7 +71,9 @@ public:
* \brief Getter for the family identifier. * \brief Getter for the family identifier.
* \return The stored family identifier. * \return The stored family identifier.
*/ */
uint32_t family() const { return _family; } uint32_t family() const {
return family_;
}
/** /**
* \brief Setter for the family identifier. * \brief Setter for the family identifier.
@@ -84,10 +90,12 @@ public:
* \brief Getter for the PDU's type. * \brief Getter for the PDU's type.
* \sa PDU::pdu_type * \sa PDU::pdu_type
*/ */
PDUType pdu_type() const { return pdu_flag; } PDUType pdu_type() const {
return pdu_flag;
}
/** /**
* \brief Check wether ptr points to a valid response for this PDU. * \brief Check whether ptr points to a valid response for this PDU.
* *
* \sa PDU::matches_response * \sa PDU::matches_response
* \param ptr The pointer to the buffer. * \param ptr The pointer to the buffer.
@@ -111,8 +119,9 @@ public:
private: private:
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent); void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
uint32_t _family; uint32_t family_;
}; };
}
} // Tins
#endif // TINS_LOOPBACK_H #endif // TINS_LOOPBACK_H

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -34,19 +34,40 @@
#include <sys/param.h> #include <sys/param.h>
#endif #endif
// Packing directives.... #include "config.h"
// Check if this is Visual Studio
#ifdef _MSC_VER #ifdef _MSC_VER
// This is Visual Studio
#define TINS_BEGIN_PACK __pragma( pack(push, 1) ) #define TINS_BEGIN_PACK __pragma( pack(push, 1) )
#define TINS_END_PACK __pragma( pack(pop) ) #define TINS_END_PACK __pragma( pack(pop) )
#define TINS_PACKED(DECLARATION) __pragma( pack(push, 1) ) DECLARATION __pragma( pack(pop) ) #define TINS_PACKED(DECLARATION) __pragma( pack(push, 1) ) DECLARATION __pragma( pack(pop) )
#define TINS_DEPRECATED(func) __declspec(deprecated) func #define TINS_DEPRECATED(func) __declspec(deprecated) func
#define TINS_NOEXCEPT #define TINS_NOEXCEPT
#define TINS_LIKELY(x) (x)
#define TINS_UNLIKELY(x) (x)
#else #else
// Not Vistual Studio. Assume this is gcc compatible
#define TINS_BEGIN_PACK #define TINS_BEGIN_PACK
#define TINS_END_PACK __attribute__((packed)) #define TINS_END_PACK __attribute__((packed))
#define TINS_PACKED(DECLARATION) DECLARATION __attribute__((packed)) #define TINS_PACKED(DECLARATION) DECLARATION __attribute__((packed))
#define TINS_DEPRECATED(func) func __attribute__ ((deprecated)) #define TINS_DEPRECATED(func) func __attribute__ ((deprecated))
#define TINS_NOEXCEPT noexcept #define TINS_NOEXCEPT noexcept
#endif #define TINS_LIKELY(x) __builtin_expect((x),1)
#define TINS_UNLIKELY(x) __builtin_expect((x),0)
#endif // _MSC_VER
#endif // If libtins was built into a shared library
#if defined(_WIN32) && !defined(TINS_STATIC)
// Export/import symbols, depending on whether we're compiling or consuming the lib
#ifdef tins_EXPORTS
#define TINS_API __declspec(dllexport)
#else
#define TINS_API __declspec(dllimport)
#endif // tins_EXPORTS
#else
// Otherwise, default this to an empty macro
#define TINS_API
#endif // _WIN32 && !TINS_STATIC
#endif // TINS_MACROS_H

View File

@@ -0,0 +1,264 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_MEMORY_HELPERS_H
#define TINS_MEMORY_HELPERS_H
#include <stdint.h>
#include <cstring>
#include <algorithm>
#include <vector>
#include "exceptions.h"
#include "ip_address.h"
#include "ipv6_address.h"
#include "hw_address.h"
#include "endianness.h"
namespace Tins {
/**
* \cond
*/
namespace Memory {
inline void read_data(const uint8_t* buffer, uint8_t* output_buffer, size_t size) {
std::memcpy(output_buffer, buffer, size);
}
template <typename T>
void read_value(const uint8_t* buffer, T& value) {
std::memcpy(&value, buffer, sizeof(value));
}
inline void write_data(uint8_t* buffer, const uint8_t* ptr, size_t size) {
std::memcpy(buffer, ptr, size);
}
template <typename T>
void write_value(uint8_t* buffer, const T& value) {
std::memcpy(buffer, &value, sizeof(value));
}
class InputMemoryStream {
public:
InputMemoryStream(const uint8_t* buffer, size_t total_sz)
: buffer_(buffer), size_(total_sz) {
}
InputMemoryStream(const std::vector<uint8_t>& data)
: buffer_(&data[0]), size_(data.size()) {
}
void skip(size_t size) {
if (TINS_UNLIKELY(size > size_)) {
throw malformed_packet();
}
buffer_ += size;
size_ -= size;
}
bool can_read(size_t byte_count) const {
return TINS_LIKELY(size_ >= byte_count);
}
template <typename T>
T read() {
T output;
read(output);
return output;
}
template <typename T>
T read_le() {
return Endian::le_to_host(read<T>());
}
template <typename T>
T read_be() {
return Endian::be_to_host(read<T>());
}
template <typename T>
void read(T& value) {
if (!can_read(sizeof(value))) {
throw malformed_packet();
}
read_value(buffer_, value);
skip(sizeof(value));
}
void read(std::vector<uint8_t>& value, size_t count) {
if (!can_read(count)) {
throw malformed_packet();
}
value.assign(pointer(), pointer() + count);
skip(count);
}
void read(IPv4Address& address) {
address = IPv4Address(read<uint32_t>());
}
void read(IPv6Address& address) {
if (!can_read(IPv6Address::address_size)) {
throw malformed_packet();
}
address = pointer();
skip(IPv6Address::address_size);
}
template <size_t n>
void read(HWAddress<n>& address) {
if (!can_read(HWAddress<n>::address_size)) {
throw malformed_packet();
}
address = pointer();
skip(HWAddress<n>::address_size);
}
void read(void* output_buffer, size_t output_buffer_size) {
if (!can_read(output_buffer_size)) {
throw malformed_packet();
}
read_data(buffer_, (uint8_t*)output_buffer, output_buffer_size);
skip(output_buffer_size);
}
const uint8_t* pointer() const {
return buffer_;
}
size_t size() const {
return size_;
}
void size(size_t new_size) {
size_ = new_size;
}
operator bool() const {
return size_ > 0;
}
private:
const uint8_t* buffer_;
size_t size_;
};
class OutputMemoryStream {
public:
OutputMemoryStream(uint8_t* buffer, size_t total_sz)
: buffer_(buffer), size_(total_sz) {
}
OutputMemoryStream(std::vector<uint8_t>& buffer)
: buffer_(&buffer[0]), size_(buffer.size()) {
}
void skip(size_t size) {
if (TINS_UNLIKELY(size > size_)) {
throw malformed_packet();
}
buffer_ += size;
size_ -= size;
}
template <typename T>
void write(const T& value) {
if (TINS_UNLIKELY(size_ < sizeof(value))) {
throw serialization_error();
}
write_value(buffer_, value);
skip(sizeof(value));
}
template <typename T>
void write_be(const T& value) {
write(Endian::host_to_be(value));
}
template <typename T>
void write_le(const T& value) {
write(Endian::host_to_le(value));
}
template <typename ForwardIterator>
void write(ForwardIterator start, ForwardIterator end) {
const size_t length = std::distance(start, end);
if (TINS_UNLIKELY(size_ < length)) {
throw serialization_error();
}
std::copy(start, end, buffer_);
skip(length);
}
void write(const uint8_t* ptr, size_t length) {
write(ptr, ptr + length);
}
void write(const IPv4Address& address) {
write(static_cast<uint32_t>(address));
}
void write(const IPv6Address& address) {
write(address.begin(), address.end());
}
template <size_t n>
void write(const HWAddress<n>& address) {
write(address.begin(), address.end());
}
void fill(size_t size, uint8_t value) {
if (TINS_UNLIKELY(size_ < size)) {
throw serialization_error();
}
std::fill(buffer_, buffer_ + size, value);
skip(size);
}
uint8_t* pointer() {
return buffer_;
}
size_t size() const {
return size_;
}
private:
uint8_t* buffer_;
size_t size_;
};
/**
* \endcond
*/
} // Memory
} // Tins
#endif // TINS_MEMORY_HELPERS_H

157
include/tins/mpls.h Normal file
View File

@@ -0,0 +1,157 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_MPLS_H
#define TINS_MPLS_H
#include "pdu.h"
#include "endianness.h"
#include "macros.h"
#include "small_uint.h"
namespace Tins {
class ICMPExtension;
/**
* \class MPLS
* \brief Represents an MPLS PDU
*/
class TINS_API MPLS : public PDU {
public:
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::MPLS;
/**
* \brief Default constructor
*/
MPLS();
/**
* \brief Construct an MPLS layer from an ICMP extension
*
* This will use the extension's payload to build this packet.
* The extension's class and type are not checked.
*
*/
MPLS(const ICMPExtension& extension);
/**
* \brief Constructor from buffer
*/
MPLS(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Getter for the label field.
*/
small_uint<20> label() const {
return (Endian::be_to_host(header_.label_high) << 4) |
((header_.label_low_and_bottom >> 4) & 0xf);
}
/**
* \brief Getter for the bottom of the stack field.
*/
small_uint<1> bottom_of_stack() const {
return header_.label_low_and_bottom & 0x1;
}
/**
* \brief Getter for the ttl field.
*/
uint8_t ttl() const {
return header_.ttl;
}
/**
* \brief Setter for the label field
*
* \param value The new label field value
*/
void label(small_uint<20> value);
/**
* \brief Setter for the bottom of the stack field
*
* Note that if this MPLS layer is somewhere between an Ethernet and IP
* layers, the bottom of the stack field will be overriden and set
* automatically. You should only set this field when constructing ICMP
* extensions.
*
* \param value The new bottom of the stack field value
*/
void bottom_of_stack(small_uint<1> value);
/**
* \brief Setter for the ttl field
*
* \param value The new ttl field value
*/
void ttl(uint8_t value);
/**
* \brief Returns the MPLS frame's header length.
*
* \return The header's size.
* \sa PDU::header_size()
*/
uint32_t header_size() const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const {
return pdu_flag;
}
/**
* \sa PDU::clone
*/
MPLS* clone() const {
return new MPLS(*this);
}
private:
TINS_BEGIN_PACK
struct mpls_header {
uint16_t label_high;
uint8_t label_low_and_bottom;
uint8_t ttl;
} TINS_END_PACK;
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
mpls_header header_;
};
} // Tins
#endif // TINS_MPLS_H

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Matias Fontanini * Copyright (c) 2016, Matias Fontanini
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -33,15 +33,18 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <stdint.h> #include <stdint.h>
#include "macros.h"
#include "hw_address.h" #include "hw_address.h"
#include "ip_address.h" #include "ip_address.h"
#include "ipv6_address.h"
namespace Tins { namespace Tins {
/** /**
* \class NetworkInterface * \class NetworkInterface
* \brief Abstraction of a network interface * \brief Abstraction of a network interface
*/ */
class NetworkInterface { class TINS_API NetworkInterface {
public: public:
/** /**
* \brief The type used to store the interface's identifier. * \brief The type used to store the interface's identifier.
@@ -53,12 +56,22 @@ public:
*/ */
typedef HWAddress<6> address_type; typedef HWAddress<6> address_type;
/**
*
*/
struct IPv6Prefix {
IPv6Address address;
uint32_t prefix_length;
};
/** /**
* \brief Struct that holds an interface's addresses. * \brief Struct that holds an interface's addresses.
*/ */
struct Info { struct Info {
IPv4Address ip_addr, netmask, bcast_addr; IPv4Address ip_addr, netmask, bcast_addr;
std::vector<IPv6Prefix> ipv6_addrs;
address_type hw_addr; address_type hw_addr;
bool is_up;
}; };
/** /**
@@ -112,7 +125,7 @@ public:
* \return id_type containing the identifier. * \return id_type containing the identifier.
*/ */
id_type id() const { id_type id() const {
return iface_id; return iface_id_;
} }
/** /**
@@ -126,14 +139,43 @@ public:
*/ */
std::string name() const; std::string name() const;
/**
* \brief Retrieves this interface's friendly name.
*
* The name returned by this method can be more human-friendly than
* the one returned by NetworkInterface::name, depending on the platform
* in which it's used.
*
* On GNU/Linux and OSX/FreeBSD, this returns the same string as
* NetworkInterface::name.
*
* On Windows, this method returns a name such as
* "Local Area Connection 1".
*
* Note thaat this returns a wstring rather than a string, to comply
* with Window's adapter's FriendlyName type.
*
* \return std::wstring containing this interface's name.
*/
std::wstring friendly_name() const;
/** /**
* \brief Retrieve this interface's addresses. * \brief Retrieve this interface's addresses.
* *
* This method is deprecated. You should use NetworkInterface::info (this
* is just a naming deprecation, NetworkInterface::info is equivalent).
* \deprecated
*/
Info addresses() const;
/**
* \brief Retrieve this interface's information.
*
* This method iterates through all the interface's until the * This method iterates through all the interface's until the
* correct one is found. Therefore it's O(N), being N the amount * correct one is found. Therefore it's O(N), being N the amount
* of interfaces in the system. * of interfaces in the system.
*/ */
Info addresses() const; Info info() const;
/** /**
* \brief Tests whether this is a valid interface; * \brief Tests whether this is a valid interface;
@@ -142,7 +184,7 @@ public:
* default constructor. * default constructor.
*/ */
operator bool() const { operator bool() const {
return iface_id != 0; return iface_id_ != 0;
} }
/** /**
@@ -151,13 +193,46 @@ public:
*/ */
bool is_loopback() const; bool is_loopback() const;
/**
* \brief Indicates whether this interface is up.
*
* This is equivalent to getting the interface info and checking for the is_up
* attribute.
*/
bool is_up() const;
/**
* \brief Retrieves the hardware address for this interface.
*/
address_type hw_address() const;
/**
* \brief Retrieves the IPv4 address for this interface.
*/
IPv4Address ipv4_address() const;
/**
* \brief Retrieves the IPv4 netmask for this interface.
*/
IPv4Address ipv4_mask() const;
/**
* \brief Retrieves the broadcast IPv4 address for this interface.
*/
IPv4Address ipv4_broadcast() const;
/**
* \brief Retrieves the IPv6 addresses for this interface.
*/
std::vector<IPv6Prefix> ipv6_addresses() const;
/** /**
* \brief Compares this interface for equality. * \brief Compares this interface for equality.
* *
* \param rhs The interface being compared. * \param rhs The interface being compared.
*/ */
bool operator==(const NetworkInterface& rhs) const { bool operator==(const NetworkInterface& rhs) const {
return iface_id == rhs.iface_id; return iface_id_ == rhs.iface_id_;
} }
/** /**
@@ -171,7 +246,9 @@ public:
private: private:
id_type resolve_index(const char* name); id_type resolve_index(const char* name);
id_type iface_id; id_type iface_id_;
}; };
}
} // Tins
#endif // TINS_NETWORK_INTERFACE_H #endif // TINS_NETWORK_INTERFACE_H

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