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

58 Commits
v1.0 ... v1.2

Author SHA1 Message Date
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
138 changed files with 12452 additions and 7116 deletions

54
CHANGES
View File

@@ -1,3 +1,57 @@
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

View File

@@ -31,7 +31,7 @@ PROJECT_NAME = libtins
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER = 1.0
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.
@@ -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

View File

@@ -13,6 +13,7 @@ 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 \
@@ -20,7 +21,6 @@ libtins_la_SOURCES=src/arp.cpp \
src/dhcpv6.cpp \
src/dns.cpp \
src/dns_record.cpp \
src/dot11.cpp \
src/dot3.cpp \
src/dot1q.cpp \
src/eapol.cpp \
@@ -36,8 +36,10 @@ libtins_la_SOURCES=src/arp.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 \
@@ -46,10 +48,19 @@ libtins_la_SOURCES=src/arp.cpp \
src/tcp.cpp \
src/tcp_stream.cpp \
src/udp.cpp \
src/utils.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
libtins_includedir = $(includedir)/tins
libtins_include_HEADERS = include/internals.h \
libtinsdir = $(includedir)/tins
libtins_HEADERS = include/internals.h \
include/dhcpv6.h \
include/dot11.h \
include/dot1q.h \
@@ -60,6 +71,7 @@ libtins_include_HEADERS = include/internals.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 \
@@ -81,6 +93,7 @@ libtins_include_HEADERS = include/internals.h \
include/bootp.h \
include/network_interface.h \
include/sll.h \
include/ppi.h \
include/radiotap.h \
include/dns.h \
include/rawpdu.h \
@@ -98,4 +111,18 @@ libtins_include_HEADERS = include/internals.h \
include/utils.h \
include/cxxstd.h \
include/stp.h \
include/exceptions.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/

View File

@@ -55,11 +55,12 @@ build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
subdir = .
DIST_COMMON = README $(am__configure_deps) $(libtins_include_HEADERS) \
$(srcdir)/Makefile.am $(srcdir)/Makefile.in \
$(srcdir)/libtins.pc.in $(top_srcdir)/configure \
$(top_srcdir)/include/config.h.in AUTHORS THANKS TODO \
config.guess config.sub depcomp install-sh ltmain.sh missing
DIST_COMMON = README $(am__configure_deps) $(libtins_HEADERS) \
$(libtins_dot11_HEADERS) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in $(srcdir)/libtins.pc.in \
$(top_srcdir)/configure $(top_srcdir)/include/config.h.in \
AUTHORS COPYING INSTALL THANKS TODO config.guess config.sub \
depcomp install-sh ltmain.sh missing
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
@@ -101,20 +102,25 @@ am__uninstall_files_from_dir = { \
$(am__cd) "$$dir" && rm -f $$files; }; \
}
am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" \
"$(DESTDIR)$(libtins_includedir)"
"$(DESTDIR)$(libtinsdir)" "$(DESTDIR)$(libtins_dot11dir)"
LTLIBRARIES = $(lib_LTLIBRARIES)
libtins_la_LIBADD =
am__dirstamp = $(am__leading_dot)dirstamp
am_libtins_la_OBJECTS = src/arp.lo src/bootp.lo src/stp.lo \
src/pppoe.lo src/crypto.lo src/dhcp.lo src/dhcpv6.lo \
src/dns.lo src/dns_record.lo src/dot11.lo src/dot3.lo \
src/dot1q.lo src/eapol.lo src/ethernetII.lo src/icmp.lo \
src/icmpv6.lo src/internals.lo src/ip.lo src/ip_address.lo \
src/ipv6.lo src/ipv6_address.lo src/llc.lo src/loopback.lo \
src/network_interface.lo src/packet_sender.lo \
src/packet_writer.lo src/pdu.lo src/radiotap.lo src/rawpdu.lo \
am_libtins_la_OBJECTS = src/arp.lo src/bootp.lo \
src/handshake_capturer.lo src/stp.lo src/pppoe.lo \
src/crypto.lo src/dhcp.lo src/dhcpv6.lo src/dns.lo \
src/dns_record.lo src/dot3.lo src/dot1q.lo src/eapol.lo \
src/ethernetII.lo src/icmp.lo src/icmpv6.lo src/internals.lo \
src/ip.lo src/ip_address.lo src/ipv6.lo src/ipv6_address.lo \
src/llc.lo src/loopback.lo src/network_interface.lo \
src/packet_sender.lo src/packet_writer.lo src/ppi.lo \
src/pdu.lo src/radiotap.lo src/address_range.lo src/rawpdu.lo \
src/rsn_information.lo src/sll.lo src/snap.lo src/sniffer.lo \
src/tcp.lo src/tcp_stream.lo src/udp.lo src/utils.lo
src/tcp.lo src/tcp_stream.lo src/udp.lo src/utils.lo \
src/dot11/dot11_base.lo src/dot11/dot11_data.lo \
src/dot11/dot11_mgmt.lo src/dot11/dot11_beacon.lo \
src/dot11/dot11_assoc.lo src/dot11/dot11_auth.lo \
src/dot11/dot11_probe.lo src/dot11/dot11_control.lo
libtins_la_OBJECTS = $(am_libtins_la_OBJECTS)
libtins_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
@@ -140,7 +146,7 @@ am__can_run_installinfo = \
*) (install-info --version) >/dev/null 2>&1;; \
esac
DATA = $(pkgconfig_DATA)
HEADERS = $(libtins_include_HEADERS)
HEADERS = $(libtins_HEADERS) $(libtins_dot11_HEADERS)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -295,6 +301,7 @@ 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 \
@@ -302,7 +309,6 @@ libtins_la_SOURCES = src/arp.cpp \
src/dhcpv6.cpp \
src/dns.cpp \
src/dns_record.cpp \
src/dot11.cpp \
src/dot3.cpp \
src/dot1q.cpp \
src/eapol.cpp \
@@ -318,8 +324,10 @@ libtins_la_SOURCES = src/arp.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 \
@@ -328,10 +336,18 @@ libtins_la_SOURCES = src/arp.cpp \
src/tcp.cpp \
src/tcp_stream.cpp \
src/udp.cpp \
src/utils.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
libtins_includedir = $(includedir)/tins
libtins_include_HEADERS = include/internals.h \
libtinsdir = $(includedir)/tins
libtins_HEADERS = include/internals.h \
include/dhcpv6.h \
include/dot11.h \
include/dot1q.h \
@@ -342,6 +358,7 @@ libtins_include_HEADERS = include/internals.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 \
@@ -363,6 +380,7 @@ libtins_include_HEADERS = include/internals.h \
include/bootp.h \
include/network_interface.h \
include/sll.h \
include/ppi.h \
include/radiotap.h \
include/dns.h \
include/rawpdu.h \
@@ -380,8 +398,21 @@ libtins_include_HEADERS = include/internals.h \
include/utils.h \
include/cxxstd.h \
include/stp.h \
include/exceptions.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/
all: all-am
.SUFFIXES:
@@ -477,6 +508,8 @@ src/$(DEPDIR)/$(am__dirstamp):
@: > src/$(DEPDIR)/$(am__dirstamp)
src/arp.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/bootp.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/handshake_capturer.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/stp.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/pppoe.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/crypto.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
@@ -484,7 +517,6 @@ src/dhcp.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/dhcpv6.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/dns.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/dns_record.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/dot11.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/dot3.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/dot1q.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/eapol.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
@@ -504,8 +536,11 @@ src/packet_sender.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/packet_writer.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/ppi.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/pdu.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/radiotap.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/address_range.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/rawpdu.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/rsn_information.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
@@ -516,11 +551,35 @@ src/tcp.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/tcp_stream.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/udp.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/utils.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/dot11/$(am__dirstamp):
@$(MKDIR_P) src/dot11
@: > src/dot11/$(am__dirstamp)
src/dot11/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) src/dot11/$(DEPDIR)
@: > src/dot11/$(DEPDIR)/$(am__dirstamp)
src/dot11/dot11_base.lo: src/dot11/$(am__dirstamp) \
src/dot11/$(DEPDIR)/$(am__dirstamp)
src/dot11/dot11_data.lo: src/dot11/$(am__dirstamp) \
src/dot11/$(DEPDIR)/$(am__dirstamp)
src/dot11/dot11_mgmt.lo: src/dot11/$(am__dirstamp) \
src/dot11/$(DEPDIR)/$(am__dirstamp)
src/dot11/dot11_beacon.lo: src/dot11/$(am__dirstamp) \
src/dot11/$(DEPDIR)/$(am__dirstamp)
src/dot11/dot11_assoc.lo: src/dot11/$(am__dirstamp) \
src/dot11/$(DEPDIR)/$(am__dirstamp)
src/dot11/dot11_auth.lo: src/dot11/$(am__dirstamp) \
src/dot11/$(DEPDIR)/$(am__dirstamp)
src/dot11/dot11_probe.lo: src/dot11/$(am__dirstamp) \
src/dot11/$(DEPDIR)/$(am__dirstamp)
src/dot11/dot11_control.lo: src/dot11/$(am__dirstamp) \
src/dot11/$(DEPDIR)/$(am__dirstamp)
libtins.la: $(libtins_la_OBJECTS) $(libtins_la_DEPENDENCIES) $(EXTRA_libtins_la_DEPENDENCIES)
$(libtins_la_LINK) -rpath $(libdir) $(libtins_la_OBJECTS) $(libtins_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
-rm -f src/address_range.$(OBJEXT)
-rm -f src/address_range.lo
-rm -f src/arp.$(OBJEXT)
-rm -f src/arp.lo
-rm -f src/bootp.$(OBJEXT)
@@ -535,8 +594,22 @@ mostlyclean-compile:
-rm -f src/dns.lo
-rm -f src/dns_record.$(OBJEXT)
-rm -f src/dns_record.lo
-rm -f src/dot11.$(OBJEXT)
-rm -f src/dot11.lo
-rm -f src/dot11/dot11_assoc.$(OBJEXT)
-rm -f src/dot11/dot11_assoc.lo
-rm -f src/dot11/dot11_auth.$(OBJEXT)
-rm -f src/dot11/dot11_auth.lo
-rm -f src/dot11/dot11_base.$(OBJEXT)
-rm -f src/dot11/dot11_base.lo
-rm -f src/dot11/dot11_beacon.$(OBJEXT)
-rm -f src/dot11/dot11_beacon.lo
-rm -f src/dot11/dot11_control.$(OBJEXT)
-rm -f src/dot11/dot11_control.lo
-rm -f src/dot11/dot11_data.$(OBJEXT)
-rm -f src/dot11/dot11_data.lo
-rm -f src/dot11/dot11_mgmt.$(OBJEXT)
-rm -f src/dot11/dot11_mgmt.lo
-rm -f src/dot11/dot11_probe.$(OBJEXT)
-rm -f src/dot11/dot11_probe.lo
-rm -f src/dot1q.$(OBJEXT)
-rm -f src/dot1q.lo
-rm -f src/dot3.$(OBJEXT)
@@ -545,6 +618,8 @@ mostlyclean-compile:
-rm -f src/eapol.lo
-rm -f src/ethernetII.$(OBJEXT)
-rm -f src/ethernetII.lo
-rm -f src/handshake_capturer.$(OBJEXT)
-rm -f src/handshake_capturer.lo
-rm -f src/icmp.$(OBJEXT)
-rm -f src/icmp.lo
-rm -f src/icmpv6.$(OBJEXT)
@@ -571,6 +646,8 @@ mostlyclean-compile:
-rm -f src/packet_writer.lo
-rm -f src/pdu.$(OBJEXT)
-rm -f src/pdu.lo
-rm -f src/ppi.$(OBJEXT)
-rm -f src/ppi.lo
-rm -f src/pppoe.$(OBJEXT)
-rm -f src/pppoe.lo
-rm -f src/radiotap.$(OBJEXT)
@@ -599,6 +676,7 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/address_range.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/arp.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bootp.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/crypto.Plo@am__quote@
@@ -606,11 +684,11 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dhcpv6.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dns.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dns_record.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dot11.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dot1q.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dot3.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/eapol.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/ethernetII.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/handshake_capturer.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/icmp.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/icmpv6.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/internals.Plo@am__quote@
@@ -624,6 +702,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/packet_sender.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/packet_writer.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/pdu.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/ppi.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/pppoe.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/radiotap.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/rawpdu.Plo@am__quote@
@@ -636,6 +715,14 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/tcp_stream.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/udp.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/utils.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/dot11/$(DEPDIR)/dot11_assoc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/dot11/$(DEPDIR)/dot11_auth.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/dot11/$(DEPDIR)/dot11_base.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/dot11/$(DEPDIR)/dot11_beacon.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/dot11/$(DEPDIR)/dot11_control.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/dot11/$(DEPDIR)/dot11_data.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/dot11/$(DEPDIR)/dot11_mgmt.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/dot11/$(DEPDIR)/dot11_probe.Plo@am__quote@
.cpp.o:
@am__fastdepCXX_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
@@ -667,6 +754,7 @@ mostlyclean-libtool:
clean-libtool:
-rm -rf .libs _libs
-rm -rf src/.libs src/_libs
-rm -rf src/dot11/.libs src/dot11/_libs
distclean-libtool:
-rm -f libtool config.lt
@@ -691,27 +779,48 @@ uninstall-pkgconfigDATA:
@list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir)
install-libtins_includeHEADERS: $(libtins_include_HEADERS)
install-libtinsHEADERS: $(libtins_HEADERS)
@$(NORMAL_INSTALL)
@list='$(libtins_include_HEADERS)'; test -n "$(libtins_includedir)" || list=; \
@list='$(libtins_HEADERS)'; test -n "$(libtinsdir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(libtins_includedir)'"; \
$(MKDIR_P) "$(DESTDIR)$(libtins_includedir)" || exit 1; \
echo " $(MKDIR_P) '$(DESTDIR)$(libtinsdir)'"; \
$(MKDIR_P) "$(DESTDIR)$(libtinsdir)" || exit 1; \
fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libtins_includedir)'"; \
$(INSTALL_HEADER) $$files "$(DESTDIR)$(libtins_includedir)" || exit $$?; \
echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libtinsdir)'"; \
$(INSTALL_HEADER) $$files "$(DESTDIR)$(libtinsdir)" || exit $$?; \
done
uninstall-libtins_includeHEADERS:
uninstall-libtinsHEADERS:
@$(NORMAL_UNINSTALL)
@list='$(libtins_include_HEADERS)'; test -n "$(libtins_includedir)" || list=; \
@list='$(libtins_HEADERS)'; test -n "$(libtinsdir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
dir='$(DESTDIR)$(libtins_includedir)'; $(am__uninstall_files_from_dir)
dir='$(DESTDIR)$(libtinsdir)'; $(am__uninstall_files_from_dir)
install-libtins_dot11HEADERS: $(libtins_dot11_HEADERS)
@$(NORMAL_INSTALL)
@list='$(libtins_dot11_HEADERS)'; test -n "$(libtins_dot11dir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(libtins_dot11dir)'"; \
$(MKDIR_P) "$(DESTDIR)$(libtins_dot11dir)" || exit 1; \
fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libtins_dot11dir)'"; \
$(INSTALL_HEADER) $$files "$(DESTDIR)$(libtins_dot11dir)" || exit $$?; \
done
uninstall-libtins_dot11HEADERS:
@$(NORMAL_UNINSTALL)
@list='$(libtins_dot11_HEADERS)'; test -n "$(libtins_dot11dir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
dir='$(DESTDIR)$(libtins_dot11dir)'; $(am__uninstall_files_from_dir)
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
@@ -931,7 +1040,7 @@ check-am: all-am
check: check-am
all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS)
installdirs:
for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(libtins_includedir)"; do \
for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(libtinsdir)" "$(DESTDIR)$(libtins_dot11dir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
@@ -962,6 +1071,8 @@ distclean-generic:
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-rm -f src/$(DEPDIR)/$(am__dirstamp)
-rm -f src/$(am__dirstamp)
-rm -f src/dot11/$(DEPDIR)/$(am__dirstamp)
-rm -f src/dot11/$(am__dirstamp)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@@ -973,7 +1084,7 @@ clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
distclean: distclean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf src/$(DEPDIR)
-rm -rf src/$(DEPDIR) src/dot11/$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-hdr distclean-libtool distclean-tags
@@ -990,7 +1101,8 @@ info: info-am
info-am:
install-data-am: install-libtins_includeHEADERS install-pkgconfigDATA
install-data-am: install-libtinsHEADERS install-libtins_dot11HEADERS \
install-pkgconfigDATA
install-dvi: install-dvi-am
@@ -1021,7 +1133,7 @@ installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf $(top_srcdir)/autom4te.cache
-rm -rf src/$(DEPDIR)
-rm -rf src/$(DEPDIR) src/dot11/$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
@@ -1038,8 +1150,8 @@ ps: ps-am
ps-am:
uninstall-am: uninstall-libLTLIBRARIES \
uninstall-libtins_includeHEADERS uninstall-pkgconfigDATA
uninstall-am: uninstall-libLTLIBRARIES uninstall-libtinsHEADERS \
uninstall-libtins_dot11HEADERS uninstall-pkgconfigDATA
.MAKE: install-am install-strip
@@ -1053,14 +1165,15 @@ uninstall-am: uninstall-libLTLIBRARIES \
install install-am install-data install-data-am install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am \
install-libLTLIBRARIES install-libtins_includeHEADERS \
install-man install-pdf install-pdf-am install-pkgconfigDATA \
install-ps install-ps-am install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags uninstall uninstall-am uninstall-libLTLIBRARIES \
uninstall-libtins_includeHEADERS uninstall-pkgconfigDATA
install-libLTLIBRARIES install-libtinsHEADERS \
install-libtins_dot11HEADERS install-man install-pdf \
install-pdf-am install-pkgconfigDATA install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
pdf pdf-am ps ps-am tags uninstall uninstall-am \
uninstall-libLTLIBRARIES uninstall-libtinsHEADERS \
uninstall-libtins_dot11HEADERS uninstall-pkgconfigDATA
# Tell versions [3.59,3.63) of GNU make to not export all variables.

2
README
View File

@@ -1,5 +1,5 @@
------------------------------------------------------------------------
libtins v1.0
libtins v1.1
------------------------------------------------------------------------

106
configure vendored
View File

