mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 18:55:58 +01:00
Compare commits
58 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
08113b8f5f | ||
|
|
6dd949611d | ||
|
|
b6a55935b4 | ||
|
|
01b2a9c7b2 | ||
|
|
58e2c93e30 | ||
|
|
bcfe26175a | ||
|
|
c4e6a7c0d6 | ||
|
|
9cbac6b044 | ||
|
|
2414edd1e7 | ||
|
|
74ef177e25 | ||
|
|
54d012b92e | ||
|
|
1b4efc1520 | ||
|
|
96ecd054ab | ||
|
|
d7d2dec5cb | ||
|
|
20f3911e12 | ||
|
|
f8d71687e1 | ||
|
|
d393c1fbfc | ||
|
|
e21e34e194 | ||
|
|
a01fff411e | ||
|
|
7d4222fb17 | ||
|
|
de0ec914cc | ||
|
|
15f2896811 | ||
|
|
b26f353e46 | ||
|
|
5f2c923c48 | ||
|
|
4ca21bdad7 | ||
|
|
2cc0ceb1aa | ||
|
|
7063e60af9 | ||
|
|
21b80a7370 | ||
|
|
fb8fb92ee6 | ||
|
|
2a5b64526f | ||
|
|
02d3a14083 | ||
|
|
3b349471ea | ||
|
|
f385e4e975 | ||
|
|
acff8f1e1f | ||
|
|
59090e62d2 | ||
|
|
74594a3b20 | ||
|
|
681bdc727f | ||
|
|
996e0f139e | ||
|
|
c2353314fa | ||
|
|
5d315c5b6d | ||
|
|
87ac5acdd8 | ||
|
|
3b4dc10211 | ||
|
|
8c1d71c7b7 | ||
|
|
5db196a630 | ||
|
|
ec8374be60 | ||
|
|
eeb62add59 | ||
|
|
908fcb56e8 | ||
|
|
ddf47365c1 | ||
|
|
b052aa1d88 | ||
|
|
cacf75995d | ||
|
|
4960077495 | ||
|
|
8147a2bfb7 | ||
|
|
28c8d393d6 | ||
|
|
ec7e718e38 | ||
|
|
62740e8e64 | ||
|
|
2bb699dc97 | ||
|
|
14b1a4988b | ||
|
|
7f6e4446b4 |
54
CHANGES
54
CHANGES
@@ -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
|
||||
|
||||
4
Doxyfile
4
Doxyfile
@@ -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
|
||||
|
||||
37
Makefile.am
37
Makefile.am
@@ -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/
|
||||
|
||||
209
Makefile.in
209
Makefile.in
@@ -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
2
README
@@ -1,5 +1,5 @@
|
||||
------------------------------------------------------------------------
|
||||
libtins v1.0
|
||||
libtins v1.1
|
||||
------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
106
configure
vendored
106
configure
vendored
@@ -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\\"
|
||||
|
||||
|
||||
29
configure.ac
29
configure.ac
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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".
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
331
include/address_range.h
Normal 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
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
174
include/crypto.h
174
include/crypto.h
@@ -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>
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -442,7 +442,6 @@ public:
|
||||
* \return The stored options.
|
||||
*/
|
||||
const options_type &options() const { return options_; }
|
||||
;
|
||||
|
||||
// Setters
|
||||
/**
|
||||
|
||||
@@ -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.
|
||||
|
||||
3578
include/dot11.h
3578
include/dot11.h
File diff suppressed because it is too large
Load Diff
620
include/dot11/dot11_assoc.h
Normal file
620
include/dot11/dot11_assoc.h
Normal 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
258
include/dot11/dot11_auth.h
Normal 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
515
include/dot11/dot11_base.h
Normal 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
|
||||
164
include/dot11/dot11_beacon.h
Normal file
164
include/dot11/dot11_beacon.h
Normal 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
|
||||
743
include/dot11/dot11_control.h
Normal file
743
include/dot11/dot11_control.h
Normal 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
343
include/dot11/dot11_data.h
Normal 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
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
230
include/dot11/dot11_probe.h
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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; };
|
||||
|
||||
|
||||
@@ -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)))));
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
167
include/handshake_capturer.h
Normal file
167
include/handshake_capturer.h
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
18
include/ip.h
18
include/ip.h
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -117,7 +117,9 @@ namespace Tins {
|
||||
DHCPv6,
|
||||
DOT1Q,
|
||||
PPPOE,
|
||||
STP
|
||||
STP,
|
||||
PPI,
|
||||
USER_DEFINED_PDU = 1000
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
182
include/pdu_allocator.h
Normal file
182
include/pdu_allocator.h
Normal 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
134
include/ppi.h
Normal 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
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
57
src/address_range.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
454
src/crypto.cpp
454
src/crypto.cpp
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
45
src/dns.cpp
45
src/dns.cpp
@@ -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)
|
||||
)
|
||||
|
||||
1645
src/dot11.cpp
1645
src/dot11.cpp
File diff suppressed because it is too large
Load Diff
249
src/dot11/dot11_assoc.cpp
Normal file
249
src/dot11/dot11_assoc.cpp
Normal 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
123
src/dot11/dot11_auth.cpp
Normal 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
275
src/dot11/dot11_base.cpp
Normal 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
|
||||
79
src/dot11/dot11_beacon.cpp
Normal file
79
src/dot11/dot11_beacon.cpp
Normal 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
283
src/dot11/dot11_control.cpp
Normal 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
182
src/dot11/dot11_data.cpp
Normal 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
641
src/dot11/dot11_mgmt.cpp
Normal 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, ¤t_channel);
|
||||
}
|
||||
|
||||
void Dot11ManagementFrame::cf_parameter_set(const cf_params_set ¶ms) {
|
||||
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 ¶ms) {
|
||||
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 ¶ms) {
|
||||
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 ¶ms) {
|
||||
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
97
src/dot11/dot11_probe.cpp
Normal 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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
95
src/handshake_capturer.cpp
Normal file
95
src/handshake_capturer.cpp
Normal 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;
|
||||
17
src/icmp.cpp
17
src/icmp.cpp
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
27
src/ip.cpp
27
src/ip.cpp
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
18
src/ipv6.cpp
18
src/ipv6.cpp
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
93
src/ppi.cpp
Normal 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");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
138
src/radiotap.cpp
138
src/radiotap.cpp
@@ -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));
|
||||
|
||||
124
src/sniffer.cpp
124
src/sniffer.cpp
@@ -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 ******************************
|
||||
|
||||
74
src/tcp.cpp
74
src/tcp.cpp
@@ -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);
|
||||
|
||||
@@ -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
228
tests/configure
vendored
@@ -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'
|
||||
|
||||
@@ -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)
|
||||
|
||||
2280
tests/depends.d
2280
tests/depends.d
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
27
tests/include/tests/dot11_control.h
Normal file
27
tests/include/tests/dot11_control.h
Normal 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
|
||||
38
tests/include/tests/dot11_data.h
Normal file
38
tests/include/tests/dot11_data.h
Normal 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
|
||||
89
tests/include/tests/dot11_mgmt.h
Normal file
89
tests/include/tests/dot11_mgmt.h
Normal 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
161
tests/src/address_range.cpp
Normal 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
119
tests/src/allocators.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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"));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user