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

228 Commits
v0.2 ... v2.0

Author SHA1 Message Date
Matias F
ed175e0ad6 Updated CHANGES, README and configure.ac files. 2014-01-23 11:30:05 -03:00
Matias Fontanini
c5404a6111 Removed DNSResourceRecord. Records in DNS are now managed completely by DNS::Resource. 2014-01-21 22:56:53 -03:00
Matias Fontanini
6d7e06535a Fixed some endianness bugs on ICMPv6 and PPI. 2014-01-19 14:40:57 -03:00
Matias Fontanini
853e1ce647 tins.h now includes ppi.h. 2014-01-19 14:17:25 -03:00
Matias Fontanini
dbcdda9d36 Rewrote the DNS parsing algorithm. Everything is now done on the read buffer, without any extra data structures, making it work about 400% faster than before. 2014-01-19 13:11:50 -03:00
Matias Fontanini
17ceba6064 Fixed broken strict-aliasing rules on ICMPv6. 2014-01-15 19:56:58 -03:00
Matias Fontanini
52078cc567 Finished porting DHCPv6. 2014-01-15 19:39:07 -03:00
Matias Fontanini
e2656739f1 Ported DHCP and Dot11. Almost ported DHCPv6 completely. 2013-12-23 23:02:58 -03:00
Matias Fontanini
33091ccbae Ported PPPoE and started porting Dot11. 2013-12-18 13:02:41 -03:00
Matias Fontanini
ca6b603478 Finished porting ICMPv6. 2013-12-17 19:00:00 -03:00
Matias Fontanini
069ae82b10 Keep porting ICMPv6 to use PDUOption::to<>. 2013-12-17 00:10:26 -03:00
Matias Fontanini
ea6638c163 IP now uses PDUOption::to<>. Started porting ICMPv6 to do so as well. 2013-12-16 15:50:17 -03:00
Matias Fontanini
112a357726 Added PDUOption::to<>. TCP options now use this method when being converted to their appropriate types. 2013-12-16 14:11:53 -03:00
Matias Fontanini
0e54579200 Layer 3 packets sent using PacketSender::send_recv for which the answer is a different PDU type(such as ICMP destination unreachable), are detected by PacketSender and matched like usual. 2013-12-14 18:10:33 -03:00
Matias Fontanini
ccb8ffd1b5 ICMP::gateway is now an IPv4Address. 2013-12-14 14:28:39 -03:00
Matias Fontanini
b83c1a2a96 Added support for ICMP address mask request/reply. 2013-12-14 14:21:04 -03:00
Matias Fontanini
81a947e3b3 Fixed bug on ICMP checksum calculation when using timestamp request/replies. 2013-12-14 13:42:12 -03:00
Matias Fontanini
1cec0f106d Fixed bug in PacketSender when using send_recv and a layer 2 PDU. The interface in which the packet was sent was not the default_interface set when the sender was constructed. 2013-12-14 12:49:50 -03:00
Matias Fontanini
0acb0fee3e IP packets sent using PacketSender::send_recv now match ICMP responses. 2013-12-14 12:48:56 -03:00
Matias Fontanini
9b57585b62 Added support for ICMP timestamp request/reply packets. ICMP::matches_response now works with these types of packets as well. 2013-12-13 17:23:17 -03:00
Matias Fontanini
2ddec368c3 Fixed bug on IP when serializing fragmented packets.
The original protocol id was being overwritten with 0xff(unknown)
when the inner_pdu was a RawPDU, even if it was just a fragment of
a transport layer PDU. The protocol id is now kept if the packet
is fragmented.
2013-12-04 10:56:48 -03:00
matias
83dc8819b6 Updated README.md. 2013-11-24 16:37:10 -03:00
matias
5e668e6e83 Updated README.md 2013-11-24 13:31:19 -03:00
matias
ca4912ded4 Added README.md and updated README. 2013-11-24 11:07:39 -03:00
Matias Fontanini
295ebb679c Added 1000ms as the default read timeout used when calling pcap_open_live. Added BaseSniffer::set_timeout to modify this parameter. 2013-11-19 20:51:58 -03:00
Matias Fontanini
6355aff3cd Added IPv4Reassembler class. 2013-11-17 15:32:24 -03:00
Matias Fontanini
a6655191d4 Fragmented IP packet's inner_pdu PDUs are not decoded now. 2013-11-16 19:40:08 -03:00
Matias Fontanini
dc6c37777b Updated configure.ac and README files. 2013-11-10 14:14:25 -03:00
Matias Fontanini
23552ea105 Fixed issue with relative include paths in dot11 headers. 2013-11-10 11:55:36 -03:00
Matias Fontanini
9962381fc7 Added the --disable-dot11 configure switch. 2013-11-09 14:41:08 -03:00
Matias Fontanini
93ab8d3b91 Removed useless include directives from ip.cpp and ipv6.cpp. 2013-11-04 23:31:46 -03:00
Matias Fontanini
5345b29f8c Added support for IPSec. 2013-11-04 23:05:00 -03:00
Matias Fontanini
de06fee5ab Fixed bug triggered when ifaddrs::ifa_addr was null. 2013-11-04 15:53:55 -03:00
Matias Fontanini
6d329424f1 Created an overload of Internals::pdu_from_flag for transport layer PDUs. 2013-11-04 13:46:25 -03:00
Matias Fontanini
dfbbea33d5 Added another overload of Utils::route_entries and fixed a bug in Utils::network_interfaces. 2013-11-02 19:19:55 -03:00
Matias Fontanini
0b02af616a Added ARP monitor example. 2013-10-29 21:10:11 -03:00
Matias Fontanini
a101ec9796 Added the missing WPS detector example. 2013-10-29 19:19:53 -03:00
Matias Fontanini
b0868b5d60 Added another Sniffer constructor. 2013-10-21 23:31:07 -03:00
Matias Fontanini
f57b8c189c Added WPS detector example. Updated configure files. 2013-10-21 22:54:18 -03:00
Matias Fontanini
a507355e27 Added tins_cast as a replacement for dynamic_cast when using it on PDU classes. 2013-10-18 09:28:43 -03:00
Matias Fontanini
87fdd62b57 Added some examples. 2013-10-17 20:44:54 -03:00
Matias Fontanini
3337335df2 Fixed compilation error on internals.h. 2013-10-16 14:45:03 -03:00
Matias Fontanini
08113b8f5f Updated the CHANGES file. 2013-10-07 23:50:54 -03:00
Matias Fontanini
6dd949611d Modified some header documentation. 2013-10-07 23:31:22 -03:00
Matias Fontanini
b6a55935b4 Modified some Dot11ManagementFrame documentation. 2013-10-07 14:00:45 -03:00
Matias Fontanini
01b2a9c7b2 Modified some examples fixed some doxygen documentation. 2013-10-06 23:00:20 -03:00
Matias Fontanini
58e2c93e30 Added HWAddress and IPv4Address::is_unicast and a static const member 'broadcast' for both classes. 2013-10-06 22:56:00 -03:00
Matias Fontanini
bcfe26175a BaseSniffer now uses pcap_loop instead of pcap_dispatch. 2013-09-24 08:59:46 -03:00
Matias Fontanini
c4e6a7c0d6 Fixed some compilation errors/warnings and bugs when using Big Endian architectures. 2013-09-24 00:34:14 -03:00
Matias Fontanini
9cbac6b044 BaseSniffer::next_packet now uses pcap_dispatch. 2013-09-23 22:55:18 -03:00
Matias Fontanini
2414edd1e7 Fixed a bug in PPI and Dot1Q triggered when constructing from buffer/serializing. Done some documentation fixes. 2013-09-22 19:37:02 -03:00
Matias Fontanini
74ef177e25 Added address_range.cpp. 2013-09-21 01:21:15 -03:00
Matias Fontanini
54d012b92e Done some fixes on HWAddress. Added HWAddress::operator/ which returns an AddressRange. 2013-09-20 17:37:20 -03:00
Matias Fontanini
1b4efc1520 Rolled the BaseSniffer changes since that was OK. 2013-09-20 12:37:21 -03:00
Matias Fontanini
96ecd054ab Fixed issue with bpf_programs on BaseSniffer. Done some documentation changes. 2013-09-20 11:07:09 -03:00
Matias Fontanini
d7d2dec5cb Done some optimizations on TCP's constructor from buffer. 2013-09-15 16:01:00 -03:00
Matias Fontanini
20f3911e12 BaseSniffer::sniff_loop now uses begin() and end() to process packets, making it around 8% faster. Also added BaseSniffer::link_type to retrieve the pcap handle link type. 2013-09-15 12:16:54 -03:00
Matias Fontanini
f8d71687e1 Modified some classes' documentation. 2013-09-14 19:01:05 -03:00
Matias Fontanini
d393c1fbfc Moved calls to pcap_loop and pcap_breakloop to sniffer.cpp. 2013-09-08 19:20:52 -03:00
Matias Fontanini
e21e34e194 Added IPv4Address, IPv6Address and HWAddress<> 'is_multicast' member function. 2013-09-08 17:23:08 -03:00
Matias Fontanini
a01fff411e Added missing PPI files. 2013-09-05 09:09:56 -03:00
Matias Fontanini
7d4222fb17 Added PPI PDU. 2013-09-05 00:49:11 -03:00
Matias Fontanini
de0ec914cc Fixed bug in RadioTap. The flags field was being used even if it was not present. 2013-09-04 16:34:24 -03:00
Matias Fontanini
15f2896811 Added is_private and is_loopback methods to IPv4 and IPv6 addresses. 2013-09-04 12:57:36 -03:00
Matias Fontanini
b26f353e46 Added helper functions to Dot11Data to retrieve the source, destination and BSSID addresses. 2013-09-03 22:58:07 -03:00
Matias Fontanini
5f2c923c48 Added PDUAllocator class, which makes extending PDUs easier. 2013-08-29 23:31:10 -03:00
Matias Fontanini
4ca21bdad7 Fixed some issues when parsing DNS answers. MX records are now serialized correctly. 2013-08-04 14:27:03 -03:00
Matias Fontanini
2cc0ceb1aa Fixed bug triggered in DNS when parsing some unknown record types. 2013-07-25 10:47:09 -03:00
Matias Fontanini
7063e60af9 Merge branch 'master' of ssh://git.code.sf.net/p/libtins/code 2013-07-24 23:32:55 -03:00
Matias Fontanini
21b80a7370 BaseSniffer is now iterable. 2013-07-24 23:32:33 -03:00
Matias Fontanini
fb8fb92ee6 BaseSniffer::next_packet now loops until either a valid packet is found or pcap_next fails. 2013-07-24 22:27:53 -03:00
Santiago Alessandri
2a5b64526f Replaced tabs for spaces in the previous commit 2013-07-14 13:13:38 -03:00
Santiago Alessandri
02d3a14083 Fixed issue related with EthernetII protocol.
The Ethernet II protocol forces a minimum length of 60 bytes. It is necessary to add a trailer for padding of null-bytes when the inner_pdu's size does not meet the requirement.

Also EthernetII packets received were being incorrectly parsed due to the existance of this padding.

The issue has been solved and several tests were added. All tests successfully pass.
2013-07-12 20:06:55 -03:00
Matias Fontanini
3b349471ea Added AddressRange class template. 2013-07-06 17:48:26 -03:00
Matias Fontanini
f385e4e975 Added a const overload of TCP::get_flag. Added TCP::flags. 2013-06-17 21:25:30 -03:00
Matias Fontanini
acff8f1e1f The --disable-wpa2 switch now works as expected. 2013-06-15 10:00:50 -03:00
Matias Fontanini
59090e62d2 Added -Wno-extra-portability to automake's flags. 2013-06-07 10:28:19 -03:00
Matias Fontanini
74594a3b20 Updated CHANGES file. 2013-06-05 09:08:42 -03:00
Matias Fontanini
681bdc727f Updated configure.ac and README files. 2013-06-04 20:04:10 -03:00
Matias Fontanini
996e0f139e Fixed bug on Dot11QoSData. 2013-06-04 15:49:49 -03:00
Matias Fontanini
c2353314fa WEPDecrypter now returns true iff the packet was decrypted successfully. 2013-06-04 15:49:33 -03:00
Matias Fontanini
5d315c5b6d Fixed a CCMP padding bug. 2013-06-02 16:14:21 -03:00
Matias Fontanini
87ac5acdd8 WPA2Decrypter now decrypts both CCMP and TKIP encrypted traffic. 2013-06-01 21:29:06 -03:00
Matias Fontanini
3b4dc10211 Added HWAddress<>::operator[]. 2013-06-01 12:05:53 -03:00
Matias Fontanini
8c1d71c7b7 Both of WPA2Decrypter::add_supplicant_data overloads work. 2013-06-01 10:48:22 -03:00
Matias Fontanini
5db196a630 Fixed tests dependency file. 2013-05-31 22:33:50 -03:00
Matias Fontanini
ec8374be60 Split dot11.h and dot11.cpp into several files. 2013-05-31 22:16:56 -03:00
Matias Fontanini
eeb62add59 Added WPA2Decrypter tests. 2013-05-31 14:11:12 -03:00
Matias Fontanini
908fcb56e8 Added WPA2Decrypter class. 2013-05-30 23:36:14 -03:00
Matias Fontanini
ddf47365c1 RadioTap now calculates its size always while serializing. Added 2 missing RadioTap fields as well. 2013-05-30 18:14:11 -03:00
Matias Fontanini
b052aa1d88 Added HWAddress<>::is_broadcast. 2013-05-29 11:14:36 -03:00
Matias Fontanini
cacf75995d Added automake foreign option. 2013-05-28 15:19:00 -03:00
Matias Fontanini
4960077495 RSNHandshakeCapturer is now DefaultConstructible. 2013-05-28 10:15:33 -03:00
Matias Fontanini
8147a2bfb7 Added RSNHandshakeCapturer class. 2013-05-25 18:00:20 -03:00
Piotr Haber
28c8d393d6 do not parse Dot11 frame if FCS is wrong
Signed-off-by: Matias Fontanini <matias.fontanini@gmail.com>
2013-05-23 17:54:17 -03:00
Matias Fontanini
ec7e718e38 Implemented std::hash for IPv4Address and IPv6Address. 2013-05-21 13:07:14 -03:00
Matias Fontanini
62740e8e64 Implemented std::hash specialization for HWAddress. 2013-05-04 20:09:32 -03:00
Matias Fontanini
2bb699dc97 Merge branch 'master' of ssh://git.code.sf.net/p/libtins/code 2013-05-01 14:08:16 -03:00
Piotr Haber
14b1a4988b take wildcard SSID into account
Specification states (Ch 8.4.2.2 of IEEE Std 802.11-2007)
that in Probe Reqest frames SSID IE of length 0 signifies
"wildcard" SSID.
Return "BROADCAST" from Dot11ManagementFrame::ssid()
in such case.

Signed-off-by: Matias Fontanini <matias.fontanini@gmail.com>
2013-05-01 14:06:02 -03:00
Matias Fontanini
7f6e4446b4 Fixed the examples. 2013-04-24 12:07:52 -03:00
Matias Fontanini
cf19c8758d UDP now calculates the checksum when the transport layer protocol is IPv6. 2013-04-23 23:00:43 -03:00
Matias Fontanini
5197e7f5f1 Sniffer now differentiates between EthernetII and Dot3 when sniffing. 2013-04-23 22:55:32 -03:00
Matias Fontanini
eb87b82c17 Fixed the CHANGES and README files. 2013-04-23 20:57:56 -03:00
Matias Fontanini
5064a9255b Fixed BSD notice. Updated AUTHORS file. 2013-04-23 20:33:00 -03:00
Matias Fontanini
bf604339f0 Removed the PDU* parameter in several PDU's constructors. 2013-04-23 20:03:08 -03:00
Matias Fontanini
7e85058ef1 Added another overload of Utils::resolv_hwaddr. 2013-04-23 15:19:48 -03:00
Matias Fontanini
ec05a49cce Done minor modifications on configure.ac 2013-04-23 14:46:56 -03:00
Matias Fontanini
b0eefe15f9 Modified the soname. 2013-04-23 13:43:12 -03:00
Matias Fontanini
0f2bc45059 Moved definitions inside TINS_IS_CXX11 into header files. 2013-04-23 13:04:57 -03:00
Matias Fontanini
f8134be8b7 Done some modifications on the configure script. 2013-04-23 13:03:00 -03:00
Matias Fontanini
8afbe14c82 PacketSender is not copyable and movable. 2013-04-23 11:05:44 -03:00
Matias Fontanini
fdfb8b0dea Fixed compilation issues triggered in GNU/kFreeBSD. 2013-04-22 23:48:53 -03:00
Matias Fontanini
9be4f0ca37 Removed IP, UDP and IP checksum setters. Added some checksum tests. 2013-04-22 20:06:35 -03:00
Matias Fontanini
66ff604580 assert() is only called when TINS_DEBUG is defined. 2013-04-22 18:45:56 -03:00
Matias Fontanini
7e0e85db65 Added AC_CANONICAL_SYSTEM to configure.ac. 2013-04-22 13:58:42 -03:00
Matias Fontanini
ed39eb36f5 Dot11BlockAck and Dot11BlockAckRequests' frag_seq, start_sequence and bar_control now use small_uint rather than uintX_t. 2013-04-22 12:54:27 -03:00
Matias Fontanini
7da8de6ea7 Added another test case for RadioTap's constructor from buffer. 2013-04-22 12:53:01 -03:00
Matias Fontanini
d1b64ec48e PDU::matches_response is now const. 2013-04-21 20:03:47 -03:00
Matias Fontanini
69968cbc5c Removed deprecated methods/types. 2013-04-21 19:52:39 -03:00
Matias Fontanini
9e20c0241f Added a default interface to PacketSender. 2013-04-21 19:40:17 -03:00
Matias Fontanini
97f049580b Link layer PDUs no longer contain a NetworkInterface. 2013-04-21 18:50:08 -03:00
Matias Fontanini
6f04329fbe All tests now run successfully on big endian architectures. 2013-04-21 15:40:28 -03:00
Matias Fontanini
077b54bbed Added STP root_id and bridge_id setters/getters. 2013-04-21 13:22:15 -03:00
Matias Fontanini
759e92706f Sniffer::sniff_loop now catches malformed_packet and pdu_not_found, when thrown by the functor argument. 2013-04-21 13:21:47 -03:00
Matias Fontanini
2ea952d6ab Added PDU::rfind_pdu. 2013-04-19 22:27:48 -03:00
Matias Fontanini
91bdcca577 Dot11 now uses option_not_found. Sniffer catches malformed_packet rather than std::runtime_error while sniffing. 2013-04-19 14:06:59 -03:00
Matias Fontanini
75bd445bd3 Dot11 now uses malformed_packet. 2013-04-19 02:05:28 -03:00
Matias Fontanini
9812ad441f Added missing exceptions.h file. 2013-04-18 17:52:53 -03:00
Matias Fontanini
3fd1b3d37d Added malformed_packet exception. Every class except Dot11* use it. 2013-04-18 00:12:20 -03:00
Matias Fontanini
923f51ae15 Fixed bug triggered when parsing Dot11 QoS packets. 2013-04-16 15:01:48 -03:00
Matias Fontanini
804ea411fc Fixed bug in RadioTap when using FCS at the end. 2013-04-16 13:45:30 -03:00
Piotr Haber
9bcfd07896 fix radiotap header parsing
Signed-off-by: Matias Fontanini <matias.fontanini@gmail.com>
2013-04-16 13:37:31 -03:00
Matias Fontanini
58c8eccc46 Makefile issue fix. 2013-04-16 13:15:35 -03:00
Matias F
a674640ef2 Now hopefully make problems are fixed. 2013-04-16 13:00:12 -03:00
Matias F
dde890b24b Fixed make issues. 2013-04-16 12:51:07 -03:00
Matias Fontanini
38ccb4413b STP is now serialized correctly. LLC behaves correctly when it contains an STP is its inner pdu. 2013-04-16 01:05:06 -03:00
Matias F
9631734805 Added STP class. 2013-04-15 14:01:44 -03:00
Matias Fontanini
7faf514496 Merge branch 'master' of ssh://git.code.sf.net/p/libtins/code 2013-04-15 08:49:25 -03:00
Matias Fontanini
08091fc7c2 Added missing the deprecated header ieee802_3.h to Makefile.am. 2013-04-15 08:48:51 -03:00
Matias Fontanini
1450c8cf26 Fixed missing header in Makefile.in as well. 2013-04-15 08:41:21 -03:00
Matias Fontanini
b533775cb4 Added missing the deprecated header ieee802_3.h to Makefile.am. 2013-04-15 08:35:34 -03:00
Matias Fontanini
3f4c48ad9f Fixed bug triggered when parsing EOL and NOP options in IP. 2013-04-15 00:23:29 -03:00
Matias Fontanini
30d6a4f2e0 UDP checksum is now calculated always inside write_serialization. 2013-04-12 13:42:11 -03:00
Matias Fontanini
f4522acd44 IP and TCP now calculate checksums always inside write_serialization. 2013-04-11 00:57:36 -03:00
Matias Fontanini
1fbef641da TCP options now use PDUOption<>::length_field when it is != from data_size. 2013-04-10 18:44:00 -03:00
Matias Fontanini
fee938b46d Added move constructor/assignment operator to PDU. 2013-04-10 18:43:24 -03:00
Matias Fontanini
ae1e1c2ce2 Modified some protocols' internal type names. 2013-04-09 15:40:58 -03:00
Matias Fontanini
20054e6c73 Several classes now use PDUOption::length_field instead of data_size. 2013-04-08 11:58:12 -03:00
Matias Fontanini
f7f5a9bc9a Added PPPoE. 2013-04-07 20:57:43 -03:00
Matias Fontanini
f2a5f73337 Implemented matches_response on several PDUs. Added some test cases. 2013-04-02 21:05:53 -03:00
Matias Fontanini
97049140af Added some helper methods to Dot1Q. 2013-03-26 23:42:43 -03:00
Matias Fontanini
dfc0498b70 DNS, RadioTap and Dot1Q work when using PacketSender::send_recv. 2013-03-26 14:54:24 -03:00
Matias Fontanini
1cec099c0e Dot3::matches_response now works as expected. 2013-03-26 00:25:47 -03:00
Matias Fontanini
3989566608 Renamed IEEE802_3 to Dot3. 2013-03-25 15:35:30 -03:00
Matias Fontanini
b32586e739 Fixed compilation error on IP and TCP. 2013-03-25 15:17:26 -03:00
Matias Fontanini
82ef41dd92 IP now fills automatically the sender address when no link layer PDU is present. Made some protocols work when using PacketSender::send_recv. 2013-03-25 14:08:59 -03:00
Matias Fontanini
b0dc376494 Fixed compilation error in pdu_cacher.h. 2013-03-25 09:55:15 -03:00
Matias Fontanini
8be0c4c23c Marked PDU::clone_packet as deprecated. 2013-03-24 16:08:09 -03:00
Matias Fontanini
d7dd1e131f Added an overload of add_option that takes an rvalue-ref in IP, TCP, DHCP, ICMPv6 and Dot11. 2013-03-24 00:08:53 -03:00
Matias Fontanini
584fe81f04 Optimized TCP, IP and PDUOption<>. 2013-03-23 13:44:33 -03:00
Matias Fontanini
16a99ef35b Added an overload of PacketSender::send that takes a NetworkInterface. 2013-03-20 23:24:43 -03:00
Matias Fontanini
247273e086 Added constructor from buffer test for Dot11BlockAckRequest. 2013-03-18 13:32:34 -03:00
Matias Fontanini
0f27b04a92 Fixed lots of warnings in test cases, due to narrowing conversions. 2013-03-18 11:32:34 -03:00
Matias Fontanini
a8edc2af74 Added serialization test for Dot1Q. 2013-03-18 10:17:43 -03:00
Matias Fontanini
f5ecaa3faa Added Dot1Q class. 2013-03-17 23:27:34 -03:00
Matias Fontanini
b5f9f5095e Added Utils::resolve_domain and resolve_domain6. 2013-03-15 15:43:42 -03:00
Matias Fontanini
02a53da361 Fixed bug triggered when parsing RadioTap in BE architectures. 2013-03-15 15:13:00 -03:00
Matias Fontanini
f86f727810 Added RadioTap::iface. 2013-02-06 14:10:21 -03:00
Matias Fontanini
836dbd8955 Fixed compilation issue in 2 examples. 2013-02-01 13:55:29 -03:00
Matias Fontanini
a24e0d5a4b Done some changes on the build system. 2013-01-31 16:48:32 -03:00
Bruno Nery
c6dc18d215 Added get_fd() to BaseSniffer.
Signed-off-by: Matias Fontanini <matias.fontanini@gmail.com>
2013-01-29 20:25:48 -03:00
Matias Fontanini
931a86eff9 Done minor modification, mostly on documentation. 2013-01-29 16:18:08 -03:00
Matias Fontanini
2a1a28c3fb Added README, THANKS and CHANGES files. 2013-01-28 17:57:43 -03:00
Matias Fontanini
3f060de381 PacketWriter is now movable. 2013-01-28 17:56:59 -03:00
Matias Fontanini
0945e0b29e Added DHCPv6 client/server id options' getters/setters. 2013-01-28 16:23:47 -03:00
Matias Fontanini
5ee0ebb264 Added some fixes to the build system. Fixed bugs in DNS and ICMPv6 triggered in big-endian architectures. 2013-01-24 23:55:01 -03:00
Matias Fontanini
0dc762f15d Added missing build system files. 2013-01-24 13:52:45 -03:00
Matias Fontanini
c7c56a610c Done some -pedantic modifications. 2013-01-24 13:44:30 -03:00
Matias Fontanini
a826d92666 The build system now uses libtool. 2013-01-24 13:44:15 -03:00
Matias Fontanini
5b2e117347 Implemented every DHCPv6 option getter/setter, except for those involving DUIDs. 2013-01-22 23:24:10 -03:00
Matias Fontanini
e712550cb8 Move constructors are now noexcept. 2013-01-20 00:22:21 -03:00
Matias Fontanini
044d0a5a31 Added DHCPv6 initial support. 2013-01-16 20:15:04 -03:00
Matias Fontanini
9d0e84f1fa Added SLL tests. 2013-01-16 16:24:44 -03:00
Matias Fontanini
02265061cc Added SLL pseudo protocol header. 2013-01-16 00:05:28 -03:00
Bruno Nery
a13d7d0cb1 Fixed Timestamp::operator std::chrono::microseconds issue.
Signed-off-by: Matias Fontanini <matias.fontanini@gmail.com>
2013-01-15 18:38:35 -03:00
Matias Fontanini
7a86012292 IPv6::send now works on linux. BSD does not support sending IPv6 as the lowest layer. 2012-12-10 20:31:32 -03:00
Matias Fontanini
c933faaf5e Null/Loopback PDUs can now be sent on *BSD. 2012-12-09 13:05:39 -03:00
Matias Fontanini
a7e0c094fb Implemented several ICMPv6 option getters/setters. 2012-12-08 11:15:41 -03:00
Matias Fontanini
592a15ebe4 Added some ICMPv6 option getters/setters. 2012-12-05 23:33:09 -03:00
Matias Fontanini
75b32c75bc Added concat operator to Packet and an overload that takes a PDU*. 2012-12-05 17:04:39 -03:00
Matias Fontanini
765285c6ee Added several ICMPv6 option getters/setters. 2012-12-04 23:15:38 -03:00
Matias Fontanini
356fe00aad Fixed compilation error in OSX. Fixed bug when sending IP PDUs in BSD. 2012-12-04 16:15:08 -03:00
Matias Fontanini
647ba1f46e Fixed ternary operator associativity issue in dot11.h. 2012-12-03 20:56:47 -03:00
Matias Fontanini
53fe80d8a7 Added fix for IP::tot_len's endianess in OSX. 2012-12-03 20:34:15 -03:00
Matias Fontanini
742276c251 libtins compiles and runs under windows. Packets apparently can't be sent yet. 2012-12-02 20:25:05 -03:00
Matias Fontanini
6d1e96866e libtins now compiles on windows. A couple of features were disabled and need to be fixed though. 2012-12-02 00:45:10 -03:00
Matias Fontanini
dbe67c8cae DNSRecords are now movable.! 2012-12-01 20:18:23 -03:00
Matias Fontanini
dd9c0b3fd5 Fixed bugs in IPv6 and ICMPv6 when constructing an object from a buffer. 2012-12-01 13:43:19 -03:00
Matias Fontanini
9bdee61e5b Fixed some issues with Endian::change_endian triggered in OSX. 2012-11-29 21:30:13 -03:00
Matias Fontanini
e2426b493e configure script now works on BSD. 2012-11-29 18:00:41 -03:00
Matias Fontanini
acff776d56 Utils::route_entries now works on BSD. 2012-11-29 17:11:10 -03:00
Matias Fontanini
4036e7daa2 Merge branch 'master' of ssh://git.code.sf.net/p/libtins/code 2012-11-29 14:01:55 -03:00
Matias Fontanini
93b5b86c5d Added some ICMPv6 option getters/setters. 2012-11-29 14:01:22 -03:00
Matias Fontanini
de82dc2322 Link layer protocols can now be sent on BSD. 2012-11-28 16:50:47 -03:00
Matias Fontanini
6696c1b284 Ported almost everything to BSD. Utils::route_entries and sending link layer PDUs still don't work. 2012-11-28 00:11:42 -03:00
Matias Fontanini
e6e3e8453b Fixed some bugs in ICMPv6. 2012-11-26 19:47:15 -03:00
Matias Fontanini
4576d8746c Added another constructor to Packet. 2012-11-26 16:01:26 -03:00
Matias Fontanini
b42c868a66 Added .so file symlinks. 2012-11-26 15:50:06 -03:00
Matias Fontanini
a18cd3e0de PDU::find_pdu now has a const overload. 2012-11-26 15:38:53 -03:00
Matias Fontanini
88faee9b26 Added Packet conversion to bool. 2012-11-26 15:22:29 -03:00
Matias Fontanini
16a29fab3e Fixed memory leak in Packet's copy assignment operator. 2012-11-26 15:03:09 -03:00
Matias Fontanini
cd6bc16d48 Packets are now copyable and movable. 2012-11-26 14:02:50 -03:00
Matias Fontanini
443803caf0 Added ICMPv6 class. It's working. Option getters/setters are missing. 2012-11-24 18:50:21 -03:00
Matias Fontanini
75a4bbfed6 Added Timestamp conversion to std::chrono::microseconds. BaseSniffer is now movable. 2012-11-23 20:30:16 -03:00
Matias Fontanini
b74a353c17 Added packet.h and timestamp.h to tins.h 2012-11-23 18:56:39 -03:00
Matias Fontanini
492fd611f9 Added Packet and some wrapper packet classes. Modified the return value of BaseSniffer::next_packet. 2012-11-23 18:10:51 -03:00
Matias Fontanini
a938d2ecfd Added support for IPv6 extension headers. Specific headers getters and setters are not yet implemented. 2012-11-22 17:18:59 -03:00
Matias Fontanini
8276e7d086 Added IPv6 class. It's working, but there's no support for extension headers yet. 2012-11-21 22:09:58 -03:00
Matias Fontanini
ffdfb160c4 Added ipv6_address.h include to tins.h. 2012-11-21 15:52:31 -03:00
Matias Fontanini
bf6c086b3d Added BaseSniffer::timestamp method. 2012-11-21 13:33:28 -03:00
Matias Fontanini
08b4c92dac Added support for IPv6 addresses in DNS. 2012-11-20 23:57:02 -03:00
Matias Fontanini
2a0b248518 Added IPv6Address. 2012-11-20 23:46:22 -03:00
Matias Fontanini
60323ded9b AAAA records are now parsed correctly. 2012-11-20 21:19:05 -03:00
Matias Fontanini
f3ea99e0b0 Used a better strategy in DNSResourceRecord's constructor from buffer which will parse the data even if contains_dname returns false. 2012-11-20 18:31:33 -03:00
Matias Fontanini
7e080cf1ab Added some missing DNS record types which contain domain names to the 'contains_dname' helper function. 2012-11-20 18:27:59 -03:00
Matias Fontanini
688be1e1da Fixed the try/catch block in BaseSniffer::sniff_loop. It now only catches std::runtime_errors. 2012-11-20 16:33:26 -03:00
Bruno Nery
28e5df3abc Fixed BaseSniffer::next_packet() to return when error occurred. Updated its documentation.
Signed-off-by: Matias Fontanini <matias.fontanini@gmail.com>
2012-11-20 16:30:34 -03:00
Matias Fontanini
d0048e3aef Fixed bug in DNS triggered when adding two records for the same domain name. 2012-11-20 16:10:24 -03:00
215 changed files with 71236 additions and 11587 deletions

11
AUTHORS
View File

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

187
CHANGES Normal file
View File

@@ -0,0 +1,187 @@
v2.0 - Thu Jan 23 11:09:38 ART 2014
- DNSResourceRecord was removed. Now DNS records are added using
DNS::Resource.
- tins.h now includes ppi.h.
- Done significant improvements in the speed of DNS parsing.
- Added PDUOption<>::to<> which converts a PDUOption to a specific type.
- Layer 3 packets sent using PacketSender::send_recv for which the
answer is a different PDU type.
- ICMP::gateway now uses IPv4Address.
- Added support for ICMP address mask request/reply.
- Fixed bug in PacketSender when using send_recv and a layer 2 PDU. The
interface in which the packet was sent was not the default_interface
set when the sender was constructed.
- IP packets sent using PacketSender::send_recv now match ICMP
responses.
- Added support for ICMP timestamp request/reply packets.
ICMP::matches_response now works with these types of packets as well.
- Added support for reassembling of fragmented IP packets via the
IPv4Reassembler class.
- Fragmented IP packet's inner_pdu PDUs are not decoded now.
- Added 1000ms as the default read timeout used when calling
pcap_open_live. Added BaseSniffer::set_timeout to modify this parameter.
- Added the --disable-dot11 configure switch.
- Added support for IPSec.
- Fixed bug triggered when ifaddrs::ifa_addr was null in
NetworkInterface::addresses.
- Added another overload of Utils::route_entries which returns the
result either than storing it in a parameter.
- Added ARP monitor, WPS detector, DNS queries sniffer and DNS spoofer
examples.
- Added another Sniffer constructor which doesn't expect the maximum
capture size.
- Added tins_cast as a replacement for dynamic_cast on PDUs.
v1.2 - Mon oct 7 23:33:49 ART 2013
- Added BaseSniffer::begin and BaseSniffer::end.
- BaseSniffer::next_packet uses pcap_loop instead of pcap_next, which
doesn't work well on some linux distributions.
- Added PPI PDU class.
- Fixed a bug in EthernetII triggered when the size of the whole frame
was lower than 60 bytes.
- Added AddressRange class and IPv4Address, IPv6Address and
HWAddress<>::operator/.
- Added is_broadcast, is_multicast and is_unicast to IPv4, IPv6
and HWAddress.
- Added is_private and is_loopback methods to IPv4 and IPv6 addresses.
- Done some optimizations on TCP's constructor from buffer.
- Added helper functions to Dot11Data to retrieve the source,
destination and BSSID addresses.
- Fixed bugs in DNS triggered when parsing MX and unknown records.
- BaseSniffer::next_packet now iterates until a valid packet is found.
- TCP::get_flag is now const.
- The --disable-wpa2 now works as expected.
v1.1 - Wed Jun 5 09:03:37 ART 2013
- Implemented std::hash specialization for IPv4, IPv6 and HWAddress<>
types.
- Added a RSNHandshakeCapturer class.
- Added WPA2Decrypter class.
- IEEE 802.11 frames are not parsed if the RadioTap FAILED_FCS flag
is on.
- RadioTap now calculates its size everytime it's serialized.
- Splitted the dot11.h and dot11.cpp files into several files to
speed up compilation times.
- Added HWAddress<>::is_broadcast and HWAddress::operator[].
- Fixed a bug triggered when parsing Dot11QoSData frames.
v1.0 - Tue Apr 23 20:40:57 ART 2013
- Link layer protocol PDUs now don't hold a NetworkInterface. This led
to changes in their constructors.
- Removed the obsolete PDU* parameter taken by several classes'
constructors.
- IP now sets the sender's address automatically when no link layer
PDU is used.
- IP, TCP and UDP now calculate the checksum everytime they're
serialized.
- Added PDU::rfind_pdu.
- Defined several exception types.
- Implemented matches_response on several protocols.
- PacketSender is now movable.
- Added an overload of add_option that takes an rvalue-reference in IP,
TCP, DHCP, ICMPv6 and Dot11.
- Added support for GNU/kFreeBSD.
- Removed several deprecated methods, such as PDU::clone_packet.
- Added PacketSender::send(PDU&, NetworkInterface).
- Normalized the TLV options naming conventions in all of the classes
that used them.
- Added support for Dot1Q, STP, PPPoE protocols.
- Made some important optimizations on PDUOption<>'s constructors.
- Added Utils::resolve_domain and Utils::resolve_domain6
v0.3 - Thu Jan 31 16:47:27 ART 2013
- Added IPv6, ICMPv6 and DHCPv6 classes.
- Added support for Loopback interfaces and the Linux Crooked Capture
pseudo protocol.
- Added support for IPv6 records in DNS.
- Added Packet/RefPacket class.
- Added support for FreeBSD, OSX and Windows.
- Added C++11 move semantics to several classes.
- Done a complete rewrite of the build system; it now uses libtool.
- Fixed several bugs in DNS.
v0.2 - Sat Oct 20 11:26:40 2012
- Added support for big endian architectures.
- Simplified several interfaces.
- Added IPv4Address and HWAddress class to simplify handling IP and hardware addresses.
- Added NetworkInterface class to abstract network interfaces.
- Added TCPStreamFollower class to follow TCP streams on the fly.
- Added WEPDecrypter class to decrypt WEP-encrypted 802.11 data frames on the fly.
- Added several new PDUs: Loopback, IEEE802_3, LLC, DNS.
- Added support for reading and writing pcap files.
- Moved to BSD-2 license.

View File

@@ -31,14 +31,14 @@ PROJECT_NAME = libtins
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER = 0.1
PROJECT_NUMBER = 1.2
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
OUTPUT_DIRECTORY = docs/
OUTPUT_DIRECTORY = ../docs/
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
# 4096 sub-directories (in 2 levels) under the output directory of each output
@@ -1085,7 +1085,7 @@ SERVER_BASED_SEARCH = NO
# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
# generate Latex output.
GENERATE_LATEX = YES
GENERATE_LATEX = NO
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be

131
Makefile.am Normal file
View File

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

File diff suppressed because it is too large Load Diff

73
README Normal file
View File

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

85
README.md Normal file
View File

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

4
THANKS Normal file
View File

@@ -0,0 +1,4 @@
We'd like to thank the following people, who have been of great help
through the development of libtins:
- Raúl Benencia <rbenencia@gmail.com> - For creating the Debian package.

1017
aclocal.m4 vendored Normal file

File diff suppressed because it is too large Load Diff

1530
config.guess vendored Executable file

File diff suppressed because it is too large Load Diff

1782
config.sub vendored Executable file

File diff suppressed because it is too large Load Diff

15032
configure vendored

File diff suppressed because it is too large Load Diff

View File

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

708
depcomp Executable file
View File

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

558
depends.d
View File

@@ -1,558 +0,0 @@
src/arp.o: src/arp.cpp include/arp.h include/pdu.h include/endianness.h \
include/hw_address.h include/ip_address.h include/ip.h \
include/small_uint.h include/pdu_option.h include/ethernetII.h \
include/network_interface.h include/rawpdu.h include/constants.h \
include/network_interface.h
include/arp.h:
include/pdu.h:
include/endianness.h:
include/hw_address.h:
include/ip_address.h:
include/ip.h:
include/small_uint.h:
include/pdu_option.h:
include/ethernetII.h:
include/network_interface.h:
include/rawpdu.h:
include/constants.h:
include/network_interface.h:
src/bootp.o: src/bootp.cpp include/bootp.h include/pdu.h \
include/endianness.h include/ip_address.h include/hw_address.h
include/bootp.h:
include/pdu.h:
include/endianness.h:
include/ip_address.h:
include/hw_address.h:
src/crypto.o: src/crypto.cpp include/crypto.h include/dot11.h \
include/pdu.h include/endianness.h include/hw_address.h \
include/small_uint.h include/pdu_option.h include/network_interface.h \
include/ip_address.h include/utils.h include/snap.h include/rawpdu.h
include/crypto.h:
include/dot11.h:
include/pdu.h:
include/endianness.h:
include/hw_address.h:
include/small_uint.h:
include/pdu_option.h:
include/network_interface.h:
include/ip_address.h:
include/utils.h:
include/snap.h:
include/rawpdu.h:
src/dhcp.o: src/dhcp.cpp include/endianness.h include/dhcp.h \
include/bootp.h include/pdu.h include/endianness.h include/ip_address.h \
include/hw_address.h include/pdu_option.h include/ethernetII.h \
include/network_interface.h
include/endianness.h:
include/dhcp.h:
include/bootp.h:
include/pdu.h:
include/endianness.h:
include/ip_address.h:
include/hw_address.h:
include/pdu_option.h:
include/ethernetII.h:
include/network_interface.h:
src/dns.o: src/dns.cpp include/dns.h include/pdu.h include/endianness.h \
include/dns_record.h include/ip_address.h
include/dns.h:
include/pdu.h:
include/endianness.h:
include/dns_record.h:
include/ip_address.h:
src/dns_record.o: src/dns_record.cpp include/dns_record.h \
include/endianness.h
include/dns_record.h:
include/endianness.h:
src/dot11.o: src/dot11.cpp include/dot11.h include/pdu.h \
include/endianness.h include/hw_address.h include/small_uint.h \
include/pdu_option.h include/network_interface.h include/ip_address.h \
include/rawpdu.h include/radiotap.h include/rsn_information.h \
include/packet_sender.h include/snap.h
include/dot11.h:
include/pdu.h:
include/endianness.h:
include/hw_address.h:
include/small_uint.h:
include/pdu_option.h:
include/network_interface.h:
include/ip_address.h:
include/rawpdu.h:
include/radiotap.h:
include/rsn_information.h:
include/packet_sender.h:
include/snap.h:
src/eapol.o: src/eapol.cpp include/eapol.h include/pdu.h \
include/small_uint.h include/endianness.h include/dot11.h \
include/hw_address.h include/pdu_option.h include/network_interface.h \
include/ip_address.h include/rsn_information.h
include/eapol.h:
include/pdu.h:
include/small_uint.h:
include/endianness.h:
include/dot11.h:
include/hw_address.h:
include/pdu_option.h:
include/network_interface.h:
include/ip_address.h:
include/rsn_information.h:
src/ethernetII.o: src/ethernetII.cpp include/ethernetII.h include/pdu.h \
include/endianness.h include/hw_address.h include/network_interface.h \
include/ip_address.h include/packet_sender.h include/rawpdu.h \
include/ip.h include/small_uint.h include/pdu_option.h include/arp.h \
include/constants.h
include/ethernetII.h:
include/pdu.h:
include/endianness.h:
include/hw_address.h:
include/network_interface.h:
include/ip_address.h:
include/packet_sender.h:
include/rawpdu.h:
include/ip.h:
include/small_uint.h:
include/pdu_option.h:
include/arp.h:
include/constants.h:
src/icmp.o: src/icmp.cpp include/icmp.h include/pdu.h \
include/endianness.h include/rawpdu.h include/utils.h \
include/ip_address.h include/hw_address.h
include/icmp.h:
include/pdu.h:
include/endianness.h:
include/rawpdu.h:
include/utils.h:
include/ip_address.h:
include/hw_address.h:
src/ieee802_3.o: src/ieee802_3.cpp include/ieee802_3.h include/pdu.h \
include/endianness.h include/hw_address.h include/network_interface.h \
include/ip_address.h include/packet_sender.h include/llc.h
include/ieee802_3.h:
include/pdu.h:
include/endianness.h:
include/hw_address.h:
include/network_interface.h:
include/ip_address.h:
include/packet_sender.h:
include/llc.h:
src/ip_address.o: src/ip_address.cpp include/ip_address.h \
include/endianness.h
include/ip_address.h:
include/endianness.h:
src/ip.o: src/ip.cpp include/ip.h include/pdu.h include/small_uint.h \
include/endianness.h include/ip_address.h include/pdu_option.h \
include/tcp.h include/udp.h include/icmp.h include/rawpdu.h \
include/utils.h include/hw_address.h include/packet_sender.h \
include/constants.h
include/ip.h:
include/pdu.h:
include/small_uint.h:
include/endianness.h:
include/ip_address.h:
include/pdu_option.h:
include/tcp.h:
include/udp.h:
include/icmp.h:
include/rawpdu.h:
include/utils.h:
include/hw_address.h:
include/packet_sender.h:
include/constants.h:
src/llc.o: src/llc.cpp include/pdu.h include/llc.h include/pdu.h \
include/endianness.h include/rawpdu.h
include/pdu.h:
include/llc.h:
include/pdu.h:
include/endianness.h:
include/rawpdu.h:
src/loopback.o: src/loopback.cpp include/loopback.h include/pdu.h \
include/packet_sender.h include/ip.h include/small_uint.h \
include/endianness.h include/ip_address.h include/pdu_option.h \
include/llc.h include/rawpdu.h
include/loopback.h:
include/pdu.h:
include/packet_sender.h:
include/ip.h:
include/small_uint.h:
include/endianness.h:
include/ip_address.h:
include/pdu_option.h:
include/llc.h:
include/rawpdu.h:
src/network_interface.o: src/network_interface.cpp \
include/network_interface.h include/hw_address.h include/ip_address.h \
include/utils.h include/endianness.h
include/network_interface.h:
include/hw_address.h:
include/ip_address.h:
include/utils.h:
include/endianness.h:
src/packet_sender.o: src/packet_sender.cpp include/pdu.h \
include/packet_sender.h
include/pdu.h:
include/packet_sender.h:
src/packet_writer.o: src/packet_writer.cpp include/packet_writer.h \
include/pdu.h
include/packet_writer.h:
include/pdu.h:
src/pdu.o: src/pdu.cpp include/pdu.h include/rawpdu.h include/pdu.h \
include/packet_sender.h
include/pdu.h:
include/rawpdu.h:
include/pdu.h:
include/packet_sender.h:
src/radiotap.o: src/radiotap.cpp include/radiotap.h include/pdu.h \
include/endianness.h include/network_interface.h include/hw_address.h \
include/ip_address.h include/dot11.h include/small_uint.h \
include/pdu_option.h include/utils.h include/packet_sender.h
include/radiotap.h:
include/pdu.h:
include/endianness.h:
include/network_interface.h:
include/hw_address.h:
include/ip_address.h:
include/dot11.h:
include/small_uint.h:
include/pdu_option.h:
include/utils.h:
include/packet_sender.h:
src/rawpdu.o: src/rawpdu.cpp include/rawpdu.h include/pdu.h
include/rawpdu.h:
include/pdu.h:
src/rsn_information.o: src/rsn_information.cpp include/rsn_information.h \
include/endianness.h
include/rsn_information.h:
include/endianness.h:
src/snap.o: src/snap.cpp include/snap.h include/pdu.h \
include/endianness.h include/small_uint.h include/constants.h \
include/arp.h include/hw_address.h include/ip_address.h include/ip.h \
include/pdu_option.h include/eapol.h
include/snap.h:
include/pdu.h:
include/endianness.h:
include/small_uint.h:
include/constants.h:
include/arp.h:
include/hw_address.h:
include/ip_address.h:
include/ip.h:
include/pdu_option.h:
include/eapol.h:
src/sniffer.o: src/sniffer.cpp include/sniffer.h include/pdu.h \
include/ethernetII.h include/endianness.h include/hw_address.h \
include/network_interface.h include/ip_address.h include/radiotap.h \
include/loopback.h include/dot11.h include/small_uint.h \
include/pdu_option.h
include/sniffer.h:
include/pdu.h:
include/ethernetII.h:
include/endianness.h:
include/hw_address.h:
include/network_interface.h:
include/ip_address.h:
include/radiotap.h:
include/loopback.h:
include/dot11.h:
include/small_uint.h:
include/pdu_option.h:
src/tcp.o: src/tcp.cpp include/tcp.h include/pdu.h include/endianness.h \
include/small_uint.h include/pdu_option.h include/ip.h \
include/ip_address.h include/constants.h include/rawpdu.h \
include/utils.h include/hw_address.h
include/tcp.h:
include/pdu.h:
include/endianness.h:
include/small_uint.h:
include/pdu_option.h:
include/ip.h:
include/ip_address.h:
include/constants.h:
include/rawpdu.h:
include/utils.h:
include/hw_address.h:
src/tcp_stream.o: src/tcp_stream.cpp include/rawpdu.h include/pdu.h \
include/tcp_stream.h include/sniffer.h include/ethernetII.h \
include/endianness.h include/hw_address.h include/network_interface.h \
include/ip_address.h include/radiotap.h include/loopback.h \
include/dot11.h include/small_uint.h include/pdu_option.h include/tcp.h \
include/ip.h
include/rawpdu.h:
include/pdu.h:
include/tcp_stream.h:
include/sniffer.h:
include/ethernetII.h:
include/endianness.h:
include/hw_address.h:
include/network_interface.h:
include/ip_address.h:
include/radiotap.h:
include/loopback.h:
include/dot11.h:
include/small_uint.h:
include/pdu_option.h:
include/tcp.h:
include/ip.h:
src/udp.o: src/udp.cpp include/udp.h include/pdu.h include/endianness.h \
include/constants.h include/utils.h include/ip_address.h \
include/hw_address.h include/ip.h include/small_uint.h \
include/pdu_option.h include/rawpdu.h
include/udp.h:
include/pdu.h:
include/endianness.h:
include/constants.h:
include/utils.h:
include/ip_address.h:
include/hw_address.h:
include/ip.h:
include/small_uint.h:
include/pdu_option.h:
include/rawpdu.h:
src/utils.o: src/utils.cpp include/utils.h include/ip_address.h \
include/hw_address.h include/pdu.h include/ip.h include/pdu.h \
include/small_uint.h include/endianness.h include/pdu_option.h \
include/arp.h include/endianness.h include/network_interface.h \
include/packet_sender.h
include/utils.h:
include/ip_address.h:
include/hw_address.h:
include/pdu.h:
include/ip.h:
include/pdu.h:
include/small_uint.h:
include/endianness.h:
include/pdu_option.h:
include/arp.h:
include/endianness.h:
include/network_interface.h:
include/packet_sender.h:

View File

@@ -1,7 +1,7 @@
CXX=@CXX@
CXXFLAGS=-Wall @CXXFLAGS@
LDFLAGS=-ltins
EXECUTABLES=arpspoof portscan traceroute beacon_display
EXECUTABLES=arpspoofing arpmonitor portscan traceroute beacon_display dns_queries dns_spoof wps_detect
all: $(EXECUTABLES)
@@ -9,11 +9,23 @@ compile: $(OBJECTS)
recompile: clean all
arpspoof:
arpspoofing:
$(CXX) arpspoofing.cpp -o arpspoofing $(CXXFLAGS) $(LDFLAGS)
arpmonitor:
$(CXX) arpmonitor.cpp -o arpmonitor -std=c++0x $(CXXFLAGS) $(LDFLAGS)
dns_queries:
$(CXX) dns_queries.cpp -o dns_queries -std=c++0x $(CXXFLAGS) $(LDFLAGS)
dns_spoof:
$(CXX) dns_spoof.cpp -o dns_spoof -std=c++0x $(CXXFLAGS) $(LDFLAGS)
beacon_display:
$(CXX) beacon_display.cpp -o beacon_display $(CXXFLAGS) $(LDFLAGS)
wps_detect:
$(CXX) wps_detect.cpp -o wps_detect -std=c++0x $(CXXFLAGS) $(LDFLAGS)
portscan:
$(CXX) portscan.cpp -o portscan $(CXXFLAGS) $(LDFLAGS) -lpthread

63
examples/arpmonitor.cpp Normal file
View File

@@ -0,0 +1,63 @@
#include <tins/tins.h>
#include <map>
#include <iostream>
#include <functional>
using namespace Tins;
class arp_monitor {
public:
void run(Sniffer &sniffer);
private:
bool callback(const PDU &pdu);
std::map<IPv4Address, HWAddress<6>> addresses;
};
void arp_monitor::run(Sniffer &sniffer)
{
sniffer.sniff_loop(
std::bind(
&arp_monitor::callback,
this,
std::placeholders::_1
)
);
}
bool arp_monitor::callback(const PDU &pdu)
{
// Retrieve the ARP layer
const ARP &arp = pdu.rfind_pdu<ARP>();
// Is it an ARP reply?
if(arp.opcode() == ARP::REPLY) {
// Let's check if there's already an entry for this address
auto iter = addresses.find(arp.sender_ip_addr());
if(iter == addresses.end()) {
// We haven't seen this address. Save it.
addresses.insert({ arp.sender_ip_addr(), arp.sender_hw_addr()});
std::cout << "[INFO] " << arp.sender_ip_addr() << " is at "
<< arp.sender_hw_addr() << std::endl;
}
else {
// We've seen this address. If it's not the same HW address, inform it
if(arp.sender_hw_addr() != iter->second) {
std::cout << "[WARNING] " << arp.sender_ip_addr() << " is at "
<< iter->second << " but also at " << arp.sender_hw_addr()
<< std::endl;
}
}
}
return true;
}
int main(int argc, char *argv[])
{
if(argc != 2) {
std::cout << "Usage: " << *argv << " <interface>\n";
return 1;
}
arp_monitor monitor;
Sniffer sniffer(argv[1], 2000, true, "arp");
monitor.run(sniffer);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,6 +32,7 @@
#include <string>
#include <stdexcept>
#include <cstdlib>
#include <unistd.h>
#include <tins/arp.h>
#include <tins/network_interface.h>
#include <tins/utils.h>
@@ -42,23 +43,18 @@ using namespace std;
using namespace Tins;
int do_arp_spoofing(NetworkInterface iface, IPv4Address gw, IPv4Address victim,
void do_arp_spoofing(NetworkInterface iface, IPv4Address gw, IPv4Address victim,
const NetworkInterface::Info &info)
{
PacketSender sender;
EthernetII::address_type gw_hw, victim_hw;
// Resolves gateway's hardware address.
if(!Utils::resolve_hwaddr(iface, gw, &gw_hw, sender)) {
cout << "Could not resolve gateway's ip address.\n";
return 5;
}
gw_hw = Utils::resolve_hwaddr(iface, gw, sender);
// Resolves victim's hardware address.
if(!Utils::resolve_hwaddr(iface, victim, &victim_hw, sender)) {
cout << "Could not resolve victim's ip address.\n";
return 6;
}
victim_hw = Utils::resolve_hwaddr(iface, victim, sender);
// Print out the hw addresses we're using.
cout << " Using gateway hw address: " << gw_hw << "\n";
cout << " Using victim hw address: " << victim_hw << "\n";
@@ -66,22 +62,22 @@ int do_arp_spoofing(NetworkInterface iface, IPv4Address gw, IPv4Address victim,
/* We tell the gateway that the victim is at out hw address,
* and tell the victim that the gateway is at out hw address */
ARP *gw_arp = new ARP(gw, victim, gw_hw, info.hw_addr),
*victim_arp = new ARP(victim, gw, victim_hw, info.hw_addr);
ARP gw_arp(gw, victim, gw_hw, info.hw_addr),
victim_arp(victim, gw, victim_hw, info.hw_addr);
// We are "replying" ARP requests
gw_arp->opcode(ARP::REPLY);
victim_arp->opcode(ARP::REPLY);
gw_arp.opcode(ARP::REPLY);
victim_arp.opcode(ARP::REPLY);
/* The packet we'll send to the gateway and victim.
* We include our hw address as the source address
* in ethernet layer, to avoid possible packet dropping
* performed by any routers. */
EthernetII to_gw(iface, gw_hw, info.hw_addr, gw_arp);
EthernetII to_victim(iface, victim_hw, info.hw_addr, victim_arp);
EthernetII to_gw = EthernetII(gw_hw, info.hw_addr) / gw_arp;
EthernetII to_victim = EthernetII(victim_hw, info.hw_addr) / victim_arp;
while(true) {
// Just send them once every 5 seconds.
sender.send(to_gw);
sender.send(to_victim);
sender.send(to_gw, iface);
sender.send(to_victim, iface);
sleep(5);
}
}
@@ -115,7 +111,7 @@ int main(int argc, char *argv[]) {
return 3;
}
try {
return do_arp_spoofing(iface, gw, victim, info);
do_arp_spoofing(iface, gw, victim, info);
}
catch(std::runtime_error &ex) {
std::cout << "Runtime error: " << ex.what() << std::endl;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -53,11 +53,11 @@ void BeaconSniffer::run(const std::string &iface) {
bool BeaconSniffer::callback(PDU &pdu) {
// Get the Dot11 layer
Dot11Beacon *beacon = pdu.find_pdu<Dot11Beacon>();
const Dot11Beacon &beacon = pdu.rfind_pdu<Dot11Beacon>();
// All beacons must have from_ds == to_ds == 0
if(beacon && !beacon->from_ds() && !beacon->to_ds()) {
if(!beacon.from_ds() && !beacon.to_ds()) {
// Get the AP address
address_type addr = beacon->addr2();
address_type addr = beacon.addr2();
// Look it up in our set
ssids_type::iterator it = ssids.find(addr);
if(it == ssids.end()) {
@@ -66,7 +66,7 @@ bool BeaconSniffer::callback(PDU &pdu) {
/* If no ssid option is set, then Dot11::ssid will throw
* a std::runtime_error.
*/
std::string ssid = beacon->ssid();
std::string ssid = beacon.ssid();
// Save it so we don't show it again.
ssids.insert(addr);
// Display the tuple "address - ssid".

460
examples/configure vendored
View File

@@ -1,11 +1,9 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.67 for myconfig 0.1.
# Generated by GNU Autoconf 2.69 for myconfig 0.1.
#
#
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
# Foundation, Inc.
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
#
#
# This configure script is free software; the Free Software Foundation
@@ -89,6 +87,7 @@ fi
IFS=" "" $as_nl"
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
*[\\/]* ) as_myself=$0 ;;
*) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -133,6 +132,31 @@ export LANGUAGE
# CDPATH.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# Use a proper internal environment variable to ensure we don't fall
# into an infinite loop, continuously re-executing ourselves.
if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
_as_can_reexec=no; export _as_can_reexec;
# We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
# works around shells that cannot unset nonexistent variables.
# Preserve -v and -x to the replacement shell.
BASH_ENV=/dev/null
ENV=/dev/null
(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
case $- in # ((((
*v*x* | *x*v* ) as_opts=-vx ;;
*v* ) as_opts=-v ;;
*x* ) as_opts=-x ;;
* ) as_opts= ;;
esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
as_fn_exit 255
fi
# We don't want this to propagate to other subprocesses.
{ _as_can_reexec=; unset _as_can_reexec;}
if test "x$CONFIG_SHELL" = x; then
as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
emulate sh
@@ -166,7 +190,8 @@ if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
else
exitcode=1; echo positional parameters were not saved.
fi
test x\$exitcode = x0 || exit 1"
test x\$exitcode = x0 || exit 1
test -x / || exit 1"
as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
@@ -211,14 +236,25 @@ IFS=$as_save_IFS
if test "x$CONFIG_SHELL" != x; then :
# We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
# works around shells that cannot unset nonexistent variables.
BASH_ENV=/dev/null
ENV=/dev/null
(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
export CONFIG_SHELL
exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
export CONFIG_SHELL
# We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
# works around shells that cannot unset nonexistent variables.
# Preserve -v and -x to the replacement shell.
BASH_ENV=/dev/null
ENV=/dev/null
(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
case $- in # ((((
*v*x* | *x*v* ) as_opts=-vx ;;
*v* ) as_opts=-v ;;
*x* ) as_opts=-x ;;
* ) as_opts= ;;
esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
fi
if test x$as_have_required = xno; then :
@@ -320,6 +356,14 @@ $as_echo X"$as_dir" |
} # as_fn_mkdir_p
# as_fn_executable_p FILE
# -----------------------
# Test if FILE is an executable regular file.
as_fn_executable_p ()
{
test -f "$1" && test -x "$1"
} # as_fn_executable_p
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
@@ -441,6 +485,10 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
chmod +x "$as_me.lineno" ||
{ $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
# If we had to re-execute with $CONFIG_SHELL, we're ensured to have
# already done that, so ensure we don't try to do so again and fall
# in an infinite loop. This has already happened in practice.
_as_can_reexec=no; export _as_can_reexec
# Don't try to exec as it changes $[0], causing all sort of problems
# (the dirname of $[0] is not the place where we might find the
# original and so on. Autoconf is especially sensitive to this).
@@ -475,16 +523,16 @@ if (echo >conf$$.file) 2>/dev/null; then
# ... but there are two gotchas:
# 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
# 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
# In both cases, we have to default to `cp -p'.
# In both cases, we have to default to `cp -pR'.
ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
as_ln_s='cp -p'
as_ln_s='cp -pR'
elif ln conf$$.file conf$$ 2>/dev/null; then
as_ln_s=ln
else
as_ln_s='cp -p'
as_ln_s='cp -pR'
fi
else
as_ln_s='cp -p'
as_ln_s='cp -pR'
fi
rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
rmdir conf$$.dir 2>/dev/null
@@ -496,28 +544,8 @@ else
as_mkdir_p=false
fi
if test -x / >/dev/null 2>&1; then
as_test_x='test -x'
else
if ls -dL / >/dev/null 2>&1; then
as_ls_L_option=L
else
as_ls_L_option=
fi
as_test_x='
eval sh -c '\''
if test -d "$1"; then
test -d "$1/.";
else
case $1 in #(
-*)set "./$1";;
esac;
case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
???[sx]*):;;*)false;;esac;fi
'\'' sh
'
fi
as_executable_p=$as_test_x
as_test_x='test -x'
as_executable_p=as_fn_executable_p
# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -592,7 +620,6 @@ ac_includes_default="\
ac_subst_vars='LTLIBOBJS
LIBOBJS
CFLAGS
EGREP
GREP
CXXCPP
@@ -1059,7 +1086,7 @@ Try \`$0 --help' for more information"
$as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
$as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
: ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
: "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
;;
esac
@@ -1110,8 +1137,6 @@ target=$target_alias
if test "x$host_alias" != x; then
if test "x$build_alias" = x; then
cross_compiling=maybe
$as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
If a cross compiler is detected then cross compile mode will be used" >&2
elif test "x$build_alias" != "x$host_alias"; then
cross_compiling=yes
fi
@@ -1339,9 +1364,9 @@ test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
myconfig configure 0.1
generated by GNU Autoconf 2.67
generated by GNU Autoconf 2.69
Copyright (C) 2010 Free Software Foundation, Inc.
Copyright (C) 2012 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
@@ -1385,11 +1410,57 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
fi
eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_cxx_try_compile
# ac_fn_cxx_try_link LINENO
# -------------------------
# Try to link conftest.$ac_ext, and return whether this succeeded.
ac_fn_cxx_try_link ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
rm -f conftest.$ac_objext conftest$ac_exeext
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_link") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
grep -v '^ *+' conftest.err >conftest.er1
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_cxx_werror_flag" ||
test ! -s conftest.err
} && test -s conftest$ac_exeext && {
test "$cross_compiling" = yes ||
test -x conftest$ac_exeext
}; then :
ac_retval=0
else
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
fi
# Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
# created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
# interfere with the next link command; also delete a directory that is
# left behind by Apple's compiler. We do this before executing the actions.
rm -rf conftest.dSYM conftest_ipa8_conftest.oo
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_cxx_try_link
# ac_fn_cxx_try_cpp LINENO
# ------------------------
# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
@@ -1422,7 +1493,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
fi
eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_cxx_try_cpp
@@ -1435,10 +1506,10 @@ fi
ac_fn_cxx_check_header_mongrel ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
if eval "test \"\${$3+set}\"" = set; then :
if eval \${$3+:} false; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
if eval "test \"\${$3+set}\"" = set; then :
if eval \${$3+:} false; then :
$as_echo_n "(cached) " >&6
fi
eval ac_res=\$$3
@@ -1501,7 +1572,7 @@ $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
if eval "test \"\${$3+set}\"" = set; then :
if eval \${$3+:} false; then :
$as_echo_n "(cached) " >&6
else
eval "$3=\$ac_header_compiler"
@@ -1510,7 +1581,7 @@ eval ac_res=\$$3
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
fi
eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_cxx_check_header_mongrel
@@ -1551,7 +1622,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=$ac_status
fi
rm -rf conftest.dSYM conftest_ipa8_conftest.oo
eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_cxx_try_run
@@ -1565,7 +1636,7 @@ ac_fn_cxx_check_header_compile ()
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
if eval "test \"\${$3+set}\"" = set; then :
if eval \${$3+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -1583,61 +1654,15 @@ fi
eval ac_res=\$$3
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_cxx_check_header_compile
# ac_fn_cxx_try_link LINENO
# -------------------------
# Try to link conftest.$ac_ext, and return whether this succeeded.
ac_fn_cxx_try_link ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
rm -f conftest.$ac_objext conftest$ac_exeext
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_link") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
grep -v '^ *+' conftest.err >conftest.er1
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_cxx_werror_flag" ||
test ! -s conftest.err
} && test -s conftest$ac_exeext && {
test "$cross_compiling" = yes ||
$as_test_x conftest$ac_exeext
}; then :
ac_retval=0
else
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
fi
# Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
# created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
# interfere with the next link command; also delete a directory that is
# left behind by Apple's compiler. We do this before executing the actions.
rm -rf conftest.dSYM conftest_ipa8_conftest.oo
eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
as_fn_set_status $ac_retval
} # ac_fn_cxx_try_link
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by myconfig $as_me 0.1, which was
generated by GNU Autoconf 2.67. Invocation command line was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -1895,7 +1920,7 @@ $as_echo "$as_me: loading site script $ac_site_file" >&6;}
|| { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "failed to load site script $ac_site_file
See \`config.log' for more details" "$LINENO" 5 ; }
See \`config.log' for more details" "$LINENO" 5; }
fi
done
@@ -2001,7 +2026,7 @@ if test -z "$CXX"; then
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if test "${ac_cv_prog_CXX+set}" = set; then :
if ${ac_cv_prog_CXX+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$CXX"; then
@@ -2013,7 +2038,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -2045,7 +2070,7 @@ do
set dummy $ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then :
if ${ac_cv_prog_ac_ct_CXX+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$ac_ct_CXX"; then
@@ -2057,7 +2082,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CXX="$ac_prog"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -2209,7 +2234,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "C++ compiler cannot create executables
See \`config.log' for more details" "$LINENO" 5 ; }
See \`config.log' for more details" "$LINENO" 5; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
@@ -2252,7 +2277,7 @@ else
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of executables: cannot compile and link
See \`config.log' for more details" "$LINENO" 5 ; }
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest conftest$ac_cv_exeext
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
@@ -2311,7 +2336,7 @@ $as_echo "$ac_try_echo"; } >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot run C++ compiled programs.
If you meant to cross compile, use \`--host'.
See \`config.log' for more details" "$LINENO" 5 ; }
See \`config.log' for more details" "$LINENO" 5; }
fi
fi
fi
@@ -2322,7 +2347,7 @@ rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
ac_clean_files=$ac_clean_files_save
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
$as_echo_n "checking for suffix of object files... " >&6; }
if test "${ac_cv_objext+set}" = set; then :
if ${ac_cv_objext+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -2363,7 +2388,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of object files: cannot compile
See \`config.log' for more details" "$LINENO" 5 ; }
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest.$ac_cv_objext conftest.$ac_ext
fi
@@ -2373,7 +2398,7 @@ OBJEXT=$ac_cv_objext
ac_objext=$OBJEXT
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
if test "${ac_cv_cxx_compiler_gnu+set}" = set; then :
if ${ac_cv_cxx_compiler_gnu+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -2410,7 +2435,7 @@ ac_test_CXXFLAGS=${CXXFLAGS+set}
ac_save_CXXFLAGS=$CXXFLAGS
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
$as_echo_n "checking whether $CXX accepts -g... " >&6; }
if test "${ac_cv_prog_cxx_g+set}" = set; then :
if ${ac_cv_prog_cxx_g+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_save_cxx_werror_flag=$ac_cxx_werror_flag
@@ -2499,13 +2524,30 @@ ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ex
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
if test -n "$debug"
then
CFLAGS="-DDEBUG -g"
else
CFLAGS="-O3"
fi
saved_libs="${LIBS}"
LIBS="${LIBS} -ltins"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking libtins" >&5
$as_echo_n "checking libtins... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <tins/dns.h>
int
main ()
{
Tins::DNS dummy
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_link "$LINENO"; then :
echo done
else
echo error; echo *** libtins is not installed. Aborting... ***; exit 1
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS="${saved_libs}"
ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
@@ -2515,7 +2557,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5
$as_echo_n "checking how to run the C++ preprocessor... " >&6; }
if test -z "$CXXCPP"; then
if test "${ac_cv_prog_CXXCPP+set}" = set; then :
if ${ac_cv_prog_CXXCPP+:} false; then :
$as_echo_n "(cached) " >&6
else
# Double quotes because CXXCPP needs to be expanded
@@ -2631,7 +2673,7 @@ else
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check
See \`config.log' for more details" "$LINENO" 5 ; }
See \`config.log' for more details" "$LINENO" 5; }
fi
ac_ext=cpp
@@ -2643,7 +2685,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
if test "${ac_cv_path_GREP+set}" = set; then :
if ${ac_cv_path_GREP+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -z "$GREP"; then
@@ -2657,7 +2699,7 @@ do
for ac_prog in grep ggrep; do
for ac_exec_ext in '' $ac_executable_extensions; do
ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
{ test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
as_fn_executable_p "$ac_path_GREP" || continue
# Check for GNU ac_path_GREP and select it if it is found.
# Check for GNU $ac_path_GREP
case `"$ac_path_GREP" --version 2>&1` in
@@ -2706,7 +2748,7 @@ $as_echo "$ac_cv_path_GREP" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
$as_echo_n "checking for egrep... " >&6; }
if test "${ac_cv_path_EGREP+set}" = set; then :
if ${ac_cv_path_EGREP+:} false; then :
$as_echo_n "(cached) " >&6
else
if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
@@ -2723,7 +2765,7 @@ do
for ac_prog in egrep; do
for ac_exec_ext in '' $ac_executable_extensions; do
ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
{ test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
as_fn_executable_p "$ac_path_EGREP" || continue
# Check for GNU ac_path_EGREP and select it if it is found.
# Check for GNU $ac_path_EGREP
case `"$ac_path_EGREP" --version 2>&1` in
@@ -2773,7 +2815,7 @@ $as_echo "$ac_cv_path_EGREP" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
$as_echo_n "checking for ANSI C header files... " >&6; }
if test "${ac_cv_header_stdc+set}" = set; then :
if ${ac_cv_header_stdc+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -2900,65 +2942,20 @@ fi
done
for ac_header in pcap.h
for ac_header in tins/tins.h
do :
ac_fn_cxx_check_header_mongrel "$LINENO" "pcap.h" "ac_cv_header_pcap_h" "$ac_includes_default"
if test "x$ac_cv_header_pcap_h" = x""yes; then :
ac_fn_cxx_check_header_mongrel "$LINENO" "tins/tins.h" "ac_cv_header_tins_tins_h" "$ac_includes_default"
if test "x$ac_cv_header_tins_tins_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_PCAP_H 1
#define HAVE_TINS_TINS_H 1
_ACEOF
else
echo "*** Error: libtins' headers are absent ***"; exit 1;
fi
done
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcap_loop in -lpcap" >&5
$as_echo_n "checking for pcap_loop in -lpcap... " >&6; }
if test "${ac_cv_lib_pcap_pcap_loop+set}" = set; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lpcap $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char pcap_loop ();
int
main ()
{
return pcap_loop ();
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_link "$LINENO"; then :
ac_cv_lib_pcap_pcap_loop=yes
else
ac_cv_lib_pcap_pcap_loop=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcap_pcap_loop" >&5
$as_echo "$ac_cv_lib_pcap_pcap_loop" >&6; }
if test "x$ac_cv_lib_pcap_pcap_loop" = x""yes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBPCAP 1
_ACEOF
LIBS="-lpcap $LIBS"
else
as_fn_error $? "pcap library is needed!" "$LINENO" 5
fi
ac_config_files="$ac_config_files Makefile"
@@ -3026,10 +3023,21 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
:end' >>confcache
if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
if test -w "$cache_file"; then
test "x$cache_file" != "x/dev/null" &&
if test "x$cache_file" != "x/dev/null"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
$as_echo "$as_me: updating cache $cache_file" >&6;}
cat confcache >$cache_file
if test ! -f "$cache_file" || test -h "$cache_file"; then
cat confcache >"$cache_file"
else
case $cache_file in #(
*/* | ?:*)
mv -f confcache "$cache_file"$$ &&
mv -f "$cache_file"$$ "$cache_file" ;; #(
*)
mv -f confcache "$cache_file" ;;
esac
fi
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
@@ -3097,7 +3105,7 @@ LTLIBOBJS=$ac_ltlibobjs
: ${CONFIG_STATUS=./config.status}
: "${CONFIG_STATUS=./config.status}"
ac_write_fail=0
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files $CONFIG_STATUS"
@@ -3198,6 +3206,7 @@ fi
IFS=" "" $as_nl"
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
*[\\/]* ) as_myself=$0 ;;
*) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -3393,16 +3402,16 @@ if (echo >conf$$.file) 2>/dev/null; then
# ... but there are two gotchas:
# 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
# 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
# In both cases, we have to default to `cp -p'.
# In both cases, we have to default to `cp -pR'.
ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
as_ln_s='cp -p'
as_ln_s='cp -pR'
elif ln conf$$.file conf$$ 2>/dev/null; then
as_ln_s=ln
else
as_ln_s='cp -p'
as_ln_s='cp -pR'
fi
else
as_ln_s='cp -p'
as_ln_s='cp -pR'
fi
rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
rmdir conf$$.dir 2>/dev/null
@@ -3462,28 +3471,16 @@ else
as_mkdir_p=false
fi
if test -x / >/dev/null 2>&1; then
as_test_x='test -x'
else
if ls -dL / >/dev/null 2>&1; then
as_ls_L_option=L
else
as_ls_L_option=
fi
as_test_x='
eval sh -c '\''
if test -d "$1"; then
test -d "$1/.";
else
case $1 in #(
-*)set "./$1";;
esac;
case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
???[sx]*):;;*)false;;esac;fi
'\'' sh
'
fi
as_executable_p=$as_test_x
# as_fn_executable_p FILE
# -----------------------
# Test if FILE is an executable regular file.
as_fn_executable_p ()
{
test -f "$1" && test -x "$1"
} # as_fn_executable_p
as_test_x='test -x'
as_executable_p=as_fn_executable_p
# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -3505,7 +3502,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# values after options handling.
ac_log="
This file was extended by myconfig $as_me 0.1, which was
generated by GNU Autoconf 2.67. Invocation command line was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
@@ -3558,10 +3555,10 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
myconfig config.status 0.1
configured by $0, generated by GNU Autoconf 2.67,
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
Copyright (C) 2010 Free Software Foundation, Inc.
Copyright (C) 2012 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
@@ -3638,7 +3635,7 @@ fi
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
if \$ac_cs_recheck; then
set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
shift
\$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
CONFIG_SHELL='$SHELL'
@@ -3669,7 +3666,7 @@ do
case $ac_config_target in
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;;
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
esac
done
@@ -3690,9 +3687,10 @@ fi
# after its creation but before its name has been assigned to `$tmp'.
$debug ||
{
tmp=
tmp= ac_tmp=
trap 'exit_status=$?
{ test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
: "${ac_tmp:=$tmp}"
{ test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
' 0
trap 'as_fn_exit 1' 1 2 13 15
}
@@ -3700,12 +3698,13 @@ $debug ||
{
tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
test -n "$tmp" && test -d "$tmp"
test -d "$tmp"
} ||
{
tmp=./conf$$-$RANDOM
(umask 077 && mkdir "$tmp")
} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
ac_tmp=$tmp
# Set up the scripts for CONFIG_FILES section.
# No need to generate them if there are no CONFIG_FILES.
@@ -3727,7 +3726,7 @@ else
ac_cs_awk_cr=$ac_cr
fi
echo 'BEGIN {' >"$tmp/subs1.awk" &&
echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
_ACEOF
@@ -3755,7 +3754,7 @@ done
rm -f conf$$subs.sh
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
cat >>"\$tmp/subs1.awk" <<\\_ACAWK &&
cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
_ACEOF
sed -n '
h
@@ -3803,7 +3802,7 @@ t delim
rm -f conf$$subs.awk
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
_ACAWK
cat >>"\$tmp/subs1.awk" <<_ACAWK &&
cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
for (key in S) S_is_set[key] = 1
FS = ""
@@ -3835,7 +3834,7 @@ if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
else
cat
fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \
fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
|| as_fn_error $? "could not setup config files machinery" "$LINENO" 5
_ACEOF
@@ -3875,7 +3874,7 @@ do
esac
case $ac_mode$ac_tag in
:[FHL]*:*);;
:L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5 ;;
:L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
:[FH]-) ac_tag=-:-;;
:[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
esac
@@ -3894,7 +3893,7 @@ do
for ac_f
do
case $ac_f in
-) ac_f="$tmp/stdin";;
-) ac_f="$ac_tmp/stdin";;
*) # Look for the file first in the build tree, then in the source tree
# (if the path is not absolute). The absolute path cannot be DOS-style,
# because $ac_f cannot contain `:'.
@@ -3903,7 +3902,7 @@ do
[\\/$]*) false;;
*) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
esac ||
as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5 ;;
as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
esac
case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
as_fn_append ac_file_inputs " '$ac_f'"
@@ -3929,8 +3928,8 @@ $as_echo "$as_me: creating $ac_file" >&6;}
esac
case $ac_tag in
*:-:* | *:-) cat >"$tmp/stdin" \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
*:-:* | *:-) cat >"$ac_tmp/stdin" \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
esac
;;
esac
@@ -4055,21 +4054,22 @@ s&@abs_builddir@&$ac_abs_builddir&;t t
s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
$ac_datarootdir_hack
"
eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
>$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
{ ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
{ ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
{ ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
{ ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
"$ac_tmp/out"`; test -z "$ac_out"; } &&
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&5
$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&2;}
rm -f "$tmp/stdin"
rm -f "$ac_tmp/stdin"
case $ac_file in
-) cat "$tmp/out" && rm -f "$tmp/out";;
*) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";;
-) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
*) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
esac \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
;;

View File

@@ -3,14 +3,15 @@ AC_INIT(myconfig, 0.1)
AC_PROG_CXX()
AC_LANG(C++)
if test -n "$debug"
then
CFLAGS="-DDEBUG -g"
else
CFLAGS="-O3"
fi
saved_libs="${LIBS}"
LIBS="${LIBS} -ltins"
AC_MSG_CHECKING(libtins)
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <tins/dns.h>],
[Tins::DNS dummy])],
[echo done],
[echo error; echo *** libtins is not installed. Aborting... ***; exit 1])
LIBS="${saved_libs}"
AC_CHECK_HEADERS([tins/tins.h], , [echo "*** Error: libtins' headers are absent ***"; exit 1;])
AC_CHECK_HEADERS([pcap.h])
AC_CHECK_LIB(pcap, pcap_loop, [], [AC_MSG_ERROR([pcap library is needed!])])
AC_SUBST(CFLAGS)
AC_OUTPUT(Makefile)

61
examples/dns_queries.cpp Normal file
View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) 2012, 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 <tins/tins.h>
#include <iostream>
using namespace Tins;
bool callback(const PDU &pdu)
{
// The packet probably looks like this:
//
// EthernetII / IP / UDP / RawPDU
//
// So we retrieve the RawPDU layer, and construct a
// DNS PDU using its contents.
DNS dns = pdu.rfind_pdu<RawPDU>().to<DNS>();
// Retrieve the queries and print the domain name:
for(const auto &query : dns.queries())
std::cout << query.dname() << std::endl;
return true;
}
int main(int argc, char *argv[])
{
if(argc != 2) {
std::cout << "Usage: " << *argv << " <interface>" << std::endl;
return 1;
}
// Sniff on the provided interface, maximum packet size 2000
// in promiscuos mode and only udp packets sent to port 53
Sniffer sniffer(argv[1], 2000, true, "udp and dst port 53");
sniffer.sniff_loop(callback);
}

94
examples/dns_spoof.cpp Normal file
View File

@@ -0,0 +1,94 @@
/*
* Copyright (c) 2012, 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 <tins/tins.h>
#include <iostream>
using namespace Tins;
PacketSender sender;
bool callback(const PDU &pdu)
{
// The packet probably looks like this:
//
// EthernetII / IP / UDP / RawPDU
//
// So we retrieve each layer, and construct a
// DNS PDU from the RawPDU layer contents.
EthernetII eth = pdu.rfind_pdu<EthernetII>();
IP ip = eth.rfind_pdu<IP>();
UDP udp = ip.rfind_pdu<UDP>();
DNS dns = udp.rfind_pdu<RawPDU>().to<DNS>();
// Is it a DNS query?
if(dns.type() == DNS::QUERY) {
// Let's see if there's any query for an "A" record.
for(const auto &query : dns.queries()) {
if(query.type() == DNS::A) {
// Here's one! Let's add an answer.
dns.add_answer(
query.dname(),
// 777 is just a random TTL
DNS::make_info(DNS::A, query.query_class(), 777),
IPv4Address("127.0.0.1")
);
}
}
// Have we added some answers?
if(dns.answers_count() > 0) {
// It's a response now
dns.type(DNS::RESPONSE);
// Recursion is available(just in case)
dns.recursion_available(1);
// Build our packet
auto pkt = EthernetII(eth.src_addr(), eth.dst_addr()) /
IP(ip.src_addr(), ip.dst_addr()) /
UDP(udp.sport(), udp.dport()) /
dns;
// Send it!
sender.send(pkt);
}
}
return true;
}
int main(int argc, char *argv[])
{
if(argc != 2) {
std::cout << "Usage: " << *argv << " <interface>" << std::endl;
return 1;
}
// Sniff on the provided interface, maximum packet size 2000
// in promiscuos mode and only udp packets sent to port 53
Sniffer sniffer(argv[1], 2000, true, "udp and dst port 53");
// All packets will be sent through the provided interface
sender.default_interface(argv[1]);
sniffer.sniff_loop(callback);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,6 +33,7 @@
#include <string>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h>
#include <tins/ip.h>
#include <tins/tcp.h>
#include <tins/ip_address.h>
@@ -53,19 +54,17 @@ typedef std::pair<Sniffer*, std::string> sniffer_data;
* the scanned port's status.
*/
bool handler(PDU &pdu) {
TCP *tcp = pdu.find_pdu<TCP>();
if(tcp) {
// Ok, it's a TCP PDU. Is RST flag on? Then port is closed.
if(tcp->get_flag(TCP::RST)) {
// This indicates we should stop sniffing.
if(tcp->get_flag(TCP::SYN))
return false;
cout << "Port: " << setw(5) << tcp->sport() << " closed\n";
}
// Is SYN flag on? Then port is open!
else if(tcp->get_flag(TCP::SYN) && tcp->get_flag(TCP::ACK))
cout << "Port: " << setw(5) << tcp->sport() << " open\n";
const TCP &tcp = pdu.rfind_pdu<TCP>();
// Ok, it's a TCP PDU. Is RST flag on? Then port is closed.
if(tcp.get_flag(TCP::RST)) {
// This indicates we should stop sniffing.
if(tcp.get_flag(TCP::SYN))
return false;
cout << "Port: " << setw(5) << tcp.sport() << " closed\n";
}
// Is SYN flag on? Then port is open!
else if(tcp.flags() == (TCP::SYN | TCP::ACK))
cout << "Port: " << setw(5) << tcp.sport() << " open\n";
return true;
}
@@ -74,17 +73,18 @@ void send_syns(const NetworkInterface &iface, IPv4Address dest_ip, const vector<
// Retrieve the addresses.
NetworkInterface::Info info = iface.addresses();
PacketSender sender;
TCP *tcp = new TCP();
// Allocate the IP PDU
IP ip(dest_ip, info.ip_addr, tcp);
IP ip = IP(dest_ip, info.ip_addr) / TCP();
// Get the reference to the TCP PDU
TCP &tcp = ip.rfind_pdu<TCP>();
// Set the SYN flag on.
tcp->set_flag(TCP::SYN, 1);
// Just some arbitrary port.
tcp->sport(1337);
tcp.set_flag(TCP::SYN, 1);
// Just some random port.
tcp.sport(1337);
cout << "Sending SYNs..." << endl;
for(vector<string>::const_iterator it = ips.begin(); it != ips.end(); ++it) {
// Set the new port and send the packet!
tcp->dport(atoi(it->c_str()));
tcp.dport(atoi(it->c_str()));
sender.send(ip);
}
// Wait 1 second.
@@ -92,12 +92,12 @@ void send_syns(const NetworkInterface &iface, IPv4Address dest_ip, const vector<
/* Special packet to indicate that we're done. This will be sniffed
* by our function, which will in turn return false.
*/
tcp->set_flag(TCP::RST, 1);
tcp.set_flag(TCP::RST, 1);
// Pretend we're the scanned host...
ip.src_addr(dest_ip);
// We use an ethernet pdu, otherwise the kernel will drop it.
EthernetII eth(iface, info.hw_addr, info.hw_addr, ip.clone());
sender.send(eth);
EthernetII eth = EthernetII(info.hw_addr, info.hw_addr) / ip;
sender.send(eth, iface);
}
void *thread_proc(void *param) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -54,7 +54,11 @@ public:
PacketSender sender;
// Create our handler
auto handler = make_sniffer_handler(this, &Traceroute::sniff_callback);
auto handler = std::bind(
&Traceroute::sniff_callback,
this,
std::placeholders::_1
);
// We're running
running = true;
// Start the sniff thread
@@ -74,7 +78,7 @@ private:
void send_packets(PacketSender &sender) {
// ICMPs are icmp-requests by default
IP ip(addr, iface.addresses().ip_addr, new ICMP());
IP ip = IP(addr, iface.addresses().ip_addr) / ICMP();
// We'll find at most 10 hops.
for(auto i = 1; i <= 10; ++i) {
@@ -98,30 +102,20 @@ private:
}
bool sniff_callback(PDU &pdu) {
IP *ip = pdu.find_pdu<IP>();
RawPDU *raw = pdu.find_pdu<RawPDU>();
if(ip && raw) {
ttl_map::const_iterator iter;
IP inner_ip;
// This will fail if its a corrupted packet
try {
// Fetch the IP PDU attached to the ICMP response
inner_ip = IP(&raw->payload()[0], raw->payload_size());
}
catch(std::runtime_error &ex) {
return running;
}
// Critical section
{
std::lock_guard<std::mutex> _(lock);
iter = ttls.find(inner_ip.id());
}
const IP &ip = pdu.rfind_pdu<IP>();
ttl_map::const_iterator iter;
// Fetch the IP PDU attached to the ICMP response
const IP inner_ip = pdu.rfind_pdu<RawPDU>().to<IP>();
// Critical section
{
std::lock_guard<std::mutex> _(lock);
iter = ttls.find(inner_ip.id());
}
// It's an actual response
if(iter != ttls.end()) {
// Store it
results[inner_ip.id()] = ip->src_addr();
}
// It's an actual response
if(iter != ttls.end()) {
// Store it
results[inner_ip.id()] = ip.src_addr();
}
return running;
}

74
examples/wps_detect.cpp Normal file
View File

@@ -0,0 +1,74 @@
/*
* Copyright (c) 2012, 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 <tins/tins.h>
#include <iostream>
#include <set>
#include <string>
using namespace Tins;
// BSSIDs which we've already seen
std::set<HWAddress<6>> addrs;
// This will be the content of the OUI field in the vendor specific
// tagged option if it's a WPS tag.
const HWAddress<3> expected_oui("00:50:F2");
bool handler(const PDU& pdu) {
const Dot11Beacon &beacon = pdu.rfind_pdu<Dot11Beacon>();
// Only process it once
if(addrs.insert(beacon.addr3()).second) {
// Iterate the tagged options
for(const auto &opt : beacon.options()) {
// Is this a vendor-specific tag?
if(opt.option() == Dot11::VENDOR_SPECIFIC) {
// Make sure there's enough size for the OUI + identifier
if(opt.data_size() >= 4) {
// Retrieve the OUI field
HWAddress<3> addr = opt.data_ptr();
// Are we interested in this OUI and is it a WPS tag?
if(addr == expected_oui && opt.data_ptr()[3] == 0x04) {
std::cout << "[+] Access point: " << beacon.ssid() << " uses WPS\n";
}
}
}
}
}
return true;
}
int main(int argc, char *argv[]) {
if(argc != 2) {
std::cout << "Usage: " << *argv << " <DEVICE>\n";
return 1;
}
// Only sniff beacons
Sniffer sniffer(argv[1], 2000, true, "wlan type mgt subtype beacon");
sniffer.sniff_loop(handler);
}

331
include/address_range.h Normal file
View File

@@ -0,0 +1,331 @@
/*
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_ADDRESS_RANGE
#define TINS_ADDRESS_RANGE
#include <stdexcept>
#include <iterator>
#include "endianness.h"
#include "internals.h"
namespace Tins {
/**
* \brief AddressRange iterator class.
*/
template<typename Address>
class AddressRangeIterator : public std::iterator<std::forward_iterator_tag, const Address> {
public:
typedef typename std::iterator<std::forward_iterator_tag, const Address>::value_type value_type;
struct end_iterator {
};
/**
* Constructs an iterator.
*
* \param first The address held by this iterator.
*/
AddressRangeIterator(const value_type &addr)
: addr(addr), reached_end(false)
{
}
/**
* Constructs an iterator.
*
* \param first The address held by this iterator.
*/
AddressRangeIterator(const value_type &address, end_iterator)
: addr(address)
{
reached_end = Internals::increment(addr);
}
/**
* Retrieves the current address pointed by this iterator.
*/
const value_type& operator*() const {
return addr;
}
/**
* Retrieves a pointer to the current address pointed by this iterator.
*/
const value_type* operator->() const {
return &addr;
}
/**
* Compares two iterators for equality.
*
* \param rhs The iterator with which to compare.
*/
bool operator==(const AddressRangeIterator &rhs) const {
return reached_end == rhs.reached_end && addr == rhs.addr;
}
/**
* Compares two iterators for inequality.
*
* \param rhs The iterator with which to compare.
*/
bool operator!=(const AddressRangeIterator &rhs) const {
return !(*this == rhs);
}
/**
* Increments this iterator.
*/
AddressRangeIterator& operator++() {
reached_end = Internals::increment(addr);
return *this;
}
/**
* Increments this iterator.
*/
AddressRangeIterator operator++(int) {
AddressRangeIterator copy(*this);
(*this)++;
return copy;
}
private:
Address addr;
bool reached_end;
};
/**
* \brief Represents a range of addresses.
*
* This class provides a begin()/end() interface which allows
* iterating through every address stored in it.
*
* Note that when iterating a range that was created using
* operator/(IPv4Address, int) and the analog for IPv6, the
* network and broadcast addresses are discarded:
*
* \code
* auto range = IPv4Address("192.168.5.0") / 24;
* for(const auto &addr : range) {
* // process 192.168.5.1-254, .0 and .255 are discarded
* process(addr);
* }
*
* // That's only valid for iteration, not for AddressRange<>::contains
*
* assert(range.contains("192.168.5.0")); // works
* assert(range.contains("192.168.5.255")); // works
* \endcode
*
* Ranges created using AddressRange(address_type, address_type)
* will allow the iteration over the entire range:
*
* \code
* AddressRange<IPv4Address> range("192.168.5.0", "192.168.5.255");
* for(const auto &addr : range) {
* // process 192.168.5.0-255, no addresses are discarded
* process(addr);
* }
*
* assert(range.contains("192.168.5.0")); // still valid
* assert(range.contains("192.168.5.255")); // still valid
* \endcode
*
*/
template<typename Address>
class AddressRange {
public:
/**
* The type of addresses stored in the range.
*/
typedef Address address_type;
/**
* The iterator type.
*/
typedef AddressRangeIterator<address_type> const_iterator;
/**
* \brief The iterator type.
*
* This is the same type as const_iterator, since the
* addresses stored in this range are read only.
*/
typedef const_iterator iterator;
/**
* \brief Constructs an address range from two addresses.
*
* The range will consist of the addresses [first, last].
*
* If only_hosts is true, then the network and broadcast addresses
* will not be available when iterating the range.
*
* If last < first, an std::runtime_error exception is thrown.
*
* \param first The first address in the range.
* \param last The last address(inclusive) in the range.
* \param only_hosts Indicates whether only host addresses
* should be accessed when using iterators.
*/
AddressRange(const address_type &first, const address_type &last, bool only_hosts = false)
: first(first), last(last), only_hosts(only_hosts)
{
if(last < first)
throw std::runtime_error("Invalid address range");
}
/**
* \brief Creates an address range from a base address
* and a network mask.
*
* \param first The base address.
* \param mask The network mask to be used.
*/
static AddressRange from_mask(const address_type &first, const address_type &mask) {
return AddressRange<address_type>(
first,
Internals::last_address_from_mask(first, mask),
true
);
}
/**
* \brief Indicates whether an address is included in this range.
* \param addr The address to test.
* \return a bool indicating whether the address is in the range.
*/
bool contains(const address_type &addr) const {
return (first < addr && addr < last) || addr == first || addr == last;
}
/**
* \brief Returns an interator to the beginning of this range.
* \brief const_iterator pointing to the beginning of this range.
*/
const_iterator begin() const {
address_type addr = first;
if(only_hosts)
Internals::increment(addr);
return const_iterator(addr);
}
/**
* \brief Returns an interator to the end of this range.
* \brief const_iterator pointing to the end of this range.
*/
const_iterator end() const {
address_type addr = last;
if(only_hosts)
Internals::decrement(addr);
return const_iterator(addr, typename const_iterator::end_iterator());
}
/**
* \brief Indicates whether this range is iterable.
*
* Iterable ranges are those for which there is at least one
* address that could represent a host. For IPv4 ranges, a /31 or
* /32 ranges does not contain any, therefore it's not iterable.
* The same is true for /127 and /128 IPv6 ranges.
*
* If is_iterable returns false for a range, then iterating it
* through the iterators returned by begin() and end() is
* undefined.
*
* \return bool indicating whether this range is iterable.
*/
bool is_iterable() const {
// Since first < last, it's iterable
if(!only_hosts)
return true;
// We need that distance(first, last) >= 4
address_type addr(first);
for(int i = 0; i < 3; ++i) {
// If there's overflow before the last iteration, we're done
if(Internals::increment(addr) && i != 2)
return false;
}
// If addr <= last, it's OK.
return addr < last || addr == last;
}
private:
address_type first, last;
bool only_hosts;
};
/**
* An IPv4 address range.
*/
typedef AddressRange<IPv4Address> IPv4Range;
/**
* An IPv6 address range.
*/
typedef AddressRange<IPv6Address> IPv6Range;
/**
* \brief Constructs an AddressRange from a base address and a mask.
* \param addr The range's first address.
* \param mask The bit-length of the prefix.
*/
template<size_t n>
AddressRange<HWAddress<n> > operator/(const HWAddress<n> &addr, int mask) {
if(mask > 48)
throw std::logic_error("Prefix length cannot exceed 48");
HWAddress<n> last_addr;
typename HWAddress<n>::iterator it = last_addr.begin();
while(mask > 8) {
*it = 0xff;
++it;
mask -= 8;
}
*it = 0xff << (8 - mask);
return AddressRange<HWAddress<6> >::from_mask(addr, last_addr);
}
/**
* \brief Constructs an IPv6Range from a base IPv6Address and a mask.
* \param addr The range's first address.
* \param mask The bit-length of the prefix.
*/
IPv6Range operator/(const IPv6Address &addr, int mask);
/**
* \brief Constructs an IPv4Range from a base IPv4Address and a mask.
* \param addr The range's first address.
* \param mask The bit-length of the prefix.
*/
IPv4Range operator/(const IPv4Address &addr, int mask);
} // namespace Tins
#endif // TINS_ADDRESS_RANGE

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,6 +31,7 @@
#ifndef TINS_ARP_H
#define TINS_ARP_H
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
#include "hw_address.h"
@@ -70,10 +71,18 @@ namespace Tins {
};
/**
* \brief Default constructor for ARP PDU objects.
*
* \brief Constructs an ARP object using the provided addresses.
*
* ARP requests and replies can be constructed easily using
* ARP::make_arp_request/reply static functions.
* ARP::make_arp_request/reply static member functions.
*
* \sa ARP::make_arp_request
* \sa ARP::make_arp_reply
*
* \param target_ip The target IP address.
* \param sender_ip The sender IP address.
* \param target_hw The target hardware address.
* \param sender_hw The sender hardware address.
*/
ARP(ipaddress_type target_ip = ipaddress_type(),
ipaddress_type sender_ip = ipaddress_type(),
@@ -81,8 +90,14 @@ namespace Tins {
const hwaddress_type &sender_hw = hwaddress_type());
/**
* \brief Constructor which creates an ARP object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \brief Constructs an ARP object from a buffer.
*
* If there is not enough size for an ARP header in the buffer,
* a malformed_packet exception is thrown.
*
* If the buffer is bigger than the size of the ARP header,
* then the extra data is stored in a RawPDU.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
@@ -118,41 +133,42 @@ namespace Tins {
ipaddress_type target_ip_addr() const { return ipaddress_type(_arp.ar_tip); }
/**
* \brief Getter for the hardware address format.
* \brief Getter for the hardware address format field.
*
* \return The hardware address format.
*/
uint16_t hw_addr_format() const { return Endian::be_to_host(_arp.ar_hrd); }
/**
* \brief Getter for the protocol address format.
* \brief Getter for the protocol address format field.
*
* \return The protocol address format.
*/
uint16_t prot_addr_format() const { return Endian::be_to_host(_arp.ar_pro); }
/**
* \brief Getter for the hardware address length.
* \brief Getter for the hardware address length field.
*
* \return The hardware address length.
*/
uint8_t hw_addr_length() const { return _arp.ar_hln; }
/**
* \brief Getter for the protocol address length.
* \brief Getter for the protocol address length field.
*
* \return The protocol address length.
*/
uint8_t prot_addr_length() const { return _arp.ar_pln; }
/**
* \brief Getter for the ARP opcode.
* \brief Getter for the ARP opcode field.
*
* \return The ARP opcode.
*/
uint16_t opcode() const { return Endian::be_to_host(_arp.ar_op); }
/** \brief Getter for the header size.
/**
* \brief Getter for the header size.
* \return Returns the ARP header size.
* \sa PDU::header_size
*/
@@ -188,35 +204,35 @@ namespace Tins {
void target_ip_addr(ipaddress_type new_tgt_ip_addr);
/**
* \brief Setter for the hardware address format.
* \brief Setter for the hardware address format field.
*
* \param new_hw_addr_fmt The new hardware address format.
*/
void hw_addr_format(uint16_t new_hw_addr_fmt);
/**
* \brief Setter for the protocol address format.
* \brief Setter for the protocol address format field.
*
* \param new_prot_addr_fmt The new protocol address format.
*/
void prot_addr_format(uint16_t new_prot_addr_fmt);
/**
* \brief Setter for the hardware address length.
* \brief Setter for the hardware address length field.
*
* \param new_hw_addr_len The new hardware address length.
*/
void hw_addr_length(uint8_t new_hw_addr_len);
/**
* \brief Setter for the protocol address length.
* \brief Setter for the protocol address length field.
*
* \param new_prot_addr_len The new protocol address length.
*/
void prot_addr_length(uint8_t new_prot_addr_len);
/**
* \brief Setter for the ARP opcode.
* \brief Setter for the ARP opcode field.
*
* \param new_opcode Flag enum value of the ARP opcode to set.
*/
@@ -226,57 +242,46 @@ namespace Tins {
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::ARP; }
PDUType pdu_type() const { return pdu_flag; }
/**
* \brief Creates an ARP Request within a Layer 2 PDU using uint32_t for target and sender.
* \brief Creates an ARP Request within an EthernetII PDU.
*
* Creates an ARP Request PDU and embeds it within a Layer 2 PDU ready to be
* sent. The target and sender's protocol address are given using uint32_t.
* Creates an ARP Request PDU and embeds it inside an EthernetII
* PDU.
*
* \param iface string with the interface from where to send the ARP.
* \param target IPv4Address with the target's IP.
* \param sender IPv4Address with the sender's IP.
* \param hw_snd uint8_t array of 6 bytes containing the sender's hardware address.
* \return Returns a EthernetII containing the ARP Request.
* \param target The target's IP address.
* \param sender The sender's IP address.
* \param hw_snd The sender's hardware address.
* \return EthernetII object containing the ARP Request.
*/
static EthernetII make_arp_request(const NetworkInterface& iface, ipaddress_type target,
static EthernetII make_arp_request(ipaddress_type target,
ipaddress_type sender, const hwaddress_type &hw_snd = hwaddress_type());
/**
* \brief Creates an ARP Reply within a Layer 2 PDU using uint32_t for target and sender.
* \brief Creates an ARP Reply within an EthernetII PDU.
*
* Creates an ARP Reply PDU and embeds it within a Layer 2 PDU ready to be
* sent. The target and sender's protocol address are given using uint32_t.
* Creates an ARP Reply PDU and embeds it inside an EthernetII
* PDU.
*
* \param iface string with the interface from where to send the ARP.
* \param target IPv4Address with the target's IP.
* \param sender IPv4Address with the sender's IP.
* \param hw_tgt uint8_t array of 6 bytes containing the target's hardware address.
* \param hw_snd uint8_t array of 6 bytes containing the sender's hardware address.
* \return Returns an EthetnetII containing the ARP Replay.
* \param target The target's IP address.
* \param sender The sender's IP address.
* \param hw_tgt The target's hardware address.
* \param hw_snd The sender's hardware address.
* \return EthetnetII containing the ARP Replay.
*/
static EthernetII make_arp_reply(const NetworkInterface& iface, ipaddress_type target,
static EthernetII make_arp_reply(ipaddress_type target,
ipaddress_type sender, const hwaddress_type &hw_tgt = hwaddress_type(),
const hwaddress_type &hw_snd = hwaddress_type());
/** \brief Check wether ptr points to a valid response for this PDU.
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(uint8_t *ptr, uint32_t total_sz);
/** \brief Clones this pdu, filling the corresponding header with data
* extracted from a buffer.
*
* \param ptr The pointer to the from from which the data will be extracted.
* \param total_sz The size of the buffer.
* \return The cloned PDU.
* \sa PDU::clone_packet
*/
PDU *clone_packet(const uint8_t *ptr, uint32_t total_sz);
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \sa PDU::clone
@@ -285,6 +290,7 @@ namespace Tins {
return new ARP(*this);
}
private:
TINS_BEGIN_PACK
struct arphdr {
uint16_t ar_hrd; /* format of hardware address */
uint16_t ar_pro; /* format of protocol address */
@@ -300,11 +306,11 @@ namespace Tins {
uint8_t ar_tha[hwaddress_type::address_size];
/* target IP address */
uint32_t ar_tip;
} __attribute__((__packed__));
} TINS_END_PACK;
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
arphdr _arp;
};
};
}
#endif //TINS_ARP_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,6 +34,7 @@
#include <algorithm>
#include <vector>
#include "pdu.h"
#include "macros.h"
#include "endianness.h"
#include "ip_address.h"
#include "hw_address.h"
@@ -83,8 +84,11 @@ namespace Tins {
BootP();
/**
* \brief Constructor which creates a BootP object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \brief Constructs a BootP object from a buffer .
*
* If there's not enough size for a BootP header, then a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
* \param vend_field_size The vend field size to allocate.
@@ -271,7 +275,8 @@ namespace Tins {
_bootp.chaddr
);
// Fill what's left with zeros
std::fill(end, _bootp.chaddr + chaddr_type::address_size, 0);
if(end < _bootp.chaddr + chaddr_type::address_size)
std::fill(end, _bootp.chaddr + chaddr_type::address_size, 0);
}
/**
@@ -292,11 +297,22 @@ namespace Tins {
*/
void vend(const vend_type &new_vend);
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* This returns true if the xid field is equal.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::BOOTP; }
PDUType pdu_type() const { return pdu_flag; }
/**
* \sa PDU::clone
@@ -320,6 +336,7 @@ namespace Tins {
/**
* Struct that represents the Bootp datagram.
*/
TINS_BEGIN_PACK
struct bootphdr {
uint8_t opcode;
uint8_t htype;
@@ -335,11 +352,11 @@ namespace Tins {
uint8_t chaddr[16];
uint8_t sname[64];
uint8_t file[128];
} __attribute__((__packed__));
} TINS_END_PACK;
bootphdr _bootp;
vend_type _vend;
};
};
}
#endif // TINS_BOOTP_H

89
include/config.h.in Normal file
View File

@@ -0,0 +1,89 @@
/* include/config.h.in. Generated from configure.ac by autoheader. */
/* define if the compiler supports basic C++11 syntax */
#undef HAVE_CXX11
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Have IEEE 802.11 support */
#undef HAVE_DOT11
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `crypto' library (-lcrypto). */
#undef HAVE_LIBCRYPTO
/* Define to 1 if you have the `pcap' library (-lpcap). */
#undef HAVE_LIBPCAP
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the <openssl/aes.h> header file. */
#undef HAVE_OPENSSL_AES_H
/* Define to 1 if you have the <openssl/evp.h> header file. */
#undef HAVE_OPENSSL_EVP_H
/* Define to 1 if you have the <openssl/hmac.h> header file. */
#undef HAVE_OPENSSL_HMAC_H
/* Define to 1 if you have the <pcap.h> header file. */
#undef HAVE_PCAP_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Have WPA2 decryption library */
#undef HAVE_WPA2_DECRYPTION
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#undef LT_OBJDIR
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Version number of package */
#undef VERSION

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -73,7 +73,8 @@ namespace Tins {
struct Ethernet {
enum e {
PUP = 0x0200, /* Xerox PUP */
UNKNOWN = 0,
//~ PUP = 0x0200, /* Xerox PUP */
SPRITE = 0x0500, /* Sprite */
IP = 0x0800, /* IP */
ARP = 0x0806, /* Address resolution */
@@ -83,6 +84,7 @@ namespace Tins {
VLAN = 0x8100, /* IEEE 802.1Q VLAN tagging */
IPX = 0x8137, /* IPX */
IPV6 = 0x86dd, /* IP protocol version 6 */
PPPOED = 0x8863, /* PPPoE Discovery */
EAPOL = 0x888e, /* EAPOL */
LOOPBACK = 0x9000 /* used to test interfaces */
};
@@ -147,11 +149,11 @@ namespace Tins {
IEEE802154 = 804, /* IEEE 802.15.4 header. */
IEEE802154_PHY = 805, /* IEEE 802.15.4 PHY header. */
VOID_TYPE = 0xFFFF, /* Void type, nothing is known. */
NONE = 0xFFFE, /* Zero header length. */
NONE = 0xFFFE /* Zero header length. */
};
};
};
};
}
}
#endif // TINS_CONSTANTS_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,22 +27,72 @@
*
*/
#ifndef TINS_CRYPTO_H
#include "config.h"
#if !defined(TINS_CRYPTO_H) && defined(HAVE_DOT11)
#define TINS_CRYPTO_H
#include <map>
#include <string>
#include <algorithm>
#include <vector>
#include "dot11.h"
#include "utils.h"
#include "snap.h"
#include "rawpdu.h"
#include "handshake_capturer.h"
namespace Tins {
class PDU;
class Dot11;
class Dot11Data;
namespace Crypto {
/**
* \cond
*/
struct RC4Key;
#ifdef HAVE_WPA2_DECRYPTION
namespace WPA2 {
class invalid_handshake : public std::exception {
public:
const char *what() const throw() {
return "invalid handshake";
}
};
class SessionKeys {
public:
typedef Internals::byte_array<80> ptk_type;
typedef Internals::byte_array<32> pmk_type;
SessionKeys();
SessionKeys(const RSNHandshake &hs, const pmk_type &pmk);
SNAP *decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const;
private:
SNAP *ccmp_decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const;
SNAP *tkip_decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const;
RC4Key generate_rc4_key(const Dot11Data &dot11, const RawPDU &raw) const;
ptk_type ptk;
bool is_ccmp;
};
class SupplicantData {
public:
typedef HWAddress<6> address_type;
typedef SessionKeys::pmk_type pmk_type;
SupplicantData(const std::string &psk, const std::string &ssid);
const pmk_type &pmk() const;
private:
pmk_type pmk_;
};
}
#endif // HAVE_WPA2_DECRYPTION
/**
* \endcond
*/
/**
* \brief RC4 Key abstraction.
*/
@@ -65,11 +115,11 @@ namespace Crypto {
};
/**
*
* \brief Decrypts WEP-encrypted traffic.
*/
class WEPDecrypter {
public:
typedef Dot11::address_type address_type;
typedef HWAddress<6> address_type;
/**
* \brief Constructs a WEPDecrypter object.
@@ -93,19 +143,18 @@ namespace Crypto {
void remove_password(const address_type &addr);
/**
* \brief Decrypts the provided PDU and forwards the decrypted
* PDU to the functor held by this object.
* \brief Decrypts the provided PDU.
*
* A Dot11Data PDU is looked up inside the provided PDU chain.
* If no such PDU exists or there is no password associated
* with the Dot11 packet's BSSID, then the PDU is left intact.
*
* Otherwise, the packet is decrypted using the given password.
* If the CRC found after decrypting it is invalid,
* then false is returned.
* If the CRC found after decrypting is invalid, false is
* returned.
*
* \return false if decryption failed due to invalid CRC, true
* otherwise.
* \return false if no decryption was performed or decryption
* failed, true otherwise.
*/
bool decrypt(PDU &pdu);
private:
@@ -117,6 +166,96 @@ namespace Crypto {
std::vector<uint8_t> key_buffer;
};
#ifdef HAVE_WPA2_DECRYPTION
/**
* \brief Decrypts WPA2-encrypted traffic.
*
* This class takes valid PSK and SSID tuples, captures client handshakes,
* and decrypts their traffic afterwards.
*/
class WPA2Decrypter {
public:
/*
* \brief The type used to store Dot11 addresses.
*/
typedef HWAddress<6> address_type;
/**
* \brief Adds an access points's information.
*
* This associates an SSID with a PSK, and allows the decryption of
* any BSSIDs that broadcast the same SSID.
*
* The decrypter will inspect beacon frames, looking for SSID tags
* that contain the given SSID.
*
* Note that using this overload, the decryption of data frames and
* handshake capturing will be disabled until any access point
* broadcasts the provided SSID(this shouldn't take long at all).
* If this is not the desired behaviour, then you should check out
* the ovther add_ap_data overload.
*
* \param psk The PSK associated with the SSID.
* \param ssid The network's SSID.
*/
void add_ap_data(const std::string &psk, const std::string &ssid);
/**
* \brief Adds a access points's information, including its BSSID.
*
* This overload can be used if the BSSID associated with this SSID is
* known beforehand. The addr parameter indicates which specific BSSID
* is associated to the SSID.
*
* Note that if any other access point broadcasts the provided SSID,
* it will be taken into account as well.
*
* \param psk The PSK associated with this SSID.
* \param ssid The network's SSID.
* \param addr The access point's BSSID.
*/
void add_ap_data(const std::string &psk, const std::string &ssid, const address_type &addr);
/**
* \brief Decrypts the provided PDU.
*
* A Dot11Data PDU is looked up inside the provided PDU chain.
* If no such PDU exists or no PSK was associated with the SSID
* broadcasted by the Dot11 packet's BSSID, or no EAPOL handshake
* was captured for the client involved in the communication,
* then the PDU is left intact.
*
* Otherwise, the packet is decrypted using the generated PTK.
* If the resulting MIC is invalid, then the packet is left intact.
*
* \return false if no decryption was performed, or the decryption
* failed, true otherwise.
*/
bool decrypt(PDU &pdu);
private:
typedef std::map<std::string, WPA2::SupplicantData> pmks_map;
typedef std::map<address_type, WPA2::SupplicantData> bssids_map;
typedef std::pair<address_type, address_type> addr_pair;
typedef std::map<addr_pair, WPA2::SessionKeys> keys_map;
void try_add_keys(const Dot11Data &dot11, const RSNHandshake &hs);
addr_pair make_addr_pair(const address_type &addr1, const address_type &addr2) {
return (addr1 < addr2) ?
std::make_pair(addr1, addr2) :
std::make_pair(addr2, addr1);
}
addr_pair extract_addr_pair(const Dot11Data &dot11);
addr_pair extract_addr_pair_dst(const Dot11Data &dot11);
bssids_map::const_iterator find_ap(const Dot11Data &dot11);
void add_access_point(const std::string &ssid, const address_type &addr);
RSNHandshakeCapturer capturer;
pmks_map pmks;
bssids_map aps;
keys_map keys;
};
#endif // HAVE_WPA2_DECRYPTION
/**
* \brief Pluggable decrypter object which can be used to decrypt
* data on sniffing sessions.
@@ -183,7 +322,7 @@ namespace Crypto {
void rc4(ForwardIterator start, ForwardIterator end, RC4Key &key, OutputIterator output);
/**
* \brief Wrapper function to create DecrypterProxyes using a
* \brief Wrapper function to create a DecrypterProxy using a
* WEPDecrypter as the Decrypter template parameter.
*
* \param functor The functor to be forwarded to the DecrypterProxy
@@ -191,6 +330,20 @@ namespace Crypto {
*/
template<typename Functor>
DecrypterProxy<Functor, WEPDecrypter> make_wep_decrypter_proxy(const Functor &functor);
#ifdef HAVE_WPA2_DECRYPTION
/**
* \brief Wrapper function to create a DecrypterProxy using a
* WPA2Decrypter as the Decrypter template parameter.
*
* \param functor The functor to be forwarded to the DecrypterProxy
* constructor.
*/
template<typename Functor>
DecrypterProxy<Functor, WPA2Decrypter> make_wpa2_decrypter_proxy(const Functor &functor) {
return DecrypterProxy<Functor, WPA2Decrypter>(functor);
}
#endif // HAVE_WPA2_DECRYPTION
// Implementation section
@@ -229,7 +382,7 @@ namespace Crypto {
{
return DecrypterProxy<Functor, WEPDecrypter>(functor);
}
// RC4 stuff
template<typename ForwardIterator>

56
include/cxxstd.h Normal file
View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2012, 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_CXXSTD_H
#define TINS_CXXSTD_H
#include <memory>
#ifdef __GXX_EXPERIMENTAL_CXX0X__
#define TINS_CXXSTD_GCC_FIX 1
#else
#define TINS_CXXSTD_GCC_FIX 0
#endif // __GXX_EXPERIMENTAL_CXX0X__
#define TINS_IS_CXX11 (__cplusplus > 199711L || TINS_CXXSTD_GCC_FIX == 1)
namespace Tins{
namespace Internals {
template<typename T>
struct smart_ptr {
#if TINS_IS_CXX11
typedef std::unique_ptr<T> type;
#else
typedef std::auto_ptr<T> type;
#endif
};
}
}
#endif // TINS_CXXSTD_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,15 +32,19 @@
#include <list>
#include <vector>
#include <string>
#include "bootp.h"
#include "pdu_option.h"
#include "cxxstd.h"
namespace Tins {
/**
* \brief Class that represents the DHCP PDU.
*
* The end option is added automatically at the end of the option list.
*
* When adding options, the "End" option is not added automatically.
*
* \sa DHCP::end
*/
class DHCP : public BootP {
public:
@@ -66,7 +70,7 @@ namespace Tins {
/**
* \brief DHCP options enum.
*/
enum Options {
enum OptionTypes {
PAD,
SUBNET_MASK,
TIME_OFFSET,
@@ -142,12 +146,12 @@ namespace Tins {
/**
* The DHCP option type.
*/
typedef PDUOption<uint8_t> dhcp_option;
typedef PDUOption<uint8_t, DHCP> option;
/**
* The type used to store the DHCP options.
*/
typedef std::list<dhcp_option> options_type;
typedef std::list<option> options_type;
/**
* \brief Creates an instance of DHCP.
@@ -158,35 +162,57 @@ namespace Tins {
DHCP();
/**
* \brief Constructor which creates a DHCP object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \brief Constructs a DHCP object from a buffer.
*
* If there is not enough size for a BootP header, or any of
* the TLV options contains an invalid size field, then a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
* Subclasses might use 0 to provide their own interpretation of this field.
*/
DHCP(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Adds a new option to this DHCP PDU.
* \param option The option to be added.
* \param opt The option to be added.
*/
void add_option(const dhcp_option &option);
void add_option(const option &opt);
#if TINS_IS_CXX11
/**
* \brief Adds a new option to this DHCP PDU.
*
* The option is move-constructed.
*
* \param opt The option to be added.
*/
void add_option(option &&opt) {
internal_add_option(opt);
_options.push_back(std::move(opt));
}
#endif
/**
* \brief Searchs for an option that matchs the given flag.
* \param opt_flag The flag to be searched.
* \return A pointer to the option, or 0 if it was not found.
*/
const dhcp_option *search_option(Options opt) const;
const option *search_option(OptionTypes opt) const;
/**
* \brief Adds a type option the the option list.
* \brief Adds a type option to the option list.
*
* The new option is appended at the end of the list.
*
* \param type The type of this DHCP PDU.
*/
void type(Flags type);
/**
* \brief Adds an end option the the option list.
* \brief Adds an end option to the option list.
*
* The new option is appended at the end of the list.
*
* The END option is not added automatically. You should explicitly
* add it at the end of the DHCP options for the PDU to be
@@ -196,60 +222,90 @@ namespace Tins {
/**
* \brief Adds a server identifier option.
* \param ip The ip of the server.
*
* The new option is appended at the end of the list.
*
* \param ip The server's IP address.
*/
void server_identifier(ipaddress_type ip);
/**
* \brief Adds an IP address lease time option.
*
* The new option is appended at the end of the list.
*
* \param time The lease time.
*/
void lease_time(uint32_t time);
/**
* \brief Adds a lease renewal time option.
*
* The new option is appended at the end of the list.
*
* \param time The lease renew time.
*/
void renewal_time(uint32_t time);
/**
* \brief Adds a rebind time option.
*
* The new option is appended at the end of the list.
*
* \param time The lease rebind time.
*/
void rebind_time(uint32_t time);
/**
* \brief Adds a subnet mask option.
*
* The new option is appended at the end of the list.
*
* \param mask The subnet mask.
*/
void subnet_mask(ipaddress_type mask);
/**
* \brief Adds a routers option.
*
* The new option is appended at the end of the list.
*
* \param routers A list of ip addresses.
*/
void routers(const std::list<ipaddress_type> &routers);
void routers(const std::vector<ipaddress_type> &routers);
/**
* \brief Adds a domain name servers option.
*
* The new option is appended at the end of the list.
*
* \param dns A list of ip addresses.
*/
void domain_name_servers(const std::list<ipaddress_type> &dns);
void domain_name_servers(const std::vector<ipaddress_type> &dns);
/**
* \brief Adds a broadcast address option.
*
* The new option is appended at the end of the list.
*
* \param addr The broadcast address.
*/
void broadcast(ipaddress_type addr);
/**
* \brief Adds a requested address option.
*
* The new option is appended at the end of the list.
*
* \param addr The requested address.
*/
void requested_ip(ipaddress_type addr);
/**
* \brief Adds a domain name option.
*
* The new option is appended at the end of the list.
*
* \param name The domain name.
*/
void domain_name(const std::string &name);
@@ -259,7 +315,7 @@ namespace Tins {
/**
* \brief Searchs for a type option.
*
* If the option is not found, a option_not_found exception
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return uint8_t containing the type option.
@@ -269,7 +325,7 @@ namespace Tins {
/**
* \brief Searchs for a server identifier option.
*
* If the option is not found, a option_not_found exception
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return ipaddress_type Containing the server identifier.
@@ -279,7 +335,7 @@ namespace Tins {
/**
* \brief Searchs for a lease time option.
*
* If the option is not found, a option_not_found exception
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return uint32_t Containing the lease time.
@@ -289,7 +345,7 @@ namespace Tins {
/**
* \brief Searchs for a lease renewal time option.
*
* If the option is not found, a option_not_found exception
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return uint32_t Containing the renewal time.
@@ -299,7 +355,7 @@ namespace Tins {
/**
* \brief Searchs for a rebind time option.
*
* If the option is not found, a option_not_found exception
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return uint32_t Containing the rebind time.
@@ -309,7 +365,7 @@ namespace Tins {
/**
* \brief Searchs for a subnet mask option.
*
* If the option is not found, a option_not_found exception
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return ipaddress_type Containing the subnet mask.
@@ -319,29 +375,29 @@ namespace Tins {
/**
* \brief Searchs for a routers option.
*
* If the option is not found, a option_not_found exception
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return std::list<ipaddress_type> Containing the routers
* \return std::vector<ipaddress_type> Containing the routers
* option data.
*/
std::list<ipaddress_type> routers() const;
std::vector<ipaddress_type> routers() const;
/**
* \brief Searchs for a dns option.
*
* If the option is not found, a option_not_found exception
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return std::list<ipaddress_type> Contanining the DNS servers
* provided.
*/
std::list<ipaddress_type> domain_name_servers() const;
std::vector<ipaddress_type> domain_name_servers() const;
/**
* \brief Searchs for a broadcast option.
*
* If the option is not found, a option_not_found exception
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return ipaddress_type Containing the broadcast address.
@@ -351,7 +407,7 @@ namespace Tins {
/**
* \brief Searchs for a requested option.
*
* If the option is not found, a option_not_found exception
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return ipaddress_type Containing the requested IP address.
@@ -361,14 +417,15 @@ namespace Tins {
/**
* \brief Searchs for a domain name option.
*
* If the option is not found, a option_not_found exception
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return std::string Containing the domain name.
*/
std::string domain_name() const;
/** \brief Getter for the options list.
/**
* \brief Getter for the options list.
* \return The option list.
*/
const options_type options() const { return _options; }
@@ -377,7 +434,7 @@ namespace Tins {
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::DHCP; }
PDUType pdu_type() const { return pdu_flag; }
/**
* \brief Getter for the header size.
@@ -394,30 +451,23 @@ namespace Tins {
}
private:
static const uint32_t MAX_DHCP_SIZE;
template<typename T>
struct type2type {};
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
template<class T>
T generic_search(Options opt, type2type<T>) const {
const dhcp_option *option = search_option(opt);
if(option && option->data_size() == sizeof(T))
return *(const T*)option->data_ptr();
else
T search_and_convert(OptionTypes opt) const {
const option *option = search_option(opt);
if(!option)
throw option_not_found();
return option->to<T>();
}
std::list<ipaddress_type> generic_search(Options opt, type2type<std::list<ipaddress_type> >) const;
std::string generic_search(Options opt, type2type<std::string>) const;
ipaddress_type generic_search(Options opt, type2type<ipaddress_type>) const;
serialization_type serialize_list(const std::list<ipaddress_type> &ip_list);
void internal_add_option(const option &opt);
serialization_type serialize_list(const std::vector<ipaddress_type> &ip_list);
options_type _options;
uint32_t _size;
};
};
}
#endif // TINS_DHCP_H

925
include/dhcpv6.h Normal file
View File

@@ -0,0 +1,925 @@
/*
* Copyright (c) 2012, 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_DHCPV6_H
#define TINS_DHCPV6_H
#include <list>
#include "pdu.h"
#include "endianness.h"
#include "small_uint.h"
#include "ipv6_address.h"
#include "pdu_option.h"
namespace Tins {
/**
* Represents a DHCPv6 PDU.
*/
class DHCPv6 : public PDU {
public:
/**
* Represents a DHCPv6 option.
*/
typedef PDUOption<uint16_t, DHCPv6> option;
/**
* The message types.
*/
enum MessageType {
SOLICIT = 1,
ADVERTISE,
REQUEST,
CONFIRM,
RENEW,
REBIND,
REPLY,
RELEASE,
DECLINE,
RECONFIGURE,
INFO_REQUEST,
RELAY_FORWARD,
RELAY_REPLY,
LEASE_QUERY,
LEASE_QUERY_REPLY,
LEASE_QUERY_DONE,
LEASE_QUERY_DATA
};
/**
* The DHCPv6 options.
*/
enum OptionTypes {
CLIENTID = 1,
SERVERID,
IA_NA,
IA_TA,
IA_ADDR,
OPTION_REQUEST,
PREFERENCE,
ELAPSED_TIME,
RELAY_MSG,
AUTH = 11,
UNICAST,
STATUS_CODE,
RAPID_COMMIT,
USER_CLASS,
VENDOR_CLASS,
VENDOR_OPTS,
INTERFACE_ID,
RECONF_MSG,
RECONF_ACCEPT,
SIP_SERVER_D,
SIP_SERVER_A,
DNS_SERVERS,
DOMAIN_LIST,
IA_PD,
IAPREFIX,
NIS_SERVERS,
NISP_SERVERS,
NIS_DOMAIN_NAME,
NISP_DOMAIN_NAME,
SNTP_SERVERS,
INFORMATION_REFRESH_TIME,
BCMCS_SERVER_D,
BCMCS_SERVER_A,
GEOCONF_CIVIC = 36,
REMOTE_ID,
SUBSCRIBER_ID,
CLIENT_FQDN,
PANA_AGENT,
NEW_POSIX_TIMEZONE,
NEW_TZDB_TIMEZONE,
ERO,
LQ_QUERY,
CLIENT_DATA,
CLT_TIME,
LQ_RELAY_DATA,
LQ_CLIENT_LINK,
MIP6_HNIDF,
MIP6_VDINF,
V6_LOST,
CAPWAP_AC_V6,
RELAY_ID,
NTP_SERVER,
V6_ACCESS_DOMAIN,
SIP_UA_CS_LIST,
BOOTFILE_URL,
BOOTFILE_PARAM,
CLIENT_ARCH_TYPE,
NII,
GEOLOCATION,
AFTR_NAME,
ERP_LOCAL_DOMAIN_NAME,
RSOO,
PD_EXCLUDE,
VSS,
MIP6_IDINF,
MIP6_UDINF,
MIP6_HNP,
MIP6_HAA,
MIP6_HAF,
RDNSS_SELECTION,
KRB_PRINCIPAL_NAME,
KRB_REALM_NAME,
KRB_DEFAULT_REALM_NAME,
KRB_KDC
};
/**
* The type used to store the DHCPv6 options.
*/
typedef std::list<option> options_type;
/**
* The type used to store IP addresses.
*/
typedef IPv6Address ipaddress_type;
/**
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::DHCPv6;
/**
* The type used to store the Identity Association for Non-Temporary
* Addresses option.
*/
struct ia_na_type {
typedef std::vector<uint8_t> options_type;
uint32_t id, t1, t2;
options_type options;
ia_na_type(uint32_t id = 0, uint32_t t1 = 0, uint32_t t2 = 0,
const options_type& options = options_type())
: id(id), t1(t1), t2(t2), options(options) {}
static ia_na_type from_option(const option &opt);
};
/**
* The type used to store the Identity Association for Temporary
* Addresses option.
*/
struct ia_ta_type {
typedef std::vector<uint8_t> options_type;
uint32_t id;
options_type options;
ia_ta_type(uint32_t id = 0,
const options_type& options = options_type())
: id(id), options(options) {}
static ia_ta_type from_option(const option &opt);
};
/**
* The type used to store the Identity Association Address option.
*/
struct ia_address_type {
typedef std::vector<uint8_t> options_type;
ipaddress_type address;
uint32_t preferred_lifetime, valid_lifetime;
options_type options;
ia_address_type(ipaddress_type address = ipaddress_type(),
uint32_t preferred_lifetime = 0, uint32_t valid_lifetime = 0,
const options_type& options = options_type())
: address(address), preferred_lifetime(preferred_lifetime),
valid_lifetime(valid_lifetime), options(options) {}
static ia_address_type from_option(const option &opt);
};
/**
* The type used to store the Authentication option.
*/
struct authentication_type {
typedef std::vector<uint8_t> auth_info_type;
uint8_t protocol, algorithm, rdm;
uint64_t replay_detection;
auth_info_type auth_info;
authentication_type(uint8_t protocol = 0, uint8_t algorithm = 0,
uint8_t rdm = 0, uint64_t replay_detection = 0,
const auth_info_type &auth_info = auth_info_type())
: protocol(protocol), algorithm(algorithm), rdm(rdm),
replay_detection(replay_detection), auth_info(auth_info) {}
static authentication_type from_option(const option &opt);
};
/**
* The type used to store the Status Code option.
*/
struct status_code_type {
uint16_t code;
std::string message;
status_code_type(uint16_t code = 0, const std::string &message = "")
: code(code), message(message) { }
static status_code_type from_option(const option &opt);
};
/**
* The type used to store the Vendor-specific Information option.
*/
struct vendor_info_type {
typedef std::vector<uint8_t> data_type;
uint32_t enterprise_number;
data_type data;
vendor_info_type(uint32_t enterprise_number = 0,
const data_type &data = data_type())
: enterprise_number(enterprise_number), data(data) { }
static vendor_info_type from_option(const option &opt);
};
/**
* The type used to store the User Class option's user class data.
*/
typedef std::vector<uint8_t> class_option_data_type;
/**
* The type used to store the User Class option.
*/
//typedef std::vector<class_option_data_type> user_class_type;
struct user_class_type {
typedef std::vector<class_option_data_type> data_type;
data_type data;
user_class_type(const data_type &data = data_type())
: data(data)
{
}
static user_class_type from_option(const option &opt);
};
/**
* The type used to store the Vendor Class option.
*/
struct vendor_class_type {
typedef std::vector<class_option_data_type> class_data_type;
uint32_t enterprise_number;
class_data_type vendor_class_data;
vendor_class_type(uint32_t enterprise_number = 0,
const class_data_type &vendor_class_data = class_data_type())
: enterprise_number(enterprise_number),
vendor_class_data(vendor_class_data) { }
static vendor_class_type from_option(const option &opt);
};
/**
* The type used to represent DUIDs Based on Link-layer Address Plus
* Time.
*/
struct duid_llt {
static const uint16_t duid_id = 1;
typedef std::vector<uint8_t> lladdress_type;
uint16_t hw_type;
uint32_t time;
lladdress_type lladdress;
duid_llt(uint16_t hw_type = 0, uint32_t time = 0,
const lladdress_type &lladdress = lladdress_type())
: hw_type(hw_type), time(time), lladdress(lladdress) {}
PDU::serialization_type serialize() const;
static duid_llt from_bytes(const uint8_t *buffer, uint32_t total_sz);
};
/**
* The type used to represent DUIDs Based on Enterprise Number
*/
struct duid_en {
static const uint16_t duid_id = 2;
typedef std::vector<uint8_t> identifier_type;
uint32_t enterprise_number;
identifier_type identifier;
duid_en(uint32_t enterprise_number = 0,
const identifier_type &identifier = identifier_type())
: enterprise_number(enterprise_number), identifier(identifier) {}
PDU::serialization_type serialize() const;
static duid_en from_bytes(const uint8_t *buffer, uint32_t total_sz);
};
/**
* The type used to represent DUIDs Based on Link-layer Address.
*/
struct duid_ll {
static const uint16_t duid_id = 3;
typedef std::vector<uint8_t> lladdress_type;
uint16_t hw_type;
lladdress_type lladdress;
duid_ll(uint16_t hw_type = 0,
const lladdress_type &lladdress = lladdress_type())
: hw_type(hw_type), lladdress(lladdress) {}
PDU::serialization_type serialize() const;
static duid_ll from_bytes(const uint8_t *buffer, uint32_t total_sz);
};
/**
* Type type used to represent DUIDs. This will be stored as the
* value for the Client/Server Identifier options.
*/
struct duid_type {
typedef PDU::serialization_type data_type;
uint16_t id;
data_type data;
duid_type(uint16_t id = 0, const data_type &data = data_type())
: id(id), data(data) {}
duid_type(const duid_llt &identifier)
: id(duid_llt::duid_id), data(identifier.serialize()) {}
duid_type(const duid_en &identifier)
: id(duid_en::duid_id), data(identifier.serialize()) {}
duid_type(const duid_ll &identifier)
: id(duid_en::duid_id), data(identifier.serialize()) {}
static duid_type from_option(const option &opt);
};
/**
* The type used to store the Option Request option.
*/
typedef std::vector<uint16_t> option_request_type;
/**
* The type used to store the Relay Message option.
*/
typedef std::vector<uint8_t> relay_msg_type;
/**
* The type used to store the Interface-ID option.
*/
typedef std::vector<uint8_t> interface_id_type;
/**
* Default constructor.
*/
DHCPv6();
/**
* \brief Constructs a DHCPv6 object from a buffer.
*
* If there is not enough size for the DHCPv6 header, or any
* of the TLV options contains an invalid size field, a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
DHCPv6(const uint8_t *buffer, uint32_t total_sz);
// Getters
/**
* \brief Getter for the message type field.
*
* \return The stored message type field.
*/
MessageType msg_type() const {
return static_cast<MessageType>(header_data[0]);
}
/**
* \brief Getter for the hop count field.
*
* \return The stored hop count field.
*/
uint8_t hop_count() const { return header_data[1]; }
/**
* \brief Getter for the transaction id field.
*
* \return The stored transaction id field.
*/
small_uint<24> transaction_id() const {
return (header_data[1] << 16) | (header_data[2] << 8) | header_data[3];
}
/**
* \brief Getter for the peer address field.
*
* \return The stored peer address field.
*/
const ipaddress_type &peer_address() const { return peer_addr; }
/**
* \brief Getter for the link address field.
*
* \return The stored link address field.
*/
const ipaddress_type &link_address() const { return link_addr; }
/**
* \brief Getter for the DHCPv6 options.
*
* \return The stored options.
*/
const options_type &options() const { return options_; }
// Setters
/**
* \brief Setter for the message type field.
*
* \param type The new message type.
*/
void msg_type(MessageType type);
/**
* \brief Setter for the hop count field.
*
* \param count The new hop count.
*/
void hop_count(uint8_t count);
/**
* \brief Setter for the transaction id field.
*
* \param id The new transaction id.
*/
void transaction_id(small_uint<24> id);
/**
* \brief Setter for the peer address field.
*
* \param count The new peer address.
*/
void peer_address(const ipaddress_type &addr);
/**
* \brief Setter for the link address field.
*
* \param count The new link address.
*/
void link_address(const ipaddress_type &addr);
// Option getters
/**
* \brief Getter for the Identity Association for Non-Temporary
* Addresses option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
ia_na_type ia_na() const;
/**
* \brief Getter for the Identity Association for Temporary
* Addresses option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
ia_ta_type ia_ta() const;
/**
* \brief Getter for the Identity Association Address option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
ia_address_type ia_address() const;
/**
* \brief Getter for the Option Request option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
option_request_type option_request() const;
/**
* \brief Getter for the Preference option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
uint8_t preference() const;
/**
* \brief Getter for the Elapsed Time option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
uint16_t elapsed_time() const;
/**
* \brief Getter for the Relay Message option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
relay_msg_type relay_message() const;
/**
* \brief Getter for the Authentication option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
authentication_type authentication() const;
/**
* \brief Getter for the Server Unicast option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
ipaddress_type server_unicast() const;
/**
* \brief Getter for the Server Unicast option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
status_code_type status_code() const;
/**
* \brief Getter for the Rapid Commit option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
bool has_rapid_commit() const;
/**
* \brief Getter for the User Class option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
user_class_type user_class() const;
/**
* \brief Getter for the Vendor Class option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
vendor_class_type vendor_class() const;
/**
* \brief Getter for the Vendor-specific Information option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
vendor_info_type vendor_info() const;
/**
* \brief Getter for the Interface ID option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
interface_id_type interface_id() const;
/**
* \brief Getter for the Reconfigure Message option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
uint8_t reconfigure_msg() const;
/**
* \brief Getter for the Reconfigure Accept option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
bool has_reconfigure_accept() const;
/**
* \brief Getter for the Client Identifier option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
duid_type client_id() const;
/**
* \brief Getter for the Server Identifier option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
duid_type server_id() const;
// Option setters
/**
* \brief Setter for the Identity Association for Non-Temporary
* Addresses option.
*
* \param value The new IA_NA option data.
*/
void ia_na(const ia_na_type &value);
/**
* \brief Setter for the Identity Association for Temporary
* Addresses option.
*
* \param value The new IA_TA option data.
*/
void ia_ta(const ia_ta_type &value);
/**
* \brief Setter for the Identity Association Address option.
*
* \param value The new IA Address option data.
*/
void ia_address(const ia_address_type &value);
/**
* \brief Setter for the Identity Association Address option.
*
* \param value The new Option Request option data.
*/
void option_request(const option_request_type &value);
/**
* \brief Setter for the Preference option.
*
* \param value The new Preference option data.
*/
void preference(uint8_t value);
/**
* \brief Setter for the Elapsed Time option.
*
* \param value The new Elapsed Time option data.
*/
void elapsed_time(uint16_t value);
/**
* \brief Setter for the Relay Message option.
*
* \param value The new Relay Message option data.
*/
void relay_message(const relay_msg_type &value);
/**
* \brief Setter for the Authentication option.
*
* \param value The new Authentication option data.
*/
void authentication(const authentication_type &value);
/**
* \brief Setter for the Server Unicast option.
*
* \param value The new Server Unicast option data.
*/
void server_unicast(const ipaddress_type &value);
/**
* \brief Setter for the Status Code option.
*
* \param value The new Status Code option data.
*/
void status_code(const status_code_type &value);
/**
* \brief Adds a Rapid Commit option.
*/
void rapid_commit();
/**
* \brief Setter for the User Class option.
*
* \param value The new User Class option data.
*/
void user_class(const user_class_type &value);
/**
* \brief Setter for the Vendor Class option.
*
* \param value The new Vendor Class option data.
*/
void vendor_class(const vendor_class_type &value);
/**
* \brief Setter for the Vendor-specific Information option.
*
* \param value The new Vendor-specific Information option data.
*/
void vendor_info(const vendor_info_type &value);
/**
* \brief Setter for the Interface ID option.
*
* \param value The new Interface ID option data.
*/
void interface_id(const interface_id_type &value);
/**
* \brief Setter for the Reconfigure Message option.
*
* \param value The new Reconfigure Message option data.
*/
void reconfigure_msg(uint8_t value);
/**
* \brief Adds a Reconfigure Accept option.
*/
void reconfigure_accept();
/**
* \brief Setter for the Client Identifier option.
*
* \param value The new Client Identifier option data.
*/
void client_id(const duid_type &value);
/**
* \brief Setter for the Server Identifier option.
*
* \param value The new Server Identifier option data.
*/
void server_id(const duid_type &value);
// Other stuff
/**
* Indicates whether this is a relay agent/server message
*/
bool is_relay_message() const;
/**
* \brief Adds a DHCPv6 option.
*
* The option is added after the last option in the option
* fields.
*
* \param opt The option to be added
*/
void add_option(const option &opt);
/**
* \brief Searchs for an option that matchs the given flag.
*
* If the option is not found, a null pointer is returned.
* Deleting the returned pointer will result in <b>undefined
* behaviour</b>.
*
* \param id The option identifier to be searched.
*/
const option *search_option(OptionTypes id) const;
// PDU stuff
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \sa PDU::clone
*/
DHCPv6 *clone() const {
return new DHCPv6(*this);
}
private:
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
uint8_t* write_option(const option &option, uint8_t* buffer) const;
template<template <typename> class Functor>
const option *safe_search_option(OptionTypes opt, uint32_t size) const {
const option *option = search_option(opt);
if(!option || Functor<uint32_t>()(option->data_size(), size))
throw option_not_found();
return option;
}
template<typename T>
T search_and_convert(OptionTypes opt) const {
const option *option = search_option(opt);
if(!option)
throw option_not_found();
return option->to<T>();
}
uint8_t header_data[4];
uint32_t options_size;
ipaddress_type link_addr, peer_addr;
options_type options_;
};
namespace Internals {
template<typename InputIterator>
void class_option_data2option(InputIterator start, InputIterator end,
std::vector<uint8_t>& buffer, size_t start_index = 0)
{
size_t index = start_index;
while(start != end) {
buffer.resize(buffer.size() + sizeof(uint16_t) + start->size());
*(uint16_t*)&buffer[index] = Endian::host_to_be<uint16_t>(start->size());
index += sizeof(uint16_t);
std::copy(start->begin(), start->end(), buffer.begin() + index);
index += start->size();
start++;
}
}
template<typename OutputType>
OutputType option2class_option_data(const uint8_t *ptr, uint32_t total_sz)
{
typedef typename OutputType::value_type value_type;
OutputType output;
size_t index = 0;
while(index + 2 < total_sz) {
uint16_t size = Endian::be_to_host(
*(const uint16_t*)(ptr + index)
);
index += sizeof(uint16_t);
if(index + size > total_sz)
throw option_not_found();
output.push_back(
value_type(ptr + index, ptr + index + size)
);
index += size;
}
if(index != total_sz)
throw malformed_option();
return output;
}
}
}
#endif // TINS_DHCPV6_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,12 +36,13 @@
#include <cstring>
#include <string>
#include <map>
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
#include "dns_record.h"
namespace Tins {
class IPv4Address;
class IPv6Address;
/**
* \class DNS
@@ -198,14 +199,24 @@ namespace Tins {
*/
class Resource {
public:
Resource(const std::string &nm, const std::string &ad,
uint16_t t, uint16_t c, uint32_t tt)
: dname_(nm), addr_(ad), type_(t), qclass_(c), ttl_(tt) {}
/**
* Constructs a Resource object.
*
* \param dname The domain name for which this records
* provides an answer.
* \param data The resource's payload.
* \param type The type of this record.
* \param rclass The class of this record.
* \param ttl The time-to-live of this record.
*/
Resource(const std::string &dname, const std::string &data,
uint16_t type, uint16_t rclass, uint32_t ttl)
: dname_(dname), data_(data), type_(type), qclass_(rclass), ttl_(ttl) {}
Resource() : type_(), qclass_(), ttl_() {}
/**
* \brief Getter for the dname field.
* \brief Getter for the domain name field.
*
* This returns the domain name for which this record
* provides an answer.
@@ -213,9 +224,9 @@ namespace Tins {
const std::string &dname() const { return dname_; }
/**
* Getter for the type field.
* Getter for the data field.
*/
const std::string &data() const { return addr_; }
const std::string &data() const { return data_; }
/**
* Getter for the query type field.
@@ -231,8 +242,52 @@ namespace Tins {
* Getter for the type field.
*/
uint32_t ttl() const { return ttl_; }
/**
* Setter for the domain name field.
*/
void dname(const std::string &data) {
dname_ = data;
}
/**
* \brief Setter for the data field.
*
* The data will be encoded properly by the DNS class before
* being added to this packet. That means that if the type is
* A or AAAA, it will be properly encoded as an IPv4 or
* IPv6 address.
*
* The same happens for records that contain domain names,
* such as NS or CNAME. This data will be encoded using
* DNS domain name encoding.
*/
void data(const std::string &data) {
data_ = data;
}
/**
* Setter for the type field.
*/
void type(uint16_t data) {
type_ = data;
}
/**
* Setter for the class field.
*/
void query_class(uint16_t data) {
qclass_ = data;
}
/**
* Setter for the time-to-live field.
*/
void ttl(uint16_t data) {
ttl_ = data;
}
private:
std::string dname_, addr_;
std::string dname_, data_;
uint16_t type_, qclass_;
uint32_t ttl_;
};
@@ -240,6 +295,7 @@ namespace Tins {
typedef std::list<Query> queries_type;
typedef std::list<Resource> resources_type;
typedef IPv4Address address_type;
typedef IPv6Address address_v6_type;
/**
* \brief Default constructor.
@@ -249,7 +305,11 @@ namespace Tins {
DNS();
/**
* \brief Constructor which creates a DNS object from a buffer.
* \brief Constructs a DNS object from a buffer.
*
* If there's not enough size for the DNS header, or any of the
* records are malformed, a malformed_packet is be thrown.
*
* \param buffer The buffer from which this PDU will be
* constructed.
* \param total_sz The total size of the buffer.
@@ -475,81 +535,79 @@ namespace Tins {
void add_query(const Query &query);
/**
* \brief Add a query response.
* \brief Add an answer resource record.
*
* \param name The resolved name.
* \param type The type of this answer.
* \param qclass The class of this answer.
* \param ttl The time-to-live of this answer.
* \param ip The ip address of the resolved name.
* \param resource The resource to be added.
*/
void add_answer(const std::string &name,
const DNSResourceRecord::info &info, address_type ip);
void add_answer(const Resource &resource);
/**
* \brief Add a query response.
* \brief Add an authority resource record.
*
* \param name The resolved name.
* \param type The type of this answer.
* \param qclass The class of this answer.
* \param ttl The time-to-live of this answer.
* \param dname The domain of the resolved name.
* \param resource The resource to be added.
*/
void add_answer(const std::string &name,
const DNSResourceRecord::info &info, const std::string &dname);
/**
* \brief Add a query response.
*
* \param name The resolved name.
* \param type The type of this answer.
* \param qclass The class of this answer.
* \param ttl The time-to-live of this answer.
* \param data The data of this option.
* \param sz The size of the data.
*/
void add_answer(const std::string &name,
const DNSResourceRecord::info &info, const uint8_t *data, uint32_t sz);
void add_authority(const Resource &resource);
/**
* \brief Add an authority record.
* \brief Add an additional resource record.
*
* \param name The resolved name.
* \param type The type of this record.
* \param qclass The class of this record.
* \param ttl The time-to-live of this record.
* \param data The data of this option.
* \param sz The size of the data.
* \param resource The resource to be added.
*/
void add_authority(const std::string &name,
const DNSResourceRecord::info &info, const uint8_t *data, uint32_t sz);
/**
* \brief Add an additional record.
*
* \param name The resolved name.
* \param type The type of this record.
* \param qclass The class of this record.
* \param ttl The time-to-live of this record.
* \param ip The ip address of the resolved name.
*/
void add_additional(const std::string &name,
const DNSResourceRecord::info &info, uint32_t ip);
void add_additional(const Resource &resource);
/**
* \brief Getter for this PDU's DNS queries.
* \return std::list<Query> containing the queries in this
* record.
*
* \return The query records in this PDU.
*/
queries_type queries() const;
/**
* \brief Getter for this PDU's DNS answers
* \return std::list<Resource> containing the answers in this
* record.
*
* \return The answer records in this PDU.
*/
resources_type answers() const;
/**
* \brief Getter for this PDU's DNS authority records.
*
* \return The authority records in this PDU.
*/
resources_type authority() const;
/**
* \brief Getter for this PDU's DNS additional records.
*
* \return The additional records in this PDU.
*/
resources_type additional() const;
/**
* \brief Encodes a domain name.
*
* This processes the input domain name and returns the encoded
* version. Each label in the original domain name will be
* prefixed with a byte that indicates the label's length.
* The null-terminator byte <b>will</b> be included in the encoded
* string. No compression is performed.
*
* For example, given the input "www.example.com", the output would
* be "\x03www\x07example\x03com\x00".
*
* \param domain_name The domain name to encode.
* \return The encoded domain name.
*/
static std::string encode_domain_name(const std::string &domain_name);
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \sa PDU::clone
@@ -557,18 +615,8 @@ namespace Tins {
DNS *clone() const {
return new DNS(*this);
}
/**
* Helper function to create a resource record information
*
* \param type The type of the query.
* \param qclass The class of the query.
* \param ttl The time-to-live of the query.
*/
static DNSResourceRecord::info make_info(QueryType type, QueryClass qclass, uint32_t ttl) {
return DNSResourceRecord::info((uint16_t)type, (uint16_t)qclass, ttl);
}
private:
TINS_BEGIN_PACK
struct dnshdr {
uint16_t id;
#if TINS_IS_LITTLE_ENDIAN
@@ -598,39 +646,27 @@ namespace Tins {
#endif
uint16_t questions, answers,
authority, additional;
} __attribute__((packed));
} TINS_END_PACK;
typedef std::map<uint16_t, std::string> SuffixMap;
typedef std::map<uint16_t, uint16_t> SuffixIndices;
typedef std::list<DNSResourceRecord> ResourcesType;
typedef std::list<Query> QueriesType;
typedef std::vector<std::pair<uint32_t*, uint32_t> > sections_type;
const uint8_t *build_resource_list(ResourcesType &lst, const uint8_t *ptr, uint32_t &sz, uint16_t nrecs);
uint32_t find_domain_name(const std::string &dname);
bool find_domain_name(const std::string &dname, const ResourcesType &lst, uint16_t &out);
void parse_domain_name(const std::string &dn, std::string &out) const;
void unparse_domain_name(const std::string &dn, std::string &out) const;
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
uint8_t *serialize_list(const ResourcesType &lst, uint8_t *buffer) const;
void compose_name(const uint8_t *ptr, uint32_t sz, std::string &out) const;
void convert_resources(const ResourcesType &lst, std::list<Resource> &res) const;
DNSResourceRecord make_record(const std::string &name, const DNSResourceRecord::info &info, uint32_t ip);
DNSResourceRecord make_record(const std::string &name, const DNSResourceRecord::info &info, const std::string &dname);
DNSResourceRecord make_record(const std::string &name, const DNSResourceRecord::info &info, const uint8_t *ptr, uint32_t len);
void add_suffix(uint32_t index, const uint8_t *data, uint32_t sz) const;
uint32_t build_suffix_map(uint32_t index, const ResourcesType &lst) const;
uint32_t build_suffix_map(uint32_t index, const QueriesType &lst) const;
void build_suffix_map() const ;
const uint8_t* compose_name(const uint8_t *ptr, char *out_ptr) const;
void convert_records(const uint8_t *ptr, const uint8_t *end, resources_type &res) const;
const uint8_t* find_section_end(const uint8_t *ptr, const uint32_t num_records) const;
const uint8_t* find_dname_end(const uint8_t *ptr) const;
void update_records(uint32_t &section_start, uint32_t num_records, uint32_t threshold, uint32_t offset);
uint8_t *update_dname(uint8_t *ptr, uint32_t threshold, uint32_t offset);
static void inline_convert_v4(uint32_t value, char *output);
static bool contains_dname(uint16_t type);
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
void add_record(const Resource &resource, const sections_type &sections);
dnshdr dns;
uint32_t extra_size;
std::list<Query> queries_;
ResourcesType ans, arity, addit;
mutable SuffixMap suffixes;
mutable SuffixIndices suffix_indices;
byte_array records_data;
uint32_t answers_idx, authority_idx, additional_idx;
};
};
}
#endif // TINS_DNS_H

View File

@@ -1,244 +0,0 @@
/*
* Copyright (c) 2012, Nasel
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_DNS_RECORD_H
#define TINS_DNS_RECORD_H
#include <string>
#include <vector>
#include <stdint.h>
namespace Tins {
class DNSRRImpl;
/**
* \brief Abstracts a DNS resource record.
*/
class DNSResourceRecord {
public:
/**
* \brief The type used to store resource records' information.
*/
struct info {
uint16_t type, qclass;
uint32_t ttl;
info(uint16_t tp, uint16_t qc, uint32_t tm)
: type(tp), qclass(qc), ttl(tm) { }
info() : type(), qclass(), ttl() {}
} __attribute__((packed));
/**
* \brief Constructs a record.
* \param impl A pointer to the impl object.
* \param data A pointer to the start of the data buffer.
* \param len The length of the data.
*/
DNSResourceRecord(DNSRRImpl *impl = 0, const uint8_t *data = 0, uint16_t len = 0);
/**
* \brief Constructs a record.
* \param buffer A pointer to the start of the data buffer.
* \param len The length of the data.
*/
DNSResourceRecord(const uint8_t *buffer, uint32_t size);
/**
* \brief Constructs a record from an input range.
* \param impl A pointer to the impl object.
* \param start The begining of the range.
* \param end The end of the range.
*/
template<typename ForwardIterator>
DNSResourceRecord(DNSRRImpl *impl, ForwardIterator start, ForwardIterator end)
: impl(impl), data(start, end)
{ }
/**
* \brief Copy constructor.
*
* This handles cloning the impl object.
* \param rhs The record which will be copied.
*/
DNSResourceRecord(const DNSResourceRecord &rhs);
/**
* \brief Copy assignment operator.
*
* This handles cloning the impl object.
* \param rhs The record which will be copied.
*/
DNSResourceRecord& operator=(const DNSResourceRecord &rhs);
/**
* \brief Destructor.
*
* This frees the impl object.
*/
~DNSResourceRecord();
/**
* \brief Writes this record to a buffer.
*
* \param buffer The buffer in which to store the serialization.
* \return uint32_t containing the number of bytes written.
*/
uint32_t write(uint8_t *buffer) const;
/**
* \brief Returns the size of the data in this record.
*/
uint32_t data_size() const {
return data.size();
}
/**
* \brief Returns the pointer to the start of the data buffer.
*/
const uint8_t *data_ptr() const {
return &data[0];
}
/**
* \brief Returns a bool indicating whether this record contains
* a domain name as the name being resolved.
*/
bool has_domain_name() const;
/**
* \brief Returns a pointer to the domain name stored in this record.
*
* This will throw a std::bad_cast exception if the impl object is
* not of the type NamedDNSRRImpl.
*/
const std::string *dname() const;
/**
* \brief Returns the offset stored in this record.
*
* This will throw a std::bad_cast exception if the impl object is
* not of the type OffsetedDNSRRImpl.
*/
uint16_t offset() const;
/**
* \brief Returns the size of this record.
*/
uint32_t size() const;
/**
* \brief Returns a reference to the info field.
*/
info &information() {
return info_;
}
/**
* \brief Returns a const reference to the info field.
*/
const info &information() const {
return info_;
}
/**
* \brief Checks if the domain name stored in this record matches
* the given one.
*
* This is a shortcut
*/
bool matches(const std::string &dname) const;
private:
DNSRRImpl *clone_impl() const;
size_t impl_size() const;
info info_;
std::vector<uint8_t> data;
DNSRRImpl *impl;
};
/**
* \cond
*/
class DNSRRImpl {
public:
virtual ~DNSRRImpl() {}
virtual uint32_t size() const = 0;
virtual uint32_t do_write(uint8_t *buffer) const = 0;
virtual bool matches(const std::string &dname) const { return false; }
virtual DNSRRImpl *clone() const = 0;
};
class OffsetedDNSRRImpl : public DNSRRImpl {
public:
OffsetedDNSRRImpl(uint16_t off);
uint32_t do_write(uint8_t *buffer) const;
uint32_t size() const;
OffsetedDNSRRImpl *clone() const;
uint16_t offset() const;
private:
uint16_t offset_;
};
class NamedDNSRRImpl : public DNSRRImpl {
public:
NamedDNSRRImpl(const std::string &nm);
template<typename ForwardIterator>
NamedDNSRRImpl(ForwardIterator start, ForwardIterator end)
: name(start, end)
{ }
uint32_t do_write(uint8_t *buffer) const;
uint32_t size() const;
bool matches(const std::string &dname) const;
const std::string *dname_pointer() const;
NamedDNSRRImpl *clone() const;
private:
std::string name;
};
/**
* \endcond
*/
inline DNSResourceRecord make_offseted_record(uint16_t offset, const uint8_t *data = 0, uint32_t size = 0) {
return DNSResourceRecord(new OffsetedDNSRRImpl(offset), data, size);
}
inline DNSResourceRecord make_named_record(const std::string &name, const uint8_t *data = 0, uint32_t size = 0) {
return DNSResourceRecord(new NamedDNSRRImpl(name), data, size);
}
}
#endif // TINS_DNS_RECORD_H

File diff suppressed because it is too large Load Diff

622
include/dot11/dot11_assoc.h Normal file
View File

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

260
include/dot11/dot11_auth.h Normal file
View File

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

522
include/dot11/dot11_base.h Normal file
View File

@@ -0,0 +1,522 @@
/*
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "../config.h"
#if !defined(TINS_DOT11_DOT11_H) && defined(HAVE_DOT11)
#define TINS_DOT11_DOT11_H
#include <list>
#include "../pdu.h"
#include "../pdu_option.h"
#include "../small_uint.h"
#include "../hw_address.h"
#include "../endianness.h"
#include "../cxxstd.h"
#include "../macros.h"
namespace Tins {
class RSNInformation;
/**
* \brief Class representing an 802.11 frame.
*/
class Dot11 : public PDU {
public:
/**
* The type used to store hardware addresses.
*/
typedef HWAddress<6> address_type;
/**
* \brief IEEE 802.11 options struct.
*/
typedef PDUOption<uint8_t, Dot11> option;
/**
* The type used to store tagged options.
*/
typedef std::list<option> options_type;
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::DOT11;
/**
* \brief Broadcast hardware address.
*/
static const address_type BROADCAST;
/**
* The endianness used by Dot11.
*/
static const endian_type endianness = LE;
/**
* \brief Enum for the different types of 802.11 frames.
*
*/
enum Types {
MANAGEMENT = 0,
CONTROL = 1,
DATA = 2
};
/**
* \brief Enum for the different types of tagged options.
*/
enum OptionTypes {
SSID,
SUPPORTED_RATES,
FH_SET,
DS_SET,
CF_SET,
TIM,
IBSS_SET,
COUNTRY,
HOPPING_PATTERN_PARAMS,
HOPPING_PATTERN_TABLE,
REQUEST_INFORMATION,
BSS_LOAD,
EDCA,
TSPEC,
TCLAS,
SCHEDULE,
CHALLENGE_TEXT,
POWER_CONSTRAINT = 32,
POWER_CAPABILITY,
TPC_REQUEST,
TPC_REPORT,
SUPPORTED_CHANNELS,
CHANNEL_SWITCH,
MEASUREMENT_REQUEST,
MEASUREMENT_REPORT,
QUIET,
IBSS_DFS,
ERP_INFORMATION,
TS_DELAY,
TCLAS_PROCESSING,
QOS_CAPABILITY = 46,
RSN = 48,
EXT_SUPPORTED_RATES = 50,
VENDOR_SPECIFIC = 221
};
/**
* \brief Enum for the different subtypes of 802.11 management frames.
*
*/
enum ManagementSubtypes {
ASSOC_REQ = 0,
ASSOC_RESP = 1,
REASSOC_REQ = 2,
REASSOC_RESP = 3,
PROBE_REQ = 4,
PROBE_RESP = 5,
BEACON = 8,
ATIM = 9,
DISASSOC = 10,
AUTH = 11,
DEAUTH = 12
};
/**
* \brief Enum for the different subtypes of 802.11 control frames.
*
*/
enum ControlSubtypes {
BLOCK_ACK_REQ = 8,
BLOCK_ACK = 9,
PS = 10,
RTS = 11,
CTS = 12,
ACK = 13,
CF_END = 14,
CF_END_ACK = 15
};
/**
* \brief Enum fro the different subtypes of 802.11 data frames.
*
*/
enum DataSubtypes {
DATA_DATA = 0,
DATA_CF_ACK = 1,
DATA_CF_POLL = 2,
DATA_CF_ACK_POLL = 3,
DATA_NULL = 4,
CF_ACK = 5,
CF_POLL = 6,
CF_ACK_POLL = 7,
QOS_DATA_DATA = 8,
QOS_DATA_CF_ACK = 9,
QOS_DATA_CF_POLL = 10,
QOS_DATA_CF_ACK_POLL = 11,
QOS_DATA_NULL = 12
};
/**
* \brief Constructs an 802.11 PDU.
*
* \param dst_hw_addr The destination hardware address.
*/
Dot11(const address_type &dst_hw_addr = address_type());
/**
* \brief Constructs 802.11 PDU from a buffer and adds all
* identifiable PDUs found in the buffer as children of this one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for a 802.11 header in the
* buffer, a malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Getter for the protocol version field.
*
* \return The stored protocol version field.
*/
small_uint<2> protocol() const { return _header.control.protocol; }
/**
* \brief Getter for the Type field.
*
* \return The stored Type field.
*/
small_uint<2> type() const { return _header.control.type; }
/**
* \brief Getter for the Subtype field.
*
* \return The stored Subtype field.
*/
small_uint<4> subtype() const { return _header.control.subtype; }
/**
* \brief Getter for the To-DS field.
*
* \return The stored To-DS field.
*/
small_uint<1> to_ds() const { return _header.control.to_ds; }
/**
* \brief Getter for the From-DS field.
*
* \return The stored From-DS field.
*/
small_uint<1> from_ds() const { return _header.control.from_ds; }
/**
* \brief Getter for the More-Frag field.
*
* \return The stored More-Frag field.
*/
small_uint<1> more_frag() const { return _header.control.more_frag; }
/**
* \brief Getter for the Retry field.
*
* \return The stored Retry field.
*/
small_uint<1> retry() const { return _header.control.retry; }
/**
* \brief Getter for the Power-Management field.
*
* \return The stored Power-Management field.
*/
small_uint<1> power_mgmt() const { return _header.control.power_mgmt; }
/**
* \brief Getter for the WEP field.
*
* \return The stored WEP field.
*/
small_uint<1> wep() const { return _header.control.wep; }
/**
* \brief Getter for the Order field.
*
* \return The stored Order field.
*/
small_uint<1> order() const { return _header.control.order; }
/**
* \brief Getter for the Duration-ID field.
*
* \return The stored Duration-ID field.
*/
uint16_t duration_id() const { return Endian::le_to_host(_header.duration_id); }
/**
* \brief Getter for the first address.
*
* \return The stored first address.
*/
address_type addr1() const { return _header.addr1; }
// Setters
/**
* \brief Setter for the protocol version field.
*
* \param new_proto The new protocol version field value.
*/
void protocol(small_uint<2> new_proto);
/**
* \brief Setter for the type field.
*
* \param new_type The new type field value.
*/
void type(small_uint<2> new_type);
/**
* \brief Setter for the subtype field.
*
* \param new_subtype The new subtype field value.
*/
void subtype(small_uint<4> new_subtype);
/**
* \brief Setter for the To-DS field.
*
* \param new_value The new To-DS field value.
*/
void to_ds(small_uint<1> new_value);
/**
* \brief Setter for the From-DS field.
*
* \param new_value The new From-DS field value.
*/
void from_ds(small_uint<1> new_value);
/**
* \brief Setter for the More-Frag field.
*
* \param new_value The new More-Frag field value.
*/
void more_frag(small_uint<1> new_value);
/**
* \brief Setter for the Retry field.
*
* \param new_value The new Retry field value.
*/
void retry(small_uint<1> new_value);
/**
* \brief Setter for the Power-Management field.
*
* \param new_value The new Power-Management field value.
*/
void power_mgmt(small_uint<1> new_value);
/**
* \brief Setter for the WEP field.
*
* \param new_value The new WEP field value.
*/
void wep(small_uint<1> new_value);
/**
* \brief Setter for the Order field.
*
* \param new_value The new Order field value.
*/
void order(small_uint<1> new_value);
/**
* \brief Setter for the Duration-ID field.
*
* \param new_duration_id The new Duration-ID field value.
*/
void duration_id(uint16_t new_duration_id);
/**
* \brief Setter for the first address.
*
* \param new_addr1 The new first address.
*/
void addr1(const address_type &new_addr1);
/* Virtual methods */
/**
* \brief Returns the 802.11 frame's header length.
*
* \return An uint32_t with the header's size.
* \sa PDU::header_size()
*/
uint32_t header_size() const;
#ifndef WIN32
/**
* \sa PDU::send()
*/
void send(PacketSender &sender, const NetworkInterface &iface);
#endif // WIN32
/**
* \brief Adds a new option to this Dot11 PDU.
* \param opt The option to be added.
*/
void add_option(const option &opt);
#if TINS_IS_CXX11
/**
* \brief Adds a new option to this Dot11 PDU.
*
* The option is move-constructed
*
* \param opt The option to be added.
*/
void add_option(option &&opt) {
internal_add_option(opt);
_options.push_back(std::move(opt));
}
#endif
/**
* \brief Looks up a tagged option in the option list.
*
* The returned pointer <b>must not</b> be free'd.
*
* \param opt The option identifier.
* \return The option found, or 0 if no such option has been set.
*/
const option *search_option(OptionTypes opt) const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \sa PDU::clone
*/
Dot11 *clone() const {
return new Dot11(*this);
}
/**
* \brief Check wether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) const {
return flag == pdu_flag;
}
/**
* \brief Getter for the option list.
*
* \return The options list.
*/
const options_type &options() const { return _options; }
/**
* \brief Allocates an Dot11 PDU from a buffer.
*
* This can be used somehow as a "virtual constructor". This
* method instantiates the appropriate subclass of Dot11 from the
* given buffer.
*
* The allocated class' type will be figured out from the
* information provided in the buffer.
*
* \param buffer The buffer from which to take the PDU data.
* \param total_sz The total size of the buffer.
* \return The allocated Dot11 PDU.
*/
static Dot11 *from_bytes(const uint8_t *buffer, uint32_t total_sz);
protected:
virtual uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz) { return 0; }
virtual uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) { return 0; }
void parse_tagged_parameters(const uint8_t *buffer, uint32_t total_sz);
void add_tagged_option(OptionTypes opt, uint8_t len, const uint8_t *val);
protected:
/**
* Struct that represents the 802.11 header
*/
TINS_BEGIN_PACK
struct ieee80211_header {
TINS_BEGIN_PACK
struct {
#if TINS_IS_LITTLE_ENDIAN
uint16_t protocol:2,
type:2,
subtype:4,
to_ds:1,
from_ds:1,
more_frag:1,
retry:1,
power_mgmt:1,
more_data:1,
wep:1,
order:1;
#elif TINS_IS_BIG_ENDIAN
uint16_t subtype:4,
type:2,
protocol:2,
order:1,
wep:1,
more_data:1,
power_mgmt:1,
retry:1,
more_frag:1,
from_ds:1,
to_ds:1;
#endif
} TINS_END_PACK control;
uint16_t duration_id;
uint8_t addr1[address_type::address_size];
} TINS_END_PACK;
private:
Dot11(const ieee80211_header *header_ptr);
void internal_add_option(const option &opt);
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
ieee80211_header _header;
uint32_t _options_size;
options_type _options;
};
}
#endif // TINS_DOT11_DOT11_H

View File

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

View File

@@ -0,0 +1,746 @@
/*
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "../config.h"
#if !defined(TINS_DOT11_DOT11_CONTROL_H) && defined(HAVE_DOT11)
#define TINS_DOT11_DOT11_CONTROL_H
#include "../dot11/dot11_base.h"
namespace Tins {
/**
* \brief Class that represents an 802.11 control frame.
*/
class Dot11Control : public Dot11 {
public:
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::DOT11_CONTROL;
/**
* \brief Constructor for creating a 802.11 control frame PDU
*
* Constructs a 802.11 Control PDU taking the destination and
* source hardware addresses.
*
* \param dst_addr The destination hardware address.
*/
Dot11Control(const address_type &dst_addr = address_type());
/**
* \brief Constructs a Dot11Control object from a buffer and
* adds all identifiable PDUs found in the buffer as children
* of this one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for the header in the buffer
* or the input data is malformed, a malformed_packet exception
* is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11Control(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::DOT11_CONTROL; }
/**
* \brief Check wether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) const {
return flag == PDU::DOT11_CONTROL || Dot11::matches_flag(flag);
}
};
/**
* \brief Class that represents an abstraction of the 802.11 control frames
* that contain a target address.
*/
class Dot11ControlTA : public Dot11Control {
public:
/**
* \brief Getter for the target address field.
*/
address_type target_addr() const { return _taddr; }
/**
* \brief Setter for the target address field.
* \param addr The new target address.
*/
void target_addr(const address_type &addr);
protected:
/**
* \brief Constructor for creating a 802.11 control frame TA PDU
*
* Constructs a 802.11 PDU taking the destination and source
* hardware addresses.
*
* \param dst_addr The destination hardware address.
* \param target_addr The source hardware address.
*/
Dot11ControlTA(const address_type &dst_addr = address_type(),
const address_type &target_addr = address_type());
/**
* \brief Constructs a Dot11ControlTA object from a buffer and
* adds all identifiable PDUs found in the buffer as children
* of this one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for the header in the buffer
* or the input data is malformed, a malformed_packet exception
* is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11ControlTA(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Returns the 802.11 frame's header length.
*
* \return An uint32_t with the header's size.
* \sa PDU::header_size()
*/
uint32_t header_size() const;
protected:
/**
* \brief Getter for the control ta additional fields size.
*/
uint32_t controlta_size() const { return _taddr.size() + sizeof(ieee80211_header); }
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
private:
address_type _taddr;
};
/**
* \brief IEEE 802.11 RTS frame.
*/
class Dot11RTS : public Dot11ControlTA {
public:
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::DOT11_RTS;
/**
* \brief Constructor for creating a 802.11 RTS frame PDU
*
* Constructs a 802.11 RTS PDU taking the destination and source
* hardware addresses.
*
* \param dst_addr The destination hardware address.
* \param target_addr The source hardware address.
*/
Dot11RTS(const address_type &dst_addr = address_type(),
const address_type &target_addr = address_type());
/**
* \brief Constructs a Dot11RTS object from a buffer and adds all
* identifiable PDUs found in the buffer as children of this one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for the header in the buffer
* or the input data is malformed, a malformed_packet exception
* is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11RTS(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Clones this PDU.
*
* \sa PDU::clone
*/
Dot11RTS *clone() const {
return new Dot11RTS(*this);
}
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \brief Check wether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11Control::matches_flag(flag);
}
};
class Dot11PSPoll : public Dot11ControlTA {
public:
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::DOT11_PS_POLL;
/**
* \brief Constructor for creating a 802.11 PS-Poll frame PDU
*
* Constructs a 802.11 PDU taking the destination and source
* hardware addresses.
*
* \param dst_addr The destination hardware address.
* \param target_addr The source hardware address.
*/
Dot11PSPoll(const address_type &dst_addr = address_type(),
const address_type &target_addr = address_type());
/**
* \brief Constructs a Dot11PSPoll object from a buffer and
* adds all identifiable PDUs found in the buffer as children of
* this one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for the header in the buffer
* or the input data is malformed, a malformed_packet exception
* is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11PSPoll(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Clones this PDU.
*
* \sa PDU::clone
*/
Dot11PSPoll *clone() const {
return new Dot11PSPoll(*this);
}
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \brief Check wether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11Control::matches_flag(flag);
}
};
class Dot11CFEnd : public Dot11ControlTA {
public:
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::DOT11_CF_END;
/**
* \brief Constructor for creating a 802.11 CF-End frame PDU
*
* Constructs a 802.11 PDU taking the destination and source
* hardware addresses.
*
* \param dst_addr The destination hardware address.
* \param target_addr The source hardware address.
*/
Dot11CFEnd(const address_type &dst_addr = address_type(),
const address_type &target_addr = address_type());
/**
* \brief Constructs a Dot11CFEnd object from a buffer and adds
* all identifiable PDUs found in the buffer as children of this
* one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for the header in the buffer
* or the input data is malformed, a malformed_packet exception
* is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11CFEnd(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Clones this PDU.
*
* \sa PDU::clone
*/
Dot11CFEnd *clone() const {
return new Dot11CFEnd(*this);
}
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \brief Check wether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11Control::matches_flag(flag);
}
};
class Dot11EndCFAck : public Dot11ControlTA {
public:
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::DOT11_END_CF_ACK;
/**
* \brief Constructor for creating a 802.11 End-CF-Ack frame PDU
*
* Constructs a 802.11 PDU taking the destination and source
* hardware addresses.
*
* \param dst_addr The destination hardware address.
* \param target_addr The source hardware address.
*/
Dot11EndCFAck(const address_type &dst_addr = address_type(),
const address_type &target_addr = address_type());
/**
* \brief Constructs a Dot11EndCFAck frame object from a buffer
* and adds all identifiable PDUs found in the buffer as children
* of this one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for the header in the buffer
* or the input data is malformed, a malformed_packet exception
* is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11EndCFAck(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Clones this PDU.
*
* \sa PDU::clone
*/
Dot11EndCFAck *clone() const {
return new Dot11EndCFAck(*this);
}
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \brief Check wether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11Control::matches_flag(flag);
}
};
class Dot11Ack : public Dot11Control {
public:
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::DOT11_ACK;
/**
* \brief Constructor for creating a 802.11 Ack frame PDU
*
* Constructs a 802.11 PDU taking the destination and source
* hardware addresses.
*
* \param dst_addr The destination hardware address.
*/
Dot11Ack(const address_type &dst_addr = address_type());
/**
* \brief Constructs a Dot11Ack frame object from a buffer and
* adds all identifiable PDUs found in the buffer as children of
* this one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for the header in the buffer
* or the input data is malformed, a malformed_packet exception
* is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11Ack(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Clones this PDU.
*
* \sa PDU::clone
*/
Dot11Ack *clone() const {
return new Dot11Ack(*this);
}
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \brief Check wether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11Control::matches_flag(flag);
}
};
/**
* \brief Class that represents an 802.11 Block Ack Request PDU.
*/
class Dot11BlockAckRequest : public Dot11ControlTA {
public:
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::DOT11_BLOCK_ACK_REQ;
/**
* \brief Constructor for creating a 802.11 Block Ack request frame PDU
*
* Constructs a 802.11 PDU taking the destination and source
* hardware addresses.
*
* \param dst_addr The destination hardware address.
* \param target_addr The source hardware address.
*/
Dot11BlockAckRequest(const address_type &dst_addr = address_type(),
const address_type &target_addr = address_type());
/**
* \brief Constructs a Dot11BlockAckRequest object from a buffer
* and adds all identifiable PDUs found in the buffer as children
* of this one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for the header in the buffer
* or the input data is malformed, a malformed_packet exception
* is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11BlockAckRequest(const uint8_t *buffer, uint32_t total_sz);
/* Getter */
/**
* \brief Getter for the bar control field.
* \return The stored bar control field.
*/
small_uint<4> bar_control() const {
#if TINS_IS_LITTLE_ENDIAN
return _bar_control & 0xf;
#else
return (_bar_control >> 8) & 0xf;
#endif
}
/**
* \brief Getter for the start sequence field.
* \return The stored start sequence.
*/
small_uint<12> start_sequence() const {
#if TINS_IS_LITTLE_ENDIAN
return (_start_sequence >> 4) & 0xfff;
#else
return (Endian::le_to_host<uint16_t>(_start_sequence) >> 4) & 0xfff;
#endif
}
/**
* \brief Getter for the fragment number field.
* \return The stored fragment number field.
*/
small_uint<4> fragment_number() const {
#if TINS_IS_LITTLE_ENDIAN
return _start_sequence & 0xf;
#else
return (_start_sequence >> 8) & 0xf;
#endif
}
/**
* \brief Returns the 802.11 frame's header length.
*
* \return The header's size.
* \sa PDU::header_size()
*/
uint32_t header_size() const;
/* Setter */
/**
* \brief Setter for the bar control field.
* \param bar The bar control field to be set.
*/
void bar_control(small_uint<4> bar);
/**
* \brief Setter for the start sequence field.
* \param bar The start sequence field to be set.
*/
void start_sequence(small_uint<12> seq);
/**
* \brief Setter for the fragment number field.
* \param frag The fragment number field to be set.
*/
void fragment_number(small_uint<4> frag);
/**
* \brief Clones this PDU.
*
* \sa PDU::clone
*/
Dot11BlockAckRequest *clone() const {
return new Dot11BlockAckRequest(*this);
}
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \brief Check wether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11Control::matches_flag(flag);
}
protected:
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
private:
void init_block_ack();
uint16_t _bar_control;
uint16_t _start_sequence;
};
/**
* \brief Class that represents an 802.11 block ack frame.
*/
class Dot11BlockAck : public Dot11ControlTA {
public:
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::DOT11_BLOCK_ACK;
/**
* The size of the bitmap field.
*/
static const size_t bitmap_size = 8;
/**
* \brief Constructor for creating a 802.11 Block Ack frame PDU
*
* Constructs a 802.11 PDU taking the destination and source
* hardware addresses.
*
* \param dst_addr The destination hardware address.
* \param target_addr The source hardware address.
*/
Dot11BlockAck(const address_type &dst_addr = address_type(),
const address_type &target_addr = address_type());
/**
* \brief Constructs a Dot11BlockAck frame object from a buffer
* and adds all identifiable PDUs found in the buffer as children
* of this one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for the header in the buffer
* or the input data is malformed, a malformed_packet exception
* is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11BlockAck(const uint8_t *buffer, uint32_t total_sz);
/* Getters */
/**
* \brief Getter for the bar control field.
* \return The stored bar control field.
*/
small_uint<4> bar_control() const {
#if TINS_IS_LITTLE_ENDIAN
return _bar_control & 0xf;
#else
return (_bar_control >> 8) & 0xf;
#endif
}
/**
* \brief Getter for the start sequence field.
* \return The stored start sequence.
*/
small_uint<12> start_sequence() const {
#if TINS_IS_LITTLE_ENDIAN
return (_start_sequence >> 4) & 0xfff;
#else
return (Endian::le_to_host<uint16_t>(_start_sequence) >> 4) & 0xfff;
#endif
}
/**
* \brief Getter for the fragment number field.
* \return The stored fragment number field.
*/
small_uint<4> fragment_number() const {
#if TINS_IS_LITTLE_ENDIAN
return _start_sequence & 0xf;
#else
return (_start_sequence >> 8) & 0xf;
#endif
}
/**
* \brief Returns the 802.11 frame's header length.
*
* \return An uint32_t with the header's size.
* \sa PDU::header_size()
*/
uint32_t header_size() const;
/* Setters */
/**
* \brief Setter for the bar control field.
* \param bar The bar control field to be set.
*/
void bar_control(small_uint<4> bar);
/**
* \brief Setter for the start sequence field.
* \param bar The start sequence field to be set.
*/
void start_sequence(small_uint<12> seq);
/**
* \brief Setter for the fragment number field.
* \param frag The fragment number field to be set.
*/
void fragment_number(small_uint<4> frag);
/**
* \brief Getter for the bitmap field.
*
* The returned pointer <b>must not</b> be free'd.
*
* \return The bitmap field.
*/
const uint8_t *bitmap() const { return _bitmap; }
/**
* \brief Setter for the bitmap field.
* \param bit The new bitmap field to be set.
*/
void bitmap(const uint8_t *bit);
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \brief Check wether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11Control::matches_flag(flag);
}
/**
* \brief Clones this PDU.
*
* \sa PDU::clone
*/
Dot11BlockAck *clone() const {
return new Dot11BlockAck(*this);
}
private:
void init_block_ack();
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
uint16_t _bar_control, _start_sequence;
uint8_t _bitmap[bitmap_size];
};
} // namespace Tins
#endif // TINS_DOT11_DOT11_CONTROL_H

345
include/dot11/dot11_data.h Normal file
View File

@@ -0,0 +1,345 @@
/*
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "../config.h"
#if !defined(TINS_DOT11_DOT11_DATA_H) && defined(HAVE_DOT11)
#define TINS_DOT11_DOT11_DATA_H
#include "../dot11/dot11_base.h"
namespace Tins {
class Dot11Data : public Dot11 {
public:
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::DOT11_DATA;
/**
* \brief Constructor for creating a 802.11 Data frame.
*
* Constructs a 802.11 Data frame taking the
* destination and source hardware addresses.
*
* \param dst_hw_addr The destination hardware address.
* \param src_hw_addr The source hardware address.
*/
Dot11Data(const address_type &dst_hw_addr = address_type(),
const address_type &src_hw_addr = address_type());
/**
* \brief Constructs a Dot11Data object from a buffer and adds
* all identifiable PDUs found in the buffer as children of
* this one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for the header in the buffer
* or the input data is malformed, a malformed_packet exception
* is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11Data(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Getter for the second address.
*
* \return The stored second address.
*/
address_type addr2() const { return _ext_header.addr2; }
/**
* \brief Getter for the third address.
*
* \return The stored third address.
*/
address_type addr3() const { return _ext_header.addr3; }
/**
* \brief Getter for the fragment number field.
*
* \return The stored fragment number.
*/
small_uint<4> frag_num() const {
#if TINS_IS_LITTLE_ENDIAN
return _ext_header.frag_seq & 0xf;
#else
return (_ext_header.frag_seq >> 8) & 0xf;
#endif
}
/**
* \brief Getter for the sequence number field.
*
* \return The stored sequence number.
*/
small_uint<12> seq_num() const {
#if TINS_IS_LITTLE_ENDIAN
return (_ext_header.frag_seq >> 4) & 0xfff;
#else
return (Endian::le_to_host<uint16_t>(_ext_header.frag_seq) >> 4) & 0xfff;
#endif
}
/**
* \brief Getter for the fourth address.
*
* \return The fourth address.
*/
address_type addr4() const { return _addr4; }
/**
* \brief Setter for the second address.
*
* \param new_addr2 The second address to be set.
*/
void addr2(const address_type &new_addr2);
/**
* \brief Setter for the third address.
*
* \param new_addr3 The third address to be set.
*/
void addr3(const address_type &new_addr3);
/**
* \brief Setter for the fragment number field.
*
* \param new_frag_num The fragment number to be set.
*/
void frag_num(small_uint<4> new_frag_num);
/**
* \brief Setter for the sequence number field.
*
* \param new_seq_num The sequence number to be set.
*/
void seq_num(small_uint<12> new_seq_num);
/**
* \brief Setter for the fourth address field.
*
* \param new_addr4 The fourth address to be set.
*/
void addr4(const address_type &new_addr4);
/**
* \brief Retrieves the frame's source address.
*
* This is a wrapper over the addr* member functions which
* takes into account the value of the FromDS and ToDS bits.
*
* If FromDS == ToDS == 1, the return value is not defined.
*/
address_type src_addr() const {
if(!from_ds() && !to_ds())
return addr2();
if(!from_ds() && to_ds())
return addr2();
return addr3();
}
/**
* \brief Retrieves the frame's destination address.
*
* This is a wrapper over the addr* member functions which
* takes into account the value of the FromDS and ToDS bits.
*
* If FromDS == ToDS == 1, the return value is not defined.
*/
address_type dst_addr() const {
if(!from_ds() && !to_ds())
return addr1();
if(!from_ds() && to_ds())
return addr3();
return addr1();
}
/**
* \brief Retrieves the frame's BSSID address.
*
* This is a wrapper over the addr* member functions which
* takes into account the value of the FromDS and ToDS bits.
*
* If FromDS == ToDS == 1, the return value is not defined.
*/
address_type bssid_addr() const {
if(!from_ds() && !to_ds())
return addr3();
if(!from_ds() && to_ds())
return addr1();
return addr2();
}
/**
* \brief Returns the 802.11 frame's header length.
*
* \return An uint32_t with the header's size.
* \sa PDU::header_size()
*/
uint32_t header_size() const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \brief Check wether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11::matches_flag(flag);
}
/**
* \brief Clones this PDU.
*
* \sa PDU::clone
*/
Dot11Data *clone() const {
return new Dot11Data(*this);
}
protected:
TINS_BEGIN_PACK
struct ExtendedHeader {
uint8_t addr2[address_type::address_size];
uint8_t addr3[address_type::address_size];
uint16_t frag_seq;
} TINS_END_PACK;
struct no_inner_pdu { };
Dot11Data(const uint8_t *buffer, uint32_t total_sz, no_inner_pdu);
uint32_t init(const uint8_t *buffer, uint32_t total_sz);
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
uint32_t data_frame_size() {
return Dot11::header_size() + sizeof(_ext_header) +
((from_ds() && to_ds()) ? _addr4.size() : 0);
}
private:
ExtendedHeader _ext_header;
address_type _addr4;
};
class Dot11QoSData : public Dot11Data {
public:
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::DOT11_QOS_DATA;
/**
* \brief Constructor for creating a 802.11 QoS Data PDU
*
* Constructs a 802.11 QoS Data PDU taking the
* destination and source hardware addresses.
*
* \param dst_hw_addr The destination hardware address.
* \param src_hw_addr The source hardware address.
*/
Dot11QoSData(const address_type &dst_hw_addr = address_type(),
const address_type &src_hw_addr = address_type());
/**
* \brief Constructors Dot11QoSData object from a buffer and adds
* all identifiable PDUs found in the buffer as children of this
* one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for the header in the buffer
* or the input data is malformed, a malformed_packet exception
* is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot11QoSData(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Getter for the QOS Control field.
*
* \return The stored QOS Control field value.
*/
uint16_t qos_control() const { return Endian::le_to_host(_qos_control); }
/**
* \brief Setter for the QOS Control field.
*
* \param new_qos_control The QOS Control to be set.
*/
void qos_control(uint16_t new_qos_control);
/**
* \brief Returns the frame's header length.
*
* \return An uint32_t with the header's size.
* \sa PDU::header_size()
*/
uint32_t header_size() const;
/**
* \brief Clones this PDU.
*
* \sa PDU::clone
*/
Dot11QoSData *clone() const {
return new Dot11QoSData(*this);
}
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::DOT11_QOS_DATA; }
/**
* \brief Check wether this PDU matches the specified flag.
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) const {
return flag == PDU::DOT11_QOS_DATA || Dot11Data::matches_flag(flag);
}
private:
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
uint16_t _qos_control;
};
}
#endif // TINS_DOT11_DOT11_DATA_H

1160
include/dot11/dot11_mgmt.h Normal file

File diff suppressed because it is too large Load Diff

233
include/dot11/dot11_probe.h Normal file
View File

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

212
include/dot1q.h Normal file
View File

@@ -0,0 +1,212 @@
/*
* Copyright (c) 2012, 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_DOT1Q_H
#define TINS_DOT1Q_H
#include "pdu.h"
#include "endianness.h"
#include "small_uint.h"
namespace Tins {
/**
* Represents an IEEE 802.1q PDU.
*/
class Dot1Q : public PDU {
public:
/**
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::DOT1Q;
/**
* Default constructor
*/
Dot1Q(small_uint<12> tag_id = 0, bool append_pad = true);
/**
* \brief Constructs a Dot1Q object from a buffer and adds all
* identifiable PDUs found in the buffer as children of this
* one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for a Dot1Q header in the buffer,
* a malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot1Q(const uint8_t *buffer, uint32_t total_sz);
// Getters
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \brief Returns the frame's trailer size.
* \return The trailer's size.
*/
uint32_t trailer_size() const;
/**
* \brief Getter for the priority field.
* \return The stored priority field value.
*/
small_uint<3> priority() const {
return _header.priority;
}
/**
* \brief Getter for the Canonical Format Identifier field.
* \return The stored CFI field value.
*/
small_uint<1> cfi() const {
return _header.cfi;
}
/**
* \brief Getter for the VLAN ID field.
* \return The stored VLAN ID field value.
*/
small_uint<12> id() const {
#if TINS_IS_LITTLE_ENDIAN
return _header.idL | (_header.idH << 8);
#else
return _header.id;
#endif
}
/**
* \brief Getter for the payload type field.
* \return The stored type field value.
*/
uint16_t payload_type() const {
return Endian::be_to_host(_header.type);
}
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \sa PDU::clone
*/
Dot1Q *clone() const {
return new Dot1Q(*this);
}
/**
* \brief Retrieves the flag indicating whether padding will be
* appended at the end of this packet.
*/
bool append_padding() const {
return _append_padding;
}
// Setters
/**
* \brief Setter for the priority field.
* \param new_priority The new priority field value.
*/
void priority(small_uint<3> new_priority);
/**
* \brief Setter for the Canonical Format Identifie field.
* \param new_cfi The new CFI field value.
*/
void cfi(small_uint<1> new_cfi);
/**
* \brief Setter for the VLAN ID field.
* \param new_id The new VLAN ID field value.
*/
void id(small_uint<12> new_id);
/**
* \brief Setter for the payload type field.
* \param new_type The new type field value.
*/
void payload_type(uint16_t new_type);
/**
* \brief Indicates whether the appropriate padding will be
* at the end of the packet.
*
* This flag could be disabled in case two or more contiguous Dot1Q
* PDUs are added to a packet. In that case, only the Dot1Q which is
* closer to the link layer should add the padding at the end.
*
* \param value A boolean indicating whether padding will be appended.
*/
void append_padding(bool value);
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
private:
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
TINS_BEGIN_PACK
struct dot1q_hdr {
#if TINS_IS_BIG_ENDIAN
uint16_t priority:3,
cfi:1,
id:12;
uint16_t type;
#else
uint16_t idH:4,
cfi:1,
priority:3,
idL:8;
uint16_t type;
#endif
} TINS_END_PACK;
static uint16_t get_id(const dot1q_hdr *hdr);
dot1q_hdr _header;
bool _append_padding;
};
}
#endif // TINS_DOT1Q_H

193
include/dot3.h Normal file
View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,6 +32,7 @@
#include <stdint.h>
#include "pdu.h"
#include "macros.h"
#include "small_uint.h"
#include "endianness.h"
@@ -66,6 +67,12 @@ namespace Tins {
/**
* \brief Static method to instantiate the correct EAPOL subclass
* based on a raw buffer.
*
* If no valid EAPOL type is detected, a null pointer is returned.
*
* \sa RC4EAPOL
* \sa RSNEAPOL
*
* \param buffer The buffer from which the data will be taken.
* \param total_sz The total size of the buffer.
*/
@@ -134,11 +141,6 @@ namespace Tins {
*/
EAPOL(uint8_t packet_type, EAPOLTYPE type);
/**
* \brief Copy constructor.
*/
EAPOL(const EAPOL &other);
/**
* \brief Constructor which creates an EAPOL object from a buffer.
* \param buffer The buffer from which this PDU will be constructed.
@@ -146,13 +148,12 @@ namespace Tins {
*/
EAPOL(const uint8_t *buffer, uint32_t total_sz);
void copy_eapol_fields(const EAPOL *other);
TINS_BEGIN_PACK
struct eapolhdr {
uint8_t version, packet_type;
uint16_t length;
uint8_t type;
} __attribute__((__packed__));
} TINS_END_PACK;
/**
* \brief Virtual method which should serialize the subclass specific
@@ -202,12 +203,16 @@ namespace Tins {
static const size_t key_sign_size = 16;
/**
* \brief Creates an instance of RC4EAPOL
* \brief Default constructor.
*/
RC4EAPOL();
/**
* \brief Constructor which creates an RC4EAPOL object from a buffer.
* \brief Constructs a RC4EAPOL object from a buffer.
*
* If there is not enough size for a RC4EAPOL header in the
* buffer, a malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
@@ -324,7 +329,7 @@ namespace Tins {
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return flag == PDU::RC4EAPOL || EAPOL::matches_flag(flag);
}
@@ -337,6 +342,7 @@ namespace Tins {
return new RC4EAPOL(*this);
}
private:
TINS_BEGIN_PACK
struct rc4hdr {
uint16_t key_length;
uint64_t replay_counter;
@@ -344,7 +350,7 @@ namespace Tins {
uint8_t key_index:7,
key_flag:1;
uint8_t key_sign[16];
} __attribute__((__packed__));
} TINS_END_PACK;
void write_body(uint8_t *buffer, uint32_t total_sz);
@@ -400,7 +406,11 @@ namespace Tins {
RSNEAPOL();
/**
* \brief Constructor which creates an RSNEAPOL object from a buffer.
* \brief Constructs a RSNEAPOL object from a buffer.
*
* If there is not enough size for the RSNEAPOL header, a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
@@ -463,8 +473,8 @@ namespace Tins {
const key_type &key() const { return _key; }
/**
* \brief Getter for the key_mic field.
* \return The key_mic field.
* \brief Getter for the key mic field.
* \return 1 if this EAPOL PDU contains a valid MIC, 0 otherwise.
*/
small_uint<1> key_mic() const { return _header.key_mic; };
@@ -490,17 +500,18 @@ namespace Tins {
* \brief Getter for 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.
* \return The key_descriptor field.
* \brief Getter for the key descriptor field.
* \return The key descriptor field.
*/
small_uint<3> key_descriptor() const { return _header.key_descriptor; };
/**
* \brief Getter for the key_t field.
* \return The key_t field.
* \brief Getter for the key type field.
*
* \return 1 if this is a pairwise key, 0 otherwise.
*/
small_uint<1> key_t() const { return _header.key_t; };
@@ -665,7 +676,7 @@ namespace Tins {
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return flag == PDU::RSNEAPOL || EAPOL::matches_flag(flag);
}
@@ -678,6 +689,7 @@ namespace Tins {
return new RSNEAPOL(*this);
}
private:
TINS_BEGIN_PACK
struct rsnhdr {
#if TINS_IS_LITTLE_ENDIAN
uint16_t key_mic:1,
@@ -716,7 +728,7 @@ namespace Tins {
uint8_t mic[mic_size];
uint16_t wpa_length;
#endif
} __attribute__((__packed__));
} TINS_END_PACK;
void write_body(uint8_t *buffer, uint32_t total_sz);
@@ -724,6 +736,6 @@ namespace Tins {
rsnhdr _header;
key_type _key;
};
};
}
#endif // TINS_EAPOL_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,21 +31,46 @@
#define TINS_ENDIANNESS_H
#include <stdint.h>
#ifndef WIN32
#include "macros.h"
#if defined(__APPLE__)
#include <sys/types.h>
#define TINS_IS_LITTLE_ENDIAN (BYTE_ORDER == LITTLE_ENDIAN)
#define TINS_IS_BIG_ENDIAN (BYTE_ORDER == BIG_ENDIAN)
#elif defined(BSD)
#include <sys/endian.h>
#define TINS_IS_LITTLE_ENDIAN (_BYTE_ORDER == _LITTLE_ENDIAN)
#define TINS_IS_BIG_ENDIAN (_BYTE_ORDER == _BIG_ENDIAN)
#elif defined(WIN32)
// Assume windows == little endian. fixme later
#define TINS_IS_LITTLE_ENDIAN 1
#define TINS_IS_BIG_ENDIAN 0
#else
#include <endian.h>
#define TINS_IS_LITTLE_ENDIAN (__BYTE_ORDER == __LITTLE_ENDIAN)
#define TINS_IS_BIG_ENDIAN (__BYTE_ORDER == __BIG_ENDIAN)
#endif
#define TINS_IS_LITTLE_ENDIAN (__BYTE_ORDER == __LITTLE_ENDIAN)
#define TINS_IS_BIG_ENDIAN (__BYTE_ORDER == __BIG_ENDIAN)
namespace Tins {
namespace Endian {
/**
* \brief "Changes" a 8-bit integral value's endianess. This is an
* identity function.
*
* \param data The data to convert.
*/
inline uint8_t do_change_endian(uint8_t data) {
return data;
}
/**
* \brief Changes a 16-bit integral value's endianess.
*
* \param data The data to convert.
*/
inline uint16_t change_endian(uint16_t data) {
inline uint16_t do_change_endian(uint16_t data) {
return ((data & 0xff00) >> 8) | ((data & 0x00ff) << 8);
}
@@ -54,7 +79,7 @@ namespace Endian {
*
* \param data The data to convert.
*/
inline uint32_t change_endian(uint32_t data) {
inline uint32_t do_change_endian(uint32_t data) {
return (((data & 0xff000000) >> 24) | ((data & 0x00ff0000) >> 8) |
((data & 0x0000ff00) << 8) | ((data & 0x000000ff) << 24));
}
@@ -64,9 +89,61 @@ namespace Endian {
*
* \param data The data to convert.
*/
inline uint64_t change_endian(uint64_t data) {
return (((uint64_t)(change_endian((uint32_t)((data << 32) >> 32))) << 32) |
(change_endian(((uint32_t)(data >> 32)))));
inline uint64_t do_change_endian(uint64_t data) {
return (((uint64_t)(do_change_endian((uint32_t)(data & 0xffffffff))) << 32) |
(do_change_endian(((uint32_t)(data >> 32)))));
}
/**
* \cond
*/
// Helpers to convert
template<typename T>
struct conversion_dispatch_helper {
static T dispatch(T data) {
return do_change_endian(data);
}
};
template<size_t>
struct conversion_dispatcher;
template<>
struct conversion_dispatcher<sizeof(uint8_t)>
: public conversion_dispatch_helper<uint8_t>
{ };
template<>
struct conversion_dispatcher<sizeof(uint16_t)>
: public conversion_dispatch_helper<uint16_t>
{ };
template<>
struct conversion_dispatcher<sizeof(uint32_t)>
: public conversion_dispatch_helper<uint32_t>
{ };
template<>
struct conversion_dispatcher<sizeof(uint64_t)>
: public conversion_dispatch_helper<uint64_t>
{ };
/**
* \endcond
*/
/**
* \brief Changes an integral value's endianess.
*
* This dispatchs to the corresponding function.
*
* \param data The data to convert.
*/
template<typename T>
inline T change_endian(T data) {
return conversion_dispatcher<sizeof(T)>::dispatch(data);
}
#if TINS_IS_LITTLE_ENDIAN

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,11 +31,10 @@
#define TINS_ETHERNET_II_H
#include <stdint.h>
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
#include "hw_address.h"
#include "network_interface.h"
namespace Tins {
@@ -60,24 +59,23 @@ namespace Tins {
static const address_type BROADCAST;
/**
* \brief Constructor for creating an ethernet PDU
* \brief Constructs an ethernet II PDU.
*
* Constructor that builds an ethernet PDU taking the interface name,
* destination's and source's MAC.
*
* \param iface string containing the interface's name from where to send the packet.
* \param dst_hw_addr address_type containing the destination's MAC(optional).
* \param src_hw_addr address_type containing the source's MAC(optional).
* \param child PDU* with the PDU contained by the ethernet PDU (optional).
* \param dst_hw_addr address_type containing the destination's MAC.
* \param src_hw_addr address_type containing the source's MAC.
*/
EthernetII(const NetworkInterface& iface = NetworkInterface(),
const address_type &dst_hw_addr = address_type(),
const address_type &src_hw_addr = address_type(),
PDU* child = 0);
EthernetII(const address_type &dst_hw_addr = address_type(),
const address_type &src_hw_addr = address_type());
/**
* \brief Constructor which creates an EthernetII object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \brief Constructs a EthernetII object from a buffer and adds
* all identifiable PDUs found in the buffer as children of
* this one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for a EthernetII header in the
* buffer, a malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
@@ -100,13 +98,6 @@ namespace Tins {
*/
address_type src_addr() const { return _eth.src_mac; }
/**
* \brief Getter for the interface.
*
* \return Returns the interface in which this PDU will be sent.
*/
const NetworkInterface &iface() const { return _iface; }
/**
* \brief Getter for the payload_type
* \return The payload type.
@@ -129,13 +120,6 @@ namespace Tins {
*/
void src_addr(const address_type &new_src_addr);
/**
* \brief Setter for the interface.
*
* \param new_iface the interface to be set.
*/
void iface(const NetworkInterface& new_iface);
/**
* \brief Setter for the payload type.
*
@@ -152,29 +136,38 @@ namespace Tins {
*/
uint32_t header_size() const;
/**
* \brief Returns the ethernet II frame's padding.
*
* \return An uint32_t with the padding size.
* \sa PDU::trailer_size()
*/
uint32_t trailer_size() const;
// Windows does not support sending L2 PDUs.
#ifndef WIN32
/**
* \sa PDU::send()
*/
void send(PacketSender &sender);
void send(PacketSender &sender, const NetworkInterface &iface);
#endif // WIN32
/** \brief Check wether ptr points to a valid response for this PDU.
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(uint8_t *ptr, uint32_t total_sz);
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
#ifndef WIN32
/** \brief Receives a matching response for this packet.
/**
* \brief Receives a matching response for this packet.
*
* \sa PDU::recv_response
* \param sender The packet sender which will receive the packet.
*/
PDU *recv_response(PacketSender &sender);
PDU *recv_response(PacketSender &sender, const NetworkInterface &iface);
#endif // WIN32
/**
@@ -183,16 +176,6 @@ namespace Tins {
*/
PDUType pdu_type() const { return PDU::ETHERNET_II; }
/** \brief Clones this pdu, filling the corresponding header with data
* extracted from a buffer.
*
* \param ptr The pointer to the from from which the data will be extracted.
* \param total_sz The size of the buffer.
* \return The cloned PDU.
* \sa PDU::clone_packet
*/
PDU *clone_packet(const uint8_t *ptr, uint32_t total_sz);
/**
* \sa PDU::clone
*/
@@ -203,19 +186,19 @@ namespace Tins {
/**
* Struct that represents the Ethernet II header
*/
TINS_BEGIN_PACK
struct ethhdr {
uint8_t dst_mac[address_type::address_size];
uint8_t src_mac[address_type::address_size];
uint16_t payload_type;
} __attribute__((__packed__));
} TINS_END_PACK;
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
ethhdr _eth;
NetworkInterface _iface;
};
};
}
#endif // TINS_ETHERNET_II_H

172
include/exceptions.h Normal file
View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,6 +37,7 @@
#include <iomanip>
#include <iostream>
#include <sstream>
#include "cxxstd.h"
namespace Tins {
/**
@@ -68,6 +69,11 @@ public:
* elements in this address.
*/
static const size_t address_size = n;
/**
* \brief The broadcast address.
*/
static const HWAddress<n, Storage> broadcast;
/**
* \brief Constructor from a const storage_type*.
@@ -137,11 +143,18 @@ public:
*/
template<size_t i>
HWAddress(const HWAddress<i> &rhs) {
std::copy(
rhs.begin(),
rhs.begin() + std::min(i, n),
begin()
// Fill extra bytes
std::fill(
// Copy as most as we can
std::copy(
rhs.begin(),
rhs.begin() + std::min(i, n),
begin()
),
end(),
0
);
}
/**
@@ -226,6 +239,27 @@ public:
return address_size;
}
/**
* \brief Indicates whether this is a broadcast address.
*/
bool is_broadcast() const {
return *this == broadcast;
}
/**
* \brief Indicates whether this is a multicast address.
*/
bool is_multicast() const {
return (buffer[0] & 0x01);
}
/**
* \brief Indicates whether this is an unicast address.
*/
bool is_unicast() const {
return !is_broadcast() && !is_multicast();
}
/**
* \brief Convert this address to a hex-notation std::string address.
*
@@ -236,6 +270,15 @@ public:
oss << *this;
return oss.str();
}
/**
* \brief Retrieves the i-th storage_type in this address.
*
* \param i The element to retrieve.
*/
storage_type operator[](size_t i) const {
return buffer[i];
}
/**
* \brief Writes this HWAddress in hex-notation to a std::ostream.
@@ -295,13 +338,16 @@ void HWAddress<n, Storage>::convert(const std::string &hw_addr,
OutputIterator output)
{
unsigned i(0);
size_t count(0);
storage_type tmp;
while(i < hw_addr.size()) {
while(i < hw_addr.size() && count < n) {
const unsigned end = i+2;
tmp = storage_type();
while(i < end) {
if(hw_addr[i] >= 'a' && hw_addr[i] <= 'f')
tmp = (tmp << 4) | (hw_addr[i] - 'a' + 10);
else if(hw_addr[i] >= 'A' && hw_addr[i] <= 'F')
tmp = (tmp << 4) | (hw_addr[i] - 'A' + 10);
else if(hw_addr[i] >= '0' && hw_addr[i] <= '9')
tmp = (tmp << 4) | (hw_addr[i] - '0');
else if(hw_addr[i] == ':')
@@ -311,6 +357,7 @@ void HWAddress<n, Storage>::convert(const std::string &hw_addr,
i++;
}
*(output++) = tmp;
count++;
if(i < hw_addr.size()) {
if(hw_addr[i] == ':')
i++;
@@ -318,6 +365,23 @@ void HWAddress<n, Storage>::convert(const std::string &hw_addr,
throw std::runtime_error("Invalid separator");
}
}
while(count++ < n) {
*(output++) = storage_type();
}
}
}
template<size_t n, typename Storage>
const HWAddress<n, Storage> HWAddress<n, Storage>::broadcast("ff:ff:ff:ff:ff:ff");
} // namespace Tins
#if TINS_IS_CXX11
namespace std
{
template<size_t n>
struct hash<Tins::HWAddress<n>> {
size_t operator()(const Tins::HWAddress<n> &addr) const {
return std::hash<std::string>()(addr.to_string());
}
};
} // namespace std
#endif
#endif // TINS_HWADDRESS_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,9 +30,10 @@
#ifndef TINS_ICMP_H
#define TINS_ICMP_H
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
#include "ip_address.h"
namespace Tins {
@@ -48,6 +49,11 @@ namespace Tins {
*/
static const PDU::PDUType pdu_flag = PDU::ICMP;
/**
* The type used to store addresses.
*/
typedef IPv4Address address_type;
/** \brief ICMP flags
*/
enum Flags {
@@ -58,8 +64,12 @@ namespace Tins {
ECHO_REQUEST = 8,
TIME_EXCEEDED = 11,
PARAM_PROBLEM = 12,
TIMESTAMP_REQUEST = 13,
TIMESTAMP_REPLY = 14,
INFO_REQUEST = 15,
INFO_REPLY = 16
INFO_REPLY = 16,
ADDRESS_MASK_REQUEST = 17,
ADDRESS_MASK_REPLY = 18
};
/**
@@ -71,8 +81,13 @@ namespace Tins {
ICMP(Flags flag = ECHO_REQUEST);
/**
* \brief Constructor which creates an ICMP object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \brief Constructs an ICMP object from a buffer.
*
* If there is not enough size for an ICMP header, a
* malformed_packet exception is thrown.
*
* Any extra data in the buffer will be stored in a RawPDU.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
@@ -91,13 +106,6 @@ namespace Tins {
*/
void type(Flags type);
/**
* \brief Setter for checksum field.
*
* \param new_check uint16_t with the new checksum.
*/
void check(uint16_t new_check);
/**
* \brief Setter for the id field.
*
@@ -115,9 +123,9 @@ namespace Tins {
/**
* \brief Setter for the gateway field.
*
* \param new_gw uint32_t with the new gateway.
* \param new_gw The new value for the gateway field.
*/
void gateway(uint32_t new_gw);
void gateway(address_type new_gw);
/**
* \brief Setter for the mtu field.
@@ -133,6 +141,34 @@ namespace Tins {
*/
void pointer(uint8_t new_pointer);
/**
* \brief Setter for the original timestamp field.
*
* \param new_timestamp the value to be set.
*/
void original_timestamp(uint32_t new_timestamp);
/**
* \brief Setter for the receive timestamp field.
*
* \param new_timestamp the value to be set.
*/
void receive_timestamp(uint32_t new_timestamp);
/**
* \brief Setter for the transmit timestamp field.
*
* \param new_timestamp the value to be set.
*/
void transmit_timestamp(uint32_t new_timestamp);
/**
* \brief Setter for the address mask field.
*
* \param new_mask the value to be set.
*/
void address_mask(address_type new_mask);
/**
* \brief Sets echo request flag for this PDU.
*
@@ -141,14 +177,6 @@ namespace Tins {
*/
void set_echo_request(uint16_t id, uint16_t seq);
/**
* \brief Sets echo request flag for this PDU.
*
* This uses a global id and sequence number to fill the request's
* fields.
*/
void set_echo_request();
/**
* \brief Sets echo reply flag for this PDU.
*
@@ -157,14 +185,6 @@ namespace Tins {
*/
void set_echo_reply(uint16_t id, uint16_t seq);
/**
* \brief Sets echo reply flag for this PDU.
*
* This uses a global id and sequence number to fill the request's
* fields.
*/
void set_echo_reply();
/**
* \brief Sets information request flag for this PDU.
*
@@ -217,7 +237,7 @@ namespace Tins {
* \param address Address of the gateway to which traffic should
* be sent.
*/
void set_redirect(uint8_t icode, uint32_t address);
void set_redirect(uint8_t icode, address_type address);
/**
* \brief Getter for the ICMP type flag.
@@ -238,7 +258,7 @@ namespace Tins {
*
* \return Returns the checksum as an unit16_t.
*/
uint16_t check() const { return Endian::be_to_host(this->_icmp.check); }
uint16_t check() const { return Endian::be_to_host(_icmp.check); }
/**
* \brief Getter for the echo id.
@@ -257,23 +277,55 @@ namespace Tins {
/**
* \brief Getter for the gateway field.
*
* \return Returns the gateways in an unit32_t.
* \return Returns the gateway field value.
*/
uint32_t gateway() const { return Endian::be_to_host(this->_icmp.un.gateway); }
address_type gateway() const {
return address_type(Endian::be_to_host(_icmp.un.gateway));
}
/**
* \brief Getter for the pointer field.
*
* \return Returns the pointer value.
* \return Returns the pointer field value.
*/
uint8_t pointer() const { return this->_icmp.un.pointer; }
/**
* \brief Getter for the mtu field.
*
* \return Returns the mtu value in an uint16_t.
* \return Returns the mtu field value.
*/
uint16_t mtu() const { return Endian::be_to_host(this->_icmp.un.frag.mtu); }
uint16_t mtu() const { return Endian::be_to_host(_icmp.un.frag.mtu); }
/**
* \brief Getter for the original timestamp field.
*
* \return Returns the original timestamp value.
*/
uint32_t original_timestamp() const { return Endian::be_to_host(_orig_timestamp_or_address_mask); }
/**
* \brief Getter for the receive timestamp field.
*
* \return Returns the receive timestamp value.
*/
uint32_t receive_timestamp() const { return Endian::be_to_host(_recv_timestamp); }
/**
* \brief Getter for the transmit timestamp field.
*
* \return Returns the transmit timestamp value.
*/
uint32_t transmit_timestamp() const { return Endian::be_to_host(_trans_timestamp); }
/**
* \brief Getter for the address mask field.
*
* \return Returns the address mask value.
*/
address_type address_mask() const {
return address_type(Endian::be_to_host(_orig_timestamp_or_address_mask));
}
/**
* \brief Returns the header size.
@@ -290,7 +342,7 @@ namespace Tins {
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(uint8_t *ptr, uint32_t total_sz);
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \brief Getter for the PDU's type.
@@ -298,17 +350,6 @@ namespace Tins {
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::ICMP; }
/**
* \brief Clones this pdu, filling the corresponding header with data
* extracted from a buffer.
*
* \param ptr The pointer to the from from which the data will be extracted.
* \param total_sz The size of the buffer.
* \return The cloned PDU.
* \sa PDU::clone_packet
*/
PDU *clone_packet(const uint8_t *ptr, uint32_t total_sz);
/**
* \sa PDU::clone
@@ -317,8 +358,7 @@ namespace Tins {
return new ICMP(*this);
}
private:
static uint16_t global_id, global_seq;
TINS_BEGIN_PACK
struct icmphdr {
uint8_t type;
uint8_t code;
@@ -330,12 +370,14 @@ namespace Tins {
} echo;
uint32_t gateway;
struct {
uint16_t __unused;
uint16_t unused;
uint16_t mtu;
} frag;
uint8_t pointer;
} un;
} __attribute__((__packed__));
} TINS_END_PACK;
void check(uint16_t new_check);
/** \brief Serialices this ICMP PDU.
* \param buffer The buffer in which the PDU will be serialized.
@@ -345,7 +387,8 @@ namespace Tins {
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
icmphdr _icmp;
uint32_t _orig_timestamp_or_address_mask, _recv_timestamp, _trans_timestamp;
};
};
}
#endif // TINS_ICMP_H

1337
include/icmpv6.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,191 +30,11 @@
#ifndef TINS_IEEE802_3_H
#define TINS_IEEE802_3_H
#include <stdint.h>
#include "pdu.h"
#include "endianness.h"
#include "hw_address.h"
#include "network_interface.h"
#include "dot3.h"
namespace Tins {
/**
* \brief Class representing an Ethernet II PDU.
*/
class IEEE802_3 : public PDU {
public:
/**
* \brief The address type.
*/
typedef HWAddress<6> address_type;
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::IEEE802_3;
/**
* \brief Represents the IEEE802_3 broadcast address.
*/
static const address_type BROADCAST;
/**
* \brief Constructor for creating an IEEE802_3 PDU
*
* Constructor that builds an IEEE802_3 PDU taking the interface name,
* destination's and source's MAC.
*
* \param iface string containing the interface's name from where to send the packet.
* \param dst_hw_addr The destination hardware address.
* \param src_hw_addr The source hardware address.
* \param child The PDU which will be set as the inner PDU.
*/
IEEE802_3(const NetworkInterface& iface = NetworkInterface(),
const address_type &dst_hw_addr = address_type(),
const address_type &src_hw_addr = address_type(),
PDU* child = 0);
/**
* \brief Constructor which creates an IEEE802_3 object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
IEEE802_3(const uint8_t *buffer, uint32_t total_sz);
/* Getters */
/**
* \brief Getter for the destination hardware address.
*
* \return The destination hardware address.
*/
address_type dst_addr() const { return _eth.dst_mac; }
/**
* \brief Getter for the source hardware address.
*
* \return The source hardware address.
*/
address_type src_addr() const { return _eth.src_mac; }
/**
* \brief Getter for the interface.
*
* \return The network interface.
*/
const NetworkInterface &iface() const { return this->_iface; }
/**
* \brief Getter for the length field.
* \return The length field value.
*/
uint16_t length() const { return Endian::be_to_host(_eth.length); };
/* Setters */
/**
* \brief Setter for the destination hardware address.
*
* \param new_dst_mac The new destination hardware address.
*/
void dst_addr(const address_type &new_dst_mac);
/**
* \brief Setter for the source hardware address.
*
* \param new_src_mac The new source hardware address.
*/
void src_addr(const address_type &new_src_mac);
/**
* \brief Setter for the interface.
*
* \param new_iface The interface in which to send this PDU.
*/
void iface(const NetworkInterface &new_iface);
/**
* \brief Setter for the length field.
*
* \param new_length uint16_t with the new value of the length field.
*/
void length(uint16_t new_length);
/* Virtual methods */
/**
* \brief Returns the IEEE802_3 frame's header length.
*
* \return An uint32_t with the header's size.
* \sa PDU::header_size()
*/
uint32_t header_size() const;
#ifndef WIN32
/**
* \sa PDU::send()
*/
void send(PacketSender &sender);
#endif // WIN32
/** \brief Check wether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(uint8_t *ptr, uint32_t total_sz);
#ifndef WIN32
/** \brief Receives a matching response for this packet.
*
* \sa PDU::recv_response
* \param sender The packet sender which will receive the packet.
*/
PDU *recv_response(PacketSender &sender);
#endif // WIN32
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::IEEE802_3; }
/**
* \brief Clones this pdu, filling the corresponding header with data
* extracted from a buffer.
*
* \param ptr The pointer to the from from which the data will be extracted.
* \param total_sz The size of the buffer.
* \return The cloned PDU.
* \sa PDU::clone_packet
*/
PDU *clone_packet(const uint8_t *ptr, uint32_t total_sz);
/**
* \sa PDU::clone
*/
IEEE802_3 *clone() const {
return new IEEE802_3(*this);
}
private:
/**
* Struct that represents the Ethernet II header
*/
struct ethhdr {
uint8_t dst_mac[address_type::address_size];
uint8_t src_mac[address_type::address_size];
uint16_t length;
} __attribute__((__packed__));
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
ethhdr _eth;
NetworkInterface _iface;
};
};
typedef Dot3 IEEE802_3;
}
#endif // TINS_IEEE802_3_H

207
include/internals.h Normal file
View File

@@ -0,0 +1,207 @@
/*
* Copyright (c) 2012, 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_INTERNALS_H
#define TINS_INTERNALS_H
#include <sstream>
#include <string>
#include <stdint.h>
#include "constants.h"
#include "pdu.h"
#include "hw_address.h"
/**
* \cond
*/
namespace Tins {
class IPv4Address;
class IPv6Address;
namespace Internals {
template<size_t n>
class byte_array {
public:
typedef uint8_t* iterator;
typedef const uint8_t* const_iterator;
byte_array() {
std::fill(begin(), end(), 0);
}
template<typename InputIterator>
byte_array(InputIterator start, InputIterator last) {
std::copy(start, last, data);
}
template<typename InputIterator>
byte_array(InputIterator start) {
std::copy(start, n, data);
}
uint8_t &operator[](size_t i) {
return data[i];
}
uint8_t operator[](size_t i) const{
return data[i];
}
iterator begin() {
return data;
}
iterator end() {
return data + n;
}
const_iterator begin() const {
return data;
}
const_iterator end() const {
return data + n;
}
size_t size() const {
return n;
}
private:
uint8_t data[n];
};
void skip_line(std::istream &input);
bool from_hex(const std::string &str, uint32_t &result);
template<bool, typename T = void>
struct enable_if {
typedef T type;
};
template<typename T>
struct enable_if<false, T> {
};
PDU *pdu_from_flag(Constants::Ethernet::e flag, const uint8_t *buffer,
uint32_t size, bool rawpdu_on_no_match = true);
PDU *pdu_from_flag(Constants::IP::e flag, const uint8_t *buffer,
uint32_t size, bool rawpdu_on_no_match = true);
PDU *pdu_from_flag(PDU::PDUType type, const uint8_t *buffer, uint32_t size);
Constants::Ethernet::e pdu_flag_to_ether_type(PDU::PDUType flag);
Constants::IP::e pdu_flag_to_ip_type(PDU::PDUType flag);
template<typename T>
bool increment_buffer(T &addr) {
typename T::iterator it = addr.end() - 1;
while(it >= addr.begin() && *it == 0xff) {
*it = 0;
--it;
}
// reached end
if(it < addr.begin())
return true;
(*it)++;
return false;
}
template<typename T>
bool decrement_buffer(T &addr) {
typename T::iterator it = addr.end() - 1;
while(it >= addr.begin() && *it == 0) {
*it = 0xff;
--it;
}
// reached end
if(it < addr.begin())
return true;
(*it)--;
return false;
}
bool increment(IPv4Address &addr);
bool increment(IPv6Address &addr);
bool decrement(IPv4Address &addr);
bool decrement(IPv6Address &addr);
template<size_t n>
bool increment(HWAddress<n> &addr) {
return increment_buffer(addr);
}
template<size_t n>
bool decrement(HWAddress<n> &addr) {
return decrement_buffer(addr);
}
IPv4Address last_address_from_mask(IPv4Address addr, IPv4Address mask);
IPv6Address last_address_from_mask(IPv6Address addr, const IPv6Address &mask);
template<size_t n>
HWAddress<n> last_address_from_mask(HWAddress<n> addr, const HWAddress<n> &mask) {
typename HWAddress<n>::iterator addr_iter = addr.begin();
for(typename HWAddress<n>::const_iterator it = mask.begin(); it != mask.end(); ++it, ++addr_iter) {
*addr_iter = *addr_iter | ~*it;
}
return addr;
}
inline bool is_dot3(const uint8_t *ptr, size_t sz) {
return (sz >= 13 && ptr[12] < 8);
}
template<typename T>
struct is_unsigned_integral {
static const bool value = false;
};
template<>
struct is_unsigned_integral<uint8_t> {
static const bool value = true;
};
template<>
struct is_unsigned_integral<uint16_t> {
static const bool value = true;
};
template<>
struct is_unsigned_integral<uint32_t> {
static const bool value = true;
};
template<>
struct is_unsigned_integral<uint64_t> {
static const bool value = true;
};
} // namespace Internals
} // namespace Tins
/**
* \endcond
*/
#endif

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,6 +36,8 @@
#include "endianness.h"
#include "ip_address.h"
#include "pdu_option.h"
#include "macros.h"
#include "cxxstd.h"
namespace Tins {
@@ -49,7 +51,7 @@ namespace Tins {
class IP : public PDU {
public:
/**
* his PDU's flag.
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::IP;
@@ -99,6 +101,7 @@ namespace Tins {
/**
* \brief The type used to represent an option's type.
*/
TINS_BEGIN_PACK
struct option_identifier {
#if TINS_IS_LITTLE_ENDIAN
uint8_t number:5,
@@ -161,12 +164,12 @@ namespace Tins {
bool operator==(const option_identifier &rhs) const {
return number == rhs.number && op_class == rhs.op_class && copied == rhs.copied;
}
} __attribute__((__packed__));
} TINS_END_PACK;
/**
* The IP options type.
*/
typedef PDUOption<option_identifier> ip_option;
typedef PDUOption<option_identifier, IP> option;
/**
* The type of the security option.
@@ -181,6 +184,8 @@ namespace Tins {
: security(sec), compartments(comp),
handling_restrictions(hand_res), transmission_control(tcc)
{}
static security_type from_option(const option &opt);
};
/**
@@ -195,6 +200,8 @@ namespace Tins {
generic_route_option_type(uint8_t ptr = 0,
routes_type rts = routes_type())
: pointer(ptr), routes(rts) {}
static generic_route_option_type from_option(const option &opt);
};
/**
@@ -212,6 +219,11 @@ namespace Tins {
*/
typedef generic_route_option_type record_route_type;
/**
* The type used to store IP options.
*/
typedef std::list<option> options_type;
/**
* \brief Constructor for building the IP PDU.
*
@@ -221,16 +233,18 @@ namespace Tins {
*
* \param ip_dst The destination ip address(optional).
* \param ip_src The source ip address(optional).
* \param child pointer to a PDU which will be set as the inner_pdu
* for the packet being constructed(optional).
*/
IP(address_type ip_dst = address_type(),
address_type ip_src = address_type(),
PDU *child = 0);
address_type ip_src = address_type());
/**
* \brief Constructor which creates an IP object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \brief Constructs an IP object from a buffer and adds all
* identifiable PDUs found in the buffer as children of this
* one.
*
* If there is not enough size for an IP header, a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
@@ -257,7 +271,9 @@ namespace Tins {
*
* \return The total length of this IP PDU.
*/
uint16_t tot_len() const { return Endian::be_to_host(_ip.tot_len); }
uint16_t tot_len() const {
return Endian::be_to_host(_ip.tot_len);
}
/**
* \brief Getter for the id field.
@@ -292,7 +308,7 @@ namespace Tins {
*
* \return The checksum for this IP PDU.
*/
uint16_t check() const { return Endian::be_to_host(_ip.check); }
uint16_t checksum() const { return Endian::be_to_host(_ip.check); }
/**
* \brief Getter for the source address field.
@@ -313,14 +329,13 @@ namespace Tins {
*/
small_uint<4> version() const { return _ip.version; }
/* Setters */
/**
* \brief Setter for the header length field.
*
* \param new_head_len The new header length.
/**
* \brief Getter for the IP options.
* \return The stored options.
*/
void head_len(small_uint<4> new_head_len);
const options_type &options() const { return _ip_options; }
/* Setters */
/**
* \brief Setter for the type of service field.
@@ -329,13 +344,6 @@ namespace Tins {
*/
void tos(uint8_t new_tos);
/**
* \brief Setter for the total length field.
*
* \param new_tot_len The new total length.
*/
void tot_len(uint16_t new_tot_len);
/**
* \brief Setter for the id field.
*
@@ -360,17 +368,21 @@ namespace Tins {
/**
* \brief Setter for the protocol field.
*
* Note that this protocol will be overwritten using the
* inner_pdu's protocol type during serialization unless the IP
* datagram is fragmented.
*
* If the packet is fragmented and was originally sniffed, the
* original protocol type will be kept when serialized.
*
* If this packet has been crafted manually and the inner_pdu
* is, for example, a RawPDU, then setting the protocol yourself
* is necessary.
*
* \param new_protocol The new protocol.
*/
void protocol(uint8_t new_protocol);
/**
* \brief Setter for the checksum field.
*
* \param new_check The new checksum.
*/
void check(uint16_t new_check);
/**
* \brief Setter for the source address field.
*
@@ -398,15 +410,34 @@ namespace Tins {
* The option is added after the last option in the option
* fields.
*
* \param option The option to be added
* \param opt The option to be added
*/
void add_option(const ip_option &option);
void add_option(const option &opt);
#if TINS_IS_CXX11
/**
* \brief Adds an IP option.
*
* The option is move-constructed.
*
* \param opt The option to be added.
*/
void add_option(option &&opt) {
internal_add_option(opt);
_ip_options.push_back(std::move(opt));
}
#endif
/**
* \brief Searchs for an option that matchs the given flag.
*
* If the option is not found, a null pointer is returned.
* Deleting the returned pointer will result in <b>undefined
* behaviour</b>.
*
* \param id The option identifier to be searched.
*/
const ip_option *search_option(option_identifier id) const;
const option *search_option(option_identifier id) const;
// Option setters
@@ -533,7 +564,7 @@ namespace Tins {
/**
* \sa PDU::send()
*/
void send(PacketSender &sender);
void send(PacketSender &sender, const NetworkInterface &);
/**
* \brief Check wether ptr points to a valid response for this PDU.
@@ -542,7 +573,7 @@ namespace Tins {
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(uint8_t *ptr, uint32_t total_sz);
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \brief Receives a matching response for this packet.
@@ -550,7 +581,14 @@ namespace Tins {
* \sa PDU::recv_response
* \param sender The packet sender which will receive the packet.
*/
PDU *recv_response(PacketSender &sender);
PDU *recv_response(PacketSender &sender, const NetworkInterface &);
/**
* Indicates whether this PDU is fragmented.
*
* \return true if this PDU is fragmented, false otherwise.
*/
bool is_fragmented() const;
/**
* \brief Getter for the PDU's type.
@@ -558,17 +596,6 @@ namespace Tins {
*/
PDUType pdu_type() const { return PDU::IP; }
/**
* \brief Clones this pdu, filling the corresponding header with data
* extracted from a buffer.
*
* \param ptr The pointer to the from from which the data will be extracted.
* \param total_sz The size of the buffer.
* \return The cloned PDU.
* \sa PDU::clone_packet
*/
PDU *clone_packet(const uint8_t *ptr, uint32_t total_sz);
/**
* \sa PDU::clone
*/
@@ -578,15 +605,14 @@ namespace Tins {
private:
static const uint8_t DEFAULT_TTL;
TINS_BEGIN_PACK
struct iphdr {
#if TINS_IS_LITTLE_ENDIAN
unsigned int ihl:4;
unsigned int version:4;
#elif TINS_IS_BIG_ENDIAN
unsigned int version:4;
unsigned int ihl:4;
uint8_t ihl:4,
version:4;
#else
# error "Endian is not LE nor BE..."
uint8_t version:4,
ihl:4;
#endif
uint8_t tos;
uint16_t tot_len;
@@ -598,18 +624,25 @@ namespace Tins {
uint32_t saddr;
uint32_t daddr;
/*The options start here. */
} __attribute__((__packed__));
} TINS_END_PACK;
void head_len(small_uint<4> new_head_len);
void tot_len(uint16_t new_tot_len);
void prepare_for_serialize(const PDU *parent);
void internal_add_option(const option &option);
void init_ip_fields();
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
uint8_t* write_option(const ip_option &opt, uint8_t* buffer);
uint8_t* write_option(const option &opt, uint8_t* buffer);
void add_route_option(option_identifier id, const generic_route_option_type &data);
generic_route_option_type search_route_option(option_identifier id) const;
void checksum(uint16_t new_check);
iphdr _ip;
std::list<ip_option> _ip_options;
uint32_t _options_size, _padded_options_size;
uint16_t _options_size, _padded_options_size;
options_type _ip_options;
};
};
}
#endif // TINS_IP_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,110 +33,167 @@
#include <string>
#include <iostream>
#include <stdint.h>
#include "cxxstd.h"
namespace Tins {
/**
* \class IPv4Address
* \brief Abstraction of an IPv4 address.
*/
class IPv4Address {
public:
/**
* \class IPv4Address
* \brief Abstraction of an IPv4 address.
* The address size.
*/
class IPv4Address {
public:
/**
* The address size.
*/
static const size_t address_size = sizeof(uint32_t);
/**
* \brief Constructor taking a const char*.
*
* Constructs an IPv4Address from a dotted-notation address
* cstring. If the pointer provided is null, then a default
* IPv4Address object is constructed, which corresponds to
* the 0.0.0.0 address.
*
* \param ip const char* containing the dotted-notation address.
*/
IPv4Address(const char *ip = 0);
/**
* \brief Constructor taking a std::string.
*
* Constructs an IPv4Address from a dotted-notation std::strings
*
* \param ip std::string containing the dotted-notation address.
*/
IPv4Address(const std::string &ip);
/**
* \brief Constructor taking a IP address represented as a
* big endian integer.
*
* This constructor should be used internally by PDUs that
* handle IP addresses. The provided integer <b>must</b> be
* be in big endian.
*/
explicit IPv4Address(uint32_t ip);
/**
* \brief User defined conversion to big endian integral value.
*/
operator uint32_t() const;
/**
* \brief Retrieve the string representation of this address.
*
* \return std::string containing the representation of this address.
*/
std::string to_string() const;
/**
* \brief Compare this IPv4Address for equality.
*
* \param rhs The address to be compared.
* \return bool indicating whether this address equals rhs.
*/
bool operator==(const IPv4Address &rhs) const {
return ip_addr == rhs.ip_addr;
}
/**
* \brief Compare this IPv4Address for inequality.
*
* \param rhs The address to be compared.
* \return bool indicating whether this address is distinct
* from rhs.
*/
bool operator!=(const IPv4Address &rhs) const {
return !(*this == rhs);
}
/**
* \brief Compare this IPv4Address for less-than inequality.
*
* \param rhs The address to be compared.
* \return bool indicating whether this address is less-than rhs.
*/
bool operator< (const IPv4Address &rhs) const {
return ip_addr < rhs.ip_addr;
}
/**
* \brief Writes this address to a std::ostream.
*
* This method writes addr in a dotted-string notation address
* to the std::ostream argument.
*
* \param output The std::ostream in which to write the address.
* \param addr The IPv4Address to be written.
* \return std::stream& pointing to output.
*/
friend std::ostream &operator<<(std::ostream &output, const IPv4Address &addr);
private:
uint32_t ip_to_int(const std::string &ip);
static const size_t address_size = sizeof(uint32_t);
/**
* The broadcast address.
*/
static const IPv4Address broadcast;
/**
* \brief Constructor taking a const char*.
*
* Constructs an IPv4Address from a dotted-notation address
* cstring. If the pointer provided is null, then a default
* IPv4Address object is constructed, which corresponds to
* the 0.0.0.0 address.
*
* \param ip const char* containing the dotted-notation address.
*/
IPv4Address(const char *ip = 0);
uint32_t ip_addr;
};
/**
* \brief Constructor taking a std::string.
*
* Constructs an IPv4Address from a dotted-notation std::strings
*
* \param ip std::string containing the dotted-notation address.
*/
IPv4Address(const std::string &ip);
/**
* \brief Constructor taking a IP address represented as a
* big endian integer.
*
* This constructor should be used internally by PDUs that
* handle IP addresses. The provided integer <b>must</b> be
* be in big endian.
*/
explicit IPv4Address(uint32_t ip);
/**
* \brief User defined conversion to big endian integral value.
*/
operator uint32_t() const;
/**
* \brief Retrieve the string representation of this address.
*
* \return std::string containing the representation of this address.
*/
std::string to_string() const;
/**
* \brief Compare this IPv4Address for equality.
*
* \param rhs The address to be compared.
* \return bool indicating whether this address equals rhs.
*/
bool operator==(const IPv4Address &rhs) const {
return ip_addr == rhs.ip_addr;
}
/**
* \brief Compare this IPv4Address for inequality.
*
* \param rhs The address to be compared.
* \return bool indicating whether this address is distinct
* from rhs.
*/
bool operator!=(const IPv4Address &rhs) const {
return !(*this == rhs);
}
/**
* \brief Compare this IPv4Address for less-than inequality.
*
* \param rhs The address to be compared.
* \return bool indicating whether this address is less-than rhs.
*/
bool operator< (const IPv4Address &rhs) const {
return ip_addr < rhs.ip_addr;
}
/**
* \brief Returns true if this is a private IPv4 address.
*
* This takes into account the private network ranges defined in
* RFC 1918. Therefore, this method returns true if this address
* is in any of the following network ranges, false otherwise:
*
* - 192.168.0.0/16
* - 10.0.0.0/8
* - 172.16.0.0/12
*/
bool is_private() const;
/**
* \brief Returns true if this is a loopback IPv4 address.
*
* This method returns true if this address is in the address range
* 127.0.0.0/8, false otherwise.
*/
bool is_loopback() const;
/**
* \brief Returns true if this is a multicast IPv4 address.
*
* This method returns true if this address is in the address range
* 224.0.0.0/4, false otherwise.
*/
bool is_multicast() const;
/**
* \brief Returns true if this is an unicast IPv4 address.
*/
bool is_unicast() const;
/**
* \brief Returns true if this is a broadcast IPv4 address.
*/
bool is_broadcast() const;
/**
* \brief Writes this address to a std::ostream.
*
* This method writes addr in a dotted-string notation address
* to the std::ostream argument.
*
* \param output The std::ostream in which to write the address.
* \param addr The IPv4Address to be written.
* \return std::stream& pointing to output.
*/
friend std::ostream &operator<<(std::ostream &output, const IPv4Address &addr);
private:
uint32_t ip_to_int(const std::string &ip);
uint32_t ip_addr;
};
} //namespace Tins
#if TINS_IS_CXX11
namespace std
{
template<>
struct hash<Tins::IPv4Address> {
size_t operator()(const Tins::IPv4Address &addr) const {
return std::hash<uint32_t>()(addr);
}
};
} // namespace std
#endif
#endif // TINS_IPADDRESS_H

216
include/ip_reassembler.h Normal file
View File

@@ -0,0 +1,216 @@
/*
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_IP_REASSEMBLER_H
#define TINS_IP_REASSEMBLER_H
#include <vector>
#include <map>
#include "pdu.h"
#include "ip_address.h"
namespace Tins {
/**
* \cond
*/
class IP;
namespace Internals {
class IPv4Fragment {
public:
typedef PDU::serialization_type payload_type;
IPv4Fragment() : offset_() { }
template<typename T>
IPv4Fragment(T *pdu, uint16_t offset)
: payload_(pdu->serialize()), offset_(offset)
{
}
const payload_type &payload() const {
return payload_;
}
uint16_t offset() const {
return offset_;
}
private:
payload_type payload_;
uint16_t offset_;
};
class IPv4Stream {
public:
IPv4Stream();
void add_fragment(IP *ip);
bool is_complete() const;
PDU *allocate_pdu() const;
private:
typedef std::vector<IPv4Fragment> fragments_type;
uint16_t extract_offset(const IP *ip);
bool extract_more_frag(const IP *ip);
fragments_type fragments;
bool received_end;
uint8_t transport_proto;
size_t received_size, total_size;
};
} // namespace Internals
/**
* \endcond
*/
/**
* \brief Reassembles fragmented IP packets.
*/
class IPv4Reassembler {
public:
/**
* The status of each processed packet.
*/
enum packet_status {
NOT_FRAGMENTED,
FRAGMENTED,
REASSEMBLED
};
/**
* The type used to represent the overlapped segment
* reassembly technique to be used.
*/
enum overlapping_technique {
NONE
};
/**
* Constructs an IPV4Reassembler.
* \param technique The technique to be used for reassembling
* overlapped fragments.
*/
IPv4Reassembler(overlapping_technique technique = NONE);
/**
* \brief Processes a PDU and tries to reassemble it.
*
* This method tries to reassemble the provided packet. If
* the packet is successfully reassembled using previously
* processed packets, its contents will be modified so that
* it contains the whole payload and not just a fragment.
*
* \param pdu The PDU to process.
* \return NOT_FRAGMENTED if the PDU does not contain an IP
* layer or is not fragmented, FRAGMENTED if the packet is
* fragmented or REASSEMBLED if the packet was fragmented
* but has now been reassembled.
*/
packet_status process(PDU &pdu);
/**
* Removes all of the packets and data stored.
*/
void clear_streams();
/**
* \brief Removes all of the packets and data stored that
* belongs to IP headers whose identifier, source and destination
* addresses are equal to the provided parameters.
*
* \param id The idenfier to search.
* \param addr1 The source address to search.
* \param addr2 The destinatin address to search.
* \sa IP::id
*/
void remove_stream(uint16_t id, IPv4Address addr1, IPv4Address addr2);
private:
typedef std::pair<IPv4Address, IPv4Address> address_pair;
typedef std::pair<uint16_t, address_pair> key_type;
typedef std::map<key_type, Internals::IPv4Stream> streams_type;
key_type make_key(const IP *ip) const;
address_pair make_address_pair(IPv4Address addr1, IPv4Address addr2) const;
streams_type streams;
overlapping_technique technique;
};
/**
* Proxy functor class that reassembles PDUs.
*/
template<typename Functor>
class IPv4ReassemblerProxy {
public:
/**
* Constructs the proxy from a functor object.
*
* \param func The functor object.
*/
IPv4ReassemblerProxy(Functor func)
: functor_(func)
{
}
/**
* \brief Tries to reassemble the packet and forwards it to
* the functor.
*
* \param pdu The packet to process
* \return true if the packet wasn't forwarded, otherwise
* the value returned by the functor.
*/
bool operator()(PDU &pdu) {
// Forward it unless it's fragmented.
if(reassembler.process(pdu) != IPv4Reassembler::FRAGMENTED)
return functor_(pdu);
else
return true;
}
private:
IPv4Reassembler reassembler;
Functor functor_;
};
/**
* Helper function that creates an IPv4ReassemblerProxy.
*
* \param func The functor object to use in the IPv4ReassemblerProxy.
* \return An IPv4ReassemblerProxy.
*/
template<typename Functor>
IPv4ReassemblerProxy<Functor> make_ipv4_reassembler_proxy(Functor func) {
return IPv4ReassemblerProxy<Functor>(func);
}
}
#endif // TINS_IP_REASSEMBLER_H

264
include/ipsec.h Normal file
View File

@@ -0,0 +1,264 @@
/*
* Copyright (c) 2012, 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_IPSEC_H
#define TINS_IPSEC_H
#include "pdu.h"
#include "endianness.h"
#include "small_uint.h"
namespace Tins {
/**
* \brief Represents an IPSec Authentication Header.
*/
class IPSecAH : public PDU {
public:
/**
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::IPSEC_AH;
/**
* \brief Default constructor.
*
* The ICV field is initialized with four 0 bytes. The length
* field is initialized appropriately.
*/
IPSecAH();
/**
* \brief Constructs an IPSecAH object from a buffer and adds all
* identifiable PDUs found in the buffer as children of this
* one.
*
* If there is not enough size for an IPSecAH header, a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
IPSecAH(const uint8_t *buffer, uint32_t total_sz);
// Getters
/**
* \brief Getter for the Next header field.
* \return The stored Next header field value.
*/
uint8_t next_header() const {
return _header.next_header;
}
/**
* \brief Getter for the Length field.
* \return The stored Length field value.
*/
uint8_t length() const {
return _header.length;
}
/**
* \brief Getter for the Security Parameters Index field.
* \return The stored Security Parameters Index field value.
*/
uint32_t spi() const {
return Endian::be_to_host(_header.spi);
}
/**
* \brief Getter for the Sequence number field.
* \return The stored Sequence number field value.
*/
uint32_t seq_number() const {
return Endian::be_to_host(_header.seq_number);
}
/**
* \brief Getter for the ICV field.
* \return The stored ICV field value.
*/
const byte_array &icv() const {
return _icv;
}
// Setters
/**
* \brief Setter for the Next header field.
* \param new_next_header The new Next header field value.
*/
void next_header(uint8_t new_next_header);
/**
* \brief Setter for the Length field.
* \param new_length The new Length field value.
*/
void length(uint8_t new_length);
/**
* \brief Setter for the Security Parameters Index field.
* \param new_spi The new Security Parameters Index field value.
*/
void spi(uint32_t new_spi);
/**
* \brief Setter for the Sequence number field.
* \param new_seq_number The new Sequence number field value.
*/
void seq_number(uint32_t new_seq_number);
/**
* \brief Setter for the ICV field.
* \param new_icv The new ICV field value.
*/
void icv(const byte_array &new_icv);
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_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
*/
IPSecAH *clone() const {
return new IPSecAH(*this);
}
private:
struct header {
uint8_t next_header, length;
uint32_t spi, seq_number;
};
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
header _header;
byte_array _icv;
};
/**
* \brief Represents an IPSec Authentication Header.
*/
class IPSecESP : public PDU {
public:
/**
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::IPSEC_ESP;
/**
* \brief Default constructor.
*/
IPSecESP();
/**
* \brief Constructs an IPSecESP object from a buffer and adds all
* identifiable PDUs found in the buffer as children of this
* one.
*
* If there is not enough size for an IPSecESP header, a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
IPSecESP(const uint8_t *buffer, uint32_t total_sz);
// Getters
/**
* \brief Getter for the Security Parameters Index field.
* \return The stored Security Parameters Index field value.
*/
uint32_t spi() const {
return Endian::be_to_host(_header.spi);
}
/**
* \brief Getter for the Sequence number field.
* \return The stored Sequence number field value.
*/
uint32_t seq_number() const {
return Endian::be_to_host(_header.seq_number);
}
// Setters
/**
* \brief Setter for the Security Parameters Index field.
* \param new_spi The new Security Parameters Index field value.
*/
void spi(uint32_t new_spi);
/**
* \brief Setter for the Sequence number field.
* \param new_seq_number The new Sequence number field value.
*/
void seq_number(uint32_t new_seq_number);
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_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
*/
IPSecESP *clone() const {
return new IPSecESP(*this);
}
private:
struct header {
uint32_t spi, seq_number;
};
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
header _header;
};
}
#endif // TINS_IPSEC_H

330
include/ipv6.h Normal file
View File

@@ -0,0 +1,330 @@
/*
* Copyright (c) 2012, 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_IPV6_h
#define TINS_IPV6_h
#include <list>
#include <stdexcept>
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
#include "small_uint.h"
#include "pdu_option.h"
#include "ipv6_address.h"
namespace Tins {
class PacketSender;
/**
* Represents an IPv6 PDU.
*/
class IPv6 : public PDU {
public:
/**
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::IPv6;
/**
* The type used to store addresses.
*/
typedef IPv6Address address_type;
/**
* The type used to represent IPv6 extension headers.
*/
typedef PDUOption<uint8_t, IPv6> ext_header;
/**
* The type used to store the extension headers.
*/
typedef std::list<ext_header> headers_type;
/**
* The values used to identify extension headers.
*/
enum ExtensionHeader {
HOP_BY_HOP = 0,
DESTINATION_ROUTING_OPTIONS = 60,
ROUTING = 43,
FRAGMENT = 44,
AUTHENTICATION = 51,
SECURITY_ENCAPSULATION = 50,
DESTINATION_OPTIONS = 60,
MOBILITY = 135,
NO_NEXT_HEADER = 59
};
/**
* \brief Constructs an IPv6 object.
*
* \param ip_dst The destination ip address(optional).
* \param ip_src The source ip address(optional).
* \param child pointer to a PDU which will be set as the inner_pdu
* for the packet being constructed(optional).
*/
IPv6(address_type ip_dst = address_type(),
address_type ip_src = address_type(),
PDU *child = 0);
/**
* \brief Constructs an IPv6 object from a buffer and adds all
* identifiable PDUs found in the buffer as children of this one.
*
* If there is not enough size for an IPv6 header, a malformed_packet
* exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
IPv6(const uint8_t *buffer, uint32_t total_sz);
// Getters
/**
* \brief Getter for the version field.
* \return The stored version field value.
*/
small_uint<4> version() const {
return _header.version;
}
/**
* \brief Getter for the traffic_class field.
* \return The stored traffic_class field value.
*/
uint8_t traffic_class() const {
#if TINS_IS_LITTLE_ENDIAN
return ((_header.traffic_class << 4) & 0xf0) |
((_header.flow_label[0] >> 4) & 0x0f);
#else
return _header.traffic_class;
#endif
}
/**
* \brief Getter for the flow_label field.
* \return The stored flow_label field value.
*/
small_uint<20> flow_label() const {
#if TINS_IS_LITTLE_ENDIAN
return ((_header.flow_label[0] & 0x0f) << 16)
| (_header.flow_label[1] << 8)
| (_header.flow_label[2]);
#else
return _header.flow_label;
#endif
}
/**
* \brief Getter for the payload_length field.
* \return The stored payload_length field value.
*/
uint16_t payload_length() const {
return Endian::be_to_host(_header.payload_length);
}
/**
* \brief Getter for the next_header field.
* \return The stored next_header field value.
*/
uint8_t next_header() const {
return _header.next_header;
}
/**
* \brief Getter for the hop_limit field.
* \return The stored hop_limit field value.
*/
uint8_t hop_limit() const {
return _header.hop_limit;
}
/**
* \brief Getter for the src_addr field.
* \return The stored src_addr field value.
*/
address_type src_addr() const {
return _header.src_addr;
}
/**
* \brief Getter for the dst_addr field.
* \return The stored dst_addr field value.
*/
address_type dst_addr() const {
return _header.dst_addr;
}
/**
* \brief Getter for the IPv6 extension headers.
* \return The stored headers.
*/
const headers_type& headers() const {
return ext_headers;
}
// Setters
/**
* \brief Setter for the version field.
* \param new_version The new version field value.
*/
void version(small_uint<4> new_version);
/**
* \brief Setter for the traffic_class field.
* \param new_traffic_class The new traffic_class field value.
*/
void traffic_class(uint8_t new_traffic_class);
/**
* \brief Setter for the flow_label field.
* \param new_flow_label The new flow_label field value.
*/
void flow_label(small_uint<20> new_flow_label);
/**
* \brief Setter for the payload_length field.
* \param new_payload_length The new payload_length field value.
*/
void payload_length(uint16_t new_payload_length);
/**
* \brief Setter for the next_header field.
* \param new_next_header The new next_header field value.
*/
void next_header(uint8_t new_next_header);
/**
* \brief Setter for the hop_limit field.
* \param new_hop_limit The new hop_limit field value.
*/
void hop_limit(uint8_t new_hop_limit);
/**
* \brief Setter for the src_addr field.
* \param new_src_addr The new src_addr field value.
*/
void src_addr(const address_type &new_src_addr);
/**
* \brief Setter for the dst_addr field.
* \param new_dst_addr The new dst_addr field value.
*/
void dst_addr(const address_type &new_dst_addr);
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \sa PDU::clone
*/
IPv6 *clone() const {
return new IPv6(*this);
}
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
#ifndef BSD
/**
* \sa PDU::send()
*/
void send(PacketSender &sender, const NetworkInterface &);
#endif
/**
* Adds an extension header.
*
* \param header The extension header to be added.
*/
void add_ext_header(const ext_header &header);
/**
* \brief Searchs for an extension header that matchs the given
* flag.
*
* If the header is not found, a null pointer is returned.
* Deleting the returned pointer will result in <b>undefined
* behaviour</b>.
*
* \param id The header identifier to be searched.
*/
const ext_header *search_header(ExtensionHeader id) const;
private:
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
void set_last_next_header(uint8_t value);
static uint8_t *write_header(const ext_header &header, uint8_t *buffer);
static bool is_extension_header(uint8_t header_id);
TINS_BEGIN_PACK
struct ipv6_header {
#if TINS_IS_BIG_ENDIAN
uint32_t version:4,
traffic_class:8,
flow_label:20;
uint32_t payload_length:16,
next_header:8,
hop_limit:8;
#else
uint8_t traffic_class:4,
version:4;
uint8_t flow_label[3];
uint16_t payload_length;
uint8_t next_header;
uint8_t hop_limit;
#endif
uint8_t src_addr[16], dst_addr[16];
} TINS_END_PACK;
ipv6_header _header;
headers_type ext_headers;
uint32_t headers_size;
};
}
#endif // TINS_IPV6_h

230
include/ipv6_address.h Normal file
View File

@@ -0,0 +1,230 @@
/*
* Copyright (c) 2012, 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_IPV6_ADDRESS
#define TINS_IPV6_ADDRESS
#include <string>
#include <stdexcept>
#include <stdint.h>
#include "cxxstd.h"
namespace Tins {
/**
* Represents an IPv6 address.
*/
class IPv6Address {
public:
/**
* The exception thrown when a malformed address is parsed.
*/
class malformed_address : public std::exception {
public:
const char *what() const throw() {
return "Malformed address";
}
};
static const size_t address_size = 16;
/**
* The iterator type.
*/
typedef uint8_t* iterator;
/**
* The const iterator type.
*/
typedef const uint8_t* const_iterator;
/**
* \brief Default constructor.
* Initializes this IPv6 address to "::"
*/
IPv6Address();
/**
* \brief Constructor from a text representation char*.
* \param addr The text representation from which to construct this
* object.
*/
IPv6Address(const char *addr);
/**
* \brief Constructor from a text representation std::string.
* \param addr The text representation from which to construct this
* object.
*/
IPv6Address(const std::string &addr);
/**
* \brief Constructor from a buffer.
*
* The ptr parameter must be at least address_size bytes long.
*
* \param ptr The buffer from which to construct this object.
*/
IPv6Address(const_iterator ptr);
/**
* \brief Retrieve the string representation of this address.
*
* \return std::string containing the representation of this address.
*/
std::string to_string() const;
/**
* Returns an iterator to the beginning of this address.
*/
iterator begin() {
return address;
}
/**
* Returns a const iterator to the beginning of this address.
*/
const_iterator begin() const {
return address;
}
/**
* Returns an iterator to the one-past-the-end element of this address.
*/
iterator end() {
return address + address_size;
}
/**
* Returns a const iterator to the one-past-the-end element of this
* address.
*/
const_iterator end() const {
return address + address_size;
}
/**
* \brief Compares this address for equality.
*
* \param rhs The address to be compared to.
*
* \return bool indicating whether addresses are equal.
*/
bool operator==(const IPv6Address &rhs) const {
return std::equal(begin(), end(), rhs.begin());
}
/**
* \brief Compares this address for inequality.
*
* \param rhs The address to be compared to.
*
* \return bool indicating whether addresses are distinct.
*/
bool operator!=(const IPv6Address &rhs) const {
return !(*this == rhs);
}
/**
* \brief Compares this address for less-than inequality.
*
* \param rhs The address to be compared to.
*
* \return bool indicating whether this address is less-than rhs.
*/
bool operator<(const IPv6Address &rhs) const {
return std::lexicographical_compare(begin(), end(), rhs.begin(), rhs.end());
}
/**
* \brief Helper function which copies the address into an output
* iterator.
*
* This is the same as:
*
* std::copy(begin(), end(), iter);
*
* But since some PDUs return a IPv6Address by value, this function
* can be used to avoid temporaries.
*
* \param iter The output iterator in which to store this address.
* \return OutputIterator pointing to one-past the last position
* written.
*/
template<typename OutputIterator>
OutputIterator copy(OutputIterator iter) const {
return std::copy(begin(), end(), iter);
}
/**
* \brief Returns true if this is a loopback IPv6 address.
*
* This method returns true if this address is the ::1/128 address,
* false otherwise.
*/
bool is_loopback() const;
/**
* \brief Returns true if this is a multicast IPv6 address.
*
* This method returns true if this address is in the address range
* ff00::/8, false otherwise.
*/
bool is_multicast() const;
/**
* \brief Writes this address in hex-notation to a std::ostream.
*
* \param os The stream in which to write the address.
* \param addr The parameter to be written.
* \return std::ostream& pointing to the os parameter.
*/
friend std::ostream &operator<<(std::ostream &os, const IPv6Address &addr) {
return os << addr.to_string();
}
private:
void init(const char *addr);
uint8_t address[address_size];
};
} //namespace Tins
#if TINS_IS_CXX11
namespace std
{
template<>
struct hash<Tins::IPv6Address> {
size_t operator()(const Tins::IPv6Address &addr) const {
return std::hash<std::string>()(addr.to_string());
}
};
} // namespace std
#endif
#endif // TINS_IPV6_ADDRESS

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,6 +33,7 @@
#include <list>
#include <vector>
#include <stdint.h>
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
@@ -54,6 +55,10 @@ namespace Tins {
* \brief Represents the LLC global DSAP address.
*/
static const uint8_t GLOBAL_DSAP_ADDR;
/**
* \brief Represents the LLC NULL address.
*/
static const uint8_t NULL_ADDR;
/**
@@ -89,22 +94,25 @@ namespace Tins {
};
/**
* \brief Creates an instance of LLC
* \param child The child PDU.(optional)
* \brief Default constructor.
*/
LLC(PDU *child = 0);
LLC();
/**
* \brief Creates an instance of LLC, setting the dsap and ssap.
* The control field is set all to 0.
* @param dsap The dsap value to be set.
* @param ssap The ssap value to be set.
* \brief Constructs an instance of LLC, setting the dsap and ssap.
* The control field is set to 0.
* \param dsap The dsap value to be set.
* \param ssap The ssap value to be set.
*/
LLC(uint8_t dsap, uint8_t ssap, PDU* child = 0);
LLC(uint8_t dsap, uint8_t ssap);
/**
* \brief Constructor which creates a LLC object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \brief Constructs a LLC object from a buffer and adds all
* identifiable PDUs found in the buffer as children of this one.
*
* If there is not enough size for a LLC header, a malformed_packet
* exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
@@ -298,7 +306,7 @@ namespace Tins {
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::LLC; }
PDUType pdu_type() const { return pdu_flag; }
/**
* \brief Delete all the information fields added.
@@ -314,62 +322,67 @@ namespace Tins {
return new LLC(*this);
}
private:
TINS_BEGIN_PACK
struct llchdr {
uint8_t dsap;
uint8_t ssap;
} __attribute__((__packed__));
} TINS_END_PACK;
#if TINS_IS_LITTLE_ENDIAN
TINS_BEGIN_PACK
struct info_control_field {
uint16_t
type_bit:1,
send_seq_num:7,
poll_final_bit:1,
recv_seq_num:7;
} __attribute__((__packed__));
} TINS_END_PACK;
TINS_BEGIN_PACK
struct super_control_field {
uint16_t type_bit:2,
supervisory_func:2,
unused:4,
poll_final_bit:1,
recv_seq_num:7;
} __attribute__((__packed__));
} TINS_END_PACK;
TINS_BEGIN_PACK
struct un_control_field {
uint8_t type_bits:2,
mod_func1:2,
poll_final_bit:1,
mod_func2:3;
} __attribute__((__packed__));
} TINS_END_PACK;
#elif TINS_IS_BIG_ENDIAN
TINS_BEGIN_PACK
struct info_control_field {
uint16_t send_seq_num:7,
type_bit:1,
recv_seq_num:7,
poll_final_bit:1;
} __attribute__((__packed__));
} TINS_END_PACK;
TINS_BEGIN_PACK
struct super_control_field {
uint16_t unused:4,
supervisory_func:2,
type_bit:2,
recv_seq_num:7,
poll_final_bit:1;
} __attribute__((__packed__));
} TINS_END_PACK;
TINS_BEGIN_PACK
struct un_control_field {
uint8_t mod_func2:3,
poll_final_bit:1,
mod_func1:2,
type_bits:2;
} __attribute__((__packed__));
} TINS_END_PACK;
#endif
typedef std::vector<uint8_t> field_type;
void copy_fields(const LLC *other);
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
llchdr _header;
@@ -384,6 +397,6 @@ namespace Tins {
std::list<field_type> information_fields;
};
};
}
#endif // TINS_IEEE8022_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,6 +31,7 @@
#define TINS_LOOPBACK_H
#include "pdu.h"
#include "macros.h"
namespace Tins {
class Loopback : public PDU {
@@ -46,17 +47,16 @@ public:
* The family identifier is left as zero.
*/
Loopback();
/**
* \brief Construct a Loopback object.
*
* \param family_id The family id to be used.
* \param inner_pdu The inner pdu to be set.
*/
Loopback(uint32_t family_id, PDU *inner_pdu = 0);
/**
* \brief Construct a Loopback object from a buffer.
* \brief Construct a Loopback object from a buffer and adds
* all identifiable PDUs found in the buffer as children of
* this one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for a Loopback header, a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
@@ -84,7 +84,7 @@ public:
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::IP; }
PDUType pdu_type() const { return pdu_flag; }
/**
* \sa PDU::clone
@@ -92,6 +92,13 @@ public:
Loopback *clone() const {
return new Loopback(*this);
}
// Null/Loopback can only be sent in *BSD
#ifdef BSD
/**
* \sa PDU::send()
*/
void send(PacketSender &sender, const NetworkInterface &iface);
#endif // BSD
private:
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);

50
include/macros.h Normal file
View File

@@ -0,0 +1,50 @@
/*
* Copyright (c) 2012, 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_MACROS_H
#define TINS_MACROS_H
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <sys/param.h>
#endif
// Packing directives....
#ifdef _MSC_VER
#define TINS_BEGIN_PACK __pragma( pack(push, 1) )
#define TINS_END_PACK __pragma( pack(pop) )
#define TINS_PACKED(DECLARATION) __pragma( pack(push, 1) ) DECLARATION __pragma( pack(pop) )
#define TINS_DEPRECATED(func) __declspec(deprecated) func
#else
#define TINS_BEGIN_PACK
#define TINS_END_PACK __attribute__((packed))
#define TINS_PACKED(DECLARATION) DECLARATION __attribute__((packed))
#define TINS_DEPRECATED(func) func __attribute__ ((deprecated))
#endif
#endif

View File

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

292
include/packet.h Normal file
View File

@@ -0,0 +1,292 @@
/*
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_PACKET_H
#define TINS_PACKET_H
#include <algorithm>
#include "cxxstd.h"
#include "pdu.h"
#include "timestamp.h"
/**
* \namespace Tins
*/
namespace Tins {
template<typename WrappedType, typename TimestampType>
class PacketWrapper;
/**
* \brief Thin wrapper over a PDU and Timestamp reference.
*/
typedef PacketWrapper<PDU&, const Timestamp&> RefPacket;
/**
* \brief Thin wrapper over a PDU pointer and a Timestamp.
*/
typedef PacketWrapper<PDU*, Timestamp> PtrPacket;
/**
* \brief Represents a sniffed packet.
*
* RefPackets contain a PDU reference and a timestamp. The difference between
* this class and the Packet class is that this one contains a reference
* to a PDU, and not a pointer to one.
*
* This class is only used in some BaseSniffer methods as a thin wrapper
* to a PDU pointer/reference. Only BaseSniffer and derived objects can
* create instances of it.
*/
template<typename PDUType, typename TimestampType>
class PacketWrapper {
public:
typedef PDUType pdu_type;
typedef TimestampType timestamp_type;
/**
* \brief User defined conversion to wrapped_type.
*
* This conversion is defined so that BaseSniffer::sniff_loop callback
* or code that calls BaseSniffer::next_packet can still receive a
* PDU pointer/reference without modifying the code at all.
*/
operator pdu_type() {
return pdu_;
}
/**
* \brief Returns the wrapped_type.
*/
pdu_type pdu() {
return pdu_;
}
/**
* \brief Returns the PDU const reference.
*/
const pdu_type pdu() const {
return pdu_;
}
/**
* \brief Returns the packet timestamp.
*
* This is the timestamp in which the packet was taken out of the
* network interface/pcap file.
*/
const Timestamp &timestamp() const {
return ts_;
}
private:
friend class BaseSniffer;
PacketWrapper(pdu_type pdu, const Timestamp &ts)
: pdu_(pdu), ts_(ts) {}
PacketWrapper(const PacketWrapper&);
PacketWrapper& operator=(const PacketWrapper&);
void* operator new (size_t size);
void operator delete (void *p);
pdu_type pdu_;
timestamp_type ts_;
};
/**
* \class Represents a sniffed packet.
*
* A Packet contains a PDU pointer and a Timestamp object. Packets
* <b>will delete</b> the stored PDU* unless you call release_pdu at
* some point before destruction.
*/
class Packet {
public:
/**
* \brief Default constructs a Packet.
*
* The PDU* will be set to a null pointer.
*/
Packet()
: pdu_(0) { }
/**
* \brief Constructs a Packet from a PDU* and a Timestamp.
*
* The PDU* is cloned using PDU::clone.
*/
Packet(const PDU *apdu, const Timestamp &tstamp)
: pdu_(apdu->clone()), ts(tstamp) { }
/**
* \brief Constructs a Packet from a const PDU&.
*
* The timestamp will be set to the current time.
*
* This calls PDU::clone on the PDU parameter.
*
*/
Packet(const PDU &rhs)
: pdu_(rhs.clone()), ts(Timestamp::current_time()) { }
/**
* \brief Constructs a Packet from a RefPacket.
*
* This calls PDU::clone on the RefPacket's PDU.
*
*/
Packet(const RefPacket &pck)
: pdu_(pck.pdu().clone()), ts(pck.timestamp()) { }
/**
* \brief Constructs a Packet from a PtrPacket object.
*/
Packet(const PtrPacket &pck)
: pdu_(pck.pdu()), ts(pck.timestamp()) { }
/**
* \brief Copy constructor.
*
* This calls PDU::clone on the rhs's PDU* member.
*/
Packet(const Packet &rhs) : ts(rhs.timestamp()) {
pdu_ = rhs.pdu() ? rhs.pdu()->clone() : 0;
}
/**
* \brief Copy assignment operator.
*
* This calls PDU::clone on the rhs's PDU* member.
*/
Packet& operator=(const Packet &rhs) {
if(this != &rhs) {
delete pdu_;
ts = rhs.timestamp();
pdu_ = rhs.pdu() ? rhs.pdu()->clone() : 0;
}
return *this;
}
#if TINS_IS_CXX11
/**
* Move constructor.
*/
Packet(Packet &&rhs) noexcept : pdu_(rhs.pdu()), ts(rhs.timestamp()) {
rhs.pdu_ = nullptr;
}
/**
* Move assignment operator.
*/
Packet& operator=(Packet &&rhs) noexcept {
if(this != &rhs) {
std::swap(pdu_, rhs.pdu_);
ts = rhs.timestamp();
}
return *this;
}
#endif
/**
* \brief Packet destructor.
*
* This calls operator delete on the stored PDU*.
*/
~Packet() {
delete pdu_;
}
/**
* Returns this Packet's timestamp.
*/
const Timestamp &timestamp() const {
return ts;
}
/**
* \brief Returns the stored PDU*.
*
* Caller <b>must not</b> delete the pointer. \sa Packet::release_pdu
*/
PDU *pdu() {
return pdu_;
}
/**
* \brief Returns the stored PDU*.
*
* Caller <b>must not</b> delete the pointer. \sa Packet::release_pdu
*/
const PDU *pdu() const {
return pdu_;
}
/**
* \brief Releases ownership of the stored PDU*.
*
* This method returns the stored PDU* and sets the stored PDU* to
* a null pointer, so the destructor will be well behaved. Use this
* method if you want to keep the internal PDU* somewhere. Otherwise,
* when Packet's destructor is called, the stored pointer will be
* deleted.
*/
PDU *release_pdu() {
PDU *some_pdu = pdu_;
pdu_ = 0;
return some_pdu;
}
/**
* \brief Tests whether this is Packet contains a valid PDU.
*
* \return true if pdu() == nullptr, false otherwise.
*/
operator bool() const {
return bool(pdu_);
}
/**
*
* \brief Concatenation operator.
*
* Adds the PDU at the end of the PDU stack.
*
* \param rhs The PDU to be appended.
*/
Packet &operator/=(const PDU &rhs) {
pdu_ /= rhs;
return *this;
}
private:
PDU *pdu_;
Timestamp ts;
};
}
#endif // TINS_PACKET_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,12 +36,16 @@
#include <vector>
#include <stdint.h>
#include <map>
#include "network_interface.h"
#include "macros.h"
#include "cxxstd.h"
struct timeval;
struct sockaddr;
namespace Tins {
class PDU;
/**
* \brief Class that enables sending the created PDUs
*
@@ -60,18 +64,55 @@ namespace Tins {
*/
enum SocketType {
ETHER_SOCKET,
IP_SOCKET,
IP_TCP_SOCKET,
IP_UDP_SOCKET,
IP_RAW_SOCKET,
ARP_SOCKET,
ICMP_SOCKET,
IPV6_SOCKET,
SOCKETS_END
};
/**
* \brief Constructor for PacketSender objects.
*
* \param iface The default interface in which to send the packets.
* \param recv_timeout The timeout which will be used when receiving responses.
*/
PacketSender(uint32_t recv_timeout = DEFAULT_TIMEOUT, uint32_t usec = 0);
PacketSender(const NetworkInterface &iface = NetworkInterface(),
uint32_t recv_timeout = DEFAULT_TIMEOUT, uint32_t usec = 0);
#if TINS_IS_CXX11
/**
* \brief Move constructor.
* \param rhs The sender to be moved.
*/
PacketSender(PacketSender &&rhs) noexcept {
*this = std::move(rhs);
}
/**
* \brief Move assignment operator.
* \param rhs The sender to be moved.
*/
PacketSender& operator=(PacketSender &&rhs) noexcept {
_sockets = std::move(rhs._sockets);
rhs._sockets = std::vector<int>(SOCKETS_END, INVALID_RAW_SOCKET);
#ifndef WIN32
#if defined(BSD) || defined(__FreeBSD_kernel__)
_ether_socket = std::move(rhs._ether_socket);
#else
_ether_socket = rhs._ether_socket;
rhs._ether_socket = INVALID_RAW_SOCKET;
#endif
#endif
_types = rhs._types; // no move
_timeout = rhs._timeout;
_timeout_usec = rhs._timeout_usec;
default_iface = rhs.default_iface;
return *this;
}
#endif
/**
* \brief PacketSender destructor.
@@ -84,18 +125,18 @@ namespace Tins {
/**
* \brief Opens a layer 2 socket.
*
* If this operation fails, then a SocketOpenError will be thrown.
* If this operation fails, then a socket_open_error will be thrown.
*/
void open_l2_socket();
void open_l2_socket(const NetworkInterface& iface = NetworkInterface());
#endif // WIN32
/**
* \brief Opens a layer 3 socket, using the corresponding protocol
* for the given flag.
*
* If this operation fails, then a SocketOpenError will be thrown.
* If the provided socket type is not valid, a InvalidSocketTypeError
* will be throw.
* If this operation fails, then a socket_open_error will be thrown.
* If the provided socket type is not valid, an invalid_socket_type
* exception will be throw.
*
* \param type The type of socket which will be used to pick the protocol flag
* for this socket.
@@ -106,14 +147,29 @@ namespace Tins {
* \brief Closes the socket associated with the given flag.
*
* If the provided type is invalid, meaning no such open socket
* exists, a InvalidSocketTypeError is thrown.
* exists, an invalid_socket_type exception is thrown.
*
* If any socket close errors are encountered, a SocketCloseError
* If any socket close errors are encountered, a socket_close_error
* is thrown.
*
* \param type The type of the socket to be closed.
*/
void close_socket(SocketType type);
void close_socket(SocketType type, const NetworkInterface &iface = NetworkInterface());
/**
* \brief Sets the default interface.
*
* The interface will be used whenever PacketSender::send(PDU&)
* is called.
*/
void default_interface(const NetworkInterface &iface);
/**
* \brief Gets the default interface.
*
* \sa PacketSender::default_interface
*/
const NetworkInterface& default_interface() const;
/**
* \brief Sends a PDU.
@@ -121,11 +177,33 @@ namespace Tins {
* This method opens the appropriate socket, if it's not open yet,
* and sends the PDU on the open socket.
*
* If any send error occurs, then a SocketWriteError is thrown.
* If any send error occurs, then a socket_write_error is thrown.
*
* If the PDU contains a link layer protocol, then default_interface
* is used.
*
* \sa PacketSender::default_interface
*
* \param pdu The PDU to be sent.
*/
void send(PDU &pdu);
/**
* \brief Sends a PDU.
*
* \sa PacketSender::send
*
* This overload takes a NetworkInterface. The packet is sent
* through that interface if a link-layer PDU is present,
* otherwise this call is equivalent to send(PDU&).
*
* The interface stored in the link layer PDU(if any), is restored
* after this method ends.
*
* \param pdu The PDU to be sent.
* \param iface The network interface to use.
*/
void send(PDU &pdu, const NetworkInterface &iface);
/**
* \brief Sends a PDU and waits for its response.
@@ -139,6 +217,20 @@ namespace Tins {
* \return Returns the response PDU, 0 if not response was received.
*/
PDU *send_recv(PDU &pdu);
/**
* \brief Sends a PDU and waits for its response.
*
* This method is used to send PDUs and receive their response.
* It opens the required socket(if it's not open yet). This can be used
* to expect responses for ICMP, ARP, and such packets that are normally
* answered by the host that receives the packet.
*
* \param pdu The PDU to send.
* \param iface The network interface in which to send and receive.
* \return Returns the response PDU, 0 if not response was received.
*/
PDU *send_recv(PDU &pdu, const NetworkInterface &iface);
#ifndef WIN32
/**
@@ -152,7 +244,8 @@ namespace Tins {
* \param len_addr The sockaddr struct length.
* \return Returns the response PDU. If no response is received, then 0 is returned.
*/
PDU *recv_l2(PDU &pdu, struct sockaddr *link_addr, uint32_t len_addr);
PDU *recv_l2(PDU &pdu, struct sockaddr *link_addr, uint32_t len_addr,
const NetworkInterface &iface = NetworkInterface());
/**
* \brief Sends a level 2 PDU.
@@ -161,13 +254,14 @@ namespace Tins {
* using the corresponding flag, according to the given type of
* protocol.
*
* If any socket write error occurs, a SocketWriteError is thrown.
* If any socket write error occurs, a socket_write_error is thrown.
*
* \param pdu The PDU to send.
* \param link_addr The sockaddr struct which will be used to send the PDU.
* \param len_addr The sockaddr struct length.
*/
void send_l2(PDU &pdu, struct sockaddr* link_addr, uint32_t len_addr);
void send_l2(PDU &pdu, struct sockaddr* link_addr, uint32_t len_addr,
const NetworkInterface &iface = NetworkInterface());
#endif // WIN32
/**
@@ -190,7 +284,7 @@ namespace Tins {
* This method sends a layer 3 PDU, using a raw socket, open using the corresponding flag,
* according to the given type of protocol.
*
* If any socket write error occurs, a SocketWriteError is thrown.
* If any socket write error occurs, a socket_write_error is thrown.
*
* \param pdu The PDU to send.
* \param link_addr The sockaddr struct which will be used to send the PDU.
@@ -203,41 +297,35 @@ namespace Tins {
typedef std::map<SocketType, int> SocketTypeMap;
PacketSender(const PacketSender&);
PacketSender& operator=(const PacketSender&);
int find_type(SocketType type);
int timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y);
#ifndef WIN32
bool ether_socket_initialized(const NetworkInterface& iface = NetworkInterface()) const;
int get_ether_socket(const NetworkInterface& iface = NetworkInterface());
#endif
template<typename T>
void send(PDU &pdu, const NetworkInterface &iface) {
static_cast<T&>(pdu).send(*this, iface);
}
PDU *recv_match_loop(int sock, PDU &pdu, struct sockaddr* link_addr, uint32_t addrlen);
PDU *recv_match_loop(const std::vector<int>& sockets, PDU &pdu, struct sockaddr* link_addr,
uint32_t addrlen);
std::vector<int> _sockets;
#ifndef WIN32
#if defined(BSD) || defined(__FreeBSD_kernel__)
typedef std::map<uint32_t, int> BSDEtherSockets;
BSDEtherSockets _ether_socket;
#else
int _ether_socket;
#endif
#endif
SocketTypeMap _types;
uint32_t _timeout, _timeout_usec;
NetworkInterface default_iface;
};
class SocketOpenError : public std::runtime_error {
public:
SocketOpenError(const std::string &msg)
: std::runtime_error(msg) { }
};
class SocketCloseError : public std::runtime_error {
public:
SocketCloseError(const std::string &msg)
: std::runtime_error(msg) { }
};
class SocketWriteError : public std::runtime_error {
public:
SocketWriteError(const std::string &msg)
: std::runtime_error(msg) { }
};
class InvalidSocketTypeError : public std::exception {
public:
const char *what() const throw() {
return "The provided socket type is invalid";
}
};
};
}
#endif // TINS_PACKET_SENDER_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,6 +34,7 @@
#include <iterator>
#include <pcap.h>
#include "utils.h"
#include "cxxstd.h"
namespace Tins {
class PDU;
@@ -53,7 +54,9 @@ public:
enum LinkType {
RADIOTAP = DLT_IEEE802_11_RADIO,
DOT11 = DLT_IEEE802_11,
ETH2 = DLT_EN10MB
ETH2 = DLT_EN10MB,
DOT3 = DLT_EN10MB,
SLL = DLT_LINUX_SLL
};
/**
@@ -64,6 +67,36 @@ public:
*/
PacketWriter(const std::string &file_name, LinkType lt);
#if TINS_IS_CXX11
/**
* \brief Move constructor.
*
* Note that calling PacketWriter::write on an previously moved
* object will lead to undefined behaviour.
*
* \param rhs The PacketWriter to be moved.
*/
PacketWriter(PacketWriter &&rhs) noexcept {
*this = std::move(rhs);
}
/**
* \brief Move assignment operator.
*
* Note that calling PacketWriter::write on an previously moved
* object will lead to undefined behaviour.
*
* \param rhs The PacketWriter to be moved.
*/
PacketWriter& operator=(PacketWriter &&rhs) noexcept {
handle = 0;
dumper = 0;
std::swap(handle, rhs.handle);
std::swap(dumper, rhs.dumper);
return *this;
}
#endif
/**
* Destructor.
*/
@@ -74,6 +107,18 @@ public:
*/
void write(PDU &pdu);
/**
* \brief Writes a PDU to this file.
*
* The template parameter T must at some point yield a PDU& after
* applying operator* one or more than one time. This accepts both
* raw and smart pointers.
*/
template<typename T>
void write(T &pdu) {
write(Utils::dereference_until_pdu(pdu));
}
/**
* \brief Writes all the PDUs in the range [start, end)
* \param start A forward iterator pointing to the first PDU

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,12 +33,21 @@
#include <stdint.h>
#include <vector>
#include "macros.h"
#include "cxxstd.h"
#include "exceptions.h"
/** \brief The Tins namespace.
*/
namespace Tins {
class PacketSender;
class NetworkInterface;
/**
* The type used to store several PDU option values.
*/
typedef std::vector<uint8_t> byte_array;
/** \brief Base class for protocol data units.
*
@@ -54,7 +63,15 @@ namespace Tins {
/**
* The type that will be returned when serializing PDUs.
*/
typedef std::vector<uint8_t> serialization_type;
typedef byte_array serialization_type;
/**
* The typep used to identify the endianness of every PDU.
*/
enum endian_type {
BE,
LE
};
/**
* \brief Enum which identifies each type of PDU.
@@ -101,18 +118,56 @@ namespace Tins {
RC4EAPOL,
RSNEAPOL,
DNS,
LOOPBACK
LOOPBACK,
IPv6,
ICMPv6,
SLL,
DHCPv6,
DOT1Q,
PPPOE,
STP,
PPI,
IPSEC_AH,
IPSEC_ESP,
USER_DEFINED_PDU = 1000
};
/** \brief PDU constructor
*
* Must be called by subclasses in their constructors.
* \param flag The flag identifier for the subclass' PDU.
* \param next_pdu The child PDU. Can be obviated.
/**
* The endianness used by this PDU. This can be overriden
* by subclasses.
*/
PDU(PDU *next_pdu = 0);
static const endian_type endianness = BE;
/** \brief PDU destructor.
/**
* \brief Default constructor.
*/
PDU();
#if TINS_IS_CXX11
/**
* \brief Move constructor.
*
* \param rhs The PDU to be moved.
*/
PDU(PDU &&rhs) noexcept
: _inner_pdu(0)
{
std::swap(_inner_pdu, rhs._inner_pdu);
}
/**
* \brief Move assignment operator.
*
* \param rhs The PDU to be moved.
*/
PDU& operator=(PDU &&rhs) noexcept {
std::swap(_inner_pdu, rhs._inner_pdu);
return *this;
}
#endif
/**
* \brief PDU destructor.
*
* Deletes the inner pdu, as a consequence every child pdu is
* deleted.
@@ -159,11 +214,21 @@ namespace Tins {
/**
* \brief Sets the child PDU.
*
* \param next_pdu The new child PDU.
* When setting a new inner_pdu, the instance takesownership of
* the object, therefore deleting it when it's no longer required.
*
* \param next_pdu The new child PDU.
*/
void inner_pdu(PDU *next_pdu);
/**
* \brief Sets the child PDU.
*
* The PDU parameter is cloned using PDU::clone.
*
* \param next_pdu The new child PDU.
*/
void inner_pdu(const PDU &next_pdu);
/**
@@ -178,14 +243,14 @@ namespace Tins {
serialization_type serialize();
/**
* \brief Find and returns the first PDU that matches the given flag.
* \brief Finds and returns the first PDU that matches the given flag.
*
* This method searches for the first PDU which has the same type flag as
* the given one. If the first PDU matches that flag, it is returned.
* If no PDU matches, 0 is returned.
* \param flag The flag which being searched.
*/
template<class T>
template<typename T>
T *find_pdu(PDUType type = T::pdu_flag) {
PDU *pdu = this;
while(pdu) {
@@ -195,6 +260,43 @@ namespace Tins {
}
return 0;
}
/**
* \brief Finds and returns the first PDU that matches the given flag.
*
* \param flag The flag which being searched.
*/
template<typename T>
const T *find_pdu(PDUType type = T::pdu_flag) const {
return const_cast<PDU*>(this)->find_pdu<T>();
}
/**
* \brief Finds and returns the first PDU that matches the given flag.
*
* If the PDU is not found, a pdu_not_found exception is thrown.
*
* \sa PDU::find_pdu
*
* \param flag The flag which being searched.
*/
template<typename T>
T &rfind_pdu(PDUType type = T::pdu_flag) {
T *ptr = find_pdu<T>(type);
if(!ptr)
throw pdu_not_found();
return *ptr;
}
/**
* \brief Finds and returns the first PDU that matches the given flag.
*
* \param flag The flag which being searched.
*/
template<typename T>
const T &rfind_pdu(PDUType type = T::pdu_flag) const {
return const_cast<PDU*>(this)->rfind_pdu<T>();
}
/**
* \brief Clones this packet.
@@ -206,25 +308,37 @@ namespace Tins {
*/
virtual PDU *clone() const = 0;
/** \brief Send the stack of PDUs through a PacketSender.
/**
* \brief Send the stack of PDUs through a PacketSender.
*
* This method will be called only for the PDU on the bottom of the stack,
* therefore it should only implement this method if it can be sent.
*
* PacketSender implements specific methods to send packets which start
* on every valid TCP/IP stack layer; this should only be a proxy for
* those methods.
*
* If this PDU does not represent a link layer protocol, then
* the interface argument will be ignored.
*
* \param sender The PacketSender which will send the packet.
* \param iface The network interface in which this packet will
* be sent.
*/
virtual void send(PacketSender &sender);
virtual void send(PacketSender &sender, const NetworkInterface &iface);
/** \brief Receives a matching response for this packet.
/**
* \brief Receives a matching response for this packet.
*
* This method should act as a proxy for PacketSender::recv_lX methods.
*
* \param sender The packet sender which will receive the packet.
* \param iface The interface in which to expect the response.
*/
virtual PDU *recv_response(PacketSender &sender);
virtual PDU *recv_response(PacketSender &sender, const NetworkInterface &iface);
/** \brief Check wether ptr points to a valid response for this PDU.
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* This method must check wether the buffer pointed by ptr is a valid
* response for this PDU. If it is valid, then it might want to propagate
@@ -233,7 +347,9 @@ namespace Tins {
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
virtual bool matches_response(uint8_t *ptr, uint32_t total_sz) { return false; }
virtual bool matches_response(const uint8_t *ptr, uint32_t total_sz) const {
return false;
}
/**
* \brief Check wether this PDU matches the specified flag.
@@ -243,7 +359,7 @@ namespace Tins {
* classes' flag.
* \param flag The flag to match.
*/
virtual bool matches_flag(PDUType flag) {
virtual bool matches_flag(PDUType flag) const {
return flag == pdu_type();
}
@@ -253,15 +369,6 @@ namespace Tins {
* \return Returns the PDUType corresponding to the PDU.
*/
virtual PDUType pdu_type() const = 0;
/** \brief Clones this pdu, filling the corresponding header with data
* extracted from a buffer.
*
* \param ptr The pointer to the from from which the data will be extracted.
* \param total_sz The size of the buffer.
* \return The cloned PDU.
*/
virtual PDU *clone_packet(const uint8_t *ptr, uint32_t total_sz) { return 0; }
protected:
/**
* \brief Copy constructor.
@@ -279,6 +386,20 @@ namespace Tins {
*/
void copy_inner_pdu(const PDU &pdu);
/**
* \brief Prepares this PDU for serialization.
*
* This method is called before the inner PDUs are serialized.
* It's useful in situations such as when serializing IP PDUs,
* which don't contain any link layer encapsulation, and therefore
* require to set the source IP address before the TCP/UDP checksum
* is calculated.
*
* By default, this method does nothing
*
* \param parent The parent PDU.
*/
virtual void prepare_for_serialize(const PDU *parent) { }
/**
* \brief Serializes this PDU and propagates this action to child PDUs.
@@ -289,16 +410,6 @@ namespace Tins {
*/
void serialize(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
/**
* \brief Clones the inner pdu(if any).
*
* This method clones the inner pdu using data from a buffer.
* \param ptr The pointer from which the child PDU must be cloned.
* \param total_sz The total size of the buffer.
* \return Returns the cloned PDU. Will be 0 if cloning failed.
*/
PDU *clone_inner_pdu(const uint8_t *ptr, uint32_t total_sz);
/**
* \brief Serializes this TCP PDU.
*
@@ -350,6 +461,45 @@ namespace Tins {
lop /= rop;
return lop;
}
};
/**
* \brief Concatenation operator on PDU pointers.
*
* \sa operator/=
*/
template<typename T>
T *operator/= (T* lop, const PDU &rop) {
*lop /= rop;
return lop;
}
namespace Internals {
template<typename T>
struct remove_pointer {
typedef T type;
};
template<typename T>
struct remove_pointer<T*> {
typedef T type;
};
}
template<typename T, typename U>
T tins_cast(U *pdu) {
typedef typename Internals::remove_pointer<T>::type TrueT;
return pdu && (TrueT::pdu_flag == pdu->pdu_type()) ?
static_cast<T>(pdu) :
0;
}
template<typename T, typename U>
T &tins_cast(U &pdu) {
T *ptr = tins_cast<T*>(&pdu);
if(!ptr)
throw bad_tins_cast();
return *ptr;
}
}
#endif // TINS_PDU_H

182
include/pdu_allocator.h Normal file
View File

@@ -0,0 +1,182 @@
/*
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_PDU_ALLOCATOR_H
#define TINS_PDU_ALLOCATOR_H
#include <map>
#include "pdu.h"
namespace Tins {
/**
* \cond
*/
class EthernetII;
class SNAP;
class Dot1Q;
class SLL;
class IP;
class IPv6;
namespace Internals {
template<typename PDUType>
PDU *default_allocator(const uint8_t *buffer, uint32_t size)
{
return new PDUType(buffer, size);
}
template<typename Tag>
class PDUAllocator {
public:
typedef typename Tag::identifier_type id_type;
typedef PDU *(*allocator_type)(const uint8_t *, uint32_t);
template<typename PDUType>
static void register_allocator(id_type identifier)
{
allocators[identifier] = &default_allocator<PDUType>;
pdu_types[PDUType::pdu_flag] = identifier;
}
static PDU *allocate(id_type identifier, const uint8_t *buffer, uint32_t size)
{
typename allocators_type::const_iterator it = allocators.find(identifier);
return (it == allocators.end()) ? 0 : (*it->second)(buffer, size);
}
static bool pdu_type_registered(PDU::PDUType type)
{
return pdu_types.count(type) != 0;
}
static id_type pdu_type_to_id(PDU::PDUType type)
{
typename pdu_map_types::const_iterator it = pdu_types.find(type);
return it->second;
}
private:
typedef std::map<id_type, allocator_type> allocators_type;
typedef std::map<PDU::PDUType, id_type> pdu_map_types;
static allocators_type allocators;
static pdu_map_types pdu_types;
};
template<typename Tag>
typename PDUAllocator<Tag>::allocators_type PDUAllocator<Tag>::allocators;
template<typename Tag>
typename PDUAllocator<Tag>::pdu_map_types PDUAllocator<Tag>::pdu_types;
template<typename IDType>
struct pdu_tag {
typedef IDType identifier_type;
};
template<typename PDUType>
struct pdu_tag_mapper;
#define TINS_GENERATE_TAG_MAPPER(pdu, id_type) \
template<> \
struct pdu_tag_mapper<pdu> { \
typedef pdu_tag<id_type> type; \
};
TINS_GENERATE_TAG_MAPPER(EthernetII, uint16_t)
TINS_GENERATE_TAG_MAPPER(SNAP, uint16_t)
TINS_GENERATE_TAG_MAPPER(SLL, uint16_t)
TINS_GENERATE_TAG_MAPPER(Dot1Q, uint16_t)
TINS_GENERATE_TAG_MAPPER(IP, uint8_t)
TINS_GENERATE_TAG_MAPPER(IPv6, uint8_t)
#undef TINS_GENERATE_TAG_MAPPER
template<typename PDUType>
PDU* allocate(
typename pdu_tag_mapper<PDUType>::type::identifier_type id,
const uint8_t *buffer,
uint32_t size)
{
return PDUAllocator<typename pdu_tag_mapper<PDUType>::type>::allocate(id, buffer, size);
}
template<typename PDUType>
bool pdu_type_registered(PDU::PDUType type)
{
return PDUAllocator<typename pdu_tag_mapper<PDUType>::type>::pdu_type_registered(type);
}
template<typename PDUType>
typename pdu_tag_mapper<PDUType>::type::identifier_type pdu_type_to_id(PDU::PDUType type)
{
return PDUAllocator<typename pdu_tag_mapper<PDUType>::type>::pdu_type_to_id(type);
}
} // namespace Interals
/**
* \endcond
*/
/**
* \brief Defines inner PDU allocators.
*/
namespace Allocators {
/**
* \brief Registers an allocator for the provided PDU type.
*
* Registering a certain allocator for a PDU type is useful for
* extending the library. Once an allocator is registered, it will
* be taken into account while constructing a PDU from a buffer.
*
* If PDU finds that it cannot define which is the protocol
* that should be allocated based on its protocol identifier, it
* will try using the registered allocators if any.
*
* \code
* // Register the 0x666 identifer. Now if EthernetII finds a
* // network layer identifier field whose value is 0x666, it will
* // use SomePDUType as its inner PDU type.
* Allocators::register_allocator<EthernetII, SomePDUType>(0x666);
* \endcode
*
* Note that some PDU types are grouped together. For example,
* registering an allocator for EthernetII will make it work for
* the rest of the link layer protocols, sine they should all work
* the same way.
*/
template<typename PDUType, typename AllocatedType>
void register_allocator(typename Internals::pdu_tag_mapper<PDUType>::type::identifier_type id)
{
Internals::PDUAllocator<
typename Internals::pdu_tag_mapper<PDUType>::type
>::template register_allocator<AllocatedType>(id);
}
} // namespace Allocators
} // namespace Tins
#endif // TINS_PDU_ALLOCATOR_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,6 +32,7 @@
#include <algorithm>
#include "pdu.h"
#include "macros.h"
namespace Tins {
/**
@@ -94,28 +95,28 @@ public:
/**
* Forwards the call to the cached PDU. \sa PDU::send.
*/
void send(PacketSender &sender) {
cached.send(sender);
void send(PacketSender &sender, const NetworkInterface &iface) {
cached.send(sender, iface);
}
/**
* Forwards the call to the cached PDU. \sa PDU::recv_responde.
*/
PDU *recv_response(PacketSender &sender) {
return cached.recv_response(sender);
PDU *recv_response(PacketSender &sender, const NetworkInterface &iface) {
return cached.recv_response(sender, iface);
}
/**
* Forwards the call to the cached PDU. \sa PDU::matches_response.
*/
bool matches_response(uint8_t *ptr, uint32_t total_sz) {
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const {
return cached.matches_response(ptr, total_sz);
}
/**
* Forwards the call to the cached PDU. \sa PDU::matches_flag.
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return cached.matches_flag(flag);
}
@@ -125,13 +126,6 @@ public:
PDUType pdu_type() const {
return cached.pdu_type();
}
/**
* Forwards the call to the cached PDU. \sa PDU::clone_packet.
*/
PDU *clone_packet(const uint8_t *ptr, uint32_t total_sz) {
return cached.clone_packet(ptr, total_sz);
}
private:
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
if(cached_serialization.size() != total_sz) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,19 +32,259 @@
#include <vector>
#include <iterator>
#include <algorithm>
#include <string>
#include <stdint.h>
#include "exceptions.h"
#include "endianness.h"
#include "internals.h"
#include "ip_address.h"
#include "ipv6_address.h"
#include "hw_address.h"
namespace Tins {
/**
* \brief Exception thrown when an option is not found.
* \cond
*/
class option_not_found : public std::exception {
public:
const char* what() const throw() {
return "Option not found";
template<typename OptionType, class PDUType>
class PDUOption;
namespace Internals {
template<typename T, typename X, typename PDUType>
T convert_to_integral(const PDUOption<X, PDUType> & opt) {
if(opt.data_size() != sizeof(T))
throw malformed_option();
T data = *(T*)opt.data_ptr();
if(PDUType::endianness == PDUType::BE)
data = Endian::be_to_host(data);
else
data = Endian::le_to_host(data);
return data;
}
};
template<typename T, typename = void>
struct converter {
template<typename X, typename PDUType>
static T convert(const PDUOption<X, PDUType>& opt) {
return T::from_option(opt);
}
};
template<>
struct converter<uint8_t> {
template<typename X, typename PDUType>
static uint8_t convert(const PDUOption<X, PDUType>& opt) {
if(opt.data_size() != 1)
throw malformed_option();
return *opt.data_ptr();
}
};
template<>
struct converter<uint16_t> {
template<typename X, typename PDUType>
static uint16_t convert(const PDUOption<X, PDUType>& opt) {
return convert_to_integral<uint16_t>(opt);
}
};
template<>
struct converter<uint32_t> {
template<typename X, typename PDUType>
static uint32_t convert(const PDUOption<X, PDUType>& opt) {
return convert_to_integral<uint32_t>(opt);
}
};
template<>
struct converter<uint64_t> {
template<typename X, typename PDUType>
static uint64_t convert(const PDUOption<X, PDUType>& opt) {
return convert_to_integral<uint64_t>(opt);
}
};
template<size_t n>
struct converter<HWAddress<n> > {
template<typename X, typename PDUType>
static HWAddress<n> convert(const PDUOption<X, PDUType>& opt) {
if(opt.data_size() != n)
throw malformed_option();
return HWAddress<n>(opt.data_ptr());
}
};
template<>
struct converter<IPv4Address> {
template<typename X, typename PDUType>
static IPv4Address convert(const PDUOption<X, PDUType>& opt) {
if(opt.data_size() != sizeof(uint32_t))
throw malformed_option();
const uint32_t *ptr = (const uint32_t*)opt.data_ptr();
if(PDUType::endianness == PDUType::BE)
return IPv4Address(*ptr);
else
return IPv4Address(Endian::change_endian(*ptr));
}
};
template<>
struct converter<IPv6Address> {
template<typename X, typename PDUType>
static IPv6Address convert(const PDUOption<X, PDUType>& opt) {
if(opt.data_size() != IPv6Address::address_size)
throw malformed_option();
return IPv6Address(opt.data_ptr());
}
};
template<>
struct converter<std::string> {
template<typename X, typename PDUType>
static std::string convert(const PDUOption<X, PDUType>& opt) {
return std::string(
opt.data_ptr(),
opt.data_ptr() + opt.data_size()
);
}
};
template<>
struct converter<std::vector<float> > {
template<typename X, typename PDUType>
static std::vector<float> convert(const PDUOption<X, PDUType>& opt) {
std::vector<float> output;
const uint8_t *ptr = opt.data_ptr(), *end = ptr + opt.data_size();
while(ptr != end) {
output.push_back(float(*(ptr++) & 0x7f) / 2);
}
return output;
}
};
template<typename T>
struct converter<std::vector<T>, typename enable_if<is_unsigned_integral<T>::value>::type> {
template<typename X, typename PDUType>
static std::vector<T> convert(const PDUOption<X, PDUType>& opt) {
if(opt.data_size() % sizeof(T) != 0)
throw malformed_option();
const T *ptr = (const T*)opt.data_ptr();
const T *end = (const T*)(opt.data_ptr() + opt.data_size());
std::vector<T> output(std::distance(ptr, end));
typename std::vector<T>::iterator it = output.begin();
while(ptr < end) {
if(PDUType::endianness == PDUType::BE)
*it++ = Endian::be_to_host(*ptr++);
else
*it++ = Endian::le_to_host(*ptr++);
}
return output;
}
};
template<typename T, typename U>
struct converter<
std::vector<std::pair<T, U> >,
typename enable_if<
is_unsigned_integral<T>::value && is_unsigned_integral<U>::value
>::type
> {
template<typename X, typename PDUType>
static std::vector<std::pair<T, U> > convert(const PDUOption<X, PDUType>& opt) {
if(opt.data_size() % (sizeof(T) + sizeof(U)) != 0)
throw malformed_option();
const uint8_t *ptr = opt.data_ptr(), *end = ptr + opt.data_size();
std::vector<std::pair<T, U> > output;
while(ptr < end) {
std::pair<T, U> data;
data.first = *(const T*)ptr;
ptr += sizeof(T);
data.second = *(const U*)ptr;
ptr += sizeof(U);
if(PDUType::endianness == PDUType::BE) {
data.first = Endian::be_to_host(data.first);
data.second = Endian::be_to_host(data.second);
}
else {
data.first = Endian::le_to_host(data.first);
data.second = Endian::le_to_host(data.second);
}
output.push_back(data);
}
return output;
}
};
template<>
struct converter<std::vector<IPv4Address> > {
template<typename X, typename PDUType>
static std::vector<IPv4Address> convert(const PDUOption<X, PDUType>& opt) {
if(opt.data_size() % 4 != 0)
throw malformed_option();
const uint32_t *ptr = (const uint32_t*)opt.data_ptr();
const uint32_t *end = (const uint32_t*)(opt.data_ptr() + opt.data_size());
std::vector<IPv4Address> output(std::distance(ptr, end));
std::vector<IPv4Address>::iterator it = output.begin();
while(ptr < end) {
if(PDUType::endianness == PDUType::BE)
*it++ = IPv4Address(*ptr++);
else
*it++ = IPv4Address(Endian::change_endian(*ptr++));
}
return output;
}
};
template<>
struct converter<std::vector<IPv6Address> > {
template<typename X, typename PDUType>
static std::vector<IPv6Address> convert(const PDUOption<X, PDUType>& opt) {
if(opt.data_size() % IPv6Address::address_size != 0)
throw malformed_option();
const uint8_t *ptr = opt.data_ptr(), *end = opt.data_ptr() + opt.data_size();
std::vector<IPv6Address> output;
while(ptr < end) {
output.push_back(IPv6Address(ptr));
ptr += IPv6Address::address_size;
}
return output;
}
};
template<typename T, typename U>
struct converter<
std::pair<T, U>,
typename enable_if<
is_unsigned_integral<T>::value && is_unsigned_integral<U>::value
>::type
> {
template<typename X, typename PDUType>
static std::pair<T, U> convert(const PDUOption<X, PDUType>& opt) {
if(opt.data_size() != sizeof(T) + sizeof(U))
throw malformed_option();
std::pair<T, U> output;
output.first = *(const T*)opt.data_ptr();
output.second = *(const U*)(opt.data_ptr() + sizeof(T));
if(PDUType::endianness == PDUType::BE) {
output.first = Endian::be_to_host(output.first);
output.second = Endian::be_to_host(output.second);
}
else {
output.first = Endian::le_to_host(output.first);
output.second = Endian::le_to_host(output.second);
}
return output;
}
};
}
/**
* \endcond
*/
/**
* \class PDUOption
* \brief Represents a PDU option field.
@@ -55,16 +295,11 @@ public:
*
* The OptionType template parameter indicates the type that will be
* used to store this option's identifier.
*
* The Container template parameter indicates the container which will
* be used to store this option's data. The container <b>must</b>
* store data sequentially. std::vector<uint8_t> is the default
* container.
*/
template<typename OptionType, class Container = std::vector<uint8_t> >
template<typename OptionType, class PDUType>
class PDUOption {
public:
typedef Container container_type;
typedef std::vector<uint8_t> container_type;
typedef typename container_type::value_type data_type;
typedef OptionType option_type;
@@ -75,10 +310,8 @@ public:
* \param data The option's data(if any).
*/
PDUOption(option_type opt = option_type(), size_t length = 0, const data_type *data = 0)
: option_(opt) {
value_.push_back(length);
if(data)
value_.insert(value_.end(), data, data + length);
: option_(opt), size_(length), value_(data, data + (data ? length : 0)) {
}
/**
@@ -91,9 +324,29 @@ public:
*/
template<typename ForwardIterator>
PDUOption(option_type opt, ForwardIterator start, ForwardIterator end)
: option_(opt) {
value_.push_back(std::distance(start, end));
value_.insert(value_.end(), start, end);
: option_(opt), size_(std::distance(start, end)), value_(start, end) {
}
/**
* \brief Constructs a PDUOption from iterators, which
* indicate the data to be stored in it.
*
* The length parameter indicates the contents of the length field
* when this option is serialized. Note that this can be different
* to std::distance(start, end).
*
* \sa length_field
*
* \param opt The option type.
* \param length The length of this option.
* \param start The beginning of the option data.
* \param end The end of the option data.
*/
template<typename ForwardIterator>
PDUOption(option_type opt, size_t length, ForwardIterator start, ForwardIterator end)
: option_(opt), size_(length), value_(start, end) {
}
/**
@@ -104,6 +357,14 @@ public:
return option_;
}
/**
* Sets this option's type
* \param opt The option type to be set.
*/
void option(option_type opt) {
option_ = opt;
}
/**
* Retrieves this option's data.
*
@@ -111,20 +372,51 @@ public:
* dereferencing the returned pointer will result in undefined
* behaviour.
*
* \return const value_type& containing this option's value.
* \return const data_type& containing this option's value.
*/
const data_type *data_ptr() const {
return &*(++value_.begin());
return &*value_.begin();
}
/**
* Retrieves the length of this option's data.
* \brief Retrieves the length of this option's data.
*
* This is the actual size of the data.
*/
size_t data_size() const {
return value_.empty() ? 0 : (value_.size() - 1);
return value_.size();
}
/**
* \brief Retrieves the data length field.
*
* This is what the size field will contain when this option is
* serialized. It can differ from the actual data size.
*
* This will be equal to data_size unless the constructor that takes
* both a data length and two iterators is used.
*
* \sa data_size.
*/
size_t length_field() const {
return size_;
}
/**
* \brief Constructs a T from this PDUOption.
*
* Use this method to convert a PDUOption to the specific type that
* represents it. For example, if you know an option is of type
* PDU::SACK, you could use option.to<TCP::sack_type>().
*/
template<typename T>
T to() const {
return Internals::converter<T>::convert(*this);
}
private:
option_type option_;
uint16_t size_;
container_type value_;
};
} // namespace Tins

134
include/ppi.h Normal file
View File

@@ -0,0 +1,134 @@
/*
* Copyright (c) 2012, 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_PPI_H
#define TINS_PPI_H
#include "pdu.h"
#include "endianness.h"
#include "small_uint.h"
namespace Tins {
/**
* \brief Represents a Per-Packet Information PDU.
*
* This PDU can only be constructed from a buffer, and
* cannot be serialized. Therefore, it is only useful while
* sniffing packets.
*/
class PPI : public PDU {
public:
/**
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::PPI;
/**
* \brief Constructs an PPI object from a buffer and adds all
* identifiable PDUs found in the buffer as children of this
* one.
*
* If there is not enough size for an PPI header, a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
PPI(const uint8_t *buffer, uint32_t total_sz);
// Getters
/**
* \brief Getter for the version field.
* \return The stored version field value.
*/
uint8_t version() const {
return _header.version;
}
/**
* \brief Getter for the flags field.
* \return The stored flags field value.
*/
uint8_t flags() const {
return _header.flags;
}
/**
* \brief Getter for the length field.
* \return The stored length field value.
*/
uint16_t length() const {
return Endian::le_to_host(_header.length);
}
/**
* \brief Getter for the Data Link Type field.
* \return The stored Data Link Type field value.
*/
uint32_t dlt() const {
return Endian::le_to_host(_header.dlt);
}
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \brief Clones this PDU.
*
* \sa PDU::clone
*/
PPI *clone() const {
return new PPI(*this);
}
private:
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
struct header {
uint8_t version, flags;
uint16_t length;
uint32_t dlt;
};
header _header;
byte_array _data;
};
}
#endif // TINS_PPI_H

430
include/pppoe.h Normal file
View File

@@ -0,0 +1,430 @@
/*
* Copyright (c) 2012, 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_PPPoE_H
#define TINS_PPPoE_H
#include <list>
#include <string>
#include <vector>
#include "pdu.h"
#include "endianness.h"
#include "small_uint.h"
#include "pdu_option.h"
#include "cxxstd.h"
namespace Tins {
class PPPoE : public PDU {
public:
/**
* The tag types enum.
*/
enum TagTypes {
END_OF_LIST = 0,
SERVICE_NAME = 0x101,
#if TINS_IS_LITTLE_ENDIAN
AC_NAME = 0x201,
HOST_UNIQ = 0x301,
AC_COOKIE = 0x401,
VENDOR_SPECIFIC = 0x501,
RELAY_SESSION_ID = 0x101,
SERVICE_NAME_ERROR = 0x201,
AC_SYSTEM_ERROR = 0x202,
GENERIC_ERROR = 0x302
#else
AC_NAME = 0x102,
HOST_UNIQ = 0x103,
AC_COOKIE = 0x104,
VENDOR_SPECIFIC = 0x105,
RELAY_SESSION_ID = 0x110,
SERVICE_NAME_ERROR = 0x201,
AC_SYSTEM_ERROR = 0x202,
GENERIC_ERROR = 0x203
#endif
};
/**
* The type used to store a TLV option.
*/
typedef PDUOption<TagTypes, PPPoE> tag;
/**
* The type used to store the options.
*/
typedef std::list<tag> tags_type;
/**
* The type used to store the Vendor-Specific tag's value.
*/
struct vendor_spec_type {
typedef std::vector<uint8_t> data_type;
uint32_t vendor_id;
data_type data;
vendor_spec_type(uint32_t vendor_id = 0, const data_type &data = data_type())
: vendor_id(vendor_id), data(data) { }
static vendor_spec_type from_option(const tag &opt);
};
/**
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::PPPOE;
/**
* \brief Default constructor.
*
* This sets the version and type fields to 0x1.
*/
PPPoE();
/**
* \brief Constructor which creates an PPPoE object from a buffer.
*
* If there is not enough size for a PPPoE header, a malformed_packet
* exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
PPPoE(const uint8_t *buffer, uint32_t total_sz);
// Getters
/**
* \brief Getter for the version field.
* \return The stored version field value.
*/
small_uint<4> version() const {
return _header.version;
}
/**
* \brief Getter for the type field.
* \return The stored type field value.
*/
small_uint<4> type() const {
return _header.type;
}
/**
* \brief Getter for the code field.
* \return The stored code field value.
*/
uint8_t code() const {
return _header.code;
}
/**
* \brief Getter for the session_id field.
* \return The stored session_id field value.
*/
uint16_t session_id() const {
return Endian::be_to_host(_header.session_id);
}
/**
* \brief Getter for the payload_length field.
* \return The stored payload_length field value.
*/
uint16_t payload_length() const {
return Endian::be_to_host(_header.payload_length);
}
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \brief Returns the list of tags.
*/
const tags_type &tags() const {
return _tags;
}
/**
* \sa PDU::clone
*/
PPPoE *clone() const {
return new PPPoE(*this);
}
const tag *search_tag(TagTypes identifier) const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
// Setters
/**
* \brief Setter for the version field.
* \param new_version The new version field value.
*/
void version(small_uint<4> new_version);
/**
* \brief Setter for the type field.
* \param new_type The new type field value.
*/
void type(small_uint<4> new_type);
/**
* \brief Setter for the code field.
* \param new_code The new code field value.
*/
void code(uint8_t new_code);
/**
* \brief Setter for the session_id field.
* \param new_session_id The new session_id field value.
*/
void session_id(uint16_t new_session_id);
/**
* \brief Setter for the payload_length field.
* \param new_payload_length The new payload_length field value.
*/
void payload_length(uint16_t new_payload_length);
/**
* \brief Adds a PPPoE tag.
*
* \param option The option to be added.
*/
void add_tag(const tag &option);
#if TINS_IS_CXX11
/**
* \brief Adds a PPPoE tag.
*
* This move-constructs the option.
*
* \param option The option to be added.
*/
void add_tag(tag &&option) {
_tags_size += option.data_size() + sizeof(uint16_t) * 2;
_tags.push_back(std::move(option));
}
#endif
// Option setters
/**
* \brief Adds an end-of-list tag.
*/
void end_of_list();
/**
* \brief Adds a service-name tag.
*
* \param value The service name.
*/
void service_name(const std::string &value);
/**
* \brief Adds a AC-name tag.
*
* \param value The AC name.
*/
void ac_name(const std::string &value);
/**
* \brief Adds a host-uniq tag.
*
* \param value The tag's value.
*/
void host_uniq(const byte_array &value);
/**
* \brief Adds a AC-Cookie tag.
*
* \param value The tag's value.
*/
void ac_cookie(const byte_array &value);
/**
* \brief Adds a Vendor-Specific tag.
*
* \param value The tag's value.
*/
void vendor_specific(const vendor_spec_type &value);
/**
* \brief Adds a Relay-Session-Id tag.
*
* \param value The tag's value.
*/
void relay_session_id(const byte_array &value);
/**
* \brief Adds a Service-Name-Error tag.
*
* \param value The tag's value.
*/
void service_name_error(const std::string &value);
/**
* \brief Adds a AC-System-Error tag.
*
* \param value The tag's value.
*/
void ac_system_error(const std::string &value);
/**
* \brief Adds a Generic-Error tag.
*
* \param value The tag's value.
*/
void generic_error(const std::string &value);
// Option getters
/**
* \brief Getter for the service-name tag.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
std::string service_name() const;
/**
* \brief Getter for the AC-name tag.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
std::string ac_name() const;
/**
* \brief Getter for the host-uniq tag.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
byte_array host_uniq() const;
/**
* \brief Getter for the AC-Cookie tag.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
byte_array ac_cookie() const;
/**
* \brief Getter for the Vendor-Specific tag.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
vendor_spec_type vendor_specific() const;
/**
* \brief Getter for the Vendor-Specific tag.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
byte_array relay_session_id() const;
/**
* \brief Getter for the Service-Name-Error tag.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
std::string service_name_error() const;
/**
* \brief Getter for the AC-System-Error tag.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
std::string ac_system_error() const;
/**
* \brief Getter for the Generic-Error tag.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
std::string generic_error() const;
private:
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
template<typename T>
void add_tag_iterable(TagTypes id, const T &data) {
add_tag(
tag(
id,
data.begin(),
data.end()
)
);
}
template<typename T>
T search_and_convert(TagTypes id) const {
const tag *t = search_tag(id);
if(!t)
throw option_not_found();
return t->to<T>();
}
TINS_BEGIN_PACK
struct pppoe_hdr {
#if TINS_IS_LITTLE_ENDIAN
uint8_t version:4,
type:4;
uint8_t code;
#else
uint16_t version:4,
type:4,
code:8;
#endif
uint16_t session_id;
uint16_t payload_length;
} TINS_END_PACK;
pppoe_hdr _header;
tags_type _tags;
uint16_t _tags_size;
};
}
#endif // TINS_PPPoE_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,12 +27,14 @@
*
*/
#ifndef TINS_RADIOTAP_H
#include "config.h"
#if !defined(TINS_RADIOTAP_H) && defined(HAVE_DOT11)
#define TINS_RADIOTAP_H
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
#include "network_interface.h"
namespace Tins {
class PacketSender;
@@ -89,7 +91,8 @@ namespace Tins {
ANTENNA = 2048,
DB_SIGNAL = 4096,
DB_NOISE = 8192,
RX_FLAGS = 16382
RX_FLAGS = 16382,
CHANNEL_PLUS = 262144
};
/**
@@ -107,16 +110,17 @@ namespace Tins {
};
/**
* \brief Creates an instance of RadioTap.
* \param iface The interface in which to send this PDU.
* \param child The child PDU.(optional)
* \brief Default constructor.
*/
RadioTap(const NetworkInterface &iface = NetworkInterface(),
PDU *child = 0);
RadioTap();
/**
* \brief Constructor which creates a RadioTap object from a buffer and adds all
* \brief Constructs a RadioTap object from a buffer and adds all
* identifiable PDUs found in the buffer as children of this one.
*
* If there is not enough size for a RadioTap header, a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
@@ -124,10 +128,12 @@ namespace Tins {
/* Setters */
#ifndef WIN32
/**
* \sa PDU::send()
*/
void send(PacketSender &sender);
void send(PacketSender &sender, const NetworkInterface &iface);
#endif
/**
* \brief Setter for the version field.
@@ -184,12 +190,24 @@ namespace Tins {
*/
void dbm_noise(uint8_t new_dbm_noise);
/**
* \brief Setter for the signal quality field.
* \param new_antenna The signal quality signal.
*/
void signal_quality(uint8_t new_signal_quality);
/**
* \brief Setter for the antenna field.
* \param new_antenna The antenna signal.
*/
void antenna(uint8_t new_antenna);
/**
* \brief Setter for the db signal field.
* \param new_antenna The db signal signal.
*/
void db_signal(uint8_t new_db_signal);
/**
* \brief Setter for the rx flag field.
* \param new_rx_flag The antenna signal.
@@ -258,17 +276,29 @@ namespace Tins {
*/
uint8_t dbm_noise() const { return _dbm_noise; }
/**
* \brief Getter for the signal quality field.
* \return The signal quality field.
*/
uint16_t signal_quality() const { return _signal_quality; }
/**
* \brief Getter for the antenna field.
* \return The antenna field.
*/
uint8_t antenna() const { return _antenna; }
/**
* \brief Getter for the db signal field.
* \return The db signal field.
*/
uint8_t db_signal() const { return _db_signal; }
/**
* \brief Getter for the channel+ field.
* \return The channel+ field.
*/
uint32_t channel_plus() const { return Endian::le_to_host(_channel_type); }
uint32_t channel_plus() const { return Endian::le_to_host<uint32_t>(_channel_type); }
/**
* \brief Getter for the rx flags field.
@@ -286,9 +316,18 @@ namespace Tins {
* if its corresponding bit flag is set in the present field.
*/
PresentFlags present() const {
return (PresentFlags)*(uint32_t*)(&_radio.it_len + 1);
//return (PresentFlags)*(uint32_t*)(&_radio.it_len + 1);
return (PresentFlags)Endian::le_to_host(_radio.flags_32);
}
/** \brief Check wether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \brief Returns the RadioTap frame's header length.
*
@@ -316,70 +355,79 @@ namespace Tins {
*/
PDUType pdu_type() const { return PDU::RADIOTAP; }
private:
TINS_BEGIN_PACK
struct radiotap_hdr {
#if TINS_IS_LITTLE_ENDIAN
uint8_t it_version;
uint8_t it_pad;
uint16_t it_len;
uint32_t tsft:1,
flags:1,
rate:1,
channel:1,
fhss:1,
dbm_signal:1,
dbm_noise:1,
lock_quality:1,
tx_attenuation:1,
db_tx_attenuation:1,
dbm_tx_attenuation:1,
antenna:1,
db_signal:1,
db_noise:1,
rx_flags:1,
reserved1:3,
channel_plus:1,
reserved2:12,
ext:1;
union {
struct {
uint32_t tsft:1,
flags:1,
rate:1,
channel:1,
fhss:1,
dbm_signal:1,
dbm_noise:1,
lock_quality:1,
tx_attenuation:1,
db_tx_attenuation:1,
dbm_tx_attenuation:1,
antenna:1,
db_signal:1,
db_noise:1,
rx_flags:1,
reserved1:3,
channel_plus:1,
reserved2:12,
ext:1;
} flags;
uint32_t flags_32;
};
#else
uint8_t it_pad;
uint8_t it_version;
uint16_t it_len;
uint32_t lock_quality:1,
dbm_noise:1,
dbm_signal:1,
fhss:1,
channel:1,
rate:1,
flags:1,
tsft:1,
reserved3:1,
tx_attenuation:1,
db_tx_attenuation:1,
dbm_tx_attenuation:1,
antenna:1,
db_signal:1,
db_noise:1,
rx_flags:1,
reserved2:5,
channel_plus:1,
reserved1:2,
reserved4:7,
ext:1;
union {
struct {
uint32_t lock_quality:1,
dbm_noise:1,
dbm_signal:1,
fhss:1,
channel:1,
rate:1,
flags:1,
tsft:1,
reserved3:1,
rx_flags:1,
db_tx_attenuation:1,
dbm_tx_attenuation:1,
antenna:1,
db_signal:1,
db_noise:1,
tx_attenuation:1,
reserved2:5,
channel_plus:1,
reserved1:2,
reserved4:7,
ext:1;
} flags;
uint32_t flags_32;
};
#endif
} __attribute__((__packed__));
} TINS_END_PACK;
void init();
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
radiotap_hdr _radio;
NetworkInterface _iface;
// present fields...
uint64_t _tsft;
uint32_t _channel_type;
uint16_t _channel_freq, _rx_flags;
uint8_t _antenna, _flags, _rate, _dbm_signal, _dbm_noise, _channel, _max_power;
uint16_t _channel_type, _channel_freq, _rx_flags, _signal_quality;
uint8_t _antenna, _flags, _rate, _dbm_signal, _dbm_noise, _channel, _max_power, _db_signal;
};
};
}
#endif // TINS_RADIOTAP_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -116,12 +116,33 @@ namespace Tins {
return _payload.size();
}
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* This always returns true, since we don't know what this
* RawPDU is holding.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::RAW; }
/**
* \brief Constructs the given PDU type from the raw data stored
* in this RawPDU.
*/
template<typename T>
T to() const {
return T(&_payload[0], _payload.size());
}
/**
* \sa PDU::clone
*/
@@ -133,7 +154,7 @@ namespace Tins {
payload_type _payload;
};
};
}
#endif // TINS_RAWPDU_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,149 +35,160 @@
#include "endianness.h"
namespace Tins{
class Dot11;
template<typename T, typename U>
class PDUOption;
/**
* \brief Class that models the RSN information structure.
*/
class RSNInformation {
public:
/**
* \brief Class that models the RSN information structure.
* \brief Enum that represents the different cypher suites.
*/
class RSNInformation {
public:
/**
* \brief Enum that represents the different cypher suites.
*/
enum CypherSuites {
WEP_40 = 0x01ac0f00,
TKIP = 0x02ac0f00,
CCMP = 0x04ac0f00,
WEP_104 = 0x05ac0f00
};
/**
* \brief Enum that represents the different akm suites.
*/
enum AKMSuites {
PMKSA = 0x01ac0f00,
PSK = 0x02ac0f00
};
/**
* The type used to store the cypher suites.
*/
typedef std::vector<CypherSuites> cyphers_type;
/**
* The type used to store the AKM suites.
*/
typedef std::vector<AKMSuites> akm_type;
/**
* The type returned on serialization.
*/
typedef std::vector<uint8_t> serialization_type;
/**
* \brief Creates an instance of RSNInformation.
*
* By default, the version is set to 1.
*/
RSNInformation();
/**
* \brief Creates an instance of RSNInformation from a
* serialization_type object.
*
* \param buffer The buffer from which to construct this object.
*/
RSNInformation(const serialization_type &buffer);
/**
* \brief Constructor from buffer.
*
* \param buffer The buffer from which this object will be constructed.
* \param total_sz The total size of the buffer.
*/
RSNInformation(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Helper function to create a WPA2-PSK RSNInformation
* \return An instance RSNInformation which contains information
* for a WPA2-PSK AP.
*/
static RSNInformation wpa2_psk();
/**
* \brief Adds a pairwise cypher suite.
* \param cypher The pairwise cypher suite to be added.
*/
void add_pairwise_cypher(CypherSuites cypher);
/**
* \brief Adds a akm suite.
* \param akm The akm suite to be added.
*/
void add_akm_cypher(AKMSuites akm);
/**
* \brief Sets the group suite cypher.
* \param group The group suite cypher to be set.
*/
void group_suite(CypherSuites group);
/**
* \brief Sets the version.
* \param ver The version to be set.
*/
void version(uint16_t ver);
/**
* \brief Sets the capabilities field.
* \param cap The capabilities to be set.
*/
void capabilities(uint16_t cap);
/* Getters */
/**
* \brief Getter for the group suite field.
* \return The group suite field.
*/
CypherSuites group_suite() const { return _group_suite; }
/**
* \brief Getter for the version field.
* \return The version field.
*/
uint16_t version() const { return Endian::le_to_host(_version); }
/**
* \brief Getter for the capabilities field.
* \return The version field.
*/
uint16_t capabilities() const { return Endian::le_to_host(_capabilities); }
/**
* \brief Getter for the pairwise cypher suite list.
* \return A list of pairwise cypher suites.
*/
const cyphers_type &pairwise_cyphers() const { return _pairwise_cyphers; }
/**
* \brief Getter for the akm suite list.
* \return A list of akm suites.
*/
const akm_type &akm_cyphers() const { return _akm_cyphers; }
/**
* \brief Serializes this object.
* \return The result of the serialization.
*/
serialization_type serialize() const;
private:
void init(const uint8_t *buffer, uint32_t total_sz);
uint16_t _version, _capabilities;
CypherSuites _group_suite;
akm_type _akm_cyphers;
cyphers_type _pairwise_cyphers;
enum CypherSuites {
WEP_40 = 0x01ac0f00,
TKIP = 0x02ac0f00,
CCMP = 0x04ac0f00,
WEP_104 = 0x05ac0f00
};
/**
* \brief Enum that represents the different akm suites.
*/
enum AKMSuites {
PMKSA = 0x01ac0f00,
PSK = 0x02ac0f00
};
/**
* The type used to store the cypher suites.
*/
typedef std::vector<CypherSuites> cyphers_type;
/**
* The type used to store the AKM suites.
*/
typedef std::vector<AKMSuites> akm_type;
/**
* The type returned on serialization.
*/
typedef std::vector<uint8_t> serialization_type;
/**
* \brief Constructs an RSNInformation object.
*
* By default, the version is set to 1.
*/
RSNInformation();
/**
* \brief Constructs an RSNInformation object from a
* serialization_type object.
*
* \param buffer The buffer from which to construct this object.
*/
RSNInformation(const serialization_type &buffer);
/**
* \brief Constructs a RSNInformation from a buffer.
*
* If the input is malformed, a malformed_packet exception is
* thrown.
*
* \param buffer The buffer from which this object will be constructed.
* \param total_sz The total size of the buffer.
*/
RSNInformation(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Helper function to create a WPA2-PSK RSNInformation
* \return An instance RSNInformation which contains information
* for a WPA2-PSK AP.
*/
static RSNInformation wpa2_psk();
/**
* \brief Adds a pairwise cypher suite.
* \param cypher The pairwise cypher suite to be added.
*/
void add_pairwise_cypher(CypherSuites cypher);
/**
* \brief Adds an akm suite.
* \param akm The akm suite to be added.
*/
void add_akm_cypher(AKMSuites akm);
/**
* \brief Sets the group suite cypher.
* \param group The group suite cypher to be set.
*/
void group_suite(CypherSuites group);
/**
* \brief Sets the version.
* \param ver The version to be set.
*/
void version(uint16_t ver);
/**
* \brief Sets the capabilities field.
* \param cap The capabilities to be set.
*/
void capabilities(uint16_t cap);
/* Getters */
/**
* \brief Getter for the group suite field.
* \return The group suite field.
*/
CypherSuites group_suite() const { return _group_suite; }
/**
* \brief Getter for the version field.
* \return The version field.
*/
uint16_t version() const { return Endian::le_to_host(_version); }
/**
* \brief Getter for the capabilities field.
* \return The version field.
*/
uint16_t capabilities() const { return Endian::le_to_host(_capabilities); }
/**
* \brief Getter for the pairwise cypher suite list.
* \return A list of pairwise cypher suites.
*/
const cyphers_type &pairwise_cyphers() const { return _pairwise_cyphers; }
/**
* \brief Getter for the akm suite list.
* \return A list of akm suites.
*/
const akm_type &akm_cyphers() const { return _akm_cyphers; }
/**
* \brief Serializes this object.
* \return The result of the serialization.
*/
serialization_type serialize() const;
/**
* Constructs an RSNInformation object from a Dot11 tagged option.
*/
static RSNInformation from_option(const PDUOption<uint8_t, Dot11> &opt);
private:
void init(const uint8_t *buffer, uint32_t total_sz);
uint16_t _version, _capabilities;
CypherSuites _group_suite;
akm_type _akm_cyphers;
cyphers_type _pairwise_cyphers;
};
} // namespace Tins
#endif // TINS_RSN_INFORMATION

177
include/sll.h Normal file
View File

@@ -0,0 +1,177 @@
/*
* Copyright (c) 2012, 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_SLL_H
#define TINS_SLL_H
#include <vector>
#include "pdu.h"
#include "endianness.h"
#include "hw_address.h"
namespace Tins {
class SLL : public PDU {
public:
/**
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::SLL;
/**
* The type of the address type
*/
typedef HWAddress<8> address_type;
/**
* Default constructor
*/
SLL();
/**
* \brief Constructs a SLL object from a buffer and adds all
* identifiable PDUs found in the buffer as children of this one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for a SLL header in the
* buffer, a malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
SLL(const uint8_t *buffer, uint32_t total_sz);
// Getters
/**
* \brief Getter for the Packet Type field.
* \return The stored Packet Type field value.
*/
uint16_t packet_type() const {
return Endian::be_to_host(_header.packet_type);
}
/**
* \brief Getter for the LLADDR Type field.
* \return The stored LLADDR Type field value.
*/
uint16_t lladdr_type() const {
return Endian::be_to_host(_header.lladdr_type);
}
/**
* \brief Getter for the LLADDR Length field.
* \return The stored LLADDR Length field value.
*/
uint16_t lladdr_len() const {
return Endian::be_to_host(_header.lladdr_len);
}
/**
* \brief Getter for the Address field.
* \return The stored Address field value.
*/
address_type address() const {
return _header.address;
}
/**
* \brief Getter for the Protocol field.
* \return The stored Protocol field value.
*/
uint16_t protocol() const {
return Endian::be_to_host(_header.protocol);
}
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
// Setters
/**
* \brief Setter for the Packet Type field.
* \param new_packet_type The new Packet Type field value.
*/
void packet_type(uint16_t new_packet_type);
/**
* \brief Setter for the LLADDR Type field.
* \param new_lladdr_type The new LLADDR Type field value.
*/
void lladdr_type(uint16_t new_lladdr_type);
/**
* \brief Setter for the LLADDR Length field.
* \param new_lladdr_len The new LLADDR Length field value.
*/
void lladdr_len(uint16_t new_lladdr_len);
/**
* \brief Setter for the Address field.
* \param new_address The new Address field value.
*/
void address(const address_type &new_address);
/**
* \brief Setter for the Protocol field.
* \param new_protocol The new Protocol field value.
*/
void protocol(uint16_t new_protocol);
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \sa PDU::clone
*/
SLL *clone() const {
return new SLL(*this);
}
private:
TINS_BEGIN_PACK
struct sllhdr {
uint16_t packet_type, lladdr_type, lladdr_len;
uint8_t address[8];
uint16_t protocol;
} TINS_END_PACK;
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
sllhdr _header;
};
}
#endif // TINS_SLL_H

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,6 +33,7 @@
#include <stdint.h>
#include "pdu.h"
#include "macros.h"
#include "endianness.h"
#include "small_uint.h"
@@ -55,13 +56,18 @@ namespace Tins {
* \brief Creates an instance of SNAP
* This constructor sets the dsap and ssap fields to 0xaa, and
* the id field to 3.
* \param child The child PDU.(optional)
*/
SNAP(PDU *child = 0);
SNAP();
/**
* \brief Constructor which creates a SNAP object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \brief Constructs a SNAP object from a buffer and adds all
* identifiable PDUs found in the buffer as children of this one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for a SNAP header in the
* buffer, a malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
@@ -70,40 +76,40 @@ namespace Tins {
/* Setters */
/**
* \brief Setter for the control field.
* \param new_id The new control to be set.
* \brief Setter for the Control field.
* \param new_id The new Control to be set.
*/
void control(uint8_t new_control);
/**
* \brief Setter for the org code field.
* \param new_org The new org code to be set.
* \brief Setter for the Organization Code field.
* \param new_org The new Organization Code to be set.
*/
void org_code(small_uint<24> new_org);
/**
* \brief Setter for the eth type field.
* \param new_eth The new eth type to be set.
* \brief Setter for the Ethernet Type field.
* \param new_eth The new Ethernet Type to be set.
*/
void eth_type(uint16_t new_eth);
/* Getters */
/**
* \brief Getter for the dsap field.
* \return The dsap field.
* \brief Getter for the DSAP field.
* \return The DSAP field.
*/
uint8_t dsap() const { return _snap.dsap; }
/**
* \brief Getter for the ssap field.
* \return The ssap field.
* \brief Getter for the SSAP field.
* \return The SSAP field.
*/
uint8_t ssap() const { return _snap.ssap; }
/**
* \brief Getter for the control field.
* \return The control field.
* \brief Getter for the Control field.
* \return The Control field.
*/
uint8_t control() const {
#if TINS_IS_LITTLE_ENDIAN
@@ -114,8 +120,8 @@ namespace Tins {
}
/**
* \brief Getter for the org code field.
* \return The org code field.
* \brief Getter for the Organization Code field.
* \return The Organization Code field.
*/
small_uint<24> org_code() const {
#if TINS_IS_LITTLE_ENDIAN
@@ -126,8 +132,8 @@ namespace Tins {
}
/**
* \brief Getter for the eth type field.
* \return The eth field.
* \brief Getter for the Ethernet Type field.
* \return The Ethernet Type field.
*/
uint16_t eth_type() const { return Endian::be_to_host(_snap.eth_type); }
@@ -143,7 +149,7 @@ namespace Tins {
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::SNAP; }
PDUType pdu_type() const { return pdu_flag; }
/**
* \brief Clones this PDU.
@@ -154,25 +160,18 @@ namespace Tins {
return new SNAP(*this);
}
private:
TINS_BEGIN_PACK
struct snaphdr {
uint8_t dsap;
uint8_t ssap;
/*#if TINS_IS_LITTLE_ENDIAN
uint32_t control:8,
org_code:24;
#elif TINS_IS_BIG_ENDIAN
uint32_t org_code:24,
control:8;
#endif*/
uint32_t control_org;
uint16_t eth_type;
} __attribute__((__packed__));
} TINS_END_PACK;
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
snaphdr _snap;
};
};
}
#endif // TINS_SNAP_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,13 +36,16 @@
#include <string>
#include <memory>
#include <stdexcept>
#include <iterator>
#include "pdu.h"
#include "ethernetII.h"
#include "radiotap.h"
#include "loopback.h"
#include "dot11.h"
#include "packet.h"
#include "cxxstd.h"
#include "exceptions.h"
#include "internals.h"
namespace Tins {
class SnifferIterator;
/**
* \class BaseSniffer
* \brief Base class for sniffers.
@@ -55,6 +58,35 @@ namespace Tins {
*/
class BaseSniffer {
public:
/**
* The iterator type.
*/
typedef SnifferIterator iterator;
#if TINS_IS_CXX11
/**
* \brief Move constructor.
* This constructor is available only in C++11.
*/
BaseSniffer(BaseSniffer &&rhs) noexcept
: handle(nullptr), mask()
{
*this = std::move(rhs);
}
/**
* \brief Move assignment operator.
* This operator is available only in C++11.
*/
BaseSniffer& operator=(BaseSniffer &&rhs) noexcept
{
using std::swap;
swap(handle, rhs.handle);
swap(mask, rhs.mask);
return *this;
}
#endif
/**
* \brief Sniffer destructor.
* This frees all memory used by the pcap handle.
@@ -64,33 +96,77 @@ namespace Tins {
/**
* \brief Compiles a filter and uses it to capture one packet.
*
* This method returns the first sniffed packet that matches the
* This method returns the first valid sniffed packet that matches the
* sniffer's filter, or the first sniffed packet if no filter has
* been set.
* \return The captured packet, matching the given filter, 0 if an
* error occured(probably compiling the filter).
*
* The return type is a thin wrapper over a PDU* and a Timestamp
* object. This wrapper can be both implicitly converted to a
* PDU* and a Packet object. So doing this:
*
* \code
* Sniffer s(...);
* std::unique_ptr<PDU> pdu(s.next_packet());
* // Packet takes care of the PDU*.
* Packet packet(s.next_packet());
* \endcode
*
* Is fine, but this:
*
* \code
* // bad!!
* PtrPacket p = s.next_packet();
* \endcode
*
* Is not, since PtrPacket can't be copy constructed.
*
* \sa Packet::release_pdu
*
* \return A captured packet. If an error occured, PtrPacket::pdu
* will return 0. Caller takes ownership of the PDU pointer stored in
* the PtrPacket.
*/
PDU *next_packet();
PtrPacket next_packet();
/**
* \brief Starts a sniffing loop, using a callback object for every
* \brief Starts a sniffing loop, using a callback functor for every
* sniffed packet.
*
* The callback object must implement an operator with the
* following(or compatible) signature:
* The functor must implement an operator with one of the
* following signatures:
*
* bool operator()(PDU&);
* \code
* bool(PDU&);
* bool(const PDU&);
* \endcode
*
* This operator will be called using the sniffed packets
* as arguments. You can modify the PDU argument as you wish.
* Calling PDU methods like PDU::release_inner_pdu is perfectly
* valid.
* This functor will be called using the each of the sniffed packets
* as its argument. Using PDU member functions that modify the PDU,
* such as PDU::release_inner_pdu, is perfectly valid.
*
* Note that the Functor object will be copied using its copy
* constructor, so that object should be some kind of proxy to
* Note that if you're using a functor object, it will be copied using
* its copy constructor, so it should be some kind of proxy to
* another object which will process the packets(e.g. std::bind).
*
* Sniffing will stop when either max_packets are sniffed(if it is != 0),
* or when the functor returns false.
*
* This method catches both malformed_packet and pdu_not_found exceptions,
* which allows writing much cleaner code, since you can call PDU::rfind_pdu
* without worrying about catching the exception that can be thrown. This
* allows writing code such as the following:
*
* \code
* bool callback(const PDU& pdu) {
* // If either RawPDU is not found, or construction of the DNS
* // object fails, the BaseSniffer object will trap the exceptions,
* // so we don't need to worry about it.
* DNS dns = pdu.rfind_pdu<RawPDU>().to<DNS>();
* return true;
* }
* \endcode
*
* \param cback_handler The callback handler object which should process packets.
* \param function The callback handler object which should process packets.
* \param max_packets The maximum amount of packets to sniff. 0 == infinite.
*/
template<class Functor>
@@ -105,8 +181,42 @@ namespace Tins {
/**
* \brief Stops sniffing loops.
*
* This method must be called from the same thread from which
* BaseSniffer::sniff_loop was called.
*/
void stop_sniff();
/**
* \brief Gets the file descriptor associated with the sniffer.
*/
int get_fd();
/**
* \brief Sets the read timeout for this sniffer.
*
* This calls pcap_set_timeout using the provided parameter.
* \param ms The amount of milliseconds.
*/
void set_timeout(int ms);
/**
* \brief Retrieves this sniffer's link type.
*
* This calls pcap_datalink on the stored pcap handle and
* returns its result.
*/
int link_type() const;
/**
* Retrieves an iterator to the next packet in this sniffer.
*/
iterator begin();
/**
* Retrieves an end iterator.
*/
iterator end();
protected:
/**
* Default constructor.
@@ -124,48 +234,26 @@ namespace Tins {
*/
void init(pcap_t *phandle, const std::string &filter, bpf_u_int32 if_mask);
private:
template<class Functor>
struct LoopData {
pcap_t *handle;
Functor c_handler;
int iface_type;
LoopData(pcap_t *_handle, const Functor _handler,
int if_type)
: handle(_handle), c_handler(_handler), iface_type(if_type) { }
};
BaseSniffer(const BaseSniffer&);
BaseSniffer &operator=(const BaseSniffer&);
template<class ConcretePDU, class Functor>
static bool call_functor(LoopData<Functor> *data, const u_char *packet, size_t len);
bool compile_set_filter(const std::string &filter, bpf_program &prog);
template<class Functor>
static void callback_handler(u_char *args, const struct pcap_pkthdr *header, const u_char *packet);
pcap_t *handle;
bpf_u_int32 mask;
bpf_program actual_filter;
int iface_type;
};
/**
* \class Sniffer
* \brief Sniffs packets using pcap filters.
*
* This class uses a given filter to sniff packets and allow the user
* to handle them. Each time a filter is set, it's used until a new one
* is set. Both Sniffer::next_packet and Sniffer::sniff_loop have an
* optional filter parameter. If a filter is set using those parameter,
* the previously set filter is freed and the new one is used.
* \brief Sniffs packets from a network interface.
*/
class Sniffer : public BaseSniffer {
public:
enum promisc_type {
NON_PROMISC,
PROMISC
};
/**
* \brief Constructs an instance of Sniffer.
* Constructs an instance of Sniffer.
* \param device The device which will be sniffed.
* \param max_packet_size The maximum packet size to be read.
* \param promisc bool indicating wether to put the interface in promiscuous mode.(optional)
@@ -173,11 +261,27 @@ namespace Tins {
*/
Sniffer(const std::string &device, unsigned max_packet_size,
bool promisc = false, const std::string &filter = "");
/**
* \brief Constructs an instance of Sniffer.
*
* The maximum capture size is set to 65535. By default the interface won't
* be put into promiscuous mode.
*
* \param device The device which will be sniffed.
* \param promisc Indicates if the interface should be put in promiscuous mode.
* \param filter A capture filter to be used on the sniffing session.(optional);
*/
Sniffer(const std::string &device, promisc_type promisc = NON_PROMISC,
const std::string &filter = "");
private:
void init_sniffer(const std::string &device, unsigned max_packet_size,
bool promisc = false, const std::string &filter = "");
};
/**
* \class FileSniffer
* \brief Parses pcap files and interprets the packets in it.
* \brief Reads pcap files and interprets the packets in it.
*
* This class acts exactly in the same way that Sniffer, but reads
* packets from a pcap file instead of an interface.
@@ -191,44 +295,6 @@ namespace Tins {
*/
FileSniffer(const std::string &file_name, const std::string &filter = "");
};
template<class Functor>
void Tins::BaseSniffer::sniff_loop(Functor function, uint32_t max_packets) {
LoopData<Functor> data(handle, function, iface_type);
pcap_loop(handle, max_packets, &BaseSniffer::callback_handler<Functor>, (u_char*)&data);
}
template<class ConcretePDU, class Functor>
bool Tins::BaseSniffer::call_functor(LoopData<Functor> *data, const u_char *packet, size_t len) {
ConcretePDU some_pdu((const uint8_t*)packet, len);
return data->c_handler(some_pdu);
}
template<class Functor>
void Tins::BaseSniffer::callback_handler(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) {
try {
std::auto_ptr<PDU> pdu;
LoopData<Functor> *data = reinterpret_cast<LoopData<Functor>*>(args);
bool ret_val(false);
if(data->iface_type == DLT_EN10MB)
ret_val = call_functor<Tins::EthernetII>(data, packet, header->caplen);
else if(data->iface_type == DLT_IEEE802_11_RADIO)
ret_val = call_functor<Tins::RadioTap>(data, packet, header->caplen);
else if(data->iface_type == DLT_IEEE802_11) {
std::auto_ptr<PDU> pdu(Tins::Dot11::from_bytes((const uint8_t*)packet, header->caplen));
if(pdu.get())
ret_val = data->c_handler(*pdu);
}
else if(data->iface_type == DLT_NULL)
ret_val = call_functor<Tins::Loopback>(data, packet, header->caplen);
if(!ret_val)
pcap_breakloop(data->handle);
}
catch(...) {
}
}
template<class T>
class HandlerProxy {
@@ -252,6 +318,96 @@ namespace Tins {
{
return HandlerProxy<T>(ptr, function);
}
};
/**
* \brief Iterates over packets sniffed by a BaseSniffer.
*/
class SnifferIterator : public std::iterator<std::forward_iterator_tag, PDU> {
public:
/**
* Constructs a SnifferIterator.
* \param sniffer The sniffer to iterate.
*/
SnifferIterator(BaseSniffer *sniffer = 0)
: sniffer(sniffer)
{
if(sniffer)
advance();
}
/**
* Advances the iterator.
*/
SnifferIterator& operator++() {
advance();
return *this;
}
/**
* Advances the iterator.
*/
SnifferIterator operator++(int) {
SnifferIterator other(*this);
advance();
return other;
}
/**
* Dereferences the iterator.
* \return reference to the current packet.
*/
PDU &operator*() {
return *pkt.pdu();
}
/**
* Dereferences the iterator.
* \return pointer to the current packet.
*/
PDU *operator->() {
return &(**this);
}
/**
* Compares this iterator for equality.
* \param rhs The iterator to be compared to.
*/
bool operator==(const SnifferIterator &rhs) const {
return sniffer == rhs.sniffer;
}
/**
* Compares this iterator for in-equality.
* \param rhs The iterator to be compared to.
*/
bool operator!=(const SnifferIterator &rhs) const {
return !(*this == rhs);
}
private:
void advance() {
pkt = sniffer->next_packet();
if(!pkt)
sniffer = 0;
}
BaseSniffer *sniffer;
Packet pkt;
};
template<class Functor>
void Tins::BaseSniffer::sniff_loop(Functor function, uint32_t max_packets) {
for(iterator it = begin(); it != end(); ++it) {
try {
// If the functor returns false, we're done
if(!function(*it))
return;
}
catch(malformed_packet&) { }
catch(pdu_not_found&) { }
if(max_packets && --max_packets == 0)
return;
}
}
}
#endif // TINS_SNIFFER_H

307
include/stp.h Normal file
View File

@@ -0,0 +1,307 @@
/*
* Copyright (c) 2012, 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_STP_H
#define TINS_STP_H
#include "pdu.h"
#include "endianness.h"
#include "hw_address.h"
#include "small_uint.h"
namespace Tins {
class STP : public PDU {
public:
/**
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::STP;
/**
* The type used to store BPDU identifier addresses.
*/
typedef HWAddress<6> address_type;
/**
* The type used to store the BPDU identifiers.
*/
struct bpdu_id_type {
small_uint<4> priority;
small_uint<12> ext_id;
address_type id;
bpdu_id_type(small_uint<4> priority=0, small_uint<12> ext_id=0,
const address_type& id=address_type())
: priority(priority), ext_id(ext_id), id(id) { }
};
/**
* \brief Default constructor.
*/
STP();
/**
* \brief Constructs a STP object from a buffer.
*
* If there is not enough size for a STP header, a malformed_packet
* exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
STP(const uint8_t *buffer, uint32_t total_sz);
// Getters
/**
* \brief Getter for the Protocol ID field.
* \return The stored Protocol ID field value.
*/
uint16_t proto_id() const {
return Endian::be_to_host(_header.proto_id);
}
/**
* \brief Getter for the Protocol Version field.
* \return The stored Protocol Version field value.
*/
uint8_t proto_version() const {
return _header.proto_version;
}
/**
* \brief Getter for the BDU Type field.
* \return The stored BDU Type field value.
*/
uint8_t bpdu_type() const {
return _header.bpdu_type;
}
/**
* \brief Getter for the BDU Flags field.
* \return The stored BDU Flags field value.
*/
uint8_t bpdu_flags() const {
return _header.bpdu_flags;
}
/**
* \brief Getter for the Root Path Cost field.
* \return The stored Root Path Cost field value.
*/
uint32_t root_path_cost() const {
return Endian::be_to_host(_header.root_path_cost);
}
/**
* \brief Getter for the Port ID field.
* \return The stored Port ID field value.
*/
uint16_t port_id() const {
return Endian::be_to_host(_header.port_id);
}
/**
* \brief Getter for the Message Age field.
* \return The stored Message Age field value.
*/
uint16_t msg_age() const {
return Endian::be_to_host(_header.msg_age) / 256;
}
/**
* \brief Getter for the Maximum Age field.
* \return The stored Maximum Age field value.
*/
uint16_t max_age() const {
return Endian::be_to_host(_header.max_age) / 256;
}
/**
* \brief Getter for the Hello Time field.
* \return The stored Hello Time field value.
*/
uint16_t hello_time() const {
return Endian::be_to_host(_header.hello_time) / 256;
}
/**
* \brief Getter for the Forward Delay field.
* \return The stored Forward Delay field value.
*/
uint16_t fwd_delay() const {
return Endian::be_to_host(_header.fwd_delay) / 256;
}
/**
* \brief Getter for the Root ID field.
* \return The stored Root ID field value.
*/
bpdu_id_type root_id() const;
/**
* \brief Getter for the Bridge ID field.
* \return The stored Bridge ID field value.
*/
bpdu_id_type bridge_id() const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \sa PDU::clone
*/
STP *clone() const {
return new STP(*this);
}
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;
// Setters
/**
* \brief Setter for the Protocol ID field.
* \param new_proto_id The new Protocol ID field value.
*/
void proto_id(uint16_t new_proto_id);
/**
* \brief Setter for the Protocol Version field.
* \param new_proto_version The new Protocol Version field value.
*/
void proto_version(uint8_t new_proto_version);
/**
* \brief Setter for the BPDU Type field.
* \param new_bpdu_type The new BPDU Type field value.
*/
void bpdu_type(uint8_t new_bpdu_type);
/**
* \brief Setter for the BPDU Flags field.
* \param new_bpdu_flags The new BPDU Flags field value.
*/
void bpdu_flags(uint8_t new_bpdu_flags);
/**
* \brief Setter for the Root Path Cost field.
* \param new_root_path_cost The new Root Path Cost field value.
*/
void root_path_cost(uint32_t new_root_path_cost);
/**
* \brief Setter for the Port ID field.
* \param new_port_id The new Port ID field value.
*/
void port_id(uint16_t new_port_id);
/**
* \brief Setter for the Message Age field.
* \param new_msg_age The new Message Age field value.
*/
void msg_age(uint16_t new_msg_age);
/**
* \brief Setter for the Maximum Age field.
* \param new_max_age The new Maximum Age field value.
*/
void max_age(uint16_t new_max_age);
/**
* \brief Setter for the Hello Time field.
* \param new_hello_time The new Hello Time field value.
*/
void hello_time(uint16_t new_hello_time);
/**
* \brief Setter for the Forward Delay field.
* \param new_fwd_delay The new Forward Delay field value.
*/
void fwd_delay(uint16_t new_fwd_delay);
/**
* \brief Setter for the Root ID field.
* \param new_fwd_delay The new Root ID field value.
*/
void root_id(const bpdu_id_type &id);
/**
* \brief Setter for the Bridge ID field.
* \param new_fwd_delay The new Bridge ID field value.
*/
void bridge_id(const bpdu_id_type &id);
private:
TINS_BEGIN_PACK
struct pvt_bpdu_id {
#if TINS_IS_LITTLE_ENDIAN
// fixme
uint16_t ext_id:4,
priority:4,
ext_idL:8;
#else
uint16_t priority:4,
ext_id:12;
#endif
uint8_t id[6];
} TINS_END_PACK;
TINS_BEGIN_PACK
struct stphdr {
uint16_t proto_id;
uint8_t proto_version;
uint8_t bpdu_type;
uint8_t bpdu_flags;
pvt_bpdu_id root_id;
uint32_t root_path_cost;
pvt_bpdu_id bridge_id;
uint16_t port_id;
uint16_t msg_age;
uint16_t max_age;
uint16_t hello_time;
uint16_t fwd_delay;
} TINS_END_PACK;
static bpdu_id_type convert(const pvt_bpdu_id &id);
static pvt_bpdu_id convert(const bpdu_id_type &id);
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
stphdr _header;
};
}
#endif // TINS_STP_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,9 +37,11 @@
#include <stdexcept>
#include <utility>
#include "pdu.h"
#include "macros.h"
#include "endianness.h"
#include "small_uint.h"
#include "pdu_option.h"
#include "cxxstd.h"
namespace Tins {
/**
@@ -62,14 +64,14 @@ namespace Tins {
* These flags identify those supported by the TCP PDU.
*/
enum Flags {
FIN,
SYN,
RST,
PSH,
ACK,
URG,
ECE,
CWR
FIN = 1,
SYN = 2,
RST = 4,
PSH = 8,
ACK = 16,
URG = 32,
ECE = 64,
CWR = 128
};
/**
@@ -77,8 +79,7 @@ namespace Tins {
*
* This enum identifies valid options supported by TCP PDU.
*/
enum Option {
enum OptionTypes {
EOL = 0,
NOP = 1,
MSS = 2,
@@ -98,12 +99,15 @@ namespace Tins {
CHK_16FLETCHER
};
typedef PDUOption<uint8_t> tcp_option;
/**
* The type used to store TCP options.
*/
typedef PDUOption<uint8_t, TCP> option;
/**
* The type used to store the options.
*/
typedef std::list<tcp_option> options_type;
typedef std::list<option> options_type;
/**
* The type used to store the sack option.
@@ -121,9 +125,14 @@ namespace Tins {
TCP(uint16_t dport = 0, uint16_t sport = 0);
/**
* \brief Constructor which creates an TCP object from a buffer
* and adds all identifiable PDUs found in the buffer as children
* of this one.
* \brief Constructs TCP object from a buffer.
*
* If there is not enough size for a TCP header, or any of the
* TLV options are malformed a malformed_packet exception is
* thrown.
*
* Any extra data will be stored in a RawPDU.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
@@ -169,7 +178,7 @@ namespace Tins {
*
* \return The checksum field in an uint16_t.
*/
uint16_t check() const { return Endian::be_to_host(_tcp.check); }
uint16_t checksum() const { return Endian::be_to_host(_tcp.check); }
/**
* \brief Getter for the urgent pointer field.
@@ -198,7 +207,25 @@ namespace Tins {
* \param tcp_flag The polled flag.
* \return The value of the flag.
*/
small_uint<1> get_flag(Flags tcp_flag);
small_uint<1> get_flag(Flags tcp_flag) const;
/**
*
* \brief Gets the flags' values.
*
* All of the set flags will be joined together into
* a 12 bit value. This way, you can check for multiple
* flags at the same time:
*
* \code
* TCP tcp = ...;
* if(tcp.flags() == (TCP::SYN | TCP::ACK))
* // It's a SYN+ACK!
* \endcode
*
* \return The value of the flags field.
*/
small_uint<12> flags() const;
/* Setters */
@@ -237,13 +264,6 @@ namespace Tins {
*/
void window(uint16_t new_window);
/**
* \brief Setter for the checksum field.
*
* \param new_check The new checksum.
*/
void check(uint16_t new_check);
/**
* \brief Setter for the urgent pointer field.
*
@@ -350,15 +370,46 @@ namespace Tins {
* \param value The new value for this flag. Must be 0 or 1.
*/
void set_flag(Flags tcp_flag, small_uint<1> value);
/**
* \brief Sets the value of the flag fields.
*
* This method can be used to set several flags at the
* same time.
*
* \code
* TCP tcp = ...;
* tcp.flags(TCP::SYN | TCP::ACK);
* // ...
* // only set the ACK, keeping the rest of the old flags.
* tcp.flags(tcp.flags() | TCP::ACK);
* \endcode
*
* \param value The new value of the flags.
*/
void flags(small_uint<12> value);
/**
* \brief Adds a TCP option.
*
* \param option The option type flag to be set.
* \param length The length of this option(optional).
* \param data Pointer to this option's data(optional).
* \param option The option to be added.
*/
void add_option(Option option, uint8_t length = 0, const uint8_t *data = 0);
void add_option(const option &opt);
#if TINS_IS_CXX11
/**
* \brief Adds a TCP option.
*
* This move-constructs the option.
*
* \param option The option to be added.
*/
void add_option(option &&opt) {
internal_add_option(opt);
_options.push_back(std::move(opt));
}
#endif
/**
* \brief Returns the header size.
@@ -369,6 +420,15 @@ namespace Tins {
* \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \brief Getter for the PDU's type.
@@ -382,7 +442,7 @@ namespace Tins {
* \param opt_flag The flag to be searched.
* \return A pointer to the option, or 0 if it was not found.
*/
const tcp_option *search_option(Option opt) const;
const option *search_option(OptionTypes opt) const;
/**
* \sa PDU::clone
@@ -391,6 +451,7 @@ namespace Tins {
return new TCP(*this);
}
private:
TINS_BEGIN_PACK
struct tcphdr {
uint16_t sport;
uint16_t dport;
@@ -424,26 +485,28 @@ namespace Tins {
uint16_t window;
uint16_t check;
uint16_t urg_ptr;
} __attribute__((packed));
} TINS_END_PACK;
static const uint16_t DEFAULT_WINDOW;
template<class T>
T generic_search(Option opt) const {
const tcp_option *option = search_option(opt);
if(option && option->data_size() == sizeof(T))
return *(const T*)(&option->data_ptr()[0]);
throw option_not_found();
T generic_search(OptionTypes opt_type) const {
const option *opt = search_option(opt_type);
if(!opt)
throw option_not_found();
return opt->to<T>();
}
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
uint8_t *write_option(const tcp_option &opt, uint8_t *buffer);
void internal_add_option(const option &option);
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
void checksum(uint16_t new_check);
uint8_t *write_option(const option &opt, uint8_t *buffer);
tcphdr _tcp;
uint16_t _options_size, _total_options_size;
options_type _options;
uint32_t _options_size, _total_options_size;
};
};
}
#endif // TINS_TCP_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -345,36 +345,34 @@ void TCPStreamFollower::follow_streams(ForwardIterator start, ForwardIterator en
template<typename DataFunctor, typename EndFunctor>
bool TCPStreamFollower::callback(PDU &pdu, const DataFunctor &data_fun, const EndFunctor &end_fun) {
IP *ip = pdu.find_pdu<IP>();
TCP *tcp = pdu.find_pdu<TCP>();
if(ip && tcp) {
TCPStream::StreamInfo info(
ip->src_addr(), ip->dst_addr(),
tcp->sport(), tcp->dport()
);
sessions_type::iterator it = sessions.find(info);
if(it == sessions.end()) {
std::swap(info.client_addr, info.server_addr);
std::swap(info.client_port, info.server_port);
if((it = sessions.find(info)) == sessions.end()) {
if(tcp->get_flag(TCP::SYN) && !tcp->get_flag(TCP::ACK)) {
sessions.insert(
std::make_pair(
info,
TCPStream(ip, tcp, last_identifier++)
)
);
}
return true;
IP &ip = pdu.rfind_pdu<IP>();
TCP &tcp = pdu.rfind_pdu<TCP>();
TCPStream::StreamInfo info(
ip.src_addr(), ip.dst_addr(),
tcp.sport(), tcp.dport()
);
sessions_type::iterator it = sessions.find(info);
if(it == sessions.end()) {
std::swap(info.client_addr, info.server_addr);
std::swap(info.client_port, info.server_port);
if((it = sessions.find(info)) == sessions.end()) {
if(tcp.get_flag(TCP::SYN) && !tcp.get_flag(TCP::ACK)) {
sessions.insert(
std::make_pair(
info,
TCPStream(&ip, &tcp, last_identifier++)
)
);
}
return true;
}
if(it->second.update(ip, tcp))
data_fun(it->second);
// We're done with this stream
if(it->second.is_finished()) {
end_fun(it->second);
sessions.erase(it);
}
}
if(it->second.update(&ip, &tcp))
data_fun(it->second);
// We're done with this stream
if(it->second.is_finished()) {
end_fun(it->second);
sessions.erase(it);
}
return true;
}

111
include/timestamp.h Normal file
View File

@@ -0,0 +1,111 @@
/*
* Copyright (c) 2012, 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_TIMESTAMP_H
#define TINS_TIMESTAMP_H
#ifdef WIN32
#define NOMINMAX
#include <winsock2.h>
#else
#include <sys/time.h>
#endif
#include "cxxstd.h"
#if TINS_IS_CXX11
#include <chrono>
#endif
namespace Tins {
/**
* \brief Represents a packet timestamp.
*/
class Timestamp {
public:
#ifdef WIN32
typedef long seconds_type;
typedef long microseconds_type;
#else
typedef time_t seconds_type;
typedef suseconds_t microseconds_type;
#endif
/**
* \brief Constructs a Timestamp which will hold the current time.
*/
static Timestamp current_time() {
#ifdef WIN32
//fixme
return Timestamp();
#else
timeval tv;
gettimeofday(&tv, 0);
return tv;
#endif
}
/**
* Default constructs the timestamp.
*/
Timestamp() : tv() {}
/**
* Constructs a timestamp from a timeval object.
* \param time_val The timeval object.
*/
Timestamp(const timeval &time_val) : tv(time_val) {}
/**
* Returns the amount of seconds in this timestamp.
*/
seconds_type seconds() const {
return tv.tv_sec;
}
/**
* Returns the amount of microseconds in this timestamp.
*/
microseconds_type microseconds() const {
return tv.tv_usec;
}
#if TINS_IS_CXX11
/**
* Converts this Timestamp to a std::chrono::microseconds
*/
operator std::chrono::microseconds() const {
return std::chrono::seconds(seconds()) +
std::chrono::microseconds(microseconds());
}
#endif
private:
timeval tv;
};
}
#endif // TINS_TIMESTAMP_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,6 +30,7 @@
#ifndef TINS_TINS_H
#define TINS_TINS_H
#include "dns.h"
#include "arp.h"
#include "bootp.h"
#include "dhcp.h"
@@ -38,8 +39,12 @@
#include "ieee802_3.h"
#include "llc.h"
#include "icmp.h"
#include "icmpv6.h"
#include "dot11.h"
#include "dot1q.h"
#include "dot3.h"
#include "ip.h"
#include "ipv6.h"
#include "packet_sender.h"
#include "packet_writer.h"
#include "pdu.h"
@@ -50,10 +55,23 @@
#include "tcp.h"
#include "udp.h"
#include "utils.h"
#include "dns.h"
#include "tcp_stream.h"
#include "crypto.h"
#include "pdu_cacher.h"
#include "rsn_information.h"
#include "ipv6_address.h"
#include "ip_address.h"
#include "packet.h"
#include "timestamp.h"
#include "sll.h"
#include "dhcpv6.h"
#include "pppoe.h"
#include "stp.h"
#include "handshake_capturer.h"
#include "address_range.h"
#include "pdu_allocator.h"
#include "ipsec.h"
#include "ip_reassembler.h"
#include "ppi.h"
#endif // TINS_TINS_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,7 +30,7 @@
#ifndef TINS_UDP_H
#define TINS_UDP_H
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
@@ -51,17 +51,22 @@ namespace Tins {
/**
* \brief UDP constructor.
*
* Creates an instance of UDP. Destination and source port can
* be provided, otherwise both will be 0.
* Constructs an instance of UDP. The destination and source
* port can be provided, otherwise both of them will be 0.
*
* \param dport Destination port.
* \param sport Source port.
* \param child The child PDU(optional).
* */
UDP(uint16_t dport = 0, uint16_t sport = 0, PDU *child = 0);
UDP(uint16_t dport = 0, uint16_t sport = 0);
/**
* \brief Constructor which creates an UDP object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \brief Constructs an UDP object from a buffer.
*
* If there is not enough size for a UDP header a malformed_packet
* exception is thrown.
*
* Any extra data will be stored in a RawPDU.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
@@ -84,6 +89,12 @@ namespace Tins {
* \return The length of the datagram.
*/
uint16_t length() const { return Endian::be_to_host(_udp.len); }
/**
* \brief Getter for the checksum of the datagram.
* \return The datagram's checksum.
*/
uint16_t checksum() const { return Endian::be_to_host(_udp.check); }
/**
* \brief Set the destination port.
@@ -91,19 +102,34 @@ namespace Tins {
*/
void dport(uint16_t new_dport);
/** \brief Set the source port.
/**
* \brief Set the source port.
*
* \param new_sport The new source port.
*/
void sport(uint16_t new_sport);
/** \brief Getter for the length field.
/**
* \brief Getter for the length field.
* \param new_len The new length field.
* \return The length field.
*/
void length(uint16_t new_len);
/** \brief Returns the header size.
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* This compares the source and destination ports in the provided
* response with those stored in this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. This size includes the
* payload and options size. \sa PDU::header_size
@@ -119,22 +145,22 @@ namespace Tins {
/**
* \sa PDU::clone
*/
PDU *clone() const {
UDP *clone() const {
return new UDP(*this);
}
private:
TINS_BEGIN_PACK
struct udphdr {
uint16_t sport;
uint16_t dport;
uint16_t len;
uint16_t check;
} __attribute__((packed));
} TINS_END_PACK;
void copy_fields(const UDP *other);
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
udphdr _udp;
};
};
}
#endif // TINS_UDP_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,16 +33,30 @@
#ifndef WIN32
#include <ifaddrs.h>
#else
#define NOMINMAX
#include <winsock2.h>
#include <iphlpapi.h>
#undef interface
#endif
#include "macros.h"
#if defined(BSD) || defined(__FreeBSD_kernel__)
#include <sys/file.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/route.h>
#include <netinet/in.h>
#endif
#include <string>
#include <set>
#include <fstream>
#include <vector>
#include <stdint.h>
#include "ip_address.h"
#include "ipv6_address.h"
#include "hw_address.h"
#include "internals.h"
namespace Tins {
class NetworkInterface;
@@ -81,7 +95,7 @@ namespace Tins {
*/
IPv4Address mask;
};
/**
* \brief Resolves a domain name and returns its corresponding ip address.
*
@@ -90,20 +104,17 @@ namespace Tins {
*
* \param to_resolve The domain name/ip address to resolve.
*/
IPv4Address resolve_ip(const std::string &to_resolve);
IPv4Address resolve_domain(const std::string &to_resolve);
/**
* \brief Resolves the hardware address for a given ip.
* \brief Resolves a domain name and returns its corresponding ip address.
*
* \param iface The interface in which the packet will be sent.
* \param ip The ip to resolve, in integer format.
* \param buffer The buffer in which the host's hardware address will be stored.
* \param sender The sender to use to send and receive the ARP requests.
* \return Returns true if the hardware address was resolved successfully,
* false otherwise.
* If an ip address is given, its integer representation is returned.
* Otherwise, the domain name is resolved and its ip address is returned.
*
* \param to_resolve The domain name/ip address to resolve.
*/
bool resolve_hwaddr(const NetworkInterface &iface, IPv4Address ip,
HWAddress<6> *address, PacketSender &sender);
IPv6Address resolve_domain6(const std::string &to_resolve);
/**
* \brief Resolves the hardware address for a given ip.
@@ -118,6 +129,21 @@ namespace Tins {
*/
HWAddress<6> resolve_hwaddr(const NetworkInterface &iface,
IPv4Address ip, PacketSender &sender);
/**
* \brief Resolves the hardware address for a given ip.
*
* If the address can't be resolved, a std::runtime_error
* exception is thrown.
*
* This method sends and receives the packet through
* PacketSender::default_interface.
*
* \param ip The ip to resolve, in integer format.
* \param sender The sender to use to send and receive the ARP requests.
* \return HWAddress<6> containing the resolved hardware address.
*/
HWAddress<6> resolve_hwaddr(IPv4Address ip, PacketSender &sender);
/** \brief List all network interfaces.
*
@@ -142,13 +168,20 @@ namespace Tins {
/**
* \brief Retrieves entries int the routing table.
* \brief Retrieves entries in the routing table.
*
* \brief output ForwardIterator in which entries will be stored.
*/
template<class ForwardIterator>
void route_entries(ForwardIterator output);
/**
* \brief Retrieves entries in the routing table.
*
* \return a vector which contains all of the route entries.
*/
std::vector<RouteEntry> route_entries();
/** \brief Returns the 32 bit crc of the given buffer.
*
* \param data The input buffer.
@@ -190,6 +223,16 @@ namespace Tins {
* \return The pseudo header checksum.
*/
uint32_t pseudoheader_checksum(IPv4Address source_ip, IPv4Address dest_ip, uint32_t len, uint32_t flag);
/** \brief Performs the pseudo header checksum used in TCP and UDP PDUs.
*
* \param source_ip The source ip address.
* \param dest_ip The destination ip address.
* \param len The length to be included in the pseudo header.
* \param flag The flag to use in the protocol field of the pseudo header.
* \return The pseudo header checksum.
*/
uint32_t pseudoheader_checksum(IPv6Address source_ip, IPv6Address dest_ip, uint32_t len, uint32_t flag);
/** \brief Generic function to iterate through interface and collect
* data.
@@ -228,27 +271,6 @@ namespace Tins {
}
#endif // WIN32
/**
* \cond
*/
namespace Internals {
void skip_line(std::istream &input);
bool from_hex(const std::string &str, uint32_t &result);
template<bool, typename>
struct enable_if {
};
template<typename T>
struct enable_if<true, T> {
typedef T type;
};
}
/**
* \endcond
*/
template <typename T>
struct is_pdu {
template <typename U>
@@ -280,12 +302,101 @@ namespace Tins {
dereference_until_pdu(T &value) {
return dereference_until_pdu(*value);
}
#if defined(BSD) || defined(__FreeBSD_kernel__)
inline std::vector<char> query_route_table() {
int mib[6];
std::vector<char> buf;
size_t len;
mib[0] = CTL_NET;
mib[1] = AF_ROUTE;
mib[2] = 0;
mib[3] = AF_INET;
mib[4] = NET_RT_DUMP;
mib[5] = 0;
if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
throw std::runtime_error("sysctl failed");
buf.resize(len);
if (sysctl(mib, 6, &buf[0], &len, NULL, 0) < 0) {
throw std::runtime_error("sysctl failed");
}
return buf;
}
template<typename ForwardIterator>
void parse_header(struct rt_msghdr *rtm, ForwardIterator iter)
{
char *ptr = (char *)(rtm + 1);
sockaddr *sa = 0;
for (int i = 0; i < RTAX_MAX; i++) {
if (rtm->rtm_addrs & (1 << i)) {
sa = (struct sockaddr *)ptr;
ptr += sa->sa_len;
if (sa->sa_family == 0)
sa = 0;
}
*iter++ = sa;
}
}
#endif
}
}
#if defined(BSD) || defined(__FreeBSD_kernel__)
template<class ForwardIterator>
void Tins::Utils::route_entries(ForwardIterator output) {
using namespace Utils::Internals;
std::vector<char> buffer = query_route_table();
char *next = &buffer[0], *end = &buffer[buffer.size()];
rt_msghdr *rtm;
std::vector<sockaddr*> sa(RTAX_MAX);
char iface_name[IF_NAMESIZE];
while(next < end) {
rtm = (rt_msghdr*)next;
parse_header(rtm, sa.begin());
if (sa[RTAX_DST] && sa[RTAX_GATEWAY] && if_indextoname(rtm->rtm_index, iface_name)) {
RouteEntry entry;
entry.destination = IPv4Address(((struct sockaddr_in *)sa[RTAX_DST])->sin_addr.s_addr);
entry.gateway = IPv4Address(((struct sockaddr_in *)sa[RTAX_GATEWAY])->sin_addr.s_addr);
if(sa[RTAX_GENMASK])
entry.mask = IPv4Address(((struct sockaddr_in *)sa[RTAX_GENMASK])->sin_addr.s_addr);
else
entry.mask = IPv4Address(uint32_t());
entry.interface = iface_name;
*output++ = entry;
}
next += rtm->rtm_msglen;
}
}
#elif defined(WIN32)
template<class ForwardIterator>
void Tins::Utils::route_entries(ForwardIterator output) {
MIB_IPFORWARDTABLE *table;
ULONG size = 0;
char iface_name[256];
GetIpForwardTable(0, &size, 0);
std::vector<uint8_t> buffer(size);
table = (MIB_IPFORWARDTABLE*)&buffer[0];
GetIpForwardTable(table, &size, 0);
for (DWORD i = 0; i < table->dwNumEntries; i++) {
MIB_IPFORWARDROW *row = &table->table[i];
if(row->dwForwardType == MIB_IPROUTE_TYPE_INDIRECT) {
if_indextoname(row->dwForwardIfIndex, iface_name);
RouteEntry entry;
entry.interface = iface_name;
entry.destination = IPv4Address(row->dwForwardDest);
entry.mask = IPv4Address(row->dwForwardMask);
entry.gateway = IPv4Address(row->dwForwardNextHop);
*output++ = entry;
}
}
}
#else
template<class ForwardIterator>
void Tins::Utils::route_entries(ForwardIterator output) {
using namespace Tins::Internals;
std::ifstream input("/proc/net/route");
std::string destination, mask, gw;
uint32_t dummy;
@@ -305,5 +416,6 @@ void Tins::Utils::route_entries(ForwardIterator output) {
++output;
}
}
#endif
#endif // TINS_UTILS_H

527
install-sh Executable file
View File

@@ -0,0 +1,527 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2011-01-19.21; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
nl='
'
IFS=" "" $nl"
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit=${DOITPROG-}
if test -z "$doit"; then
doit_exec=exec
else
doit_exec=$doit
fi
# Put in absolute file names if you don't have them in your path;
# or use environment vars.
chgrpprog=${CHGRPPROG-chgrp}
chmodprog=${CHMODPROG-chmod}
chownprog=${CHOWNPROG-chown}
cmpprog=${CMPPROG-cmp}
cpprog=${CPPROG-cp}
mkdirprog=${MKDIRPROG-mkdir}
mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}
posix_glob='?'
initialize_posix_glob='
test "$posix_glob" != "?" || {
if (set -f) 2>/dev/null; then
posix_glob=
else
posix_glob=:
fi
}
'
posix_mkdir=
# Desired mode of installed file.
mode=0755
chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
stripcmd=
src=
dst=
dir_arg=
dst_arg=
copy_on_change=false
no_target_directory=
usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
Options:
--help display this help and exit.
--version display version info and exit.
-c (ignored)
-C install only if different (preserve the last data modification time)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-s $stripprog installed files.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
RMPROG STRIPPROG
"
while test $# -ne 0; do
case $1 in
-c) ;;
-C) copy_on_change=true;;
-d) dir_arg=true;;
-g) chgrpcmd="$chgrpprog $2"
shift;;
--help) echo "$usage"; exit $?;;
-m) mode=$2
case $mode in
*' '* | *' '* | *'
'* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
shift;;
-o) chowncmd="$chownprog $2"
shift;;
-s) stripcmd=$stripprog;;
-t) dst_arg=$2
# Protect names problematic for `test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
shift;;
-T) no_target_directory=true;;
--version) echo "$0 $scriptversion"; exit $?;;
--) shift
break;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
*) break;;
esac
shift
done
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
# When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dst_arg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dst_arg"
shift # fnord
fi
shift # arg
dst_arg=$arg
# Protect names problematic for `test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
done
fi
if test $# -eq 0; then
if test -z "$dir_arg"; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call `install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
if test -z "$dir_arg"; then
do_exit='(exit $ret); exit $ret'
trap "ret=129; $do_exit" 1
trap "ret=130; $do_exit" 2
trap "ret=141; $do_exit" 13
trap "ret=143; $do_exit" 15
# Set umask so as not to create temps with too-generous modes.
# However, 'strip' requires both read and write access to temps.
case $mode in
# Optimize common cases.
*644) cp_umask=133;;
*755) cp_umask=22;;
*[0-7])
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw='% 200'
fi
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
*)
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw=,u+rw
fi
cp_umask=$mode$u_plus_rw;;
esac
fi
for src
do
# Protect names problematic for `test' and other utilities.
case $src in
-* | [=\(\)!]) src=./$src;;
esac
if test -n "$dir_arg"; then
dst=$src
dstdir=$dst
test -d "$dstdir"
dstdir_status=$?
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if test ! -f "$src" && test ! -d "$src"; then
echo "$0: $src does not exist." >&2
exit 1
fi
if test -z "$dst_arg"; then
echo "$0: no destination specified." >&2
exit 1
fi
dst=$dst_arg
# If destination is a directory, append the input filename; won't work
# if double slashes aren't ignored.
if test -d "$dst"; then
if test -n "$no_target_directory"; then
echo "$0: $dst_arg: Is a directory" >&2
exit 1
fi
dstdir=$dst
dst=$dstdir/`basename "$src"`
dstdir_status=0
else
# Prefer dirname, but fall back on a substitute if dirname fails.
dstdir=`
(dirname "$dst") 2>/dev/null ||
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$dst" : 'X\(//\)[^/]' \| \
X"$dst" : 'X\(//\)$' \| \
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
echo X"$dst" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'
`
test -d "$dstdir"
dstdir_status=$?
fi
fi
obsolete_mkdir_used=false
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
# Create intermediate dirs using mode 755 as modified by the umask.
# This is like FreeBSD 'install' as of 1997-10-28.
umask=`umask`
case $stripcmd.$umask in
# Optimize common cases.
*[2367][2367]) mkdir_umask=$umask;;
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
*[0-7])
mkdir_umask=`expr $umask + 22 \
- $umask % 100 % 40 + $umask % 20 \
- $umask % 10 % 4 + $umask % 2
`;;
*) mkdir_umask=$umask,go-w;;
esac
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
mkdir_mode=-m$mode
else
mkdir_mode=
fi
posix_mkdir=false
case $umask in
*[123567][0-7][0-7])
# POSIX mkdir -p sets u+wx bits regardless of umask, which
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
if (umask $mkdir_umask &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writeable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
ls_ld_tmpdir=`ls -ld "$tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/d" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
fi
trap '' 0;;
esac;;
esac
if
$posix_mkdir && (
umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
)
then :
else
# The umask is ridiculous, or mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go.
case $dstdir in
/*) prefix='/';;
[-=\(\)!]*) prefix='./';;
*) prefix='';;
esac
eval "$initialize_posix_glob"
oIFS=$IFS
IFS=/
$posix_glob set -f
set fnord $dstdir
shift
$posix_glob set +f
IFS=$oIFS
prefixes=
for d
do
test X"$d" = X && continue
prefix=$prefix$d
if test -d "$prefix"; then
prefixes=
else
if $posix_mkdir; then
(umask=$mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
else
case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;;
esac
prefixes="$prefixes '$qprefix'"
fi
fi
prefix=$prefix/
done
if test -n "$prefixes"; then
# Don't fail if two instances are running concurrently.
(umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1
obsolete_mkdir_used=true
fi
fi
fi
if test -n "$dir_arg"; then
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
else
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
# Copy the file name to the temp name.
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
# and set any options; do chmod last to preserve setuid bits.
#
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $cpprog $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
# If -C, don't bother to copy if it wouldn't change the file.
if $copy_on_change &&
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
eval "$initialize_posix_glob" &&
$posix_glob set -f &&
set X $old && old=:$2:$4:$5:$6 &&
set X $new && new=:$2:$4:$5:$6 &&
$posix_glob set +f &&
test "$old" = "$new" &&
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
then
rm -f "$dsttmp"
else
# Rename the file to the real destination.
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
{
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
test ! -f "$dst" ||
$doit $rmcmd -f "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
} ||
{ echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1
}
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst"
}
fi || exit 1
trap '' 0
fi
done
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

11
libtins.pc.in Normal file
View File

@@ -0,0 +1,11 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: @PACKAGE_NAME@
Description: C++ packet crafting, sniffing and interpretation library.
Version: @PACKAGE_VERSION@
URL: @PACKAGE_URL@
Libs: -L${libdir} -ltins
Cflags: -I${includedir}/tins

9661
ltmain.sh Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,134 @@
# ============================================================================
# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html
# ============================================================================
#
# SYNOPSIS
#
# AX_CXX_COMPILE_STDCXX_11([ext|noext],[mandatory|optional])
#
# DESCRIPTION
#
# Check for baseline language coverage in the compiler for the C++11
# standard; if necessary, add switches to CXXFLAGS to enable support.
#
# The first argument, if specified, indicates whether you insist on an
# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
# -std=c++11). If neither is specified, you get whatever works, with
# preference for an extended mode.
#
# The second argument, if specified 'mandatory' or if left unspecified,
# indicates that baseline C++11 support is required and that the macro
# should error out if no mode with that support is found. If specified
# 'optional', then configuration proceeds regardless, after defining
# HAVE_CXX11 if and only if a supporting mode is found.
#
# LICENSE
#
# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
# Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
# Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 3
m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [
template <typename T>
struct check
{
static_assert(sizeof(int) <= sizeof(T), "not big enough");
};
typedef check<check<bool>> right_angle_brackets;
int a;
decltype(a) b;
typedef check<int> check_type;
check_type c;
check_type&& cr = static_cast<check_type&&>(c);
auto d = a;
])
AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl
m4_if([$1], [], [],
[$1], [ext], [],
[$1], [noext], [],
[m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_11])])dnl
m4_if([$2], [], [ax_cxx_compile_cxx11_required=true],
[$2], [mandatory], [ax_cxx_compile_cxx11_required=true],
[$2], [optional], [ax_cxx_compile_cxx11_required=false],
[m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX_11])])dnl
AC_LANG_PUSH([C++])dnl
ac_success=no
AC_CACHE_CHECK(whether $CXX supports C++11 features by default,
ax_cv_cxx_compile_cxx11,
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
[ax_cv_cxx_compile_cxx11=yes],
[ax_cv_cxx_compile_cxx11=no])])
if test x$ax_cv_cxx_compile_cxx11 = xyes; then
ac_success=yes
fi
m4_if([$1], [noext], [], [dnl
if test x$ac_success = xno; then
for switch in -std=gnu++11 -std=gnu++0x; do
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch])
AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch,
$cachevar,
[ac_save_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS $switch"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
[eval $cachevar=yes],
[eval $cachevar=no])
CXXFLAGS="$ac_save_CXXFLAGS"])
if eval test x\$$cachevar = xyes; then
CXXFLAGS="$CXXFLAGS $switch"
ac_success=yes
break
fi
done
fi])
m4_if([$1], [ext], [], [dnl
if test x$ac_success = xno; then
for switch in -std=c++11 -std=c++0x; do
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch])
AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch,
$cachevar,
[ac_save_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS $switch"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
[eval $cachevar=yes],
[eval $cachevar=no])
CXXFLAGS="$ac_save_CXXFLAGS"])
if eval test x\$$cachevar = xyes; then
CXXFLAGS="$CXXFLAGS $switch"
ac_success=yes
break
fi
done
fi])
AC_LANG_POP([C++])
if test x$ax_cxx_compile_cxx11_required = xtrue; then
if test x$ac_success = xno; then
AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.])
fi
else
if test x$ac_success = xno; then
HAVE_CXX11=0
AC_MSG_NOTICE([No compiler with C++11 support was found])
else
HAVE_CXX11=1
AC_DEFINE(HAVE_CXX11,1,
[define if the compiler supports basic C++11 syntax])
fi
AC_SUBST(HAVE_CXX11)
fi
])

8001
m4/libtool.m4 vendored Normal file

File diff suppressed because it is too large Load Diff

384
m4/ltoptions.m4 vendored Normal file
View File

@@ -0,0 +1,384 @@
# Helper functions for option handling. -*- Autoconf -*-
#
# Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation,
# Inc.
# Written by Gary V. Vaughan, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 7 ltoptions.m4
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
# ------------------------------------------
m4_define([_LT_MANGLE_OPTION],
[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
# ---------------------------------------
# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
# matching handler defined, dispatch to it. Other OPTION-NAMEs are
# saved as a flag.
m4_define([_LT_SET_OPTION],
[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
_LT_MANGLE_DEFUN([$1], [$2]),
[m4_warning([Unknown $1 option `$2'])])[]dnl
])
# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
# ------------------------------------------------------------
# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
m4_define([_LT_IF_OPTION],
[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
# -------------------------------------------------------
# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
# are set.
m4_define([_LT_UNLESS_OPTIONS],
[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
[m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
[m4_define([$0_found])])])[]dnl
m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
])[]dnl
])
# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
# ----------------------------------------
# OPTION-LIST is a space-separated list of Libtool options associated
# with MACRO-NAME. If any OPTION has a matching handler declared with
# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
# the unknown option and exit.
m4_defun([_LT_SET_OPTIONS],
[# Set options
m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
[_LT_SET_OPTION([$1], _LT_Option)])
m4_if([$1],[LT_INIT],[
dnl
dnl Simply set some default values (i.e off) if boolean options were not
dnl specified:
_LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
])
_LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
])
dnl
dnl If no reference was made to various pairs of opposing options, then
dnl we run the default mode handler for the pair. For example, if neither
dnl `shared' nor `disable-shared' was passed, we enable building of shared
dnl archives by default:
_LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
_LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
_LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
_LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
[_LT_ENABLE_FAST_INSTALL])
])
])# _LT_SET_OPTIONS
## --------------------------------- ##
## Macros to handle LT_INIT options. ##
## --------------------------------- ##
# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
# -----------------------------------------
m4_define([_LT_MANGLE_DEFUN],
[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
# -----------------------------------------------
m4_define([LT_OPTION_DEFINE],
[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
])# LT_OPTION_DEFINE
# dlopen
# ------
LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
])
AU_DEFUN([AC_LIBTOOL_DLOPEN],
[_LT_SET_OPTION([LT_INIT], [dlopen])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the `dlopen' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
# win32-dll
# ---------
# Declare package support for building win32 dll's.
LT_OPTION_DEFINE([LT_INIT], [win32-dll],
[enable_win32_dll=yes
case $host in
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
AC_CHECK_TOOL(AS, as, false)
AC_CHECK_TOOL(DLLTOOL, dlltool, false)
AC_CHECK_TOOL(OBJDUMP, objdump, false)
;;
esac
test -z "$AS" && AS=as
_LT_DECL([], [AS], [1], [Assembler program])dnl
test -z "$DLLTOOL" && DLLTOOL=dlltool
_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl
test -z "$OBJDUMP" && OBJDUMP=objdump
_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl
])# win32-dll
AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
_LT_SET_OPTION([LT_INIT], [win32-dll])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the `win32-dll' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
# _LT_ENABLE_SHARED([DEFAULT])
# ----------------------------
# implement the --enable-shared flag, and supports the `shared' and
# `disable-shared' LT_INIT options.
# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
m4_define([_LT_ENABLE_SHARED],
[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([shared],
[AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
[build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_shared=yes ;;
no) enable_shared=no ;;
*)
enable_shared=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
for pkg in $enableval; do
IFS="$lt_save_ifs"
if test "X$pkg" = "X$p"; then
enable_shared=yes
fi
done
IFS="$lt_save_ifs"
;;
esac],
[enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
_LT_DECL([build_libtool_libs], [enable_shared], [0],
[Whether or not to build shared libraries])
])# _LT_ENABLE_SHARED
LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
# Old names:
AC_DEFUN([AC_ENABLE_SHARED],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
])
AC_DEFUN([AC_DISABLE_SHARED],
[_LT_SET_OPTION([LT_INIT], [disable-shared])
])
AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AM_ENABLE_SHARED], [])
dnl AC_DEFUN([AM_DISABLE_SHARED], [])
# _LT_ENABLE_STATIC([DEFAULT])
# ----------------------------
# implement the --enable-static flag, and support the `static' and
# `disable-static' LT_INIT options.
# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
m4_define([_LT_ENABLE_STATIC],
[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([static],
[AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
[build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_static=yes ;;
no) enable_static=no ;;
*)
enable_static=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
for pkg in $enableval; do
IFS="$lt_save_ifs"
if test "X$pkg" = "X$p"; then
enable_static=yes
fi
done
IFS="$lt_save_ifs"
;;
esac],
[enable_static=]_LT_ENABLE_STATIC_DEFAULT)
_LT_DECL([build_old_libs], [enable_static], [0],
[Whether or not to build static libraries])
])# _LT_ENABLE_STATIC
LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
# Old names:
AC_DEFUN([AC_ENABLE_STATIC],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
])
AC_DEFUN([AC_DISABLE_STATIC],
[_LT_SET_OPTION([LT_INIT], [disable-static])
])
AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AM_ENABLE_STATIC], [])
dnl AC_DEFUN([AM_DISABLE_STATIC], [])
# _LT_ENABLE_FAST_INSTALL([DEFAULT])
# ----------------------------------
# implement the --enable-fast-install flag, and support the `fast-install'
# and `disable-fast-install' LT_INIT options.
# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
m4_define([_LT_ENABLE_FAST_INSTALL],
[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([fast-install],
[AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
[optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_fast_install=yes ;;
no) enable_fast_install=no ;;
*)
enable_fast_install=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
for pkg in $enableval; do
IFS="$lt_save_ifs"
if test "X$pkg" = "X$p"; then
enable_fast_install=yes
fi
done
IFS="$lt_save_ifs"
;;
esac],
[enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
_LT_DECL([fast_install], [enable_fast_install], [0],
[Whether or not to optimize for fast installation])dnl
])# _LT_ENABLE_FAST_INSTALL
LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
# Old names:
AU_DEFUN([AC_ENABLE_FAST_INSTALL],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you put
the `fast-install' option into LT_INIT's first parameter.])
])
AU_DEFUN([AC_DISABLE_FAST_INSTALL],
[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you put
the `disable-fast-install' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
# _LT_WITH_PIC([MODE])
# --------------------
# implement the --with-pic flag, and support the `pic-only' and `no-pic'
# LT_INIT options.
# MODE is either `yes' or `no'. If omitted, it defaults to `both'.
m4_define([_LT_WITH_PIC],
[AC_ARG_WITH([pic],
[AS_HELP_STRING([--with-pic@<:@=PKGS@:>@],
[try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
[lt_p=${PACKAGE-default}
case $withval in
yes|no) pic_mode=$withval ;;
*)
pic_mode=default
# Look at the argument we got. We use all the common list separators.
lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
for lt_pkg in $withval; do
IFS="$lt_save_ifs"
if test "X$lt_pkg" = "X$lt_p"; then
pic_mode=yes
fi
done
IFS="$lt_save_ifs"
;;
esac],
[pic_mode=default])
test -z "$pic_mode" && pic_mode=m4_default([$1], [default])
_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
])# _LT_WITH_PIC
LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
# Old name:
AU_DEFUN([AC_LIBTOOL_PICMODE],
[_LT_SET_OPTION([LT_INIT], [pic-only])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the `pic-only' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
## ----------------- ##
## LTDL_INIT Options ##
## ----------------- ##
m4_define([_LTDL_MODE], [])
LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
[m4_define([_LTDL_MODE], [nonrecursive])])
LT_OPTION_DEFINE([LTDL_INIT], [recursive],
[m4_define([_LTDL_MODE], [recursive])])
LT_OPTION_DEFINE([LTDL_INIT], [subproject],
[m4_define([_LTDL_MODE], [subproject])])
m4_define([_LTDL_TYPE], [])
LT_OPTION_DEFINE([LTDL_INIT], [installable],
[m4_define([_LTDL_TYPE], [installable])])
LT_OPTION_DEFINE([LTDL_INIT], [convenience],
[m4_define([_LTDL_TYPE], [convenience])])

123
m4/ltsugar.m4 vendored Normal file
View File

@@ -0,0 +1,123 @@
# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
#
# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 6 ltsugar.m4
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
# lt_join(SEP, ARG1, [ARG2...])
# -----------------------------
# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
# associated separator.
# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
# versions in m4sugar had bugs.
m4_define([lt_join],
[m4_if([$#], [1], [],
[$#], [2], [[$2]],
[m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
m4_define([_lt_join],
[m4_if([$#$2], [2], [],
[m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
# lt_car(LIST)
# lt_cdr(LIST)
# ------------
# Manipulate m4 lists.
# These macros are necessary as long as will still need to support
# Autoconf-2.59 which quotes differently.
m4_define([lt_car], [[$1]])
m4_define([lt_cdr],
[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
[$#], 1, [],
[m4_dquote(m4_shift($@))])])
m4_define([lt_unquote], $1)
# lt_append(MACRO-NAME, STRING, [SEPARATOR])
# ------------------------------------------
# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'.
# Note that neither SEPARATOR nor STRING are expanded; they are appended
# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
# No SEPARATOR is output if MACRO-NAME was previously undefined (different
# than defined and empty).
#
# This macro is needed until we can rely on Autoconf 2.62, since earlier
# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
m4_define([lt_append],
[m4_define([$1],
m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
# ----------------------------------------------------------
# Produce a SEP delimited list of all paired combinations of elements of
# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list
# has the form PREFIXmINFIXSUFFIXn.
# Needed until we can rely on m4_combine added in Autoconf 2.62.
m4_define([lt_combine],
[m4_if(m4_eval([$# > 3]), [1],
[m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
[[m4_foreach([_Lt_prefix], [$2],
[m4_foreach([_Lt_suffix],
]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
[_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
# -----------------------------------------------------------------------
# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
m4_define([lt_if_append_uniq],
[m4_ifdef([$1],
[m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
[lt_append([$1], [$2], [$3])$4],
[$5])],
[lt_append([$1], [$2], [$3])$4])])
# lt_dict_add(DICT, KEY, VALUE)
# -----------------------------
m4_define([lt_dict_add],
[m4_define([$1($2)], [$3])])
# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
# --------------------------------------------
m4_define([lt_dict_add_subkey],
[m4_define([$1($2:$3)], [$4])])
# lt_dict_fetch(DICT, KEY, [SUBKEY])
# ----------------------------------
m4_define([lt_dict_fetch],
[m4_ifval([$3],
m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
# -----------------------------------------------------------------
m4_define([lt_if_dict_fetch],
[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
[$5],
[$6])])
# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
# --------------------------------------------------------------
m4_define([lt_dict_filter],
[m4_if([$5], [], [],
[lt_join(m4_quote(m4_default([$4], [[, ]])),
lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
[lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
])

23
m4/ltversion.m4 vendored Normal file
View File

@@ -0,0 +1,23 @@
# ltversion.m4 -- version numbers -*- Autoconf -*-
#
# Copyright (C) 2004 Free Software Foundation, Inc.
# Written by Scott James Remnant, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# @configure_input@
# serial 3337 ltversion.m4
# This file is part of GNU Libtool
m4_define([LT_PACKAGE_VERSION], [2.4.2])
m4_define([LT_PACKAGE_REVISION], [1.3337])
AC_DEFUN([LTVERSION_VERSION],
[macro_version='2.4.2'
macro_revision='1.3337'
_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
_LT_DECL(, macro_revision, 0)
])

98
m4/lt~obsolete.m4 vendored Normal file
View File

@@ -0,0 +1,98 @@
# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
#
# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
# Written by Scott James Remnant, 2004.
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 5 lt~obsolete.m4
# These exist entirely to fool aclocal when bootstrapping libtool.
#
# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN)
# which have later been changed to m4_define as they aren't part of the
# exported API, or moved to Autoconf or Automake where they belong.
#
# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN
# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
# using a macro with the same name in our local m4/libtool.m4 it'll
# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
# and doesn't know about Autoconf macros at all.)
#
# So we provide this file, which has a silly filename so it's always
# included after everything else. This provides aclocal with the
# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
# because those macros already exist, or will be overwritten later.
# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
#
# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
# Yes, that means every name once taken will need to remain here until
# we give up compatibility with versions before 1.7, at which point
# we need to keep only those names which we still refer to.
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])])
m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])])
m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])])
m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])])
m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])])
m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])])
m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])])
m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])])
m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])])
m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])])
m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])])
m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])])
m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])])
m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])])
m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])])
m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])])
m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])])
m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])])
m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])])
m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])])
m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])])
m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])])
m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])])
m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])])

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