@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for libtins 1.0.
# Generated by GNU Autoconf 2.69 for libtins 1.2.
#
# Report bugs to <matias.fontanini@gmail.com>.
#
@@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='libtins'
PACKAGE_TARNAME='libtins'
PACKAGE_VERSION='1.0'
PACKAGE_STRING='libtins 1.0'
PACKAGE_VERSION='1.2'
PACKAGE_STRING='libtins 1.2'
PACKAGE_BUGREPORT='matias.fontanini@gmail.com'
PACKAGE_URL='http://libtins.sourceforge.net'
@@ -775,6 +775,7 @@ enable_maintainer_mode
with_pcap_include_path
with_pcap_lib_path
enable_c__11
enable_wpa2
'
ac_precious_vars='build_alias
host_alias
@@ -1329,7 +1330,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures libtins 1.0 to adapt to many kinds of systems.
\`configure' configures libtins 1.2 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1400,7 +1401,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of libtins 1.0:";;
short | recursive ) echo "Configuration of libtins 1.2:";;
esac
cat <<\_ACEOF
@@ -1418,6 +1419,7 @@ Optional Features:
--disable-maintainer-mode disable make rules and dependencies not useful
(and sometimes confusing) to the casual installer
--enable-c++11 enable C++11 features
--disable-wpa2 disable WPA2 decryption features
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -1512,7 +1514,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
libtins configure 1.0
libtins configure 1.2
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2002,7 +2004,7 @@ 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 libtins $as_me 1.0, which was
It was created by libtins $as_me 1.2, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2930,7 +2932,7 @@ fi
# Define the identity of the package.
PACKAGE='libtins'
VERSION='1.0'
VERSION='1.2'
cat >>confdefs.h <<_ACEOF
@@ -15199,6 +15201,8 @@ CPPFLAGS=$old_cppflags
# Options
wpa2_msg="WPA2 decryption(which requires openssl) can be disabled using the --disable-wpa2 flag."
# Check whether --enable-c++11 was given.
if test "${enable_c__11+set}" = set; then :
enableval=$enable_c__11; ax_cxx_compile_cxx11_required=truednl
@@ -15324,6 +15328,86 @@ $as_echo "#define HAVE_CXX11 1" >>confdefs.h
fi
fi
# Check whether --enable-wpa2 was given.
if test "${enable_wpa2+set}" = set; then :
enableval=$enable_wpa2;
else
for ac_header in openssl/evp.h openssl/hmac.h openssl/aes.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_cxx_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
else
as_fn_error $? "openssl headers are missing! $wpa2_msg " "$LINENO" 5
$as_echo "#define HAVE_WPA2_DECRYPTION 0" >>confdefs.h
fi
done
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PKCS5_PBKDF2_HMAC_SHA1 in -lcrypto" >&5
$as_echo_n "checking for PKCS5_PBKDF2_HMAC_SHA1 in -lcrypto... " >&6; }
if ${ac_cv_lib_crypto_PKCS5_PBKDF2_HMAC_SHA1+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lcrypto $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 PKCS5_PBKDF2_HMAC_SHA1 ();
int
main ()
{
return PKCS5_PBKDF2_HMAC_SHA1 ();
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_link "$LINENO"; then :
ac_cv_lib_crypto_PKCS5_PBKDF2_HMAC_SHA1=yes
else
ac_cv_lib_crypto_PKCS5_PBKDF2_HMAC_SHA1=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_crypto_PKCS5_PBKDF2_HMAC_SHA1" >&5
$as_echo "$ac_cv_lib_crypto_PKCS5_PBKDF2_HMAC_SHA1" >&6; }
if test "x$ac_cv_lib_crypto_PKCS5_PBKDF2_HMAC_SHA1" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBCRYPTO 1
_ACEOF
LIBS="-lcrypto $LIBS"
else
as_fn_error $? "openssl library is missing! $wpa2_msg " "$LINENO" 5
fi
$as_echo "#define HAVE_WPA2_DECRYPTION 1" >>confdefs.h
fi
@@ -15332,7 +15416,7 @@ fi
LIBTINS_VERSION=1:0:0
LIBTINS_VERSION=1:1:0
ac_config_files="$ac_config_files Makefile libtins.pc"
@@ -15866,7 +15950,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by libtins $as_me 1.0, which was
This file was extended by libtins $as_me 1.2, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -15933,7 +16017,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
libtins config.status 1.0
libtins config.status 1.2
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"

View File

@@ -1,7 +1,7 @@
AC_INIT([libtins], [1.0], [matias.fontanini@gmail.com], [libtins], [http://libtins.sourceforge.net])
AC_INIT([libtins], [1.2], [matias.fontanini@gmail.com], [libtins], [http://libtins.sourceforge.net])
AC_CANONICAL_SYSTEM
AC_CONFIG_HEADER(include/config.h)
AM_INIT_AUTOMAKE([-Wall -Werror])
AM_INIT_AUTOMAKE([-Wall -Werror -Wno-extra-portability foreign])
LT_INIT([disable-static])
AC_CONFIG_MACRO_DIR([m4])
AM_MAINTAINER_MODE([enable])
@@ -36,17 +36,40 @@ 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(
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], [1:0:0])
AC_SUBST([LIBTINS_VERSION], [1:1:0])
AC_CONFIG_FILES([Makefile libtins.pc])
AC_OUTPUT

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
@@ -62,18 +62,18 @@ void 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(gw_hw, info.hw_addr, gw_arp);
EthernetII to_victim(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, iface);

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".

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,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;
}
@@ -75,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.
@@ -93,11 +92,11 @@ 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(info.hw_addr, info.hw_addr, ip.clone());
EthernetII eth = EthernetII(info.hw_addr, info.hw_addr) / ip;
sender.send(eth, iface);
}

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;
}

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

@@ -71,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(),
@@ -125,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
*/
@@ -195,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.
*/
@@ -233,18 +242,18 @@ 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 an EthernetII PDU.
*
* Creates an ARP Request PDU and embeds it within a Layer 2 PDU ready to be
* sent.
* Creates an ARP Request PDU and embeds it inside an EthernetII
* PDU.
*
* \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(ipaddress_type target,
ipaddress_type sender, const hwaddress_type &hw_snd = hwaddress_type());
@@ -252,20 +261,21 @@ namespace Tins {
/**
* \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.
* Creates an ARP Reply PDU and embeds it inside an EthernetII
* PDU.
*
* \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(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.

View File

@@ -275,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);
}
/**
@@ -299,7 +300,7 @@ namespace Tins {
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* This returns true, if the xid field is equal.
* This returns true if the xid field is equal.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
@@ -311,7 +312,7 @@ namespace Tins {
* \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

View File

@@ -9,12 +9,24 @@
/* 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
@@ -39,6 +51,9 @@
/* 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

View File

@@ -34,15 +34,64 @@
#include <string>
#include <algorithm>
#include <vector>
#include "dot11.h"
#include "utils.h"
#include "snap.h"
#include "rawpdu.h"
#include "handshake_capturer.h"
#include "config.h"
namespace Tins {
class PDU;
class Dot11;
class Dot11Data;
namespace Crypto {
/**
* \cond
*/
class 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 +114,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 +142,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 +165,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 +321,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 +329,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 +381,7 @@ namespace Crypto {
{
return DecrypterProxy<Functor, WEPDecrypter>(functor);
}
// RC4 stuff
template<typename ForwardIterator>

View File

@@ -40,8 +40,10 @@
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:
@@ -162,12 +164,11 @@ namespace Tins {
* \brief Constructs a DHCP object from a buffer.
*
* If there is not enough size for a BootP header, or any of
* the TLV options contain an invalid size field, then a
* 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);
@@ -199,13 +200,18 @@ namespace Tins {
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
@@ -215,60 +221,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);
/**
* \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);
/**
* \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);
@@ -278,7 +314,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.
@@ -288,7 +324,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.
@@ -298,7 +334,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.
@@ -308,7 +344,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.
@@ -318,7 +354,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.
@@ -328,7 +364,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.
@@ -338,7 +374,7 @@ 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
@@ -349,7 +385,7 @@ namespace Tins {
/**
* \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
@@ -360,7 +396,7 @@ namespace Tins {
/**
* \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.
@@ -370,7 +406,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.
@@ -380,14 +416,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; }
@@ -396,7 +433,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.

View File

@@ -442,7 +442,6 @@ public:
* \return The stored options.
*/
const options_type &options() const { return options_; }
;
// Setters
/**

View File

@@ -558,6 +558,9 @@ namespace Tins {
/**
* \brief Getter for this PDU's DNS queries.
*
* This method is <b>not thread safe</b>.
*
* \return std::list<Query> containing the queries in this
* record.
*/
@@ -565,6 +568,9 @@ namespace Tins {
/**
* \brief Getter for this PDU's DNS answers
*
* This method is <b>not thread safe</b>.
*
* \return std::list<Resource> containing the answers in this
* record.
*/
@@ -587,7 +593,7 @@ namespace Tins {
}
/**
* Helper function to create a resource record information
* Helper function to create a resource record information.
*
* \param type The type of the query.
* \param qclass The class of the query.

File diff suppressed because it is too large Load Diff

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

@@ -0,0 +1,620 @@
/*
* 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_DOT11_DOT11_ASSOC_H
#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

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

@@ -0,0 +1,258 @@
/*
* 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_DOT11_DOT11_AUTH_H
#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

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

@@ -0,0 +1,515 @@
/*
* 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_DOT11_DOT11_H
#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> 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;
/**
* \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,164 @@
/*
* 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_DOT11_DOT11_BEACON_H
#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,743 @@
/*
* 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_DOT11_DOT11_CONTROL_H
#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

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

@@ -0,0 +1,343 @@
/*
* 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_DOT11_DOT11_DATA_H
#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

1126
include/dot11/dot11_mgmt.h Normal file

File diff suppressed because it is too large Load Diff

230
include/dot11/dot11_probe.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_DOT11_DOT11_PROBE_H
#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

View File

@@ -35,6 +35,9 @@
#include "small_uint.h"
namespace Tins {
/**
* Represents an IEEE 802.1q PDU.
*/
class Dot1Q : public PDU {
public:
/**
@@ -78,24 +81,24 @@ public:
uint32_t trailer_size() const;
/**
* \brief Getter for the priority field.
* \return The stored priority field value.
* \brief Getter for the priority field.
* \return The stored priority field value.
*/
small_uint<3> priority() const {
return _header.priority;
}
/**
* \brief Getter for the cfi field.
* \return The stored cfi field value.
* \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 id field.
* \return The stored id field value.
* \brief Getter for the VLAN ID field.
* \return The stored VLAN ID field value.
*/
small_uint<12> id() const {
#if TINS_IS_LITTLE_ENDIAN
@@ -106,8 +109,8 @@ public:
}
/**
* \brief Getter for the payload type field.
* \return The stored type field value.
* \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);
@@ -137,31 +140,31 @@ public:
// Setters
/**
* \brief Setter for the priority field.
* \param new_priority The new priority field value.
* \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 cfi field.
* \param new_cfi The new cfi field value.
* \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 id field.
* \param new_id The new id field value.
* \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.
* \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
* \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

View File

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

View File

@@ -80,7 +80,7 @@ namespace Endian {
* \param data The data to convert.
*/
inline uint64_t do_change_endian(uint64_t data) {
return (((uint64_t)(do_change_endian((uint32_t)((data << 32) >> 32))) << 32) |
return (((uint64_t)(do_change_endian((uint32_t)(data & 0xffffffff))) << 32) |
(do_change_endian(((uint32_t)(data >> 32)))));
}

View File

@@ -136,6 +136,14 @@ 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
/**

View File

@@ -124,6 +124,27 @@ public:
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";
}
};
}
#endif // TINS_EXCEPTIONS_H

View File

@@ -0,0 +1,167 @@
/*
* 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_HANDSHAKE_CAPTURER_H
#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

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

@@ -96,13 +96,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.
*
@@ -227,7 +220,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.
@@ -248,7 +241,7 @@ namespace Tins {
*
* \return Returns the gateways in an unit32_t.
*/
uint32_t gateway() const { return Endian::be_to_host(this->_icmp.un.gateway); }
uint32_t gateway() const { return Endian::be_to_host(_icmp.un.gateway); }
/**
* \brief Getter for the pointer field.
@@ -262,7 +255,7 @@ namespace Tins {
*
* \return Returns the mtu value in an uint16_t.
*/
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 Returns the header size.
@@ -313,6 +306,8 @@ namespace Tins {
uint8_t pointer;
} un;
} 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.

View File

@@ -35,33 +35,144 @@
#include <stdint.h>
#include "constants.h"
#include "pdu.h"
#include "hw_address.h"
/**
* \cond
*/
namespace Tins {
namespace Internals {
void skip_line(std::istream &input);
bool from_hex(const std::string &str, uint32_t &result);
template<bool, typename>
struct enable_if {
};
class IPv4Address;
class IPv6Address;
template<typename T>
struct enable_if<true, T> {
typedef T type;
};
namespace Internals {
template<size_t n>
class byte_array {
public:
typedef uint8_t* iterator;
typedef const uint8_t* const_iterator;
PDU *pdu_from_flag(Constants::Ethernet::e flag, const uint8_t *buffer,
uint32_t size, bool rawpdu_on_no_match = true);
byte_array() {
std::fill(begin(), end(), 0);
}
PDU *pdu_from_flag(PDU::PDUType type, const uint8_t *buffer, uint32_t size);
template<typename InputIterator>
byte_array(InputIterator start, InputIterator last) {
std::copy(start, end, data);
}
Constants::Ethernet::e pdu_flag_to_ether_type(PDU::PDUType flag);
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>
struct enable_if {
};
template<typename T>
struct enable_if<true, T> {
typedef T type;
};
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(PDU::PDUType type, const uint8_t *buffer, uint32_t size);
Constants::Ethernet::e pdu_flag_to_ether_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);
}
} // namespace Internals
} // namespace Tins
/**
* \endcond
*/

View File

@@ -333,13 +333,6 @@ namespace Tins {
/* Setters */
/**
* \brief Setter for the header length field.
*
* \param new_head_len The new header length.
*/
void head_len(small_uint<4> new_head_len);
/**
* \brief Setter for the type of service field.
*
@@ -347,13 +340,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.
*
@@ -618,6 +604,10 @@ namespace Tins {
/*The options start here. */
} TINS_END_PACK;
void head_len(small_uint<4> new_head_len);
void tot_len(uint16_t new_tot_len);
void prepare_for_serialize(const PDU *parent);
void internal_add_option(const option &option);
void init_ip_fields();

View File

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

View File

@@ -33,8 +33,13 @@
#include <string>
#include <stdexcept>
#include <stdint.h>
#include "cxxstd.h"
namespace Tins {
/**
* Represents an IPv6 address.
*/
class IPv6Address {
public:
/**
@@ -177,6 +182,22 @@ public:
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.
*
@@ -192,6 +213,18 @@ private:
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

@@ -55,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;
/**
@@ -302,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.

View File

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

View File

@@ -76,6 +76,7 @@ namespace Tins {
/**
* \brief Constructor for PacketSender objects.
*
* \param iface The default interface in which to send the packets.
* \param recv_timeout The timeout which will be used when receiving responses.
*/
PacketSender(const NetworkInterface &iface = NetworkInterface(),
@@ -168,7 +169,7 @@ namespace Tins {
*
* \sa PacketSender::default_interface
*/
const NetworkInterface& default_interface();
const NetworkInterface& default_interface() const;
/**
* \brief Sends a PDU.

View File

@@ -112,7 +112,7 @@ public:
*
* 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 smartpointers.
* raw and smart pointers.
*/
template<typename T>
void write(T &pdu) {

View File

@@ -117,7 +117,9 @@ namespace Tins {
DHCPv6,
DOT1Q,
PPPOE,
STP
STP,
PPI,
USER_DEFINED_PDU = 1000
};
/**

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

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 _header.length;
}
/**
* \brief Getter for the Data Link Type field.
* \return The stored Data Link Type field value.
*/
uint32_t dlt() const {
return _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

View File

@@ -89,7 +89,8 @@ namespace Tins {
ANTENNA = 2048,
DB_SIGNAL = 4096,
DB_NOISE = 8192,
RX_FLAGS = 16382
RX_FLAGS = 16382,
CHANNEL_PLUS = 262144
};
/**
@@ -187,12 +188,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.
@@ -261,17 +274,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.
@@ -289,7 +314,8 @@ 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.
@@ -333,50 +359,60 @@ namespace Tins {
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,
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;
union {
struct {
uint32_t lock_quality:1,
dbm_noise:1,
dbm_signal:1,
fhss:1,
channel:1,
rate:1,
flags:1,
tsft:1,
reserved3:1,
rx_flags:1,
db_tx_attenuation:1,
dbm_tx_attenuation:1,
antenna:1,
db_signal:1,
db_noise:1,
tx_attenuation:1,
reserved2:5,
channel_plus:1,
reserved1:2,
reserved4:7,
ext:1;
} flags;
uint32_t flags_32;
};
#endif
} TINS_END_PACK;
@@ -387,9 +423,8 @@ namespace Tins {
radiotap_hdr _radio;
// 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;
};
}

View File

@@ -74,14 +74,14 @@ namespace Tins{
typedef std::vector<uint8_t> serialization_type;
/**
* \brief Creates an instance of RSNInformation.
* \brief Constructs an RSNInformation object.
*
* By default, the version is set to 1.
*/
RSNInformation();
/**
* \brief Creates an instance of RSNInformation from a
* \brief Constructs an RSNInformation object from a
* serialization_type object.
*
* \param buffer The buffer from which to construct this object.
@@ -113,7 +113,7 @@ namespace Tins{
void add_pairwise_cypher(CypherSuites cypher);
/**
* \brief Adds a akm suite.
* \brief Adds an akm suite.
* \param akm The akm suite to be added.
*/
void add_akm_cypher(AKMSuites akm);

View File

@@ -70,40 +70,40 @@ public:
// Getters
/**
* \brief Getter for the packet_type field.
* \return The stored packet_type field value.
* \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.
* \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_len field.
* \return The stored lladdr_len field value.
* \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.
* \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.
* \brief Getter for the Protocol field.
* \return The stored Protocol field value.
*/
uint16_t protocol() const {
return Endian::be_to_host(_header.protocol);
@@ -118,32 +118,32 @@ public:
// Setters
/**
* \brief Setter for the packet_type field.
* \param new_packet_type The new packet_type field value.
* \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.
* \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_len field.
* \param new_lladdr_len The new lladdr_len field value.
* \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.
* \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.
* \brief Setter for the Protocol field.
* \param new_protocol The new Protocol field value.
*/
void protocol(uint16_t new_protocol);

View File

@@ -76,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
@@ -120,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
@@ -132,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); }
@@ -149,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.

View File

@@ -36,18 +36,23 @@
#include <string>
#include <memory>
#include <stdexcept>
#include <iterator>
#include "pdu.h"
#include "ethernetII.h"
#include "radiotap.h"
#include "packet.h"
#include "loopback.h"
#include "dot11.h"
#include "dot11/dot11_base.h"
#include "dot3.h"
#include "sll.h"
#include "cxxstd.h"
#include "exceptions.h"
#include "internals.h"
#include "ppi.h"
namespace Tins {
class SnifferIterator;
/**
* \class BaseSniffer
* \brief Base class for sniffers.
@@ -60,28 +65,31 @@ 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 opeartor is available only in C++11.
* This operator is available only in C++11.
*/
BaseSniffer& operator=(BaseSniffer &&rhs) noexcept
{
handle = 0;
mask = rhs.mask;
iface_type = rhs.iface_type;
actual_filter.bf_insns = 0;
std::swap(handle, rhs.handle);
std::swap(actual_filter, rhs.actual_filter);
using std::swap;
swap(handle, rhs.handle);
swap(mask, rhs.mask);
return *this;
}
#endif
@@ -95,7 +103,7 @@ 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.
*
@@ -115,48 +123,57 @@ namespace Tins {
* \code
* // bad!!
* PtrPacket p = s.next_packet();
*
* \endcode
*
* Is not, since PtrPacket can't be copy constructed.
*
* \sa Packet::release_pdu
*
* \return The captured packet, matching the given filter.
* If an error occured(probably compiling the filter), PtrPacket::pdu
* will return 0. Caller takes ownership of the PDU * stored in
* \return A captured packet. If an error occured, PtrPacket::pdu
* will return 0. Caller takes ownership of the PDU pointer stored in
* the PtrPacket.
*/
PtrPacket next_packet();
/**
* \brief Starts a sniffing loop, using a callback object for every
* \brief Starts a sniffing loop, using a callback functor for every
* sniffed packet.
*
* The callback object must implement an operator with some of
* the following(or compatible) signatures:
* The functor must implement an operator with one of the
* following signatures:
*
* \code
* bool operator()(PDU&);
* bool operator()(RefPacket&);
* bool(PDU&);
* bool(const PDU&);
* \endcode
*
* This operator will be called using the sniffed packets
* as arguments. You can modify the parameter 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.
*
* The callback taking a RefPacket will contain a timestamp
* indicating the moment in which the packet was taken out of
* the wire/pcap file.
*
* 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
*
* \sa RefPacket
*
* \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>
@@ -171,6 +188,9 @@ 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();
@@ -178,6 +198,24 @@ namespace Tins {
* \brief Gets the file descriptor associated with the sniffer.
*/
int get_fd();
/**
* \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.
@@ -195,60 +233,16 @@ 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)
{ }
};
struct PCapLoopBreaker {
bool &went_well;
pcap_t *handle;
PCapLoopBreaker(bool &went_well, pcap_t *handle)
: went_well(went_well), handle(handle) { }
~PCapLoopBreaker() {
if(!went_well)
pcap_breakloop(handle);
}
};
BaseSniffer(const BaseSniffer&);
BaseSniffer &operator=(const BaseSniffer&);
static bool is_dot3(const uint8_t *ptr, size_t sz) {
return (sz >= 13 && ptr[12] < 8);
}
template<class ConcretePDU, class Functor>
static bool call_functor(LoopData<Functor> *data, const u_char *packet, const struct pcap_pkthdr *header);
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:
@@ -265,7 +259,7 @@ namespace Tins {
/**
* \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.
@@ -279,58 +273,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,
const struct pcap_pkthdr *header)
{
ConcretePDU some_pdu((const uint8_t*)packet, header->caplen);
Timestamp ts(header->ts);
RefPacket pck(some_pdu, ts);
return data->c_handler(pck);
}
template<class Functor>
void Tins::BaseSniffer::callback_handler(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) {
bool ret_val(true);
LoopData<Functor> *data = reinterpret_cast<LoopData<Functor>*>(args);
PCapLoopBreaker _(ret_val, data->handle);
try {
Internals::smart_ptr<PDU>::type pdu;
if(data->iface_type == DLT_EN10MB) {
ret_val = is_dot3((const uint8_t*)packet, header->caplen) ?
call_functor<Tins::Dot3>(data, packet, header) :
call_functor<Tins::EthernetII>(data, packet, header);
}
else if(data->iface_type == DLT_IEEE802_11_RADIO)
ret_val = call_functor<Tins::RadioTap>(data, packet, header);
else if(data->iface_type == DLT_IEEE802_11) {
Internals::smart_ptr<PDU>::type pdu(
Tins::Dot11::from_bytes((const uint8_t*)packet, header->caplen)
);
if(pdu.get()) {
RefPacket pck(*pdu, header->ts);
ret_val = data->c_handler(pck);
}
}
else if(data->iface_type == DLT_NULL)
ret_val = call_functor<Tins::Loopback>(data, packet, header);
else if(data->iface_type == DLT_LINUX_SLL)
ret_val = call_functor<Tins::SLL>(data, packet, header);
}
catch(malformed_packet&) {
ret_val = true;
}
catch(pdu_not_found&) {
ret_val = true;
}
}
template<class T>
class HandlerProxy {
@@ -354,6 +296,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

View File

@@ -80,94 +80,94 @@ public:
// Getters
/**
* \brief Getter for the proto_id field.
* \return The stored proto_id field value.
* \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 proto_version field.
* \return The stored proto_version field value.
* \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 bpdu_type field.
* \return The stored bpdu_type field value.
* \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 bpdu_flags field.
* \return The stored bpdu_flags field value.
* \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.
* \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.
* \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 msg_age field.
* \return The stored msg_age field value.
* \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 max_age field.
* \return The stored max_age field value.
* \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.
* \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 fwd_delay field.
* \return The stored fwd_delay field value.
* \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.
* \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.
* \brief Getter for the Bridge ID field.
* \return The stored Bridge ID field value.
*/
bpdu_id_type bridge_id() const;
@@ -194,74 +194,74 @@ public:
// Setters
/**
* \brief Setter for the proto_id field.
* \param new_proto_id The new proto_id field value.
* \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 proto_version field.
* \param new_proto_version The new proto_version field value.
* \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.
* \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.
* \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.
* \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.
* \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 msg_age field.
* \param new_msg_age The new msg_age field value.
* \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 max_age field.
* \param new_max_age The new max_age field value.
* \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.
* \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 fwd_delay field.
* \param new_fwd_delay The new fwd_delay field value.
* \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.
* \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.
* \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:

View File

@@ -64,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
};
/**
@@ -207,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 */
@@ -353,6 +371,25 @@ namespace Tins {
*/
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.
*

View File

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

View File

@@ -67,5 +67,8 @@
#include "dhcpv6.h"
#include "pppoe.h"
#include "stp.h"
#include "handshake_capturer.h"
#include "address_range.h"
#include "pdu_allocator.h"
#endif // TINS_TINS_H

View File

@@ -51,8 +51,8 @@ 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.

57
src/address_range.cpp Normal file
View File

@@ -0,0 +1,57 @@
/*
* 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 "address_range.h"
#include "ip_address.h"
#include "ipv6_address.h"
namespace Tins {
IPv4Range operator/(const IPv4Address &addr, int mask) {
if(mask > 32)
throw std::logic_error("Prefix length cannot exceed 32");
return IPv4Range::from_mask(
addr,
IPv4Address(Endian::host_to_be(0xffffffff << (32 - mask)))
);
}
IPv6Range operator/(const IPv6Address &addr, int mask) {
if(mask > 128)
throw std::logic_error("Prefix length cannot exceed 128");
IPv6Address last_addr;
IPv6Address::iterator it = last_addr.begin();
while(mask > 8) {
*it = 0xff;
++it;
mask -= 8;
}
*it = 0xff << (8 - mask);
return IPv6Range::from_mask(addr, last_addr);
}
}

View File

@@ -63,6 +63,7 @@ ARP::ARP(const uint8_t *buffer, uint32_t total_sz)
throw malformed_packet();
memcpy(&_arp, buffer, sizeof(arphdr));
total_sz -= sizeof(arphdr);
//TODO: Check whether this should be removed or not.
if(total_sz)
inner_pdu(new RawPDU(buffer + sizeof(arphdr), total_sz));
}

View File

@@ -26,8 +26,15 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "crypto.h"
#ifdef HAVE_WPA2_DECRYPTION
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/aes.h>
#endif // HAVE_WPA2_DECRYPTION
#include "dot11/dot11_data.h"
#include "dot11/dot11_beacon.h"
namespace Tins {
namespace Crypto {
@@ -63,14 +70,16 @@ bool WEPDecrypter::decrypt(PDU &pdu) {
passwords_type::iterator it = passwords.find(addr);
if(it != passwords.end()) {
dot11->inner_pdu(decrypt(*raw, it->second));
dot11->wep(0);
// Invalid WEP packet(CRC check failed). Skip it.
if(!dot11->inner_pdu())
return false;
// If its valid, then return true
if(dot11->inner_pdu()) {
// it's no longer encrypted.
dot11->wep(0);
return true;
}
}
}
}
return true;
return false;
}
PDU *WEPDecrypter::decrypt(RawPDU &raw, const std::string &password) {
@@ -98,5 +107,438 @@ PDU *WEPDecrypter::decrypt(RawPDU &raw, const std::string &password) {
return 0;
}
}
#ifdef HAVE_WPA2_DECRYPTION
// WPA2Decrypter
const HWAddress<6> &min(const HWAddress<6>& lhs, const HWAddress<6>& rhs) {
return lhs < rhs ? lhs : rhs;
}
const HWAddress<6> &max(const HWAddress<6>& lhs, const HWAddress<6>& rhs) {
return lhs < rhs ? rhs : lhs;
}
template<typename InputIterator1, typename InputIterator2, typename OutputIterator>
void xor_range(InputIterator1 src1, InputIterator2 src2, OutputIterator dst, size_t sz) {
for(size_t i = 0; i < sz; ++i) {
*dst++ = *src1++ ^ *src2++;
}
}
const uint16_t sbox_table[2][256]= {
{
0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A
},
{
0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491,
0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC,
0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB,
0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B,
0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83,
0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A,
0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F,
0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA,
0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B,
0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713,
0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6,
0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85,
0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411,
0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B,
0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1,
0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF,
0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E,
0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6,
0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B,
0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD,
0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8,
0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2,
0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049,
0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810,
0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197,
0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F,
0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C,
0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927,
0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733,
0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5,
0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0,
0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C
}
};
uint16_t sbox(uint16_t i) {
return sbox_table[0][i & 0xff] ^ sbox_table[1][(i >> 8)];
}
uint16_t join_bytes(uint8_t b1, uint8_t b2) {
return (static_cast<uint16_t>(b1) << 8) | b2;
}
uint16_t rotate(uint16_t value) {
return ((value >> 1) & 0x7fff) | (value << 15);
}
uint16_t upper_byte(uint16_t value) {
return (value >> 8) & 0xff;
}
uint16_t lower_byte(uint16_t value) {
return value & 0xff;
}
HWAddress<6> get_bssid(const Dot11Data &dot11) {
if(dot11.from_ds() && !dot11.to_ds())
return dot11.addr3();
else if(!dot11.from_ds() && dot11.to_ds())
return dot11.addr2();
else
return dot11.addr2();
}
namespace WPA2 {
SessionKeys::SessionKeys() {
}
SessionKeys::SessionKeys(const RSNHandshake &hs, const pmk_type &pmk) {
uint8_t PKE[100] = "Pairwise key expansion";
uint8_t MIC[16];
min(hs.client_address(), hs.supplicant_address()).copy(PKE + 23);
max(hs.client_address(), hs.supplicant_address()).copy(PKE + 29);
const uint8_t *nonce1 = hs.handshake()[1].nonce(),
*nonce2 = hs.handshake()[2].nonce();
if(std::lexicographical_compare(nonce1, nonce1 + 32, nonce2, nonce2 + 32)) {
std::copy(nonce1, nonce1 + 32, PKE + 35);
std::copy(nonce2, nonce2 + 32, PKE + 67);
}
else {
std::copy(nonce2, nonce2 + 32, PKE + 35);
std::copy(nonce1, nonce1 + 32, PKE + 67);
}
for(int i(0); i < 4; ++i) {
PKE[99] = i;
HMAC(EVP_sha1(), pmk.begin(), pmk.size(), PKE, 100, ptk.begin() + i * 20, 0);
}
PDU::serialization_type buffer = const_cast<RSNEAPOL&>(hs.handshake()[3]).serialize();
std::fill(buffer.begin() + 81, buffer.begin() + 81 + 16, 0);
if(hs.handshake()[3].key_descriptor() == 2)
HMAC(EVP_sha1(), ptk.begin(), 16, &buffer[0], buffer.size(), MIC, 0);
else
HMAC(EVP_md5(), ptk.begin(), 16, &buffer[0], buffer.size(), MIC, 0);
if(!std::equal(MIC, MIC + sizeof(MIC), hs.handshake()[3].mic()))
throw invalid_handshake();
is_ccmp = (hs.handshake()[3].key_descriptor() == 2);
}
SNAP *SessionKeys::ccmp_decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const {
RawPDU::payload_type &pload = raw.payload();
uint8_t MIC[16] = {0};
uint8_t PN[6] = {
pload[7],
pload[6],
pload[5],
pload[4],
pload[1],
pload[0]
};
uint8_t AAD[32] = {0};
AAD[0] = 0;
AAD[1] = 22 + 6 * int(dot11.from_ds() && dot11.to_ds());
if(dot11.subtype() == Dot11::QOS_DATA_DATA)
AAD[1] += 2;
AAD[2] = dot11.protocol() | (dot11.type() << 2) | ((dot11.subtype() << 4) & 0x80);
AAD[3] = 0x40 | dot11.to_ds() | (dot11.from_ds() << 1) |
(dot11.more_frag() << 2) | (dot11.order() << 7);
dot11.addr1().copy(AAD + 4);
dot11.addr2().copy(AAD + 10);
dot11.addr3().copy(AAD + 16);
AAD[22] = dot11.frag_num();
AAD[23] = 0;
if(dot11.from_ds() && dot11.to_ds())
dot11.addr4().copy(AAD + 24);
AES_KEY ctx;
AES_set_encrypt_key(ptk.begin() + 32, 128, &ctx);
uint8_t crypted_block[16];
size_t total_sz = raw.payload_size() - 16, offset = 8, blocks = (total_sz + 15) / 16;
uint8_t counter[16];
counter[0] = 0x59;
counter[1] = 0;
dot11.addr2().copy(counter + 2);
std::copy(PN, PN + 6, counter + 8);
counter[14] = (total_sz >> 8) & 0xff;
counter[15] = total_sz & 0xff;
AES_encrypt(counter, MIC, &ctx);
xor_range(MIC, AAD, MIC, 16);
AES_encrypt(MIC, MIC, &ctx);
xor_range(MIC, AAD + 16, MIC, 16);
AES_encrypt(MIC, MIC, &ctx);
counter[0] = 1;
counter[14] = counter[15] = 0;
AES_encrypt(counter, crypted_block, &ctx);
uint8_t nice_MIC[8];
std::copy(pload.begin() + pload.size() - 8, pload.end(), nice_MIC);
xor_range(crypted_block, nice_MIC, nice_MIC, 8);
for(size_t i = 1; i <= blocks; ++i) {
size_t block_sz = (i == blocks) ? (total_sz % 16) : 16;
if(block_sz == 0)
block_sz = 16;
counter[14] = (i >> 8) & 0xff;
counter[15] = i & 0xff;
AES_encrypt(counter, crypted_block, &ctx );
xor_range(crypted_block, &pload[offset], &pload[(i - 1) * 16], block_sz);
xor_range(MIC, &pload[(i - 1) * 16], MIC, block_sz);
AES_encrypt(MIC, MIC, &ctx);
offset += block_sz;
}
return (std::equal(nice_MIC, nice_MIC + sizeof(nice_MIC), MIC)) ?
new SNAP(&pload[0], total_sz) :
0;
}
RC4Key SessionKeys::generate_rc4_key(const Dot11Data &dot11, const RawPDU &raw) const {
const RawPDU::payload_type &pload = raw.payload();
const uint8_t *tk = ptk.begin() + 32;
Internals::byte_array<16> rc4_key;
uint16_t ppk[6];
const Dot11::address_type addr = get_bssid(dot11);
// Phase 1
ppk[0] = join_bytes(pload[4], pload[5]);
ppk[1] = join_bytes(pload[6], pload[7]);
ppk[2] = join_bytes(addr[1], addr[0]);
ppk[3] = join_bytes(addr[3], addr[2]);
ppk[4] = join_bytes(addr[5], addr[4]);
for(size_t i = 0; i < 4; ++i) {
ppk[0] += sbox(ppk[4] ^ join_bytes(tk[1], tk[0]));
ppk[1] += sbox(ppk[0] ^ join_bytes(tk[5], tk[4]));
ppk[2] += sbox(ppk[1] ^ join_bytes(tk[9], tk[8]));
ppk[3] += sbox(ppk[2] ^ join_bytes(tk[13], tk[12]));
ppk[4] += sbox(ppk[3] ^ join_bytes(tk[1], tk[0])) + 2*i;
ppk[0] += sbox(ppk[4] ^ join_bytes(tk[3], tk[2]));
ppk[1] += sbox(ppk[0] ^ join_bytes(tk[7], tk[6]));
ppk[2] += sbox(ppk[1] ^ join_bytes(tk[11], tk[10]));
ppk[3] += sbox(ppk[2] ^ join_bytes(tk[15], tk[14]));
ppk[4] += sbox(ppk[3] ^ join_bytes(tk[3], tk[2])) + 2*i + 1;
}
// Phase 2, step 1
ppk[5] = ppk[4] + join_bytes(pload[0], pload[2]);
// Phase 2, step 2
ppk[0] += sbox(ppk[5] ^ join_bytes(tk[1], tk[0]));
ppk[1] += sbox(ppk[0] ^ join_bytes(tk[3], tk[2]));
ppk[2] += sbox(ppk[1] ^ join_bytes(tk[5], tk[4]));
ppk[3] += sbox(ppk[2] ^ join_bytes(tk[7], tk[6]));
ppk[4] += sbox(ppk[3] ^ join_bytes(tk[9], tk[8]));
ppk[5] += sbox(ppk[4] ^ join_bytes(tk[11], tk[10]));
ppk[0] += rotate(ppk[5] ^ join_bytes(tk[13], tk[12]));
ppk[1] += rotate(ppk[0] ^ join_bytes(tk[15], tk[14]));
ppk[2] += rotate(ppk[1]);
ppk[3] += rotate(ppk[2]);
ppk[4] += rotate(ppk[3]);
ppk[5] += rotate(ppk[4]);
// Phase 2, step 3
rc4_key[0] = upper_byte(join_bytes(pload[0], pload[2]));
rc4_key[1] = (rc4_key[0] | 0x20) & 0x7f;
rc4_key[2] = lower_byte(join_bytes(pload[0], pload[2]));
rc4_key[3] = lower_byte((ppk[5] ^ join_bytes(tk[1], tk[0])) >> 1);
rc4_key[4] = lower_byte(ppk[0]);
rc4_key[5] = upper_byte(ppk[0]);
rc4_key[6] = lower_byte(ppk[1]);
rc4_key[7] = upper_byte(ppk[1]);
rc4_key[8] = lower_byte(ppk[2]);
rc4_key[9] = upper_byte(ppk[2]);
rc4_key[10] = lower_byte(ppk[3]);
rc4_key[11] = upper_byte(ppk[3]);
rc4_key[12] = lower_byte(ppk[4]);
rc4_key[13] = upper_byte(ppk[4]);
rc4_key[14] = lower_byte(ppk[5]);
rc4_key[15] = upper_byte(ppk[5]);
return RC4Key(rc4_key.begin(), rc4_key.end());
}
SNAP *SessionKeys::tkip_decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const {
// at least 20 bytes for IV + crc + stuff
if(raw.payload_size() <= 20)
return 0;
Crypto::RC4Key key = generate_rc4_key(dot11, raw);
RawPDU::payload_type &pload = raw.payload();
rc4(pload.begin() + 8, pload.end(), key, pload.begin());
uint32_t crc = Utils::crc32(&pload[0], pload.size() - 12);
if(pload[pload.size() - 12] != (crc & 0xff) ||
pload[pload.size() - 11] != ((crc >> 8) & 0xff) ||
pload[pload.size() - 10] != ((crc >> 16) & 0xff) ||
pload[pload.size() - 9] != ((crc >> 24) & 0xff))
return 0;
return new SNAP(&pload[0], pload.size() - 20);
}
SNAP *SessionKeys::SessionKeys::decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const {
return is_ccmp ?
ccmp_decrypt_unicast(dot11, raw) :
tkip_decrypt_unicast(dot11, raw);
}
// supplicant_data
SupplicantData::SupplicantData(const std::string &psk, const std::string &ssid) {
PKCS5_PBKDF2_HMAC_SHA1(
psk.c_str(),
psk.size(),
(unsigned char *)ssid.c_str(),
ssid.size(),
4096,
pmk_.size(),
pmk_.begin()
);
}
const SupplicantData::pmk_type &SupplicantData::pmk() const {
return pmk_;
}
} // namespace WPA2
void WPA2Decrypter::add_ap_data(const std::string &psk, const std::string &ssid) {
pmks.insert(std::make_pair(ssid, WPA2::SupplicantData(psk, ssid)));
}
void WPA2Decrypter::add_ap_data(const std::string &psk, const std::string &ssid,
const address_type &addr)
{
add_ap_data(psk, ssid);
add_access_point(ssid, addr);
}
void WPA2Decrypter::add_access_point(const std::string &ssid, const address_type &addr) {
pmks_map::const_iterator it = pmks.find(ssid);
if(it == pmks.end())
throw std::runtime_error("supplicant data not registered");
aps.insert(std::make_pair(addr, it->second));
}
void WPA2Decrypter::try_add_keys(const Dot11Data &dot11, const RSNHandshake &hs) {
bssids_map::const_iterator it = find_ap(dot11);
if(it != aps.end()) {
addr_pair addr_p = extract_addr_pair(dot11);
try {
WPA2::SessionKeys session(hs, it->second.pmk());
keys[addr_p] = session;
}
catch(WPA2::invalid_handshake&) { }
}
}
WPA2Decrypter::addr_pair WPA2Decrypter::extract_addr_pair(const Dot11Data &dot11) {
if(dot11.from_ds() && !dot11.to_ds())
return make_addr_pair(dot11.addr2(), dot11.addr3());
else if(!dot11.from_ds() && dot11.to_ds())
return make_addr_pair(dot11.addr1(), dot11.addr2());
else
return make_addr_pair(dot11.addr2(), dot11.addr3());
}
WPA2Decrypter::addr_pair WPA2Decrypter::extract_addr_pair_dst(const Dot11Data &dot11) {
if(dot11.from_ds() && !dot11.to_ds())
return make_addr_pair(dot11.addr1(), dot11.addr2());
else if(!dot11.from_ds() && dot11.to_ds())
return make_addr_pair(dot11.addr1(), dot11.addr3());
else
return make_addr_pair(dot11.addr1(), dot11.addr3());
}
WPA2Decrypter::bssids_map::const_iterator WPA2Decrypter::find_ap(const Dot11Data &dot11) {
if(dot11.from_ds() && !dot11.to_ds())
return aps.find(dot11.addr2());
else if(!dot11.from_ds() && dot11.to_ds())
return aps.find(dot11.addr1());
else
return aps.find(dot11.addr3());
}
bool WPA2Decrypter::decrypt(PDU &pdu) {
if(capturer.process_packet(pdu)) {
try_add_keys(pdu.rfind_pdu<Dot11Data>(), capturer.handshakes().front());
capturer.clear_handshakes();
}
else if(const Dot11Beacon *beacon = pdu.find_pdu<Dot11Beacon>()) {
if(aps.count(beacon->addr3()) == 0) {
try {
std::string ssid = beacon->ssid();
if(pmks.count(ssid)) {
add_access_point(ssid, beacon->addr3());
}
}
catch(option_not_found&) { }
}
}
else {
Dot11Data *data = pdu.find_pdu<Dot11Data>();
RawPDU *raw = pdu.find_pdu<RawPDU>();
if(data && raw && data->wep()) {
// search for the tuple (bssid, src_addr)
keys_map::const_iterator it = keys.find(extract_addr_pair(*data));
// search for the tuple (bssid, dst_addr) if the above didn't work
if(it == keys.end())
it = keys.find(extract_addr_pair_dst(*data));
if(it != keys.end()) {
SNAP *snap = it->second.decrypt_unicast(*data, *raw);
if(snap) {
data->inner_pdu(snap);
data->wep(0);
return true;
}
}
}
}
return false;
} // namespace WPA2
#endif // HAVE_WPA2_DECRYPTION
} // namespace Crypto
} // namespace Tins

View File

@@ -100,7 +100,7 @@ void DHCP::type(Flags type) {
}
void DHCP::end() {
add_option(option(DHCP_MESSAGE_TYPE));
add_option(option(END));
}
uint8_t DHCP::type() const {

View File

@@ -224,9 +224,17 @@ DNSResourceRecord DNS::make_record(const std::string &name,
const DNSResourceRecord::info &info, const uint8_t *ptr, uint32_t len)
{
string nm;
std::basic_string<uint8_t> data;
parse_domain_name(name, nm);
uint16_t index = find_domain_name(nm);
DNSResourceRecord res;
if(info.type == MX) {
data.push_back(0);
data.push_back(0);
data.insert(data.end(), ptr, ptr + len);
ptr = &data[0];
len = data.size();
}
if(index)
res = make_offseted_record(Endian::host_to_be(index), ptr, len);
else
@@ -437,23 +445,36 @@ void DNS::convert_resources(const ResourcesType &lst, std::list<Resource> &res)
}
ptr = it->data_ptr();
sz = it->data_size();
if(sz == 4)
addr = IPv4Address(*(uint32_t*)ptr).to_string();
else {
if(Endian::be_to_host(it->information().type) == MX) {
ptr += 2;
sz -= 2;
}
if(Endian::be_to_host(it->information().type) == DNS::AAAA) {
uint16_t record_type = Endian::be_to_host(it->information().type);
// Skip the preference field if it's MX
if(record_type == MX) {
ptr += 2;
sz -= 2;
}
switch(record_type) {
case AAAA:
if(sz != 16)
throw std::runtime_error("Malformed IPv6 address");
throw malformed_packet();
addr = IPv6Address(ptr).to_string();
}
else
break;
case A:
if(sz != 4)
throw malformed_packet();
addr = IPv4Address(*(uint32_t*)ptr).to_string();
break;
case NS:
case CNAME:
case DNAM:
case PTR:
case MX:
compose_name(ptr, sz, addr);
break;
default:
addr.assign(ptr, ptr + sz);
break;
}
res.push_back(
Resource(dname, addr, Endian::be_to_host(it->information().type),
Resource(dname, addr, record_type,
Endian::host_to_be(it->information().qclass),
Endian::be_to_host(it->information().ttl)
)

File diff suppressed because it is too large Load Diff

249
src/dot11/dot11_assoc.cpp Normal file
View File

@@ -0,0 +1,249 @@
/*
* 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 <cassert>
#include <cstring>
#include "dot11/dot11_assoc.h"
namespace Tins {
/* Diassoc */
Dot11Disassoc::Dot11Disassoc(const address_type &dst_hw_addr,
const address_type &src_hw_addr)
: Dot11ManagementFrame(dst_hw_addr, src_hw_addr)
{
this->subtype(Dot11::DISASSOC);
memset(&_body, 0, sizeof(_body));
}
Dot11Disassoc::Dot11Disassoc(const uint8_t *buffer, uint32_t total_sz)
: Dot11ManagementFrame(buffer, total_sz) {
uint32_t sz = management_frame_size();
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(_body))
throw malformed_packet();
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
parse_tagged_parameters(buffer, total_sz);
}
void Dot11Disassoc::reason_code(uint16_t new_reason_code) {
this->_body.reason_code = Endian::host_to_le(new_reason_code);
}
uint32_t Dot11Disassoc::header_size() const {
return Dot11ManagementFrame::header_size() + sizeof(DisassocBody);
}
uint32_t Dot11Disassoc::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) {
uint32_t sz = sizeof(DisassocBody);
#ifdef TINS_DEBUG
assert(sz <= total_sz);
#endif
memcpy(buffer, &this->_body, sz);
return sz;
}
/* Assoc request. */
Dot11AssocRequest::Dot11AssocRequest(const address_type &dst_hw_addr,
const address_type &src_hw_addr)
: Dot11ManagementFrame(dst_hw_addr, src_hw_addr)
{
subtype(Dot11::ASSOC_REQ);
memset(&_body, 0, sizeof(_body));
}
Dot11AssocRequest::Dot11AssocRequest(const uint8_t *buffer, uint32_t total_sz)
: Dot11ManagementFrame(buffer, total_sz)
{
uint32_t sz = management_frame_size();
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(_body))
throw malformed_packet();
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
parse_tagged_parameters(buffer, total_sz);
}
void Dot11AssocRequest::listen_interval(uint16_t new_listen_interval) {
this->_body.listen_interval = Endian::host_to_le(new_listen_interval);
}
uint32_t Dot11AssocRequest::header_size() const {
return Dot11ManagementFrame::header_size() + sizeof(AssocReqBody);
}
uint32_t Dot11AssocRequest::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) {
uint32_t sz = sizeof(AssocReqBody);
#ifdef TINS_DEBUG
assert(sz <= total_sz);
#endif
memcpy(buffer, &this->_body, sz);
return sz;
}
/* Assoc response. */
Dot11AssocResponse::Dot11AssocResponse(const address_type &dst_hw_addr,
const address_type &src_hw_addr)
: Dot11ManagementFrame(dst_hw_addr, src_hw_addr)
{
subtype(Dot11::ASSOC_RESP);
memset(&_body, 0, sizeof(_body));
}
Dot11AssocResponse::Dot11AssocResponse(const uint8_t *buffer, uint32_t total_sz)
: Dot11ManagementFrame(buffer, total_sz)
{
uint32_t sz = management_frame_size();
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(_body))
throw malformed_packet();
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
parse_tagged_parameters(buffer, total_sz);
}
void Dot11AssocResponse::status_code(uint16_t new_status_code) {
this->_body.status_code = Endian::host_to_le(new_status_code);
}
void Dot11AssocResponse::aid(uint16_t new_aid) {
this->_body.aid = Endian::host_to_le(new_aid);
}
uint32_t Dot11AssocResponse::header_size() const {
return Dot11ManagementFrame::header_size() + sizeof(AssocRespBody);
}
uint32_t Dot11AssocResponse::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) {
uint32_t sz = sizeof(AssocRespBody);
#ifdef TINS_DEBUG
assert(sz <= total_sz);
#endif
memcpy(buffer, &this->_body, sz);
return sz;
}
/* ReAssoc request. */
Dot11ReAssocRequest::Dot11ReAssocRequest(const address_type &dst_hw_addr,
const address_type &src_hw_addr)
: Dot11ManagementFrame(dst_hw_addr, src_hw_addr)
{
this->subtype(Dot11::REASSOC_REQ);
memset(&_body, 0, sizeof(_body));
}
Dot11ReAssocRequest::Dot11ReAssocRequest(const uint8_t *buffer, uint32_t total_sz)
: Dot11ManagementFrame(buffer, total_sz)
{
uint32_t sz = management_frame_size();
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(_body))
throw malformed_packet();
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
parse_tagged_parameters(buffer, total_sz);
}
void Dot11ReAssocRequest::listen_interval(uint16_t new_listen_interval) {
this->_body.listen_interval = Endian::host_to_le(new_listen_interval);
}
void Dot11ReAssocRequest::current_ap(const address_type &new_current_ap) {
new_current_ap.copy(_body.current_ap);
}
uint32_t Dot11ReAssocRequest::header_size() const {
return Dot11ManagementFrame::header_size() + sizeof(this->_body);
}
uint32_t Dot11ReAssocRequest::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) {
uint32_t sz = sizeof(this->_body);
#ifdef TINS_DEBUG
assert(sz <= total_sz);
#endif
memcpy(buffer, &this->_body, sz);
return sz;
}
/* ReAssoc response. */
Dot11ReAssocResponse::Dot11ReAssocResponse(const address_type &dst_hw_addr,
const address_type &src_hw_addr)
: Dot11ManagementFrame(dst_hw_addr, src_hw_addr)
{
this->subtype(Dot11::REASSOC_RESP);
memset(&_body, 0, sizeof(_body));
}
Dot11ReAssocResponse::Dot11ReAssocResponse(const uint8_t *buffer, uint32_t total_sz)
: Dot11ManagementFrame(buffer, total_sz) {
uint32_t sz = management_frame_size();
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(_body))
throw malformed_packet();
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
parse_tagged_parameters(buffer, total_sz);
}
void Dot11ReAssocResponse::status_code(uint16_t new_status_code) {
this->_body.status_code = Endian::host_to_le(new_status_code);
}
void Dot11ReAssocResponse::aid(uint16_t new_aid) {
this->_body.aid = Endian::host_to_le(new_aid);
}
uint32_t Dot11ReAssocResponse::header_size() const {
return Dot11ManagementFrame::header_size() + sizeof(this->_body);
}
uint32_t Dot11ReAssocResponse::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) {
uint32_t sz = sizeof(this->_body);
#ifdef TINS_DEBUG
assert(sz <= total_sz);
#endif
memcpy(buffer, &this->_body, sz);
return sz;
}
} // namespace Tins

123
src/dot11/dot11_auth.cpp Normal file
View File

@@ -0,0 +1,123 @@
/*
* 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 <cassert>
#include <cstring>
#include "dot11/dot11_auth.h"
namespace Tins {
/* Auth */
Dot11Authentication::Dot11Authentication(const address_type &dst_hw_addr,
const address_type &src_hw_addr)
: Dot11ManagementFrame(dst_hw_addr, src_hw_addr)
{
this->subtype(Dot11::AUTH);
memset(&_body, 0, sizeof(_body));
}
Dot11Authentication::Dot11Authentication(const uint8_t *buffer, uint32_t total_sz)
: Dot11ManagementFrame(buffer, total_sz)
{
uint32_t sz = management_frame_size();
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(_body))
throw malformed_packet();
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
parse_tagged_parameters(buffer, total_sz);
}
void Dot11Authentication::auth_algorithm(uint16_t new_auth_algorithm) {
this->_body.auth_algorithm = Endian::host_to_le(new_auth_algorithm);
}
void Dot11Authentication::auth_seq_number(uint16_t new_auth_seq_number) {
this->_body.auth_seq_number = Endian::host_to_le(new_auth_seq_number);
}
void Dot11Authentication::status_code(uint16_t new_status_code) {
this->_body.status_code = Endian::host_to_le(new_status_code);
}
uint32_t Dot11Authentication::header_size() const {
return Dot11ManagementFrame::header_size() + sizeof(_body);
}
uint32_t Dot11Authentication::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) {
uint32_t sz = sizeof(this->_body);
#ifdef TINS_DEBUG
assert(sz <= total_sz);
#endif
memcpy(buffer, &this->_body, sz);
return sz;
}
/* Deauth */
Dot11Deauthentication::Dot11Deauthentication(const address_type &dst_hw_addr,
const address_type &src_hw_addr)
: Dot11ManagementFrame(dst_hw_addr, src_hw_addr)
{
this->subtype(Dot11::DEAUTH);
memset(&_body, 0, sizeof(_body));
}
Dot11Deauthentication::Dot11Deauthentication(const uint8_t *buffer, uint32_t total_sz)
: Dot11ManagementFrame(buffer, total_sz) {
uint32_t sz = management_frame_size();
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(_body))
throw malformed_packet();
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
parse_tagged_parameters(buffer, total_sz);
}
void Dot11Deauthentication::reason_code(uint16_t new_reason_code) {
this->_body.reason_code = Endian::host_to_le(new_reason_code);
}
uint32_t Dot11Deauthentication::header_size() const {
return Dot11ManagementFrame::header_size() + sizeof(this->_body);
}
uint32_t Dot11Deauthentication::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) {
uint32_t sz = sizeof(this->_body);
#ifdef TINS_DEBUG
assert(sz <= total_sz);
#endif
memcpy(buffer, &this->_body, sz);
return sz;
}
} // namespace Tins

275
src/dot11/dot11_base.cpp Normal file
View File

@@ -0,0 +1,275 @@
/*
* 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 <cassert>
#include <cstring>
#include <stdexcept>
#include <algorithm>
#include <utility>
#include "macros.h"
#include "exceptions.h"
#include "dot11/dot11_base.h"
#ifndef WIN32
#if defined(__FreeBSD_kernel__) || defined(BSD) || defined(__APPLE__)
#include <sys/types.h>
#include <net/if_dl.h>
#else
#include <netpacket/packet.h>
#endif
#include <net/ethernet.h>
#include <netinet/in.h>
#endif
#include "dot11.h"
#include "rawpdu.h"
#include "rsn_information.h"
#include "packet_sender.h"
#include "snap.h"
namespace Tins {
const Dot11::address_type Dot11::BROADCAST = "ff:ff:ff:ff:ff:ff";
Dot11::Dot11(const address_type &dst_hw_addr)
: _options_size(0)
{
memset(&_header, 0, sizeof(ieee80211_header));
addr1(dst_hw_addr);
}
Dot11::Dot11(const ieee80211_header *header_ptr)
{
}
Dot11::Dot11(const uint8_t *buffer, uint32_t total_sz)
: _options_size(0)
{
if(total_sz < sizeof(_header))
throw malformed_packet();
std::memcpy(&_header, buffer, sizeof(_header));
}
void Dot11::parse_tagged_parameters(const uint8_t *buffer, uint32_t total_sz) {
if(total_sz > 0) {
uint8_t opcode, length;
while(total_sz >= 2) {
opcode = buffer[0];
length = buffer[1];
buffer += 2;
total_sz -= 2;
if(length > total_sz) {
throw malformed_packet();
}
add_tagged_option((OptionTypes)opcode, length, buffer);
buffer += length;
total_sz -= length;
}
}
}
void Dot11::add_tagged_option(OptionTypes opt, uint8_t len, const uint8_t *val) {
uint32_t opt_size = len + sizeof(uint8_t) * 2;
_options.push_back(option((uint8_t)opt, val, val + len));
_options_size += opt_size;
}
void Dot11::internal_add_option(const option &opt) {
_options_size += opt.data_size() + sizeof(uint8_t) * 2;
}
void Dot11::add_option(const option &opt) {
internal_add_option(opt);
_options.push_back(opt);
}
const Dot11::option *Dot11::search_option(OptionTypes opt) const {
for(std::list<option>::const_iterator it = _options.begin(); it != _options.end(); ++it)
if(it->option() == (uint8_t)opt)
return &(*it);
return 0;
}
void Dot11::protocol(small_uint<2> new_proto) {
this->_header.control.protocol = new_proto;
}
void Dot11::type(small_uint<2> new_type) {
this->_header.control.type = new_type;
}
void Dot11::subtype(small_uint<4> new_subtype) {
this->_header.control.subtype = new_subtype;
}
void Dot11::to_ds(small_uint<1> new_value) {
this->_header.control.to_ds = (new_value)? 1 : 0;
}
void Dot11::from_ds(small_uint<1> new_value) {
this->_header.control.from_ds = (new_value)? 1 : 0;
}
void Dot11::more_frag(small_uint<1> new_value) {
this->_header.control.more_frag = (new_value)? 1 : 0;
}
void Dot11::retry(small_uint<1> new_value) {
this->_header.control.retry = (new_value)? 1 : 0;
}
void Dot11::power_mgmt(small_uint<1> new_value) {
this->_header.control.power_mgmt = (new_value)? 1 : 0;
}
void Dot11::wep(small_uint<1> new_value) {
this->_header.control.wep = (new_value)? 1 : 0;
}
void Dot11::order(small_uint<1> new_value) {
this->_header.control.order = (new_value)? 1 : 0;
}
void Dot11::duration_id(uint16_t new_duration_id) {
this->_header.duration_id = Endian::host_to_le(new_duration_id);
}
void Dot11::addr1(const address_type &new_addr1) {
std::copy(new_addr1.begin(), new_addr1.end(), _header.addr1);
}
uint32_t Dot11::header_size() const {
uint32_t sz = sizeof(ieee80211_header) + _options_size;
return sz;
}
#ifndef WIN32
void Dot11::send(PacketSender &sender, const NetworkInterface &iface) {
if(!iface)
throw invalid_interface();
#if !defined(BSD) && !defined(__FreeBSD_kernel__)
sockaddr_ll addr;
memset(&addr, 0, sizeof(struct sockaddr_ll));
addr.sll_family = Endian::host_to_be<uint16_t>(PF_PACKET);
addr.sll_protocol = Endian::host_to_be<uint16_t>(ETH_P_ALL);
addr.sll_halen = 6;
addr.sll_ifindex = iface.id();
memcpy(&(addr.sll_addr), _header.addr1, 6);
sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
#else
sender.send_l2(*this, 0, 0, iface);
#endif
}
#endif // WIN32
void Dot11::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
#ifdef TINS_DEBUG
assert(total_sz >= header_size());
#endif
memcpy(buffer, &_header, sizeof(_header));
buffer += sizeof(_header);
total_sz -= sizeof(_header);
uint32_t written = write_ext_header(buffer, total_sz);
buffer += written;
total_sz -= written;
uint32_t child_len = write_fixed_parameters(buffer, total_sz - _options_size);
buffer += child_len;
#ifdef TINS_DEBUG
assert(total_sz >= child_len + _options_size);
#endif
for(std::list<option>::const_iterator it = _options.begin(); it != _options.end(); ++it) {
*(buffer++) = it->option();
*(buffer++) = it->length_field();
std::copy(it->data_ptr(), it->data_ptr() + it->data_size(), buffer);
buffer += it->data_size();
}
}
Dot11 *Dot11::from_bytes(const uint8_t *buffer, uint32_t total_sz) {
// We only need the control field, the length of the PDU will depend on the flags set.
// This should be sizeof(ieee80211_header::control), but gcc 4.2 complains
if(total_sz < 2)
throw malformed_packet();
const ieee80211_header *hdr = (const ieee80211_header*)buffer;
Dot11 *ret = 0;
if(hdr->control.type == MANAGEMENT) {
if(hdr->control.subtype == BEACON)
ret = new Dot11Beacon(buffer, total_sz);
else if(hdr->control.subtype == DISASSOC)
ret = new Dot11Disassoc(buffer, total_sz);
else if(hdr->control.subtype == ASSOC_REQ)
ret = new Dot11AssocRequest(buffer, total_sz);
else if(hdr->control.subtype == ASSOC_RESP)
ret = new Dot11AssocResponse(buffer, total_sz);
else if(hdr->control.subtype == REASSOC_REQ)
ret = new Dot11ReAssocRequest(buffer, total_sz);
else if(hdr->control.subtype == REASSOC_RESP)
ret = new Dot11ReAssocResponse(buffer, total_sz);
else if(hdr->control.subtype == AUTH)
ret = new Dot11Authentication(buffer, total_sz);
else if(hdr->control.subtype == DEAUTH)
ret = new Dot11Deauthentication(buffer, total_sz);
else if(hdr->control.subtype == PROBE_REQ)
ret = new Dot11ProbeRequest(buffer, total_sz);
else if(hdr->control.subtype == PROBE_RESP)
ret = new Dot11ProbeResponse(buffer, total_sz);
}
else if(hdr->control.type == DATA){
if(hdr->control.subtype <= 4)
ret = new Dot11Data(buffer, total_sz);
else
ret = new Dot11QoSData(buffer, total_sz);
}
else if(hdr->control.type == CONTROL){
if(hdr->control.subtype == ACK)
ret = new Dot11Ack(buffer, total_sz);
else if(hdr->control.subtype == CF_END)
ret = new Dot11CFEnd(buffer, total_sz);
else if(hdr->control.subtype == CF_END_ACK)
ret = new Dot11EndCFAck(buffer, total_sz);
else if(hdr->control.subtype == PS)
ret = new Dot11PSPoll(buffer, total_sz);
else if(hdr->control.subtype == RTS)
ret = new Dot11RTS(buffer, total_sz);
else if(hdr->control.subtype == BLOCK_ACK)
ret = new Dot11BlockAck(buffer, total_sz);
else if(hdr->control.subtype == BLOCK_ACK_REQ)
ret = new Dot11BlockAckRequest(buffer, total_sz);
}
if(ret == 0)
ret = new Dot11(buffer, total_sz);
return ret;
}
} // namespace Tins

View File

@@ -0,0 +1,79 @@
/*
* 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 <cstring>
#include <cassert>
#include "dot11/dot11_beacon.h"
namespace Tins {
/* Dot11Beacon */
Dot11Beacon::Dot11Beacon(const address_type &dst_hw_addr,
const address_type &src_hw_addr)
: Dot11ManagementFrame(dst_hw_addr, src_hw_addr)
{
subtype(Dot11::BEACON);
std::memset(&_body, 0, sizeof(_body));
}
Dot11Beacon::Dot11Beacon(const uint8_t *buffer, uint32_t total_sz)
: Dot11ManagementFrame(buffer, total_sz)
{
uint32_t sz = management_frame_size();
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(_body))
throw malformed_packet();
std::memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
parse_tagged_parameters(buffer, total_sz);
}
void Dot11Beacon::timestamp(uint64_t new_timestamp) {
this->_body.timestamp = Endian::host_to_le(new_timestamp);
}
void Dot11Beacon::interval(uint16_t new_interval) {
this->_body.interval = Endian::host_to_le(new_interval);
}
uint32_t Dot11Beacon::header_size() const {
return Dot11ManagementFrame::header_size() + sizeof(_body);
}
uint32_t Dot11Beacon::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) {
uint32_t sz = sizeof(_body);
#ifdef TINS_DEBUG
assert(sz <= total_sz);
#endif
std::memcpy(buffer, &this->_body, sz);
return sz;
}
} // namespace Tins

283
src/dot11/dot11_control.cpp Normal file
View File

@@ -0,0 +1,283 @@
/*
* 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 <cassert>
#include <cstring>
#include "dot11/dot11_control.h"
namespace Tins {
/* Dot11Control */
Dot11Control::Dot11Control(const address_type &dst_addr)
: Dot11(dst_addr)
{
type(CONTROL);
}
Dot11Control::Dot11Control(const uint8_t *buffer, uint32_t total_sz)
: Dot11(buffer, total_sz) {
}
/* Dot11ControlTA */
Dot11ControlTA::Dot11ControlTA(const address_type &dst_addr,
const address_type &target_address)
: Dot11Control(dst_addr)
{
target_addr(target_address);
}
Dot11ControlTA::Dot11ControlTA(const uint8_t *buffer, uint32_t total_sz) : Dot11Control(buffer, total_sz) {
buffer += sizeof(ieee80211_header);
total_sz -= sizeof(ieee80211_header);
if(total_sz < sizeof(_taddr))
throw malformed_packet();
//std::memcpy(_taddr, buffer, sizeof(_taddr));
_taddr = buffer;
}
uint32_t Dot11ControlTA::header_size() const {
return Dot11::header_size() + sizeof(_taddr);
}
uint32_t Dot11ControlTA::write_ext_header(uint8_t *buffer, uint32_t total_sz) {
#ifdef TINS_DEBUG
assert(total_sz >= sizeof(_taddr));
#endif
//std::memcpy(buffer, _taddr, sizeof(_taddr));
_taddr.copy(buffer);
return sizeof(_taddr);
}
void Dot11ControlTA::target_addr(const address_type &addr) {
_taddr = addr;
}
/* Dot11RTS */
Dot11RTS::Dot11RTS(const address_type &dst_addr,
const address_type &target_addr)
: Dot11ControlTA(dst_addr, target_addr)
{
subtype(RTS);
}
Dot11RTS::Dot11RTS(const uint8_t *buffer, uint32_t total_sz)
: Dot11ControlTA(buffer, total_sz) {
}
/* Dot11PSPoll */
Dot11PSPoll::Dot11PSPoll(const address_type &dst_addr,
const address_type &target_addr)
: Dot11ControlTA(dst_addr, target_addr)
{
subtype(PS);
}
Dot11PSPoll::Dot11PSPoll(const uint8_t *buffer, uint32_t total_sz)
: Dot11ControlTA(buffer, total_sz) {
}
/* Dot11CFEnd */
Dot11CFEnd::Dot11CFEnd(const address_type &dst_addr,
const address_type &target_addr)
: Dot11ControlTA(dst_addr, target_addr)
{
subtype(CF_END);
}
Dot11CFEnd::Dot11CFEnd(const uint8_t *buffer, uint32_t total_sz)
: Dot11ControlTA(buffer, total_sz) {
}
/* Dot11EndCFAck */
Dot11EndCFAck::Dot11EndCFAck(const address_type &dst_addr,
const address_type &target_addr)
: Dot11ControlTA(dst_addr, target_addr)
{
subtype(CF_END_ACK);
}
Dot11EndCFAck::Dot11EndCFAck(const uint8_t *buffer, uint32_t total_sz)
: Dot11ControlTA(buffer, total_sz) {
}
/* Dot11Ack */
Dot11Ack::Dot11Ack(const address_type &dst_addr)
: Dot11Control(dst_addr)
{
subtype(ACK);
}
Dot11Ack::Dot11Ack(const uint8_t *buffer, uint32_t total_sz)
: Dot11Control(buffer, total_sz)
{
}
/* Dot11BlockAck */
Dot11BlockAckRequest::Dot11BlockAckRequest(const address_type &dst_addr,
const address_type &target_addr)
: Dot11ControlTA(dst_addr, target_addr)
{
init_block_ack();
}
Dot11BlockAckRequest::Dot11BlockAckRequest(const uint8_t *buffer, uint32_t total_sz)
: Dot11ControlTA(buffer, total_sz)
{
uint32_t padding = controlta_size();
buffer += padding;
total_sz -= padding;
if(total_sz < sizeof(_bar_control) + sizeof(_start_sequence))
throw malformed_packet();
std::memcpy(&_bar_control, buffer, sizeof(_bar_control));
buffer += sizeof(_bar_control);
std::memcpy(&_start_sequence, buffer, sizeof(_start_sequence));
}
void Dot11BlockAckRequest::init_block_ack() {
subtype(BLOCK_ACK_REQ);
std::memset(&_bar_control, 0, sizeof(_bar_control));
std::memset(&_start_sequence, 0, sizeof(_start_sequence));
}
uint32_t Dot11BlockAckRequest::write_ext_header(uint8_t *buffer, uint32_t total_sz) {
uint32_t parent_size = Dot11ControlTA::write_ext_header(buffer, total_sz);
buffer += parent_size;
std::memcpy(buffer, &_bar_control, sizeof(_bar_control));
buffer += sizeof(_bar_control);
std::memcpy(buffer, &_start_sequence, sizeof(_start_sequence));
return parent_size + sizeof(_start_sequence) + sizeof(_bar_control);
}
void Dot11BlockAckRequest::bar_control(small_uint<4> bar) {
#if TINS_IS_LITTLE_ENDIAN
_bar_control = bar | (_bar_control & 0xfff0);
#else
_bar_control = (bar << 8) | (_bar_control & 0xf0ff);
#endif
}
void Dot11BlockAckRequest::start_sequence(small_uint<12> seq) {
#if TINS_IS_LITTLE_ENDIAN
_start_sequence = (seq << 4) | (_start_sequence & 0xf);
#else
_start_sequence = Endian::host_to_le<uint16_t>(seq << 4) | (_start_sequence & 0xf00);
#endif
}
void Dot11BlockAckRequest::fragment_number(small_uint<4> frag) {
#if TINS_IS_LITTLE_ENDIAN
_start_sequence = frag | (_start_sequence & 0xfff0);
#else
_start_sequence = (frag << 8) | (_start_sequence & 0xf0ff);
#endif
}
uint32_t Dot11BlockAckRequest::header_size() const {
return Dot11ControlTA::header_size() + sizeof(_start_sequence) + sizeof(_start_sequence);
}
/* Dot11BlockAck */
Dot11BlockAck::Dot11BlockAck(const address_type &dst_addr,
const address_type &target_addr)
: Dot11ControlTA(dst_addr, target_addr)
{
subtype(BLOCK_ACK);
std::memset(_bitmap, 0, sizeof(_bitmap));
}
Dot11BlockAck::Dot11BlockAck(const uint8_t *buffer, uint32_t total_sz) : Dot11ControlTA(buffer, total_sz) {
uint32_t padding = controlta_size();
buffer += padding;
total_sz -= padding;
if(total_sz < sizeof(_bitmap) + sizeof(_bar_control) + sizeof(_start_sequence))
throw malformed_packet();
std::memcpy(&_bar_control, buffer, sizeof(_bar_control));
buffer += sizeof(_bar_control);
std::memcpy(&_start_sequence, buffer, sizeof(_start_sequence));
buffer += sizeof(_start_sequence);
std::memcpy(&_bitmap, buffer, sizeof(_bitmap));
}
void Dot11BlockAck::bar_control(small_uint<4> bar) {
#if TINS_IS_LITTLE_ENDIAN
_bar_control = bar | (_bar_control & 0xfff0);
#else
_bar_control = (bar << 8) | (_bar_control & 0xf0ff);
#endif
}
void Dot11BlockAck::start_sequence(small_uint<12> seq) {
#if TINS_IS_LITTLE_ENDIAN
_start_sequence = (seq << 4) | (_start_sequence & 0xf);
#else
_start_sequence = Endian::host_to_le<uint16_t>(seq << 4) | (_start_sequence & 0xf00);
#endif
}
void Dot11BlockAck::fragment_number(small_uint<4> frag) {
#if TINS_IS_LITTLE_ENDIAN
_start_sequence = frag | (_start_sequence & 0xfff0);
#else
_start_sequence = (frag << 8) | (_start_sequence & 0xf0ff);
#endif
}
void Dot11BlockAck::bitmap(const uint8_t *bit) {
std::memcpy(_bitmap, bit, sizeof(_bitmap));
}
uint32_t Dot11BlockAck::write_ext_header(uint8_t *buffer, uint32_t total_sz) {
uint32_t parent_size = Dot11ControlTA::write_ext_header(buffer, total_sz);
buffer += parent_size;
std::memcpy(buffer, &_bar_control, sizeof(_bar_control));
buffer += sizeof(_bar_control);
std::memcpy(buffer, &_start_sequence, sizeof(_start_sequence));
buffer += sizeof(_start_sequence);
std::memcpy(buffer, _bitmap, sizeof(_bitmap));
return parent_size + sizeof(_bitmap) + sizeof(_bar_control) + sizeof(_start_sequence);
}
uint32_t Dot11BlockAck::header_size() const {
return Dot11ControlTA::header_size() + sizeof(_start_sequence) + sizeof(_start_sequence) + sizeof(_bitmap);
}
} // namespace Tins

182
src/dot11/dot11_data.cpp 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.
*
*/
#include <cstring>
#include <cassert>
#include "dot11/dot11_data.h"
#include "rawpdu.h"
#include "snap.h"
namespace Tins {
/* Dot11Data */
Dot11Data::Dot11Data(const uint8_t *buffer, uint32_t total_sz)
: Dot11(buffer, total_sz)
{
const uint32_t offset = init(buffer, total_sz);
buffer += offset;
total_sz -= offset;
if(total_sz) {
// If the wep bit is on, then just use a RawPDU
if(wep())
inner_pdu(new Tins::RawPDU(buffer, total_sz));
else
inner_pdu(new Tins::SNAP(buffer, total_sz));
}
}
Dot11Data::Dot11Data(const uint8_t *buffer, uint32_t total_sz, no_inner_pdu)
: Dot11(buffer, total_sz)
{
init(buffer, total_sz);
}
uint32_t Dot11Data::init(const uint8_t *buffer, uint32_t total_sz) {
const uint8_t *start_ptr = buffer;
uint32_t sz = Dot11::header_size();
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(_ext_header))
throw malformed_packet();
std::memcpy(&_ext_header, buffer, sizeof(_ext_header));
buffer += sizeof(_ext_header);
total_sz -= sizeof(_ext_header);
if(from_ds() && to_ds()) {
if(total_sz < _addr4.size())
throw malformed_packet();
_addr4 = buffer;
buffer += _addr4.size();
total_sz -= _addr4.size();
}
return buffer - start_ptr;
}
Dot11Data::Dot11Data(const address_type &dst_hw_addr,
const address_type &src_hw_addr)
: Dot11(dst_hw_addr)
{
type(Dot11::DATA);
memset(&_ext_header, 0, sizeof(_ext_header));
addr2(src_hw_addr);
}
uint32_t Dot11Data::header_size() const {
uint32_t sz = Dot11::header_size() + sizeof(_ext_header);
if (this->from_ds() && this->to_ds())
sz += 6;
return sz;
}
void Dot11Data::addr2(const address_type &new_addr2) {
std::copy(new_addr2.begin(), new_addr2.end(), _ext_header.addr2);
}
void Dot11Data::addr3(const address_type &new_addr3) {
std::copy(new_addr3.begin(), new_addr3.end(), _ext_header.addr3);
}
void Dot11Data::frag_num(small_uint<4> new_frag_num) {
#if TINS_IS_LITTLE_ENDIAN
_ext_header.frag_seq = new_frag_num | (_ext_header.frag_seq & 0xfff0);
#else
_ext_header.frag_seq = (new_frag_num << 8) | (_ext_header.frag_seq & 0xf0ff);
#endif
}
void Dot11Data::seq_num(small_uint<12> new_seq_num) {
#if TINS_IS_LITTLE_ENDIAN
_ext_header.frag_seq = (new_seq_num << 4) | (_ext_header.frag_seq & 0xf);
#else
_ext_header.frag_seq = Endian::host_to_le<uint16_t>(new_seq_num << 4) | (_ext_header.frag_seq & 0xf00);
#endif
}
void Dot11Data::addr4(const address_type &new_addr4) {
_addr4 = new_addr4;
}
uint32_t Dot11Data::write_ext_header(uint8_t *buffer, uint32_t total_sz) {
uint32_t written = sizeof(_ext_header);
memcpy(buffer, &_ext_header, sizeof(_ext_header));
buffer += sizeof(_ext_header);
if (from_ds() && to_ds()) {
written += _addr4.size();
_addr4.copy(buffer);
}
return written;
}
/* QoS data. */
Dot11QoSData::Dot11QoSData(const address_type &dst_hw_addr,
const address_type &src_hw_addr)
: Dot11Data(dst_hw_addr, src_hw_addr)
{
subtype(Dot11::QOS_DATA_DATA);
_qos_control = 0;
}
Dot11QoSData::Dot11QoSData(const uint8_t *buffer, uint32_t total_sz)
// Am I breaking something? :S
: Dot11Data(buffer, total_sz, no_inner_pdu()) {
uint32_t sz = data_frame_size();
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(_qos_control))
throw malformed_packet();
_qos_control = *(uint16_t*)buffer;
total_sz -= sizeof(uint16_t);
buffer += sizeof(uint16_t);
if(total_sz) {
// If the wep bit is on, then just use a RawPDU
if(wep())
inner_pdu(new Tins::RawPDU(buffer, total_sz));
else
inner_pdu(new Tins::SNAP(buffer, total_sz));
}
}
void Dot11QoSData::qos_control(uint16_t new_qos_control) {
this->_qos_control = Endian::host_to_le(new_qos_control);
}
uint32_t Dot11QoSData::header_size() const {
return Dot11Data::header_size() + sizeof(this->_qos_control);
}
uint32_t Dot11QoSData::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) {
uint32_t sz = sizeof(this->_qos_control);
#ifdef TINS_DEBUG
assert(sz <= total_sz);
#endif
*(uint16_t*)buffer = this->_qos_control;
return sz;
}
} // namespace Tins

641
src/dot11/dot11_mgmt.cpp Normal file
View File

@@ -0,0 +1,641 @@
/*
* 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 <cstring>
#include "dot11/dot11_mgmt.h"
#include "rsn_information.h"
namespace Tins {
/* Dot11ManagementFrame */
Dot11ManagementFrame::Dot11ManagementFrame(const uint8_t *buffer, uint32_t total_sz)
: Dot11(buffer, total_sz)
{
buffer += sizeof(ieee80211_header);
total_sz -= sizeof(ieee80211_header);
if(total_sz < sizeof(_ext_header))
throw malformed_packet();
std::memcpy(&_ext_header, buffer, sizeof(_ext_header));
total_sz -= sizeof(_ext_header);
if(from_ds() && to_ds()) {
if(total_sz >= _addr4.size())
_addr4 = buffer + sizeof(_ext_header);
else
throw malformed_packet();
}
}
Dot11ManagementFrame::Dot11ManagementFrame(const address_type &dst_hw_addr,
const address_type &src_hw_addr)
: Dot11(dst_hw_addr)
{
type(Dot11::MANAGEMENT);
memset(&_ext_header, 0, sizeof(_ext_header));
addr2(src_hw_addr);
}
uint32_t Dot11ManagementFrame::header_size() const {
uint32_t sz = Dot11::header_size() + sizeof(_ext_header);
if (this->from_ds() && this->to_ds())
sz += 6;
return sz;
}
void Dot11ManagementFrame::addr2(const address_type &new_addr2) {
std::copy(new_addr2.begin(), new_addr2.end(), _ext_header.addr2);
}
void Dot11ManagementFrame::addr3(const address_type &new_addr3) {
std::copy(new_addr3.begin(), new_addr3.end(), _ext_header.addr3);
}
void Dot11ManagementFrame::frag_num(small_uint<4> new_frag_num) {
#if TINS_IS_LITTLE_ENDIAN
_ext_header.frag_seq = new_frag_num | (_ext_header.frag_seq & 0xfff0);
#else
_ext_header.frag_seq = (new_frag_num << 8) | (_ext_header.frag_seq & 0xf0ff);
#endif
}
void Dot11ManagementFrame::seq_num(small_uint<12> new_seq_num) {
#if TINS_IS_LITTLE_ENDIAN
_ext_header.frag_seq = (new_seq_num << 4) | (_ext_header.frag_seq & 0xf);
#else
_ext_header.frag_seq = Endian::host_to_le<uint16_t>(new_seq_num << 4) | (_ext_header.frag_seq & 0xf00);
#endif
}
void Dot11ManagementFrame::addr4(const address_type &new_addr4) {
_addr4 = new_addr4;
}
uint32_t Dot11ManagementFrame::write_ext_header(uint8_t *buffer, uint32_t total_sz) {
uint32_t written = sizeof(_ext_header);
memcpy(buffer, &_ext_header, sizeof(this->_ext_header));
buffer += sizeof(_ext_header);
if (from_ds() && to_ds()) {
written += 6;
std::copy(_addr4.begin(), _addr4.end(), buffer);
}
return written;
}
void Dot11ManagementFrame::ssid(const std::string &new_ssid) {
add_tagged_option(Dot11::SSID, new_ssid.size(), (const uint8_t*)new_ssid.c_str());
}
void Dot11ManagementFrame::rsn_information(const RSNInformation& info) {
RSNInformation::serialization_type buffer = info.serialize();
add_tagged_option(RSN, buffer.size(), &buffer[0]);
}
uint8_t *Dot11ManagementFrame::serialize_rates(const rates_type &rates) {
uint8_t *buffer = new uint8_t[rates.size()], *ptr = buffer;
for(rates_type::const_iterator it = rates.begin(); it != rates.end(); ++it) {
uint8_t result = *it * 2;
if(result == 2 || result == 4 || result == 11 || result == 22)
result |= 0x80;
*(ptr++) = result;
}
return buffer;
}
Dot11ManagementFrame::rates_type Dot11ManagementFrame::deserialize_rates(const option *opt) {
rates_type 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;
}
void Dot11ManagementFrame::supported_rates(const rates_type &new_rates) {
uint8_t *buffer = serialize_rates(new_rates);
add_tagged_option(SUPPORTED_RATES, new_rates.size(), buffer);
delete[] buffer;
}
void Dot11ManagementFrame::extended_supported_rates(const rates_type &new_rates) {
uint8_t *buffer = serialize_rates(new_rates);
add_tagged_option(EXT_SUPPORTED_RATES, new_rates.size(), buffer);
delete[] buffer;
}
void Dot11ManagementFrame::qos_capability(uint8_t new_qos_capability) {
add_tagged_option(QOS_CAPABILITY, 1, &new_qos_capability);
}
void Dot11ManagementFrame::power_capability(uint8_t min_power, uint8_t max_power) {
uint8_t buffer[2];
buffer[0] = min_power;
buffer[1] = max_power;
add_tagged_option(POWER_CAPABILITY, 2, buffer);
}
void Dot11ManagementFrame::supported_channels(const channels_type &new_channels) {
std::vector<uint8_t> buffer(new_channels.size() * 2);
uint8_t* ptr = &buffer[0];
for(channels_type::const_iterator it = new_channels.begin(); it != new_channels.end(); ++it) {
*(ptr++) = it->first;
*(ptr++) = it->second;
}
add_tagged_option(SUPPORTED_CHANNELS, buffer.size(), &buffer[0]);
}
void Dot11ManagementFrame::edca_parameter_set(uint32_t ac_be, uint32_t ac_bk, uint32_t ac_vi, uint32_t ac_vo) {
uint8_t buffer[18];
buffer[0] = 0;
buffer[1] = 0;
uint32_t* ptr = (uint32_t*)(buffer + 2);
*(ptr++) = Endian::host_to_le(ac_be);
*(ptr++) = Endian::host_to_le(ac_bk);
*(ptr++) = Endian::host_to_le(ac_vi);
*(ptr++) = Endian::host_to_le(ac_vo);
add_tagged_option(EDCA, sizeof(buffer), buffer);
}
void Dot11ManagementFrame::request_information(const request_info_type elements) {
add_tagged_option(REQUEST_INFORMATION, elements.size(), &elements[0]);
}
void Dot11ManagementFrame::fh_parameter_set(const fh_params_set &fh_params) {
uint8_t data[5];
uint16_t dwell = Endian::host_to_le(fh_params.dwell_time);
std::memcpy(data, &dwell, sizeof(dwell));
data[2] = fh_params.hop_set;
data[3] = fh_params.hop_pattern;
data[4] = fh_params.hop_index;
add_tagged_option(FH_SET, sizeof(data), data);
}
void Dot11ManagementFrame::ds_parameter_set(uint8_t current_channel) {
add_tagged_option(DS_SET, 1, &current_channel);
}
void Dot11ManagementFrame::cf_parameter_set(const cf_params_set &params) {
uint8_t data[6];
data[0] = params.cfp_count;
data[1] = params.cfp_period;
uint16_t dummy = Endian::host_to_le(params.cfp_max_duration);
std::memcpy(data + 2, &dummy, sizeof(uint16_t));
dummy = Endian::host_to_le(params.cfp_dur_remaining);
std::memcpy(data + 4, &dummy, sizeof(uint16_t));
add_tagged_option(CF_SET, sizeof(data), data);
}
void Dot11ManagementFrame::ibss_parameter_set(uint16_t atim_window) {
atim_window = Endian::host_to_le(atim_window);
add_tagged_option(IBSS_SET, 2, (uint8_t*)&atim_window);
}
void Dot11ManagementFrame::ibss_dfs(const ibss_dfs_params &params) {
uint8_t sz = address_type::address_size + sizeof(uint8_t) + sizeof(uint8_t) * 2 * params.channel_map.size();
uint8_t* buffer = new uint8_t[sz];
uint8_t* ptr_buffer = buffer;
ptr_buffer = params.dfs_owner.copy(ptr_buffer);
*(ptr_buffer++) = params.recovery_interval;
for (channels_type::const_iterator it = params.channel_map.begin(); it != params.channel_map.end(); ++it) {
*(ptr_buffer++) = it->first;
*(ptr_buffer++) = it->second;
}
add_tagged_option(IBSS_DFS, sz, buffer);
delete[] buffer;
}
void Dot11ManagementFrame::country(const country_params &params) {
if ((params.first_channel.size() != params.number_channels.size()) ||
(params.number_channels.size() != params.max_transmit_power.size()))
throw std::runtime_error("The length of the lists are distinct");
if(params.country.size() != 3)
throw std::runtime_error("Invalid country identifier length");
size_t sz = sizeof(uint8_t) * 3 * params.first_channel.size() + params.country.size();
// Use 1 byte padding at the end if the length is odd.
if((sz & 1) == 1)
sz++;
std::vector<uint8_t> buffer(sz);
uint8_t *ptr = std::copy(params.country.begin(), params.country.end(), &buffer[0]);
for(size_t i(0); i < params.first_channel.size(); ++i) {
*(ptr++) = params.first_channel[i];
*(ptr++) = params.number_channels[i];
*(ptr++) = params.max_transmit_power[i];
}
add_tagged_option(COUNTRY, sz, &buffer[0]);
}
void Dot11ManagementFrame::fh_parameters(uint8_t prime_radix, uint8_t number_channels) {
uint8_t buffer[2];
buffer[0] = prime_radix;
buffer[1] = number_channels;
add_tagged_option(HOPPING_PATTERN_PARAMS, 2, buffer);
}
void Dot11ManagementFrame::fh_pattern_table(const fh_pattern_type &params) {
std::vector<uint8_t> data(sizeof(uint8_t) * 4 + params.random_table.size());
uint8_t *ptr = &data[0];
*(ptr++) = params.flag;
*(ptr++) = params.number_of_sets;
*(ptr++) = params.modulus;
*(ptr++) = params.offset;
byte_array::const_iterator it(params.random_table.begin());
for(; it != params.random_table.end(); ++it)
*(ptr++) = *it;
add_tagged_option(HOPPING_PATTERN_TABLE, data.size(), &data[0]);
}
void Dot11ManagementFrame::power_constraint(uint8_t local_power_constraint) {
add_tagged_option(POWER_CONSTRAINT, 1, &local_power_constraint);
}
void Dot11ManagementFrame::channel_switch(const channel_switch_type &data) {
uint8_t buffer[3];
buffer[0] = data.switch_mode;
buffer[1] = data.new_channel;
buffer[2] = data.switch_count;
add_tagged_option(CHANNEL_SWITCH, 3, buffer);
}
void Dot11ManagementFrame::quiet(const quiet_type &data) {
uint8_t buffer[6];
uint16_t* ptr_buffer = (uint16_t*)(buffer + 2);
buffer[0] = data.quiet_count;
buffer[1] = data.quiet_period;
ptr_buffer[0] = Endian::host_to_le(data.quiet_duration);
ptr_buffer[1] = Endian::host_to_le(data.quiet_offset);
add_tagged_option(QUIET, sizeof(buffer), buffer);
}
void Dot11ManagementFrame::tpc_report(uint8_t transmit_power, uint8_t link_margin) {
uint8_t buffer[2];
buffer[0] = transmit_power;
buffer[1] = link_margin;
add_tagged_option(TPC_REPORT, 2, buffer);
}
void Dot11ManagementFrame::erp_information(uint8_t value) {
add_tagged_option(ERP_INFORMATION, 1, &value);
}
void Dot11ManagementFrame::bss_load(const bss_load_type &data) {
uint8_t buffer[5];
uint16_t dummy = Endian::host_to_le(data.station_count);
//*(uint16_t*)buffer = Endian::host_to_le(data.station_count);
#if TINS_IS_LITTLE_ENDIAN
buffer[0] = dummy & 0xff;
buffer[1] = (dummy >> 8) & 0xff;
#else
buffer[0] = (dummy >> 8) & 0xff;
buffer[1] = dummy & 0xff;
#endif
buffer[2] = data.channel_utilization;
dummy = Endian::host_to_le(data.available_capacity);
#if TINS_IS_LITTLE_ENDIAN
buffer[3] = dummy & 0xff;
buffer[4] = (dummy >> 8) & 0xff;
#else
buffer[3] = (dummy >> 8) & 0xff;
buffer[4] = dummy & 0xff;
#endif
//*(uint16_t*)(buffer + 3) = Endian::host_to_le(data.available_capacity);
add_tagged_option(BSS_LOAD, sizeof(buffer), buffer);
}
void Dot11ManagementFrame::tim(const tim_type &data) {
std::vector<uint8_t> buffer(sizeof(uint8_t) * 3 + data.partial_virtual_bitmap.size());
buffer[0] = data.dtim_count;
buffer[1] = data.dtim_period;
buffer[2] = data.bitmap_control;
std::copy(
data.partial_virtual_bitmap.begin(),
data.partial_virtual_bitmap.end(),
&buffer[3]
);
add_tagged_option(TIM, buffer.size(), &buffer[0]);
}
void Dot11ManagementFrame::challenge_text(const std::string &text) {
add_tagged_option(
CHALLENGE_TEXT,
text.size(),
(const uint8_t*)text.c_str()
);
}
void Dot11ManagementFrame::vendor_specific(const vendor_specific_type &data) {
byte_array buffer(3 + data.data.size());
std::copy(
data.data.begin(),
data.data.end(),
data.oui.copy(buffer.begin())
);
add_tagged_option(VENDOR_SPECIFIC, buffer.size(), &buffer[0]);
}
// Getters
RSNInformation Dot11ManagementFrame::rsn_information() {
const Dot11::option *option = search_option(RSN);
if(!option || option->data_size() < (sizeof(uint16_t) << 1) + sizeof(uint32_t))
throw option_not_found();
return RSNInformation(option->data_ptr(), option->data_size());
}
std::string Dot11ManagementFrame::ssid() const {
const Dot11::option *option = search_option(SSID);
if(!option)
throw option_not_found();
if(option->data_size() == 0 && this->subtype() == Dot11::PROBE_REQ)
return "BROADCAST";
else
return std::string((const char*)option->data_ptr(), option->data_size());
}
Dot11ManagementFrame::rates_type Dot11ManagementFrame::supported_rates() const {
const Dot11::option *option = search_option(SUPPORTED_RATES);
if(!option || option->data_size() == 0)
throw option_not_found();
return deserialize_rates(option);
}
Dot11ManagementFrame::rates_type Dot11ManagementFrame::extended_supported_rates() const {
const Dot11::option *option = search_option(EXT_SUPPORTED_RATES);
if(!option || option->data_size() == 0)
throw option_not_found();
return deserialize_rates(option);
}
uint8_t Dot11ManagementFrame::qos_capability() const {
const Dot11::option *option = search_option(QOS_CAPABILITY);
if(!option || option->data_size() != 1)
throw option_not_found();
return *option->data_ptr();
}
std::pair<uint8_t, uint8_t> Dot11ManagementFrame::power_capability() const {
const Dot11::option *option = search_option(POWER_CAPABILITY);
if(!option || option->data_size() != 2)
throw option_not_found();
return std::make_pair(*option->data_ptr(), *(option->data_ptr() + 1));
}
Dot11ManagementFrame::channels_type Dot11ManagementFrame::supported_channels() const {
const Dot11::option *option = search_option(SUPPORTED_CHANNELS);
// We need a multiple of two
if(!option || ((option->data_size() & 0x1) == 1))
throw option_not_found();
channels_type output;
const uint8_t *ptr = option->data_ptr(), *end = ptr + option->data_size();
while(ptr != end) {
uint8_t first = *(ptr++);
output.push_back(std::make_pair(first, *(ptr++)));
}
return output;
}
Dot11ManagementFrame::request_info_type Dot11ManagementFrame::request_information() const {
const Dot11::option *option = search_option(REQUEST_INFORMATION);
if(!option || option->data_size() == 0)
throw option_not_found();
request_info_type output;
const uint8_t *ptr = option->data_ptr(), *end = ptr + option->data_size();
output.assign(ptr, end);
return output;
}
Dot11ManagementFrame::fh_params_set Dot11ManagementFrame::fh_parameter_set() const {
const Dot11::option *option = search_option(FH_SET);
if(!option || option->data_size() != 5)
throw option_not_found();
fh_params_set output;
output.dwell_time = Endian::le_to_host(*(uint16_t*)option->data_ptr());
output.hop_set = option->data_ptr()[2];
output.hop_pattern = option->data_ptr()[3];
output.hop_index = option->data_ptr()[4];
return output;
}
uint8_t Dot11ManagementFrame::ds_parameter_set() const {
const Dot11::option *option = search_option(DS_SET);
if(!option || option->data_size() != sizeof(uint8_t))
throw option_not_found();
return *option->data_ptr();
}
Dot11ManagementFrame::cf_params_set Dot11ManagementFrame::cf_parameter_set() const {
const Dot11::option *option = search_option(CF_SET);
if(!option || option->data_size() != 6)
throw option_not_found();
cf_params_set output;
output.cfp_count = *option->data_ptr();
output.cfp_period = option->data_ptr()[1];
output.cfp_max_duration = Endian::le_to_host(*(uint16_t*)&option->data_ptr()[2]);
output.cfp_dur_remaining = Endian::le_to_host(*(uint16_t*)&option->data_ptr()[4]);
return output;
}
uint16_t Dot11ManagementFrame::ibss_parameter_set() const {
const Dot11::option *option = search_option(IBSS_SET);
if(!option || option->data_size() != sizeof(uint16_t))
throw option_not_found();
return Endian::le_to_host(*reinterpret_cast<const uint16_t*>(option->data_ptr()));
}
Dot11ManagementFrame::ibss_dfs_params Dot11ManagementFrame::ibss_dfs() const {
const Dot11::option *option = search_option(IBSS_DFS);
if(!option || option->data_size() < ibss_dfs_params::minimum_size)
throw option_not_found();
ibss_dfs_params output;
const uint8_t *ptr = option->data_ptr(), *end = ptr + option->data_size();
output.dfs_owner = ptr;
ptr += output.dfs_owner.size();
output.recovery_interval = *(ptr++);
while(ptr != end) {
uint8_t first = *(ptr++);
if(ptr == end)
throw option_not_found();
output.channel_map.push_back(std::make_pair(first, *(ptr++)));
}
return output;
}
Dot11ManagementFrame::country_params Dot11ManagementFrame::country() const {
const Dot11::option *option = search_option(COUNTRY);
if(!option || option->data_size() < country_params::minimum_size)
throw option_not_found();
country_params output;
const uint8_t *ptr = option->data_ptr(), *end = ptr + option->data_size();
std::copy(ptr, ptr + 3, std::back_inserter(output.country));
ptr += output.country.size();
while(end - ptr >= 3) {
output.first_channel.push_back(*(ptr++));
output.number_channels.push_back(*(ptr++));
output.max_transmit_power.push_back(*(ptr++));
}
if(ptr != end)
throw option_not_found();
return output;
}
std::pair<uint8_t, uint8_t> Dot11ManagementFrame::fh_parameters() const {
const Dot11::option *option = search_option(HOPPING_PATTERN_PARAMS);
if(!option || option->data_size() != sizeof(uint8_t) * 2)
throw option_not_found();
const uint8_t *ptr = option->data_ptr();
uint8_t first = *(ptr++);
return std::make_pair(first, *ptr);
}
Dot11ManagementFrame::fh_pattern_type Dot11ManagementFrame::fh_pattern_table() const {
const Dot11::option *option = search_option(HOPPING_PATTERN_TABLE);
if(!option || option->data_size() < fh_pattern_type::minimum_size)
throw option_not_found();
fh_pattern_type output;
const uint8_t *ptr = option->data_ptr(), *end = ptr + option->data_size();
output.flag = *(ptr++);
output.number_of_sets = *(ptr++);
output.modulus = *(ptr++);
output.offset = *(ptr++);
output.random_table.assign(ptr, end);
return output;
}
uint8_t Dot11ManagementFrame::power_constraint() const {
const Dot11::option *option = search_option(POWER_CONSTRAINT);
if(!option || option->data_size() != 1)
throw option_not_found();
return *option->data_ptr();
}
Dot11ManagementFrame::channel_switch_type Dot11ManagementFrame::channel_switch() const {
const Dot11::option *option = search_option(CHANNEL_SWITCH);
if(!option || option->data_size() != sizeof(uint8_t) * 3)
throw option_not_found();
const uint8_t *ptr = option->data_ptr();
channel_switch_type output;
output.switch_mode = *(ptr++);
output.new_channel = *(ptr++);
output.switch_count = *(ptr++);
return output;
}
Dot11ManagementFrame::quiet_type Dot11ManagementFrame::quiet() const {
const Dot11::option *option = search_option(QUIET);
if(!option || option->data_size() != (sizeof(uint8_t) * 2 + sizeof(uint16_t) * 2))
throw option_not_found();
const uint8_t *ptr = option->data_ptr();
quiet_type output;
output.quiet_count = *(ptr++);
output.quiet_period = *(ptr++);
const uint16_t *ptr_16 = (const uint16_t*)ptr;
output.quiet_duration = Endian::le_to_host(*(ptr_16++));
output.quiet_offset = Endian::le_to_host(*ptr_16);
return output;
}
std::pair<uint8_t, uint8_t> Dot11ManagementFrame::tpc_report() const {
const Dot11::option *option = search_option(TPC_REPORT);
if(!option || option->data_size() != sizeof(uint8_t) * 2)
throw option_not_found();
const uint8_t *ptr = option->data_ptr();
uint8_t first = *(ptr++);
return std::make_pair(first, *ptr);
}
uint8_t Dot11ManagementFrame::erp_information() const {
const Dot11::option *option = search_option(ERP_INFORMATION);
if(!option || option->data_size() != sizeof(uint8_t))
throw option_not_found();
return *option->data_ptr();
}
Dot11ManagementFrame::bss_load_type Dot11ManagementFrame::bss_load() const {
const Dot11::option *option = search_option(BSS_LOAD);
if(!option || option->data_size() != sizeof(uint8_t) + 2 * sizeof(uint16_t))
throw option_not_found();
bss_load_type output;
const uint8_t *ptr = option->data_ptr();
output.station_count = Endian::le_to_host(*(uint16_t*)ptr);
output.channel_utilization = ptr[2];
output.available_capacity = Endian::le_to_host(*(uint16_t*)(ptr + 3));
return output;
}
Dot11ManagementFrame::tim_type Dot11ManagementFrame::tim() const {
const Dot11::option *option = search_option(TIM);
if(!option || option->data_size() < 4 * sizeof(uint8_t))
throw option_not_found();
const uint8_t *ptr = option->data_ptr(), *end = ptr + option->data_size();
tim_type output;
output.dtim_count = *(ptr++);
output.dtim_period = *(ptr++);
output.bitmap_control = *(ptr++);
output.partial_virtual_bitmap.assign(ptr, end);
return output;
}
std::string Dot11ManagementFrame::challenge_text() const {
const Dot11::option *option = search_option(CHALLENGE_TEXT);
if(!option || option->data_size() == 0)
throw option_not_found();
return std::string(option->data_ptr(), option->data_ptr() + option->data_size());
}
Dot11ManagementFrame::vendor_specific_type Dot11ManagementFrame::vendor_specific() const {
const Dot11::option *option = search_option(VENDOR_SPECIFIC);
if(!option || option->data_size() < 3)
throw option_not_found();
return vendor_specific_type::from_bytes(option->data_ptr(), option->data_size());
}
Dot11ManagementFrame::vendor_specific_type
Dot11ManagementFrame::vendor_specific_type::from_bytes(const uint8_t *buffer, uint32_t sz)
{
if(sz < 3)
throw malformed_option();
return vendor_specific_type(
buffer,
byte_array(buffer + 3, buffer + sz)
);
}
} // namespace Tins

97
src/dot11/dot11_probe.cpp Normal file
View File

@@ -0,0 +1,97 @@
/*
* 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 <cstring>
#include <cassert>
#include "dot11/dot11_probe.h"
namespace Tins {
/* Probe Request */
Dot11ProbeRequest::Dot11ProbeRequest(const address_type &dst_hw_addr,
const address_type &src_hw_addr)
: Dot11ManagementFrame(dst_hw_addr, src_hw_addr)
{
this->subtype(Dot11::PROBE_REQ);
}
Dot11ProbeRequest::Dot11ProbeRequest(const uint8_t *buffer, uint32_t total_sz)
: Dot11ManagementFrame(buffer, total_sz)
{
uint32_t sz = management_frame_size();
buffer += sz;
total_sz -= sz;
parse_tagged_parameters(buffer, total_sz);
}
/* Probe Response */
Dot11ProbeResponse::Dot11ProbeResponse(const address_type &dst_hw_addr,
const address_type &src_hw_addr)
: Dot11ManagementFrame(dst_hw_addr, src_hw_addr)
{
this->subtype(Dot11::PROBE_RESP);
memset(&_body, 0, sizeof(_body));
}
Dot11ProbeResponse::Dot11ProbeResponse(const uint8_t *buffer, uint32_t total_sz)
: Dot11ManagementFrame(buffer, total_sz)
{
uint32_t sz = management_frame_size();
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(_body))
throw malformed_packet();
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
parse_tagged_parameters(buffer, total_sz);
}
void Dot11ProbeResponse::timestamp(uint64_t new_timestamp) {
this->_body.timestamp = Endian::host_to_le(new_timestamp);
}
void Dot11ProbeResponse::interval(uint16_t new_interval) {
this->_body.interval = Endian::host_to_le(new_interval);
}
uint32_t Dot11ProbeResponse::header_size() const {
return Dot11ManagementFrame::header_size() + sizeof(this->_body);
}
uint32_t Dot11ProbeResponse::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) {
uint32_t sz = sizeof(this->_body);
#ifdef TINS_DEBUG
assert(sz <= total_sz);
#endif
memcpy(buffer, &this->_body, sz);
return sz;
}
} // namespace Tins

View File

@@ -111,7 +111,9 @@ void Dot1Q::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *)
}
std::memcpy(buffer, &_header, sizeof(_header));
buffer += sizeof(_header) + inner_pdu()->size();
buffer += sizeof(_header);
if(inner_pdu())
buffer += inner_pdu()->size();
std::fill(buffer, buffer + trailer, 0);
}

View File

@@ -32,8 +32,8 @@
#include <cassert>
#endif
#include <stdexcept>
#include <iostream> // borrame
#include "eapol.h"
#include "dot11.h"
#include "rsn_information.h"
#include "exceptions.h"
@@ -57,6 +57,12 @@ EAPOL *EAPOL::from_bytes(const uint8_t *buffer, uint32_t total_sz) {
if(total_sz < sizeof(eapolhdr))
throw malformed_packet();
const eapolhdr *ptr = (const eapolhdr*)buffer;
uint32_t data_len = Endian::be_to_host<uint16_t>(ptr->length);
// at least 4 for fields always present
total_sz = std::min(
total_sz,
data_len + 4
);
switch(ptr->type) {
case RC4:
return new Tins::RC4EAPOL(buffer, total_sz);

View File

@@ -82,6 +82,7 @@ EthernetII::EthernetII(const uint8_t *buffer, uint32_t total_sz)
)
);
}
}
void EthernetII::dst_addr(const address_type &new_dst_addr) {
@@ -97,9 +98,19 @@ void EthernetII::payload_type(uint16_t new_payload_type) {
}
uint32_t EthernetII::header_size() const {
return sizeof(ethhdr);
}
uint32_t EthernetII::trailer_size() const {
int32_t padding = 60 - sizeof(ethhdr); // EthernetII min size is 60, padding is sometimes needed
if (inner_pdu()) {
padding -= inner_pdu()->size();
padding = std::max(0, padding);
}
return padding;
}
#ifndef WIN32
void EthernetII::send(PacketSender &sender, const NetworkInterface &iface) {
if(!iface)
@@ -129,8 +140,7 @@ bool EthernetII::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
const size_t addr_sz = address_type::address_size;
const ethhdr *eth_ptr = (const ethhdr*)ptr;
if(std::equal(_eth.src_mac, _eth.src_mac + addr_sz, eth_ptr->dst_mac)) {
if(std::equal(_eth.src_mac, _eth.src_mac + addr_sz, eth_ptr->dst_mac) || dst_addr() == BROADCAST ||
(_eth.src_mac[0] == 0x33 && _eth.src_mac[1] == 0x33))
if(std::equal(_eth.src_mac, _eth.src_mac + addr_sz, eth_ptr->dst_mac) || !dst_addr().is_unicast())
{
return (inner_pdu()) ? inner_pdu()->matches_response(ptr + sizeof(_eth), total_sz - sizeof(_eth)) : true;
}
@@ -140,7 +150,7 @@ bool EthernetII::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
void EthernetII::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
#ifdef TINS_DEBUG
assert(total_sz >= header_size());
assert(total_sz >= header_size() + trailer_size());
#endif
/* Inner type defaults to IP */
@@ -151,6 +161,14 @@ void EthernetII::write_serialization(uint8_t *buffer, uint32_t total_sz, const P
payload_type(static_cast<uint16_t>(flag));
}
memcpy(buffer, &_eth, sizeof(ethhdr));
uint32_t trailer = trailer_size();
if (trailer) {
uint32_t trailer_offset = header_size();
if (inner_pdu())
trailer_offset += inner_pdu()->size();
memset(buffer + trailer_offset, 0, trailer);
}
}
#ifndef WIN32

View File

@@ -0,0 +1,95 @@
/*
* 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 "handshake_capturer.h"
#include "dot11/dot11_data.h"
namespace Tins {
bool RSNHandshakeCapturer::process_packet(const PDU &pdu) {
const RSNEAPOL *eapol = pdu.find_pdu<RSNEAPOL>();
const Dot11Data *dot11 = pdu.find_pdu<Dot11Data>();
if(!eapol || !dot11)
return false;
std::pair<address_type, address_type> addresses;
if(dot11->to_ds()) {
addresses.first = dot11->addr1();
addresses.second = dot11->addr2();
}
else if(dot11->from_ds()) {
addresses.first = dot11->addr2();
addresses.second = dot11->addr1();
}
else
return false;
// 1st
if(eapol->key_t() && eapol->key_ack() && !eapol->key_mic() && !eapol->install()) {
handshakes_[addresses].assign(eapol, eapol + 1);
}
else if(eapol->key_t() && eapol->key_mic() && !eapol->install() && !eapol->key_ack()) {
if(*std::max_element(eapol->nonce(), eapol->nonce() + RSNEAPOL::nonce_size) > 0)
do_insert(addresses, eapol, 1);
else if(do_insert(addresses, eapol, 3)) {
completed_handshakes_.push_back(
handshake_type(
addresses.first,
addresses.second,
handshakes_[addresses]
)
);
handshakes_.erase(addresses);
return true;
}
}
else if(eapol->key_t() && eapol->install() && eapol->key_ack() && eapol->key_mic()) {
do_insert(addresses, eapol, 2);
}
return false;
}
bool RSNHandshakeCapturer::do_insert(const handshake_map::key_type &key,
const RSNEAPOL *eapol, size_t expected)
{
handshake_map::iterator iter = handshakes_.find(key);
if(iter != handshakes_.end()) {
if(iter->second.size() != expected) {
// skip repeated
if(iter->second.size() != expected + 1)
iter->second.clear();
}
else {
iter->second.push_back(*eapol);
return true;
}
}
return false;
}
} // namespace Tins;

View File

@@ -153,15 +153,16 @@ void ICMP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *)
#ifdef TINS_DEBUG
assert(total_sz >= sizeof(icmphdr));
#endif
if(!_icmp.check) {
uint32_t checksum = Utils::do_checksum(buffer + sizeof(icmphdr), buffer + total_sz) +
Utils::do_checksum((uint8_t*)&_icmp, ((uint8_t*)&_icmp) + sizeof(icmphdr));
while (checksum >> 16)
checksum = (checksum & 0xffff) + (checksum >> 16);
_icmp.check = Endian::host_to_be<uint16_t>(~checksum);
}
memcpy(buffer, &_icmp, sizeof(icmphdr));
_icmp.check = 0;
uint32_t checksum = Utils::do_checksum(buffer + sizeof(icmphdr), buffer + total_sz) +
Utils::do_checksum((uint8_t*)&_icmp, ((uint8_t*)&_icmp) + sizeof(icmphdr));
while (checksum >> 16)
checksum = (checksum & 0xffff) + (checksum >> 16);
_icmp.check = Endian::host_to_be<uint16_t>(~checksum);
memcpy(buffer, &_icmp, sizeof(icmphdr));
}
bool ICMP::matches_response(const uint8_t *ptr, uint32_t total_sz) const {

View File

@@ -32,13 +32,16 @@
#include "ethernetII.h"
#include "ieee802_3.h"
#include "radiotap.h"
#include "dot11.h"
#include "dot11/dot11_base.h"
#include "ipv6.h"
#include "arp.h"
#include "eapol.h"
#include "rawpdu.h"
#include "dot1q.h"
#include "pppoe.h"
#include "ip_address.h"
#include "ipv6_address.h"
#include "pdu_allocator.h"
using std::string;
@@ -72,18 +75,27 @@ Tins::PDU *pdu_from_flag(Constants::Ethernet::e flag, const uint8_t *buffer,
{
switch(flag) {
case Tins::Constants::Ethernet::IP:
return new Tins::IP(buffer, size);
return new IP(buffer, size);
case Constants::Ethernet::IPV6:
return new Tins::IPv6(buffer, size);
return new IPv6(buffer, size);
case Tins::Constants::Ethernet::ARP:
return new Tins::ARP(buffer, size);
return new ARP(buffer, size);
case Tins::Constants::Ethernet::PPPOED:
return new Tins::PPPoE(buffer, size);
return new PPPoE(buffer, size);
case Tins::Constants::Ethernet::EAPOL:
return Tins::EAPOL::from_bytes(buffer, size);
return EAPOL::from_bytes(buffer, size);
case Tins::Constants::Ethernet::VLAN:
return new Tins::Dot1Q(buffer, size);
return new Dot1Q(buffer, size);
default:
{
PDU *pdu = Internals::allocate<EthernetII>(
static_cast<uint16_t>(flag),
buffer,
size
);
if(pdu)
return pdu;
}
return rawpdu_on_no_match ? new RawPDU(buffer, size) : 0;
};
}
@@ -146,8 +158,48 @@ Constants::Ethernet::e pdu_flag_to_ether_type(PDU::PDUType flag) {
case PDU::PPPOE:
return Constants::Ethernet::PPPOED;
default:
if(Internals::pdu_type_registered<EthernetII>(flag))
return static_cast<Constants::Ethernet::e>(
Internals::pdu_type_to_id<EthernetII>(flag)
);
return Constants::Ethernet::UNKNOWN;
}
}
bool increment(IPv4Address &addr) {
uint32_t addr_int = Endian::be_to_host<uint32_t>(addr);
bool reached_end = ++addr_int == 0xffffffff;
addr = IPv4Address(Endian::be_to_host<uint32_t>(addr_int));
return reached_end;
}
bool increment(IPv6Address &addr) {
return increment_buffer(addr);
}
bool decrement(IPv4Address &addr) {
uint32_t addr_int = Endian::be_to_host<uint32_t>(addr);
bool reached_end = --addr_int == 0;
addr = IPv4Address(Endian::be_to_host<uint32_t>(addr_int));
return reached_end;
}
bool decrement(IPv6Address &addr) {
return decrement_buffer(addr);
}
IPv4Address last_address_from_mask(IPv4Address addr, IPv4Address mask) {
uint32_t addr_int = Endian::be_to_host<uint32_t>(addr),
mask_int = Endian::be_to_host<uint32_t>(mask);
return IPv4Address(Endian::host_to_be(addr_int | ~mask_int));
}
IPv6Address last_address_from_mask(IPv6Address addr, const IPv6Address &mask) {
IPv6Address::iterator addr_iter = addr.begin();
for(IPv6Address::const_iterator it = mask.begin(); it != mask.end(); ++it, ++addr_iter) {
*addr_iter = *addr_iter | ~*it;
}
return addr;
}
} // namespace Internals
} // namespace Tins

View File

@@ -52,6 +52,7 @@
#include "constants.h"
#include "network_interface.h"
#include "exceptions.h"
#include "pdu_allocator.h"
using std::list;
@@ -115,6 +116,9 @@ IP::IP(const uint8_t *buffer, uint32_t total_sz)
uint8_t padding = _options_size % 4;
_padded_options_size = padding ? (_options_size - padding + 4) : _options_size;
// check this line PLX
total_sz = std::min(total_sz, (uint32_t)tot_len());
if (total_sz < head_len() * sizeof(uint32_t))
throw malformed_packet();
total_sz -= head_len() * sizeof(uint32_t);
if (total_sz) {
switch(_ip.protocol) {
@@ -131,7 +135,15 @@ IP::IP(const uint8_t *buffer, uint32_t total_sz)
inner_pdu(new Tins::IPv6(buffer, total_sz));
break;
default:
inner_pdu(new Tins::RawPDU(buffer, total_sz));
inner_pdu(
Internals::allocate<IP>(
_ip.protocol,
buffer,
total_sz
)
);
if(!inner_pdu())
inner_pdu(new RawPDU(buffer, total_sz));
break;
}
}
@@ -394,8 +406,13 @@ void IP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU* pare
new_flag = Constants::IP::PROTO_ICMP;
break;
default:
// check for other protos
new_flag = 0xff;
if(Internals::pdu_type_registered<IP>(inner_pdu()->pdu_type()))
new_flag = static_cast<Constants::IP::e>(
Internals::pdu_type_to_id<IP>(inner_pdu()->pdu_type())
);
else
// check for other protos
new_flag = 0xff;
};
protocol(new_flag);
//flag(new_flag);
@@ -430,8 +447,8 @@ bool IP::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
return false;
const iphdr *ip_ptr = (const iphdr*)ptr;
// checks for broadcast addr
if((_ip.saddr == ip_ptr->daddr && (_ip.daddr == ip_ptr->saddr || _ip.daddr == 0xffffffff)) ||
(_ip.daddr == 0xffffffff && _ip.saddr == 0)) {
if((_ip.saddr == ip_ptr->daddr && (_ip.daddr == ip_ptr->saddr || dst_addr().is_broadcast())) ||
(dst_addr().is_broadcast() && _ip.saddr == 0)) {
uint32_t sz = std::min<uint32_t>(_ip.ihl * sizeof(uint32_t), total_sz);
return inner_pdu() ? inner_pdu()->matches_response(ptr + sz, total_sz - sz) : true;
}

View File

@@ -31,10 +31,22 @@
#include <sstream>
#include "ip_address.h"
#include "endianness.h"
#include "address_range.h"
using std::string;
namespace Tins{
const IPv4Address IPv4Address::broadcast("255.255.255.255");
const AddressRange<IPv4Address> private_ranges[] = {
IPv4Address("192.168.0.0") / 16,
IPv4Address("10.0.0.0") / 8,
IPv4Address("172.16.0.0") / 12
};
const AddressRange<IPv4Address> loopback_range = IPv4Address("127.0.0.0") / 8;
const AddressRange<IPv4Address> multicast_range = IPv4Address("224.0.0.0") / 4;
IPv4Address::IPv4Address(uint32_t ip)
: ip_addr(Endian::be_to_host(ip)) {
@@ -94,4 +106,30 @@ std::ostream &operator<<(std::ostream &output, const IPv4Address &addr) {
}
return output;;
}
bool IPv4Address::is_private() const {
const AddressRange<IPv4Address> *iter = private_ranges;
while(iter != private_ranges + 3) {
if(iter->contains(*this))
return true;
++iter;
}
return false;
}
bool IPv4Address::is_loopback() const {
return loopback_range.contains(*this);
}
bool IPv4Address::is_multicast() const {
return multicast_range.contains(*this);
}
bool IPv4Address::is_unicast() const {
return !is_multicast() && !is_broadcast();
}
bool IPv4Address::is_broadcast() const {
return *this == broadcast;
}
}

View File

@@ -48,6 +48,7 @@
#include "icmpv6.h"
#include "rawpdu.h"
#include "exceptions.h"
#include "pdu_allocator.h"
namespace Tins {
@@ -101,7 +102,15 @@ IPv6::IPv6(const uint8_t *buffer, uint32_t total_sz)
inner_pdu(new Tins::ICMPv6(buffer, total_sz));
break;
default:
inner_pdu(new Tins::RawPDU(buffer, total_sz));
inner_pdu(
Internals::allocate<IPv6>(
current_header,
buffer,
total_sz
)
);
if(!inner_pdu())
inner_pdu(new Tins::RawPDU(buffer, total_sz));
break;
}
total_sz = 0;
@@ -214,10 +223,13 @@ void IPv6::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *pa
new_flag = Constants::IP::PROTO_ICMPV6;
break;
default:
if(Internals::pdu_type_registered<IPv6>(inner_pdu()->pdu_type()))
new_flag = static_cast<Constants::IP::e>(
Internals::pdu_type_to_id<IPv6>(inner_pdu()->pdu_type())
);
break;
};
if(new_flag != 0xff)
set_last_next_header(new_flag);
set_last_next_header(new_flag);
}
payload_length(total_sz - sizeof(_header));
std::memcpy(buffer, &_header, sizeof(_header));

View File

@@ -41,61 +41,72 @@
#include <limits>
#include <sstream>
#include "ipv6_address.h"
#include "address_range.h"
namespace Tins {
IPv6Address::IPv6Address() {
std::fill(address, address + address_size, 0);
}
IPv6Address::IPv6Address(const char *addr) {
init(addr);
}
IPv6Address::IPv6Address(const_iterator ptr) {
std::copy(ptr, ptr + address_size, address);
}
IPv6Address::IPv6Address(const std::string &addr) {
init(addr.c_str());
}
void IPv6Address::init(const char *addr) {
#ifdef WIN32
// mingw on linux somehow doesn't have InetPton
#ifdef _MSC_VER
if(InetPtonA(AF_INET6, addr, address) != 1)
throw malformed_address();
#else
ULONG dummy1;
USHORT dummy2;
// Maybe change this, mingw doesn't have any other conversion function
if(RtlIpv6StringToAddressExA(addr, (IN6_ADDR*)address, &dummy1, &dummy2) != NO_ERROR)
throw malformed_address();
#endif
#else
if(inet_pton(AF_INET6, addr, address) == 0)
throw malformed_address();
#endif
}
const IPv6Address loopback_address = "::1";
const AddressRange<IPv6Address> multicast_range = IPv6Address("ff00::") / 8;
std::string IPv6Address::to_string() const {
char buffer[INET6_ADDRSTRLEN];
#ifdef WIN32
// mingw on linux somehow doesn't have InetNtop
#ifdef _MSC_VER
if(InetNtopA(AF_INET6, (PVOID)address, buffer, sizeof(buffer)) != 0)
throw malformed_address();
#else
ULONG sz = sizeof(buffer);
if(RtlIpv6AddressToStringExA((const IN6_ADDR*)address, 0, 0, buffer, &sz) != NO_ERROR)
throw malformed_address();
#endif
#else
if(inet_ntop(AF_INET6, address, buffer, sizeof(buffer)) == 0)
throw malformed_address();
#endif
return buffer;
}
IPv6Address::IPv6Address() {
std::fill(address, address + address_size, 0);
}
IPv6Address::IPv6Address(const char *addr) {
init(addr);
}
IPv6Address::IPv6Address(const_iterator ptr) {
std::copy(ptr, ptr + address_size, address);
}
IPv6Address::IPv6Address(const std::string &addr) {
init(addr.c_str());
}
void IPv6Address::init(const char *addr) {
#ifdef WIN32
// mingw on linux somehow doesn't have InetPton
#ifdef _MSC_VER
if(InetPtonA(AF_INET6, addr, address) != 1)
throw malformed_address();
#else
ULONG dummy1;
USHORT dummy2;
// Maybe change this, mingw doesn't have any other conversion function
if(RtlIpv6StringToAddressExA(addr, (IN6_ADDR*)address, &dummy1, &dummy2) != NO_ERROR)
throw malformed_address();
#endif
#else
if(inet_pton(AF_INET6, addr, address) == 0)
throw malformed_address();
#endif
}
std::string IPv6Address::to_string() const {
char buffer[INET6_ADDRSTRLEN];
#ifdef WIN32
// mingw on linux somehow doesn't have InetNtop
#ifdef _MSC_VER
if(InetNtopA(AF_INET6, (PVOID)address, buffer, sizeof(buffer)) != 0)
throw malformed_address();
#else
ULONG sz = sizeof(buffer);
if(RtlIpv6AddressToStringExA((const IN6_ADDR*)address, 0, 0, buffer, &sz) != NO_ERROR)
throw malformed_address();
#endif
#else
if(inet_ntop(AF_INET6, address, buffer, sizeof(buffer)) == 0)
throw malformed_address();
#endif
return buffer;
}
bool IPv6Address::is_loopback() const {
return loopback_address == *this;
}
bool IPv6Address::is_multicast() const {
return multicast_range.contains(*this);
}
}

View File

@@ -61,7 +61,7 @@
// PDUs required by PacketSender::send(PDU&, NetworkInterface)
#include "ethernetII.h"
#include "radiotap.h"
#include "dot11.h"
#include "dot11/dot11_base.h"
#include "radiotap.h"
#include "ieee802_3.h"
#include "internals.h"
@@ -119,7 +119,7 @@ void PacketSender::default_interface(const NetworkInterface &iface) {
default_iface = iface;
}
const NetworkInterface& PacketSender::default_interface() {
const NetworkInterface& PacketSender::default_interface() const {
return default_iface;
}

93
src/ppi.cpp Normal file
View File

@@ -0,0 +1,93 @@
/*
* 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.
*
*/
#ifdef TINS_DEBUG
#include <cassert>
#endif // TINS_DEBUG
#include <algorithm>
#include <cstring>
#include <pcap/bpf.h>
#include "dot11/dot11_base.h"
#include "dot3.h"
#include "ethernetII.h"
#include "radiotap.h"
#include "loopback.h"
#include "sll.h"
#include "ppi.h"
#include "internals.h"
namespace Tins {
PPI::PPI(const uint8_t *buffer, uint32_t total_sz) {
if(total_sz < sizeof(_header))
throw malformed_packet();
std::memcpy(&_header, buffer, sizeof(_header));
if(length() > total_sz || length() < sizeof(_header))
throw malformed_packet();
buffer += sizeof(_header);
total_sz -= sizeof(_header);
// There are some options
const size_t options_length = length() - sizeof(_header);
if(options_length > 0) {
_data.assign(buffer, buffer + options_length);
buffer += options_length;
total_sz -= options_length;
}
if(total_sz > 0) {
switch(dlt()) {
case DLT_IEEE802_11:
inner_pdu(Dot11::from_bytes(buffer, total_sz));
break;
case DLT_EN10MB:
if(Internals::is_dot3(buffer, total_sz))
inner_pdu(new Dot3(buffer, total_sz));
else
inner_pdu(new EthernetII(buffer, total_sz));
break;
case DLT_IEEE802_11_RADIO:
inner_pdu(new RadioTap(buffer, total_sz));
break;
case DLT_NULL:
inner_pdu(new Loopback(buffer, total_sz));
break;
case DLT_LINUX_SLL:
inner_pdu(new Tins::SLL(buffer, total_sz));
break;
}
}
}
uint32_t PPI::header_size() const {
return sizeof(_header) + _data.size();
}
void PPI::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) {
throw std::runtime_error("PPI serialization not supported");
}
}

View File

@@ -51,6 +51,7 @@ PPPoE::PPPoE(const uint8_t *buffer, uint32_t total_sz)
std::memcpy(&_header, buffer, sizeof(_header));
buffer += sizeof(_header);
total_sz -= sizeof(_header);
total_sz = std::min(total_sz, (uint32_t)payload_length());
const uint8_t *end = buffer + total_sz;
while(buffer < end) {
if(buffer + sizeof(uint32_t) * 2 > end)

View File

@@ -42,7 +42,7 @@
#include <net/ethernet.h>
#endif
#include "radiotap.h"
#include "dot11.h"
#include "dot11/dot11_base.h"
#include "utils.h"
#include "packet_sender.h"
#include "exceptions.h"
@@ -72,66 +72,75 @@ RadioTap::RadioTap(const uint8_t *buffer, uint32_t total_sz)
check_size(total_sz, sizeof(_radio));
const uint8_t *buffer_start = buffer;
std::memcpy(&_radio, buffer, sizeof(_radio));
uint32_t radiotap_hdr_size = Endian::le_to_host(_radio.it_len);
uint32_t radiotap_hdr_size = length();
check_size(total_sz, radiotap_hdr_size);
buffer += sizeof(_radio);
radiotap_hdr_size -= sizeof(_radio);
if(_radio.tsft)
if(_radio.flags.tsft)
read_field(buffer, radiotap_hdr_size, _tsft);
if(_radio.flags)
if(_radio.flags.flags)
read_field(buffer, radiotap_hdr_size, _flags);
if(_radio.rate)
if(_radio.flags.rate)
read_field(buffer, radiotap_hdr_size, _rate);
if(_radio.channel) {
if(_radio.flags.channel) {
if(((buffer - buffer_start) & 1) == 1) {
buffer++;
radiotap_hdr_size--;
}
read_field(buffer, radiotap_hdr_size, _channel_freq);
uint16_t dummy;
read_field(buffer, radiotap_hdr_size, dummy);
_channel_type = dummy;
read_field(buffer, radiotap_hdr_size, _channel_type);
}
if(_radio.dbm_signal)
if(_radio.flags.dbm_signal)
read_field(buffer, radiotap_hdr_size, _dbm_signal);
if(_radio.dbm_noise)
if(_radio.flags.dbm_noise)
read_field(buffer, radiotap_hdr_size, _dbm_noise);
if(_radio.antenna)
if(_radio.flags.lock_quality)
read_field(buffer, radiotap_hdr_size, _signal_quality);
if(_radio.flags.antenna)
read_field(buffer, radiotap_hdr_size, _antenna);
if(_radio.rx_flags) {
if(_radio.flags.db_signal)
read_field(buffer, radiotap_hdr_size, _db_signal);
if(_radio.flags.rx_flags) {
if(((buffer - buffer_start) & 1) == 1) {
buffer++;
radiotap_hdr_size--;
}
read_field(buffer, radiotap_hdr_size, _rx_flags);
}
if(_radio.channel_plus) {
if(_radio.flags.channel_plus) {
uint32_t offset = ((buffer - buffer_start) % 4);
if(offset) {
offset = 4 - offset;
buffer += offset;
radiotap_hdr_size -= offset;
}
read_field(buffer, radiotap_hdr_size, _channel_type);
uint32_t dummy;
read_field(buffer, radiotap_hdr_size, dummy);
// nasty Big Endian fix
_channel_type = Endian::le_to_host<uint16_t>(Endian::host_to_le<uint32_t>(dummy));
read_field(buffer, radiotap_hdr_size, _channel_freq);
read_field(buffer, radiotap_hdr_size, _channel);
read_field(buffer, radiotap_hdr_size, _max_power);
}
total_sz -= Endian::le_to_host(_radio.it_len);
total_sz -= length();
buffer += radiotap_hdr_size;
if((flags() & FCS) != 0) {
if(_radio.flags.flags && (flags() & FCS) != 0) {
check_size(total_sz, sizeof(uint32_t));
total_sz -= sizeof(uint32_t);
if((flags() & FAILED_FCS) !=0)
throw malformed_packet();
}
if(total_sz)
@@ -161,67 +170,83 @@ void RadioTap::length(uint16_t new_length) {
void RadioTap::tsft(uint64_t new_tsft) {
_tsft = Endian::host_to_le(new_tsft);
_radio.tsft = 1;
_radio.flags.tsft = 1;
}
void RadioTap::flags(FrameFlags new_flags) {
_flags = (uint8_t)new_flags;
_radio.flags = 1;
_radio.flags.flags = 1;
}
void RadioTap::rate(uint8_t new_rate) {
_rate = new_rate;
_radio.rate = 1;
_radio.flags.rate = 1;
}
void RadioTap::channel(uint16_t new_freq, uint16_t new_type) {
_channel_freq = Endian::host_to_le(new_freq);
_channel_type = Endian::host_to_le<uint32_t>(new_type);
_radio.channel = 1;
_channel_type = Endian::host_to_le(new_type);
_radio.flags.channel = 1;
}
void RadioTap::dbm_signal(uint8_t new_dbm_signal) {
_dbm_signal = new_dbm_signal;
_radio.dbm_signal = 1;
_radio.flags.dbm_signal = 1;
}
void RadioTap::dbm_noise(uint8_t new_dbm_noise) {
_dbm_noise = new_dbm_noise;
_radio.dbm_noise = 1;
_radio.flags.dbm_noise = 1;
}
void RadioTap::signal_quality(uint8_t new_signal_quality) {
_signal_quality = new_signal_quality;
_radio.flags.lock_quality = 1;
}
void RadioTap::antenna(uint8_t new_antenna) {
_antenna = new_antenna;
_radio.antenna = 1;
_radio.flags.antenna = 1;
}
void RadioTap::db_signal(uint8_t new_db_signal) {
_db_signal = new_db_signal;
_radio.flags.db_signal = 1;
}
void RadioTap::rx_flags(uint16_t new_rx_flag) {
_rx_flags = Endian::host_to_le(new_rx_flag);
_radio.rx_flags = 1;
_radio.flags.rx_flags = 1;
}
uint32_t RadioTap::header_size() const {
uint32_t total_bytes = 0;
if(_radio.tsft)
if(_radio.flags.tsft)
total_bytes += sizeof(_tsft);
if(_radio.flags)
if(_radio.flags.flags)
total_bytes += sizeof(_flags);
if(_radio.rate)
if(_radio.flags.rate)
total_bytes += sizeof(_rate);
if(_radio.channel) {
if(_radio.flags.channel) {
total_bytes += (total_bytes & 1);
total_bytes += sizeof(uint16_t) * 2;
}
if(_radio.dbm_signal)
if(_radio.flags.dbm_signal)
total_bytes += sizeof(_dbm_signal);
if(_radio.dbm_noise)
if(_radio.flags.dbm_noise)
total_bytes += sizeof(_dbm_noise);
if(_radio.antenna)
if(_radio.flags.lock_quality) {
total_bytes += (total_bytes & 1);
total_bytes += sizeof(_signal_quality);
}
if(_radio.flags.antenna)
total_bytes += sizeof(_antenna);
if(_radio.rx_flags) {
if(_radio.flags.db_signal)
total_bytes += sizeof(_db_signal);
if(_radio.flags.rx_flags) {
total_bytes += (total_bytes & 1);
total_bytes += sizeof(_rx_flags);
}
if(_radio.channel_plus) {
if(_radio.flags.channel_plus) {
uint32_t offset = total_bytes % 4;
if(offset)
total_bytes += 4 - offset;
@@ -282,50 +307,58 @@ void RadioTap::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU
#ifdef TINS_DEBUG
assert(total_sz >= sz);
#endif
if(!_radio.it_len)
_radio.it_len = Endian::host_to_le<uint16_t>(sz);
_radio.it_len = Endian::host_to_le<uint16_t>(sz);
memcpy(buffer, &_radio, sizeof(_radio));
buffer += sizeof(_radio);
if(_radio.tsft) {
if(_radio.flags.tsft) {
memcpy(buffer, &_tsft, sizeof(_tsft));
buffer += sizeof(_tsft);
}
if(_radio.flags) {
if(_radio.flags.flags) {
memcpy(buffer, &_flags, sizeof(_flags));
buffer += sizeof(_flags);
}
if(_radio.rate) {
if(_radio.flags.rate) {
memcpy(buffer, &_rate, sizeof(_rate));
buffer += sizeof(_rate);
}
if(_radio.channel) {
if(_radio.flags.channel) {
if(((buffer - buffer_start) & 1) == 1)
*(buffer++) = 0;
uint16_t dummy = _channel_type;
memcpy(buffer, &_channel_freq, sizeof(_channel_freq));
buffer += sizeof(_channel_freq);
memcpy(buffer, &dummy, sizeof(dummy));
buffer += sizeof(dummy);
memcpy(buffer, &_channel_type, sizeof(_channel_type));
buffer += sizeof(_channel_type);
}
if(_radio.dbm_signal) {
if(_radio.flags.dbm_signal) {
memcpy(buffer, &_dbm_signal, sizeof(_dbm_signal));
buffer += sizeof(_dbm_signal);
}
if(_radio.dbm_noise) {
if(_radio.flags.dbm_noise) {
memcpy(buffer, &_dbm_noise, sizeof(_dbm_noise));
buffer += sizeof(_dbm_noise);
}
if(_radio.antenna) {
if(_radio.flags.lock_quality) {
if(((buffer - buffer_start) & 1) == 1)
*(buffer++) = 0;
memcpy(buffer, &_signal_quality, sizeof(_signal_quality));
buffer += sizeof(_signal_quality);
}
if(_radio.flags.antenna) {
memcpy(buffer, &_antenna, sizeof(_antenna));
buffer += sizeof(_antenna);
}
if(_radio.rx_flags) {
if(_radio.flags.db_signal) {
memcpy(buffer, &_db_signal, sizeof(_db_signal));
buffer += sizeof(_db_signal);
}
if(_radio.flags.rx_flags) {
if(((buffer - buffer_start) & 1) == 1)
*(buffer++) = 0;
memcpy(buffer, &_rx_flags, sizeof(_rx_flags));
buffer += sizeof(_rx_flags);
}
if(_radio.channel_plus) {
if(_radio.flags.channel_plus) {
uint32_t offset = ((buffer - buffer_start) % 4);
if(offset) {
offset = 4 - offset;
@@ -333,8 +366,11 @@ void RadioTap::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU
*buffer++ = 0;
}
}
memcpy(buffer, &_channel_type, sizeof(_channel_type));
buffer += sizeof(_channel_type);
uint32_t dummy = _channel_type;
// nasty Big Endian fix
dummy = Endian::le_to_host<uint32_t>(Endian::host_to_le<uint16_t>(dummy));
memcpy(buffer, &dummy, sizeof(dummy));
buffer += sizeof(dummy);
memcpy(buffer, &_channel_freq, sizeof(_channel_freq));
buffer += sizeof(_channel_freq);
memcpy(buffer, &_channel, sizeof(_channel));

View File

@@ -35,14 +35,13 @@ using std::string;
using std::runtime_error;
namespace Tins {
BaseSniffer::BaseSniffer() : handle(0), mask(0)
BaseSniffer::BaseSniffer()
: handle(0), mask(0)
{
actual_filter.bf_insns = 0;
}
BaseSniffer::~BaseSniffer() {
if(actual_filter.bf_insns)
pcap_freecode(&actual_filter);
if(handle)
pcap_close(handle);
}
@@ -53,41 +52,83 @@ void BaseSniffer::init(pcap_t *phandle, const std::string &filter,
handle = phandle;
mask = if_mask;
iface_type = pcap_datalink(handle);
actual_filter.bf_insns = 0;
if(!filter.empty() && !set_filter(filter))
throw runtime_error("Invalid filter");
}
bool BaseSniffer::compile_set_filter(const string &filter, bpf_program &prog) {
return (pcap_compile(handle, &prog, filter.c_str(), 0, mask) != -1 && pcap_setfilter(handle, &prog) != -1);
struct sniff_data {
struct timeval tv;
PDU *pdu;
bool packet_processed;
sniff_data() : pdu(0), packet_processed(true) { }
};
template<typename T>
T *safe_alloc(const u_char *bytes, bpf_u_int32 len) {
try {
return new T((const uint8_t*)bytes, len);
}
catch(malformed_packet&) {
return 0;
}
}
template<typename T>
void sniff_loop_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) {
sniff_data *data = (sniff_data*)user;
data->packet_processed = true;
data->tv = h->ts;
data->pdu = safe_alloc<T>(bytes, h->caplen);
}
void sniff_loop_eth_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) {
sniff_data *data = (sniff_data*)user;
data->packet_processed = true;
data->tv = h->ts;
if(Internals::is_dot3((const uint8_t*)bytes, h->caplen))
data->pdu = safe_alloc<Dot3>((const uint8_t*)bytes, h->caplen);
else
data->pdu = safe_alloc<EthernetII>((const uint8_t*)bytes, h->caplen);
}
void sniff_loop_dot11_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) {
sniff_data *data = (sniff_data*)user;
data->packet_processed = true;
data->tv = h->ts;
try {
data->pdu = Dot11::from_bytes(bytes, h->caplen);
}
catch(malformed_packet&) {
}
}
PtrPacket BaseSniffer::next_packet() {
pcap_pkthdr header;
PDU *ret = 0;
const u_char *content = pcap_next(handle, &header);
// timestamp_ = header.ts;
if(content) {
try {
if(iface_type == DLT_EN10MB) {
if(is_dot3((const uint8_t*)content, header.caplen))
ret = new Dot3((const uint8_t*)content, header.caplen);
else
ret = new EthernetII((const uint8_t*)content, header.caplen);
}
else if(iface_type == DLT_IEEE802_11_RADIO)
ret = new RadioTap((const uint8_t*)content, header.caplen);
else if(iface_type == DLT_IEEE802_11)
ret = Dot11::from_bytes((const uint8_t*)content, header.caplen);
else if(iface_type == DLT_LOOP)
ret = new Tins::Loopback((const uint8_t*)content, header.caplen);
else if(iface_type == DLT_LINUX_SLL)
ret = new Tins::SLL((const uint8_t*)content, header.caplen);
}
catch(malformed_packet&) {}
sniff_data data;
const int iface_type = pcap_datalink(handle);
pcap_handler handler = 0;
if(iface_type == DLT_EN10MB)
handler = sniff_loop_eth_handler;
else if(iface_type == DLT_IEEE802_11_RADIO)
handler = &sniff_loop_handler<RadioTap>;
else if(iface_type == DLT_IEEE802_11)
handler = sniff_loop_dot11_handler;
else if(iface_type == DLT_LOOP)
handler = &sniff_loop_handler<Tins::Loopback>;
else if(iface_type == DLT_LINUX_SLL)
handler = &sniff_loop_handler<SLL>;
else if(iface_type == DLT_PPI)
handler = &sniff_loop_handler<PPI>;
else
throw unknown_link_type();
// keep calling pcap_loop until a well-formed packet is found.
while(data.pdu == 0 && data.packet_processed) {
data.packet_processed = false;
if(pcap_loop(handle, 1, handler, (u_char*)&data) < 0)
return PtrPacket(0, Timestamp());
}
return PtrPacket(ret, header.ts);
return PtrPacket(data.pdu, data.tv);
}
void BaseSniffer::stop_sniff() {
@@ -98,10 +139,25 @@ int BaseSniffer::get_fd() {
return pcap_get_selectable_fd(handle);
}
int BaseSniffer::link_type() const {
return pcap_datalink(handle);
}
BaseSniffer::iterator BaseSniffer::begin() {
return iterator(this);
}
BaseSniffer::iterator BaseSniffer::end() {
return iterator(0);
}
bool BaseSniffer::set_filter(const std::string &filter) {
if(actual_filter.bf_insns)
pcap_freecode(&actual_filter);
return compile_set_filter(filter, actual_filter);
bpf_program prog;
if(pcap_compile(handle, &prog, filter.c_str(), 0, mask) == -1)
return false;
bool result = pcap_setfilter(handle, &prog) != -1;
pcap_freecode(&prog);
return result;
}
// ****************************** Sniffer ******************************

View File

@@ -56,41 +56,30 @@ TCP::TCP(const uint8_t *buffer, uint32_t total_sz)
if(total_sz < sizeof(tcphdr))
throw malformed_packet();
std::memcpy(&_tcp, buffer, sizeof(tcphdr));
if(data_offset() * sizeof(uint32_t) > total_sz || data_offset() * sizeof(uint32_t) < sizeof(tcphdr))
throw malformed_packet();
const uint8_t *header_end = buffer + (data_offset() * sizeof(uint32_t));
total_sz = total_sz - (header_end - buffer);
buffer += sizeof(tcphdr);
total_sz -= sizeof(tcphdr);
_total_options_size = 0;
_options_size = 0;
uint32_t index = 0, header_end = (data_offset() * sizeof(uint32_t)) - sizeof(tcphdr);
if(total_sz >= header_end) {
uint8_t args[2] = {0};
while(index < header_end) {
for(unsigned i(0); i < 2; ++i) {
if(index == header_end)
throw malformed_packet();
args[i] = buffer[index++];
// NOP and EOL contain no length field
if(args[0] == NOP || args[0] == EOL)
break;
}
// We don't want to store NOPs and EOLs
if(args[0] != NOP && args[0] != EOL) {
// Not enough size for this option
args[1] -= (sizeof(uint8_t) << 1);
if(header_end - index < args[1])
throw malformed_packet();
if(args[1])
add_option(option((OptionTypes)args[0], buffer + index, buffer + index + args[1]));
else
add_option(option((OptionTypes)args[0], args[1], 0));
index += args[1];
}
else
add_option(option((OptionTypes)args[0], 0));
while(buffer < header_end) {
if(*buffer <= NOP) {
add_option(option((OptionTypes)*buffer, 0));
++buffer;
}
else {
if(buffer + 1 == header_end)
throw malformed_packet();
const uint8_t len = buffer[1] - (sizeof(uint8_t) << 1);
const uint8_t *data_start = buffer + 2;
if(data_start + len > header_end)
throw malformed_packet();
add_option(option((OptionTypes)*buffer, data_start, data_start + len));
buffer = data_start + len;
}
buffer += index;
total_sz -= index;
}
if(total_sz)
inner_pdu(new RawPDU(buffer, total_sz));
@@ -208,7 +197,7 @@ TCP::AltChecksums TCP::altchecksum() const {
return static_cast<AltChecksums>(generic_search<uint8_t>(ALTCHK));
}
small_uint<1> TCP::get_flag(Flags tcp_flag) {
small_uint<1> TCP::get_flag(Flags tcp_flag) const {
switch(tcp_flag) {
case FIN:
return _tcp.fin;
@@ -240,6 +229,18 @@ small_uint<1> TCP::get_flag(Flags tcp_flag) {
};
}
small_uint<12> TCP::flags() const {
return (_tcp.res1 << 8) |
(_tcp.cwr << 7) |
(_tcp.ece << 6) |
(_tcp.urg << 5) |
(_tcp.ack << 4) |
(_tcp.psh << 3) |
(_tcp.rst << 2) |
(_tcp.syn << 1) |
_tcp.fin;
}
void TCP::set_flag(Flags tcp_flag, small_uint<1> value) {
switch(tcp_flag) {
case FIN:
@@ -269,6 +270,17 @@ void TCP::set_flag(Flags tcp_flag, small_uint<1> value) {
};
}
void TCP::flags(small_uint<12> value) {
_tcp.fin = (value & FIN) ? 1 : 0;
_tcp.syn = (value & SYN) ? 1 : 0;
_tcp.rst = (value & RST) ? 1 : 0;
_tcp.psh = (value & PSH) ? 1 : 0;
_tcp.ack = (value & ACK) ? 1 : 0;
_tcp.urg = (value & URG) ? 1 : 0;
_tcp.ece = (value & ECE) ? 1 : 0;
_tcp.cwr = (value & CWR) ? 1 : 0;
}
void TCP::add_option(const option &opt) {
_options.push_back(opt);
internal_add_option(opt);

View File

@@ -1,6 +1,6 @@
CXX=@CXX@
CFLAGS=-c -Wall @CFLAGS@ -DTINS_VERSION=@PACKAGE_VERSION@
LDFLAGS=-lpcap -lgtest -lpthread
LDFLAGS=-lpcap -lgtest -lpthread -lcrypto
SOURCES=@SOURCE_FILES@
OBJECTS=$(SOURCES:.cpp=.o)

228
tests/configure vendored
View File

@@ -1,11 +1,9 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.68 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
@@ -134,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
@@ -167,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'\" &&
@@ -212,21 +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.
# 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
export CONFIG_SHELL
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+"$@"}
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 :
@@ -328,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
@@ -449,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).
@@ -483,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
@@ -504,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'"
@@ -1120,8 +1140,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
@@ -1355,9 +1373,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.68
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
@@ -1630,7 +1648,7 @@ $as_echo "$ac_try_echo"; } >&5
test ! -s conftest.err
} && test -s conftest$ac_exeext && {
test "$cross_compiling" = yes ||
$as_test_x conftest$ac_exeext
test -x conftest$ac_exeext
}; then :
ac_retval=0
else
@@ -1653,7 +1671,7 @@ 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.68. Invocation command line was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2029,7 +2047,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
@@ -2073,7 +2091,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
@@ -2524,7 +2542,7 @@ if test "${enable_c__11+set}" = set; then :
fi
SOURCE_FILES=$(ls ../src/*cpp src/*cpp src/dot11/*cpp | tr '\n' ' ')
SOURCE_FILES=$(ls ../src/*cpp ../src/dot11/*cpp src/*cpp src/dot11/*cpp | tr '\n' ' ')
ac_ext=cpp
@@ -2677,7 +2695,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
@@ -2743,7 +2761,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
@@ -2980,7 +2998,53 @@ else
as_fn_error $? "pcap library is needed!" "$LINENO" 5
fi
#AC_CHECK_LIB([gtest_main], [main], [], [AC_MSG_ERROR([gtest library is needed!])])
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PKCS5_PBKDF2_HMAC_SHA1 in -lcrypto" >&5
$as_echo_n "checking for PKCS5_PBKDF2_HMAC_SHA1 in -lcrypto... " >&6; }
if ${ac_cv_lib_crypto_PKCS5_PBKDF2_HMAC_SHA1+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lcrypto $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 PKCS5_PBKDF2_HMAC_SHA1 ();
int
main ()
{
return PKCS5_PBKDF2_HMAC_SHA1 ();
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_link "$LINENO"; then :
ac_cv_lib_crypto_PKCS5_PBKDF2_HMAC_SHA1=yes
else
ac_cv_lib_crypto_PKCS5_PBKDF2_HMAC_SHA1=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_crypto_PKCS5_PBKDF2_HMAC_SHA1" >&5
$as_echo "$ac_cv_lib_crypto_PKCS5_PBKDF2_HMAC_SHA1" >&6; }
if test "x$ac_cv_lib_crypto_PKCS5_PBKDF2_HMAC_SHA1" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBCRYPTO 1
_ACEOF
LIBS="-lcrypto $LIBS"
else
as_fn_error $? "crypto library is needed!" "$LINENO" 5
fi
ac_config_files="$ac_config_files Makefile"
@@ -3428,16 +3492,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
@@ -3497,28 +3561,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'"
@@ -3540,7 +3592,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.68. Invocation command line was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
@@ -3593,10 +3645,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.68,
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."
@@ -3673,7 +3725,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'

View File

@@ -11,11 +11,11 @@ AC_ARG_ENABLE(
[CFLAGS="$CFLAGS -std=c++0x"]
)
SOURCE_FILES=$(ls ../src/*cpp src/*cpp src/dot11/*cpp | tr '\n' ' ')
SOURCE_FILES=$(ls ../src/*cpp ../src/dot11/*cpp src/*cpp src/dot11/*cpp | tr '\n' ' ')
AC_CHECK_HEADERS([pcap.h gtest/gtest.h])
AC_CHECK_LIB(pcap, pcap_loop, [], [AC_MSG_ERROR([pcap library is needed!])])
#AC_CHECK_LIB([gtest_main], [main], [], [AC_MSG_ERROR([gtest library is needed!])])
AC_CHECK_LIB(crypto, PKCS5_PBKDF2_HMAC_SHA1, [], [AC_MSG_ERROR([crypto library is needed!])])
AC_SUBST(CFLAGS)
AC_SUBST(SOURCE_FILES)
AC_OUTPUT(Makefile)

File diff suppressed because it is too large Load Diff

View File

@@ -1,15 +1,11 @@
#ifndef TINS_DOT11_TEST
#define TINS_DOT11_TEST
#include "dot11.h"
#include "dot11/dot11_base.h"
using Tins::Dot11;
using Tins::Dot11ManagementFrame;
using Tins::Dot11Data;
using Tins::Dot11ControlTA;
typedef Dot11::address_type address_type;
typedef Dot11ManagementFrame::capability_information capability_information;
inline void test_equals(const Dot11 &dot1, const Dot11 &dot2) {
EXPECT_EQ(dot1.protocol(), dot2.protocol());
@@ -26,80 +22,6 @@ inline void test_equals(const Dot11 &dot1, const Dot11 &dot2) {
EXPECT_EQ(dot1.addr1(), dot2.addr1());
}
inline void test_equals(const Dot11ManagementFrame& b1, const Dot11ManagementFrame& b2) {
EXPECT_EQ(b1.addr2(), b2.addr2());
EXPECT_EQ(b1.addr3(), b2.addr3());
EXPECT_EQ(b1.addr4(), b2.addr4());
EXPECT_EQ(b1.frag_num(), b2.frag_num());
EXPECT_EQ(b1.seq_num(), b2.seq_num());
test_equals(static_cast<const Dot11&>(b1), static_cast<const Dot11&>(b2));
}
inline void test_equals(const Dot11Data& b1, const Dot11Data& b2) {
EXPECT_EQ(b1.addr2(), b2.addr2());
EXPECT_EQ(b1.addr3(), b2.addr3());
EXPECT_EQ(b1.addr4(), b2.addr4());
EXPECT_EQ(b1.frag_num(), b2.frag_num());
EXPECT_EQ(b1.seq_num(), b2.seq_num());
test_equals(static_cast<const Dot11&>(b1), static_cast<const Dot11&>(b2));
}
inline void test_equals(const Dot11ControlTA& b1, const Dot11ControlTA& b2) {
EXPECT_EQ(b1.target_addr(), b2.target_addr());
test_equals(static_cast<const Dot11&>(b1), static_cast<const Dot11&>(b2));
}
inline void test_equals(const capability_information &info1, const capability_information &info2) {
EXPECT_EQ(info1.ess(), info2.ess());
EXPECT_EQ(info1.ibss(), info2.ibss());
EXPECT_EQ(info1.cf_poll(), info2.cf_poll());
EXPECT_EQ(info1.cf_poll_req(), info2.cf_poll_req());
EXPECT_EQ(info1.privacy(), info2.privacy());
EXPECT_EQ(info1.short_preamble(), info2.short_preamble());
EXPECT_EQ(info1.pbcc(), info2.pbcc());
EXPECT_EQ(info1.channel_agility(), info2.channel_agility());
EXPECT_EQ(info1.spectrum_mgmt(), info2.spectrum_mgmt());
EXPECT_EQ(info1.qos(), info2.qos());
EXPECT_EQ(info1.sst(), info2.sst());
EXPECT_EQ(info1.apsd(), info2.apsd());
EXPECT_EQ(info1.reserved(), info2.reserved());
EXPECT_EQ(info1.dsss_ofdm(), info2.dsss_ofdm());
EXPECT_EQ(info1.delayed_block_ack(), info2.delayed_block_ack());
EXPECT_EQ(info1.immediate_block_ack(), info2.immediate_block_ack());
}
inline void test_equals_expected(const Dot11ManagementFrame &dot11) {
EXPECT_EQ(dot11.protocol(), 1);
EXPECT_EQ(dot11.type(), Dot11::MANAGEMENT);
EXPECT_EQ(dot11.to_ds(), 1);
EXPECT_EQ(dot11.from_ds(), 0);
EXPECT_EQ(dot11.more_frag(), 0);
EXPECT_EQ(dot11.retry(), 0);
EXPECT_EQ(dot11.power_mgmt(), 0);
EXPECT_EQ(dot11.wep(), 0);
EXPECT_EQ(dot11.order(), 0);
EXPECT_EQ(dot11.duration_id(), 0x234f);
EXPECT_EQ(dot11.addr1(), "00:01:02:03:04:05");
EXPECT_EQ(dot11.addr2(), "01:02:03:04:05:06");
EXPECT_EQ(dot11.addr3(), "02:03:04:05:06:07");
}
inline void test_equals_expected(const Dot11Data &dot11) {
EXPECT_EQ(dot11.type(), Dot11::DATA);
EXPECT_EQ(dot11.addr1(), "00:01:02:03:04:05");
EXPECT_EQ(dot11.addr2(), "01:02:03:04:05:06");
EXPECT_EQ(dot11.addr3(), "02:03:04:05:06:07");
EXPECT_EQ(dot11.frag_num(), 0xa);
EXPECT_EQ(dot11.seq_num(), 0xf1d);
}
inline void test_equals_expected(const Dot11ControlTA &dot11) {
EXPECT_EQ(dot11.target_addr(), "01:02:03:04:05:06");
EXPECT_EQ(dot11.addr1(), "00:01:02:03:04:05");
}
inline void test_equals_empty(const Dot11 &dot11) {
Dot11::address_type empty_addr;
@@ -115,54 +37,5 @@ inline void test_equals_empty(const Dot11 &dot11) {
EXPECT_EQ(dot11.addr1(), empty_addr);
}
inline void test_equals_empty(const Dot11ManagementFrame &dot11) {
Dot11::address_type empty_addr;
EXPECT_EQ(dot11.type(), Dot11::MANAGEMENT);
EXPECT_EQ(dot11.addr2(), empty_addr);
EXPECT_EQ(dot11.addr3(), empty_addr);
EXPECT_EQ(dot11.addr4(), empty_addr);
EXPECT_EQ(dot11.frag_num(), 0);
EXPECT_EQ(dot11.seq_num(), 0);
test_equals_empty(static_cast<const Dot11 &>(dot11));
}
inline void test_equals_empty(const Dot11Data &dot11) {
Dot11::address_type empty_addr;
EXPECT_EQ(dot11.addr1(), empty_addr);
EXPECT_EQ(dot11.addr2(), empty_addr);
EXPECT_EQ(dot11.addr3(), empty_addr);
EXPECT_EQ(dot11.frag_num(), 0);
EXPECT_EQ(dot11.seq_num(), 0);
}
inline void test_equals_empty(const Dot11ControlTA &dot11) {
Dot11::address_type empty_addr;
EXPECT_EQ(dot11.target_addr(), empty_addr);
EXPECT_EQ(dot11.addr1(), empty_addr);
}
inline void test_equals_empty(const capability_information &info) {
EXPECT_EQ(info.ess(), 0);
EXPECT_EQ(info.ibss(), 0);
EXPECT_EQ(info.cf_poll(), 0);
EXPECT_EQ(info.cf_poll_req(), 0);
EXPECT_EQ(info.privacy(), 0);
EXPECT_EQ(info.short_preamble(), 0);
EXPECT_EQ(info.pbcc(), 0);
EXPECT_EQ(info.channel_agility(), 0);
EXPECT_EQ(info.spectrum_mgmt(), 0);
EXPECT_EQ(info.qos(), 0);
EXPECT_EQ(info.sst(), 0);
EXPECT_EQ(info.apsd(), 0);
EXPECT_EQ(info.reserved(), 0);
EXPECT_EQ(info.dsss_ofdm(), 0);
EXPECT_EQ(info.delayed_block_ack(), 0);
EXPECT_EQ(info.immediate_block_ack(), 0);
}
#endif // TINS_DOT11_TEST

View File

@@ -0,0 +1,27 @@
#ifndef TINS_TEST_DOT11_CONTROL_H
#define TINS_TEST_DOT11_CONTROL_H
#include "tests/dot11.h"
#include "dot11/dot11_control.h"
using Tins::Dot11ControlTA;
inline void test_equals(const Dot11ControlTA& b1, const Dot11ControlTA& b2) {
EXPECT_EQ(b1.target_addr(), b2.target_addr());
test_equals(static_cast<const Dot11&>(b1), static_cast<const Dot11&>(b2));
}
inline void test_equals_expected(const Dot11ControlTA &dot11) {
EXPECT_EQ(dot11.target_addr(), "01:02:03:04:05:06");
EXPECT_EQ(dot11.addr1(), "00:01:02:03:04:05");
}
inline void test_equals_empty(const Dot11ControlTA &dot11) {
Dot11::address_type empty_addr;
EXPECT_EQ(dot11.target_addr(), empty_addr);
EXPECT_EQ(dot11.addr1(), empty_addr);
}
#endif // TINS_TEST_DOT11_CONTROL_H

View File

@@ -0,0 +1,38 @@
#ifndef TINS_TEST_DOT11_DATA_H
#define TINS_TEST_DOT11_DATA_H
#include "tests/dot11.h"
#include "dot11/dot11_data.h"
using Tins::Dot11Data;
inline void test_equals(const Dot11Data& b1, const Dot11Data& b2) {
EXPECT_EQ(b1.addr2(), b2.addr2());
EXPECT_EQ(b1.addr3(), b2.addr3());
EXPECT_EQ(b1.addr4(), b2.addr4());
EXPECT_EQ(b1.frag_num(), b2.frag_num());
EXPECT_EQ(b1.seq_num(), b2.seq_num());
test_equals(static_cast<const Dot11&>(b1), static_cast<const Dot11&>(b2));
}
inline void test_equals_expected(const Dot11Data &dot11) {
EXPECT_EQ(dot11.type(), Dot11::DATA);
EXPECT_EQ(dot11.addr1(), "00:01:02:03:04:05");
EXPECT_EQ(dot11.addr2(), "01:02:03:04:05:06");
EXPECT_EQ(dot11.addr3(), "02:03:04:05:06:07");
EXPECT_EQ(dot11.frag_num(), 0xa);
EXPECT_EQ(dot11.seq_num(), 0xf1d);
}
inline void test_equals_empty(const Dot11Data &dot11) {
Dot11::address_type empty_addr;
EXPECT_EQ(dot11.addr1(), empty_addr);
EXPECT_EQ(dot11.addr2(), empty_addr);
EXPECT_EQ(dot11.addr3(), empty_addr);
EXPECT_EQ(dot11.frag_num(), 0);
EXPECT_EQ(dot11.seq_num(), 0);
}
#endif // TINS_TEST_DOT11_DATA_H

View File

@@ -0,0 +1,89 @@
#ifndef TINS_DOT11_MGMT_TEST_H
#define TINS_DOT11_MGMT_TEST_H
#include "tests/dot11.h"
#include "dot11/dot11_mgmt.h"
using Tins::Dot11ManagementFrame;
typedef Dot11ManagementFrame::capability_information capability_information;
inline void test_equals(const Dot11ManagementFrame& b1, const Dot11ManagementFrame& b2) {
EXPECT_EQ(b1.addr2(), b2.addr2());
EXPECT_EQ(b1.addr3(), b2.addr3());
EXPECT_EQ(b1.addr4(), b2.addr4());
EXPECT_EQ(b1.frag_num(), b2.frag_num());
EXPECT_EQ(b1.seq_num(), b2.seq_num());
test_equals(static_cast<const Dot11&>(b1), static_cast<const Dot11&>(b2));
}
inline void test_equals_expected(const Dot11ManagementFrame &dot11) {
EXPECT_EQ(dot11.protocol(), 1);
EXPECT_EQ(dot11.type(), Dot11::MANAGEMENT);
EXPECT_EQ(dot11.to_ds(), 1);
EXPECT_EQ(dot11.from_ds(), 0);
EXPECT_EQ(dot11.more_frag(), 0);
EXPECT_EQ(dot11.retry(), 0);
EXPECT_EQ(dot11.power_mgmt(), 0);
EXPECT_EQ(dot11.wep(), 0);
EXPECT_EQ(dot11.order(), 0);
EXPECT_EQ(dot11.duration_id(), 0x234f);
EXPECT_EQ(dot11.addr1(), "00:01:02:03:04:05");
EXPECT_EQ(dot11.addr2(), "01:02:03:04:05:06");
EXPECT_EQ(dot11.addr3(), "02:03:04:05:06:07");
}
inline void test_equals_empty(const Dot11ManagementFrame &dot11) {
Dot11::address_type empty_addr;
EXPECT_EQ(dot11.type(), Dot11::MANAGEMENT);
EXPECT_EQ(dot11.addr2(), empty_addr);
EXPECT_EQ(dot11.addr3(), empty_addr);
EXPECT_EQ(dot11.addr4(), empty_addr);
EXPECT_EQ(dot11.frag_num(), 0);
EXPECT_EQ(dot11.seq_num(), 0);
test_equals_empty(static_cast<const Dot11 &>(dot11));
}
inline void test_equals(const capability_information &info1, const capability_information &info2) {
EXPECT_EQ(info1.ess(), info2.ess());
EXPECT_EQ(info1.ibss(), info2.ibss());
EXPECT_EQ(info1.cf_poll(), info2.cf_poll());
EXPECT_EQ(info1.cf_poll_req(), info2.cf_poll_req());
EXPECT_EQ(info1.privacy(), info2.privacy());
EXPECT_EQ(info1.short_preamble(), info2.short_preamble());
EXPECT_EQ(info1.pbcc(), info2.pbcc());
EXPECT_EQ(info1.channel_agility(), info2.channel_agility());
EXPECT_EQ(info1.spectrum_mgmt(), info2.spectrum_mgmt());
EXPECT_EQ(info1.qos(), info2.qos());
EXPECT_EQ(info1.sst(), info2.sst());
EXPECT_EQ(info1.apsd(), info2.apsd());
EXPECT_EQ(info1.reserved(), info2.reserved());
EXPECT_EQ(info1.dsss_ofdm(), info2.dsss_ofdm());
EXPECT_EQ(info1.delayed_block_ack(), info2.delayed_block_ack());
EXPECT_EQ(info1.immediate_block_ack(), info2.immediate_block_ack());
}
inline void test_equals_empty(const capability_information &info) {
EXPECT_EQ(info.ess(), 0);
EXPECT_EQ(info.ibss(), 0);
EXPECT_EQ(info.cf_poll(), 0);
EXPECT_EQ(info.cf_poll_req(), 0);
EXPECT_EQ(info.privacy(), 0);
EXPECT_EQ(info.short_preamble(), 0);
EXPECT_EQ(info.pbcc(), 0);
EXPECT_EQ(info.channel_agility(), 0);
EXPECT_EQ(info.spectrum_mgmt(), 0);
EXPECT_EQ(info.qos(), 0);
EXPECT_EQ(info.sst(), 0);
EXPECT_EQ(info.apsd(), 0);
EXPECT_EQ(info.reserved(), 0);
EXPECT_EQ(info.dsss_ofdm(), 0);
EXPECT_EQ(info.delayed_block_ack(), 0);
EXPECT_EQ(info.immediate_block_ack(), 0);
}
#endif // TINS_DOT11_MGMT_TEST_H

161
tests/src/address_range.cpp Normal file
View File

@@ -0,0 +1,161 @@
#include <gtest/gtest.h>
#include <cstring>
#include <string>
#include <algorithm>
#include <stdint.h>
#include "address_range.h"
#include "ip_address.h"
#include "ipv6_address.h"
using namespace std;
using namespace Tins;
class AddressRangeTest : public testing::Test {
public:
void contain_tests24(const IPv4Range &range);
void contain_tests24(const IPv6Range &range);
void contain_tests26(const IPv4Range &range);
};
void AddressRangeTest::contain_tests24(const IPv4Range &range) {
EXPECT_TRUE(range.contains("192.168.0.0"));
EXPECT_TRUE(range.contains("192.168.0.1"));
EXPECT_TRUE(range.contains("192.168.0.254"));
EXPECT_TRUE(range.contains("192.168.0.255"));
EXPECT_TRUE(range.contains("192.168.0.123"));
EXPECT_FALSE(range.contains("192.168.1.1"));
}
void AddressRangeTest::contain_tests26(const IPv4Range &range) {
EXPECT_TRUE(range.contains("192.168.254.192"));
EXPECT_TRUE(range.contains("192.168.254.255"));
EXPECT_FALSE(range.contains("192.168.254.0"));
EXPECT_FALSE(range.contains("192.168.254.191"));
}
void AddressRangeTest::contain_tests24(const IPv6Range &range) {
EXPECT_TRUE(range.contains("dead::1"));
EXPECT_TRUE(range.contains("dead::1fee"));
EXPECT_TRUE(range.contains("dead::ffee"));
EXPECT_FALSE(range.contains("dead::1:1"));
EXPECT_FALSE(range.contains("dead::2:0"));
}
TEST_F(AddressRangeTest, Contains) {
contain_tests24(IPv4Range("192.168.0.0", "192.168.0.255"));
contain_tests24(IPv4Range::from_mask("192.168.0.0", "255.255.255.0"));
contain_tests26(IPv4Range("192.168.254.192", "192.168.254.255"));
contain_tests26(IPv4Range::from_mask("192.168.254.192", "255.255.255.192"));
contain_tests24(IPv6Range("dead::0", "dead::ffff"));
contain_tests24(IPv6Range::from_mask("dead::0", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:0"));
{
AddressRange<HWAddress<6> > range("00:00:00:00:00:00", "00:00:00:00:00:ff");
EXPECT_TRUE(range.contains("00:00:00:00:00:00"));
EXPECT_TRUE(range.contains("00:00:00:00:00:10"));
EXPECT_TRUE(range.contains("00:00:00:00:00:ff"));
EXPECT_FALSE(range.contains("00:00:00:00:01:00"));
}
{
AddressRange<HWAddress<6> > range = HWAddress<6>("00:00:00:00:00:00") / 40;
EXPECT_TRUE(range.contains("00:00:00:00:00:00"));
EXPECT_TRUE(range.contains("00:00:00:00:00:10"));
EXPECT_TRUE(range.contains("00:00:00:00:00:ff"));
EXPECT_FALSE(range.contains("00:00:00:00:01:00"));
}
{
AddressRange<HWAddress<6> > range = HWAddress<6>("00:00:00:00:00:00") / 38;
EXPECT_TRUE(range.contains("00:00:00:00:00:00"));
EXPECT_TRUE(range.contains("00:00:00:00:02:00"));
EXPECT_TRUE(range.contains("00:00:00:00:03:ff"));
EXPECT_FALSE(range.contains("00:00:00:00:04:00"));
}
}
TEST_F(AddressRangeTest, Iterators) {
// v4
{
IPv4Range addr = IPv4Range::from_mask("192.168.0.0", "255.255.255.252");
std::vector<IPv4Address> addresses;
addresses.push_back("192.168.0.1");
addresses.push_back("192.168.0.2");
EXPECT_TRUE(std::equal(addr.begin(), addr.end(), addresses.begin()));
EXPECT_TRUE(addr.is_iterable());
}
{
IPv4Range addr = IPv4Range::from_mask("255.255.255.252", "255.255.255.252");
std::vector<IPv4Address> addresses;
addresses.push_back("255.255.255.253");
addresses.push_back("255.255.255.254");
EXPECT_TRUE(std::equal(addr.begin(), addr.end(), addresses.begin()));
EXPECT_TRUE(addr.is_iterable());
}
// v6
{
IPv6Range addr = IPv6Range::from_mask("dead::0", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc");
std::vector<IPv6Address> addresses;
addresses.push_back("dead::1");
addresses.push_back("dead::2");
EXPECT_TRUE(std::equal(addr.begin(), addr.end(), addresses.begin()));
EXPECT_TRUE(addr.is_iterable());
}
{
IPv6Range addr =
IPv6Range::from_mask(
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc",
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc"
);
std::vector<IPv6Address> addresses;
addresses.push_back("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffd");
addresses.push_back("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe");
EXPECT_TRUE(std::equal(addr.begin(), addr.end(), addresses.begin()));
EXPECT_TRUE(addr.is_iterable());
}
}
TEST_F(AddressRangeTest, Slash) {
// v4
{
IPv4Range range1 = IPv4Range::from_mask("192.168.0.0", "255.255.255.252");
IPv4Range range2 = IPv4Address("192.168.0.0") / 30;
EXPECT_TRUE(std::equal(range1.begin(), range1.end(), range2.begin()));
EXPECT_TRUE(std::equal(range2.begin(), range2.end(), range1.begin()));
EXPECT_TRUE(range1.is_iterable());
EXPECT_TRUE(range2.is_iterable());
}
{
IPv4Range range1 = IPv4Range::from_mask("255.255.255.252", "255.255.255.252");
IPv4Range range2 = IPv4Address("255.255.255.252") / 30;
EXPECT_TRUE(std::equal(range1.begin(), range1.end(), range2.begin()));
EXPECT_TRUE(std::equal(range2.begin(), range2.end(), range1.begin()));
EXPECT_TRUE(range1.is_iterable());
EXPECT_TRUE(range2.is_iterable());
}
// v6
{
IPv6Range range1 = IPv6Range::from_mask("dead::0", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc");
IPv6Range range2 = IPv6Address("dead::0") / 126;
EXPECT_TRUE(std::equal(range1.begin(), range1.end(), range2.begin()));
EXPECT_TRUE(std::equal(range2.begin(), range2.end(), range1.begin()));
EXPECT_TRUE(range1.is_iterable());
EXPECT_TRUE(range2.is_iterable());
}
{
IPv6Range range1 =
IPv6Range::from_mask(
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc",
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc"
);
IPv6Range range2 = IPv6Address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc") / 126;
EXPECT_TRUE(std::equal(range1.begin(), range1.end(), range2.begin()));
EXPECT_TRUE(std::equal(range2.begin(), range2.end(), range1.begin()));
EXPECT_TRUE(range1.is_iterable());
EXPECT_TRUE(range2.is_iterable());
}
}

119
tests/src/allocators.cpp Normal file
View File

@@ -0,0 +1,119 @@
#include <gtest/gtest.h>
#include <vector>
#include <algorithm>
#include <stdint.h>
#include "pdu_allocator.h"
#include "ethernetII.h"
#include "snap.h"
#include "sll.h"
#include "dot1q.h"
#include "ip.h"
#include "ipv6.h"
using namespace Tins;
class AllocatorsTest : public testing::Test {
public:
static const uint8_t link_layer_data_buffer[], ipv4_data_buffer[], ipv6_data_buffer[];
};
const uint8_t AllocatorsTest::link_layer_data_buffer[] = {
0, 27, 17, 210, 243, 22, 0, 25, 209, 22, 248, 43, 6, 102, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65
};
const uint8_t AllocatorsTest::ipv4_data_buffer[] = {
255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 8, 0, 69, 0, 0, 60,
0, 1, 0, 0, 64, 255, 123, 192, 127, 0, 0, 1, 127, 0, 0, 1, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65
};
const uint8_t AllocatorsTest::ipv6_data_buffer[] = {
255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 134, 221, 96, 0, 0,
0, 0, 40, 250, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65
};
class DummyPDU : public PDU {
public:
static const PDU::PDUType pdu_flag;
DummyPDU(const uint8_t* data, uint32_t sz) : buffer(data, data + sz) { }
DummyPDU *clone() const { return new DummyPDU(*this); }
uint32_t header_size() const { return buffer.size(); }
PDUType pdu_type() const { return pdu_flag; }
void write_serialization(uint8_t *data, uint32_t, const PDU *)
{
std::copy(buffer.begin(), buffer.end(), data);
}
std::vector<uint8_t> buffer;
};
const PDU::PDUType DummyPDU::pdu_flag = USER_DEFINED_PDU;
TEST_F(AllocatorsTest, LinkLayerPDUs) {
Allocators::register_allocator<EthernetII, DummyPDU>(1638);
Allocators::register_allocator<SNAP, DummyPDU>(25);
Allocators::register_allocator<Dot1Q, DummyPDU>(4562);
Allocators::register_allocator<SLL, DummyPDU>(16705);
std::vector<uint8_t> link_layer_data(
link_layer_data_buffer,
link_layer_data_buffer + sizeof(link_layer_data_buffer)
);
{
EthernetII pkt(&link_layer_data[0], link_layer_data.size());
EXPECT_TRUE(pkt.find_pdu<DummyPDU>());
EXPECT_EQ(pkt.serialize(), link_layer_data);
}
{
SNAP pkt(&link_layer_data[0], link_layer_data.size());
EXPECT_TRUE(pkt.find_pdu<DummyPDU>());
EXPECT_EQ(pkt.serialize(), link_layer_data);
}
{
SLL pkt(&link_layer_data[0], link_layer_data.size());
EXPECT_TRUE(pkt.find_pdu<DummyPDU>());
EXPECT_EQ(pkt.serialize(), link_layer_data);
}
{
Dot1Q pkt(&link_layer_data[0], link_layer_data.size());
EXPECT_TRUE(pkt.find_pdu<DummyPDU>());
EXPECT_EQ(pkt.serialize(), link_layer_data);
}
}
TEST_F(AllocatorsTest, IP) {
std::vector<uint8_t> ipv4_data(
ipv4_data_buffer,
ipv4_data_buffer + sizeof(ipv4_data_buffer)
);
Allocators::register_allocator<IP, DummyPDU>(255);
EthernetII pkt(&ipv4_data[0], ipv4_data.size());
EXPECT_TRUE(pkt.find_pdu<IP>());
EXPECT_TRUE(pkt.find_pdu<DummyPDU>());
EXPECT_EQ(pkt.serialize(), ipv4_data);
}
TEST_F(AllocatorsTest, IPv6) {
std::vector<uint8_t> ipv6_data(
ipv6_data_buffer,
ipv6_data_buffer + sizeof(ipv6_data_buffer)
);
Allocators::register_allocator<IPv6, DummyPDU>(250);
{
EthernetII pkt(&ipv6_data[0], ipv6_data.size());
EXPECT_TRUE(pkt.find_pdu<IPv6>());
EXPECT_TRUE(pkt.find_pdu<DummyPDU>());
EXPECT_EQ(pkt.serialize(), ipv6_data);
}
}

View File

@@ -105,7 +105,7 @@ TEST_F(DHCPTest, HOps) {
TEST_F(DHCPTest, Xid) {
DHCP dhcp;
dhcp.xid(0x71bd167c);
EXPECT_EQ(dhcp.xid(), 0x71bd167c);
EXPECT_EQ(dhcp.xid(), 0x71bd167cU);
}
TEST_F(DHCPTest, Secs) {
@@ -284,7 +284,7 @@ TEST_F(DHCPTest, ConstructorFromBuffer) {
EXPECT_EQ(dhcp1.htype(), 1);
ASSERT_EQ(dhcp1.hlen(), (const size_t)EthernetII::address_type::address_size);
EXPECT_EQ(dhcp1.hops(), 0x1f);
EXPECT_EQ(dhcp1.xid(), 0x3fab23de);
EXPECT_EQ(dhcp1.xid(), 0x3fab23deU);
EXPECT_EQ(dhcp1.secs(), 0x9f1a);
EXPECT_EQ(dhcp1.padding(), 0);
EXPECT_EQ(dhcp1.ciaddr(), IPv4Address("192.168.0.102"));

View File

@@ -23,13 +23,13 @@ TEST_F(DHCPv6Test, DefaultConstructor) {
DHCPv6 dhcp;
EXPECT_EQ(0, (int)dhcp.msg_type());
EXPECT_EQ(0, dhcp.hop_count());
EXPECT_EQ(0, dhcp.transaction_id());
EXPECT_EQ(0U, dhcp.transaction_id());
}
TEST_F(DHCPv6Test, ConstructorFromBuffer) {
DHCPv6 dhcp(expected_packet, sizeof(expected_packet));
EXPECT_EQ(DHCPv6::SOLICIT, dhcp.msg_type());
EXPECT_EQ(0xe828b9, dhcp.transaction_id());
EXPECT_EQ(0xe828b9U, dhcp.transaction_id());
EXPECT_TRUE(dhcp.search_option(DHCPv6::CLIENTID));
EXPECT_TRUE(dhcp.search_option(DHCPv6::IA_NA));
EXPECT_TRUE(dhcp.search_option(DHCPv6::ELAPSED_TIME));
@@ -62,7 +62,7 @@ TEST_F(DHCPv6Test, HopCount) {
TEST_F(DHCPv6Test, TransactionId) {
DHCPv6 dhcp;
dhcp.transaction_id(0x8af2ad);
EXPECT_EQ(0x8af2ad, dhcp.transaction_id());
EXPECT_EQ(0x8af2adU, dhcp.transaction_id());
}
// Options
@@ -160,7 +160,7 @@ TEST_F(DHCPv6Test, Authentication) {
data.protocol = 0x92;
data.algorithm = 0x8f;
data.rdm = 0xa1;
data.replay_detection = 0x78ad6d5290398df7;
data.replay_detection = 0x78ad6d5290398df7ULL;
data.auth_info.push_back(0);
data.auth_info.push_back(1);
data.auth_info.push_back(2);

View File

@@ -76,11 +76,11 @@ TEST_F(DNSTest, ConstructorFromBuffer) {
EXPECT_EQ(dns.answers_count(), 1);
std::list<DNS::Query> queries = dns.queries();
ASSERT_EQ(queries.size(), 1);
ASSERT_EQ(queries.size(), 1U);
test_equals(queries.front(), DNS::Query("www.example.com", DNS::A, DNS::IN));
std::list<DNS::Resource> answers = dns.answers();
ASSERT_EQ(answers.size(), 1);
ASSERT_EQ(answers.size(), 1U);
test_equals(answers.front(), DNS::Resource("www.example.com", "192.168.0.1", DNS::A, DNS::IN, 0x1234));
}
@@ -204,7 +204,7 @@ TEST_F(DNSTest, Question) {
TEST_F(DNSTest, Answers) {
DNS dns;
dns.add_answer("www.example.com", DNS::make_info(DNS::A, DNS::IN, 0x762), IPv4Address("127.0.0.1"));
dns.add_answer("www.example2.com", DNS::make_info(DNS::MX, DNS::IN, 0x762), IPv4Address("127.0.0.1"));
dns.add_answer("www.example2.com", DNS::make_info(DNS::MX, DNS::IN, 0x762), std::string("mail.example.com"));
ASSERT_EQ(dns.answers_count(), 2);
DNS::resources_type resources = dns.answers();
@@ -212,14 +212,14 @@ TEST_F(DNSTest, Answers) {
EXPECT_TRUE(it->dname() == "www.example.com" || it->dname() == "www.example2.com");
if(it->dname() == "www.example.com") {
EXPECT_EQ(it->type(), DNS::A);
EXPECT_EQ(it->ttl(), 0x762);
EXPECT_EQ(it->ttl(), 0x762U);
EXPECT_EQ(it->data(), "127.0.0.1");
EXPECT_EQ(it->query_class(), DNS::IN);
}
else if(it->dname() == "www.example2.com") {
EXPECT_EQ(it->type(), DNS::MX);
EXPECT_EQ(it->ttl(), 0x762);
EXPECT_EQ(it->data(), "127.0.0.1");
EXPECT_EQ(it->ttl(), 0x762U);
EXPECT_EQ(it->data(), "mail.example.com");
EXPECT_EQ(it->query_class(), DNS::IN);
}
}
@@ -235,7 +235,7 @@ TEST_F(DNSTest, AnswersWithSameName) {
EXPECT_TRUE(it->data() == "127.0.0.1" || it->data() == "127.0.0.2");
EXPECT_EQ(it->dname(), "www.example.com");
EXPECT_EQ(it->type(), DNS::A);
EXPECT_EQ(it->ttl(), 0x762);
EXPECT_EQ(it->ttl(), 0x762U);
EXPECT_EQ(it->query_class(), DNS::IN);
}
}
@@ -250,7 +250,7 @@ TEST_F(DNSTest, AnswersV6) {
for(DNS::resources_type::const_iterator it = resources.begin(); it != resources.end(); ++it) {
EXPECT_EQ(it->dname(), "www.example.com");
EXPECT_EQ(it->type(), DNS::AAAA);
EXPECT_EQ(it->ttl(), 0x762);
EXPECT_EQ(it->ttl(), 0x762U);
EXPECT_EQ(it->data(), "f9a8:239::1:1");
EXPECT_EQ(it->query_class(), DNS::IN);
}

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