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

95 Commits
v1.2 ... v3.0

Author SHA1 Message Date
Matias Fontanini
5d8f3e6741 Updated README and CHANGES files. 2014-08-07 21:39:54 -03:00
Matias Fontanini
5d0ba22ac4 Fixed invalid parsing of unknown DNS records. 2014-08-07 21:22:31 -03:00
Matias Fontanini
8a44b29d92 Protocols now always set the next layer protocol flag. 2014-08-07 20:42:17 -03:00
Matias Fontanini
1b47623484 Timestamps can now be constructed from std::chrono::duration. 2014-08-07 20:12:19 -03:00
Matias Fontanini
282cd0913c Added Packet constructor. 2014-08-07 19:58:41 -03:00
Matias Fontanini
aed5ccdfca Updated configure files. 2014-08-07 19:56:29 -03:00
Matias Fontanini
8e6ddfd764 Fixed bug in EthernetII when changing its inner PDU. 2014-08-07 19:38:05 -03:00
Matias Fontanini
1c2bfd42ca Fixed invalid address passed to memcpy. 2014-08-07 19:37:06 -03:00
Matias Fontanini
b9db3ea1d3 Merge pull request #22 from mantiz/fix-armv5-alignment-issues
fix armv5 alignment issues
2014-07-31 13:47:17 -03:00
Christian Hammerl
52b0ee7ceb fix armv5 alignment issues 2014-07-31 15:49:52 +00:00
Matias Fontanini
3ef85aae38 Added BaseSniffer::set_extract_raw_pdus. 2014-07-30 23:01:03 -03:00
Matias Fontanini
3bb310dd6b Updated autotools files. 2014-07-30 22:59:14 -03:00
Matias Fontanini
a918229d4b Merge pull request #21 from jedahan/master
minimum automake version from 1.13 -> 1.11
2014-07-30 22:52:08 -03:00
Jonathan Dahan
95a9d18b6b minimum automake version from 1.13 -> 1.11 2014-07-30 11:44:24 -04:00
Matias Fontanini
7371b95ebc Merge pull request #19 from kylemcdonald/master
added Utils::to_string(PDU::PDUType). closes #12.
2014-07-29 08:57:44 -03:00
Kyle McDonald
416edc34f7 added Utils::to_string(PDU::PDUType). closes #12. 2014-07-27 00:24:16 -04:00
Matias Fontanini
2dff95700f Updated copyright notice. 2014-07-13 11:04:29 -03:00
Matias Fontanini
46b52ad26e Updated example. 2014-07-13 10:59:00 -03:00
Matias Fontanini
22e7c1d7c4 Fixed error compilations on windows. 2014-07-02 19:02:48 -03:00
Matias Fontanini
dd2ed5daa4 Added undef directive to avoid compilation error on windows. 2014-07-01 17:06:39 -03:00
Matias Fontanini
c25d4738b4 Added check for HAVE_DOT11 macro in RSNInformation header/source files. 2014-06-09 22:50:49 -03:00
Matias Fontanini
3d4f509a62 Added call to pcap_can_set_rfmon before calling pcap_set_rfmon. 2014-06-09 10:24:09 -03:00
Matias Fontanini
c9e955903e Fixed ICMPv6 checksum calculation. 2014-06-09 10:09:20 -03:00
Matias Fontanini
201ea885a1 Added method in TCP and IP that emplaces an option. 2014-06-01 12:55:36 -03:00
Matias Fontanini
356ea2a68a Added small option optimization to PDUOption. 2014-05-29 23:15:44 -03:00
Matias Fontanini
559c963d63 Fixed compilation errors on Windows. 2014-05-06 00:13:05 -03:00
Matias Fontanini
4bf5876adf Fixed compilation error in RSNInformation. 2014-05-05 08:34:16 -03:00
Matias Fontanini
b2788fad63 Simplified error string generation on Sniffer::pcap_open_live_extended. 2014-05-05 08:32:45 -03:00
Matias Fontanini
c249ff608c Merge pull request #11 from kylemcdonald/master
changed ICMP::check to ICMP::checksum
2014-05-03 18:52:29 -03:00
Kyle McDonald
bd55307b47 changed ICMP::check to ICMP::checksum for both the public getter and private setter. closes #10 2014-05-03 17:43:35 -04:00
Matias Fontanini
6b17dc78e5 Merge pull request #9 from kylemcdonald/master
Allow Sniffer to enable monitor mode on interface
2014-05-03 14:32:27 -03:00
Kyle McDonald
5fe4ab0de8 added pcap_open_live_extended() shim to sniffer.cpp and set rfmon to true in beacon capture example 2014-05-03 12:48:35 -04:00
Matias Fontanini
4ee89662f2 Fix bug on TCPStreamFollower. 2014-04-12 11:53:00 -03:00
Matias Fontanini
86e3f138f8 Added correct handling of the PDU::IPv6 flag in Internals::pdu_flag_to_ip_type. 2014-04-07 13:29:14 -03:00
Matias Fontanini
cd2b9aab98 TCPStreamFollower now doesn't clear its state each time follow_streams is called. 2014-04-07 11:29:09 -03:00
Matias Fontanini
f05840b9e9 Merge pull request #5 from lodagro/patch-1
Fix typo in test name
2014-04-03 13:38:43 -03:00
Wouter Overmeire
8c2abf9249 Fix typo in test name 2014-04-03 15:39:26 +02:00
Matias Fontanini
64d35b4903 TCPStreamFollower now handles overlapping fragments. 2014-04-02 11:10:44 -03:00
Matias Fontanini
10421fe945 Added DHCP::hostname. 2014-04-01 10:22:05 -03:00
Matias Fontanini
7c8aefccfe Merge pull request #4 from jacob-baines/patch-1
Remove Extra Qualification
2014-03-12 14:40:46 -02:00
Jacob Baines
60404296fb Remove Extra Qualification
The extra "SessionKeys::" prevents compilation on Windows.
2014-03-12 12:19:29 -04:00
Matias Fontanini
dbc3ab4c32 Updated the LICENSE file. 2014-03-05 18:23:16 -03:00
Matias Fontanini
f83521f778 Merge pull request #3 from JeanJoskin/master
PacketSender::send does not work properly
2014-02-27 11:25:54 -02:00
Jean Joskin
6fb8cbfc86 PacketSender::send matched PDU against most specific type, hence the PDU::DOT11 case would never be chosen. 2014-02-27 13:34:14 +01:00
Matias Fontanini
0acf388277 Removed 'no newline at end of file' warnings. 2014-02-10 18:21:46 -03:00
Matias F
4c4a5f6c03 Fixed bug when calling BIOCIMMEDIATE on *BSD. 2014-02-10 12:33:48 -03:00
Matias Fontanini
fbef2e765d Fixed bug on PacketSender::send_recv which didn't work under OSX and FreeBSD. 2014-02-06 15:10:23 -03:00
Matias F
ea927caa4b Added BSD notice to DNS stats example. 2014-02-03 10:57:30 -03:00
Matias F
60f9116af1 Added DNS stats example. 2014-02-03 10:55:37 -03:00
Matias Fontanini
75c6bb46dc Fixed compilation error in OSX caused by including pcap/bpf.h instead of pcap.h in src/ppi.cpp. 2014-01-25 18:45:55 -03:00
Matias Fontanini
0a2f3b477b Merge pull request #2 from itay-grudev/master
Fixed bug - not included std::string
2014-01-25 13:00:07 -08:00
Itay Grudev
e73ea43f7b Fixed bug - not included std::string
Error details:
implicit instantiation of undefined template std::basic_string
2014-01-25 22:55:59 +02:00
Matias F
17933765d3 dns_spoof example now uses DNS::Resource. 2014-01-24 09:54:03 -03:00
Matias F
ed175e0ad6 Updated CHANGES, README and configure.ac files. 2014-01-23 11:30:05 -03:00
Matias Fontanini
c5404a6111 Removed DNSResourceRecord. Records in DNS are now managed completely by DNS::Resource. 2014-01-21 22:56:53 -03:00
Matias Fontanini
6d7e06535a Fixed some endianness bugs on ICMPv6 and PPI. 2014-01-19 14:40:57 -03:00
Matias Fontanini
853e1ce647 tins.h now includes ppi.h. 2014-01-19 14:17:25 -03:00
Matias Fontanini
dbcdda9d36 Rewrote the DNS parsing algorithm. Everything is now done on the read buffer, without any extra data structures, making it work about 400% faster than before. 2014-01-19 13:11:50 -03:00
Matias Fontanini
17ceba6064 Fixed broken strict-aliasing rules on ICMPv6. 2014-01-15 19:56:58 -03:00
Matias Fontanini
52078cc567 Finished porting DHCPv6. 2014-01-15 19:39:07 -03:00
Matias Fontanini
e2656739f1 Ported DHCP and Dot11. Almost ported DHCPv6 completely. 2013-12-23 23:02:58 -03:00
Matias Fontanini
33091ccbae Ported PPPoE and started porting Dot11. 2013-12-18 13:02:41 -03:00
Matias Fontanini
ca6b603478 Finished porting ICMPv6. 2013-12-17 19:00:00 -03:00
Matias Fontanini
069ae82b10 Keep porting ICMPv6 to use PDUOption::to<>. 2013-12-17 00:10:26 -03:00
Matias Fontanini
ea6638c163 IP now uses PDUOption::to<>. Started porting ICMPv6 to do so as well. 2013-12-16 15:50:17 -03:00
Matias Fontanini
112a357726 Added PDUOption::to<>. TCP options now use this method when being converted to their appropriate types. 2013-12-16 14:11:53 -03:00
Matias Fontanini
0e54579200 Layer 3 packets sent using PacketSender::send_recv for which the answer is a different PDU type(such as ICMP destination unreachable), are detected by PacketSender and matched like usual. 2013-12-14 18:10:33 -03:00
Matias Fontanini
ccb8ffd1b5 ICMP::gateway is now an IPv4Address. 2013-12-14 14:28:39 -03:00
Matias Fontanini
b83c1a2a96 Added support for ICMP address mask request/reply. 2013-12-14 14:21:04 -03:00
Matias Fontanini
81a947e3b3 Fixed bug on ICMP checksum calculation when using timestamp request/replies. 2013-12-14 13:42:12 -03:00
Matias Fontanini
1cec0f106d Fixed bug in PacketSender when using send_recv and a layer 2 PDU. The interface in which the packet was sent was not the default_interface set when the sender was constructed. 2013-12-14 12:49:50 -03:00
Matias Fontanini
0acb0fee3e IP packets sent using PacketSender::send_recv now match ICMP responses. 2013-12-14 12:48:56 -03:00
Matias Fontanini
9b57585b62 Added support for ICMP timestamp request/reply packets. ICMP::matches_response now works with these types of packets as well. 2013-12-13 17:23:17 -03:00
Matias Fontanini
2ddec368c3 Fixed bug on IP when serializing fragmented packets.
The original protocol id was being overwritten with 0xff(unknown)
when the inner_pdu was a RawPDU, even if it was just a fragment of
a transport layer PDU. The protocol id is now kept if the packet
is fragmented.
2013-12-04 10:56:48 -03:00
matias
83dc8819b6 Updated README.md. 2013-11-24 16:37:10 -03:00
matias
5e668e6e83 Updated README.md 2013-11-24 13:31:19 -03:00
matias
ca4912ded4 Added README.md and updated README. 2013-11-24 11:07:39 -03:00
Matias Fontanini
295ebb679c Added 1000ms as the default read timeout used when calling pcap_open_live. Added BaseSniffer::set_timeout to modify this parameter. 2013-11-19 20:51:58 -03:00
Matias Fontanini
6355aff3cd Added IPv4Reassembler class. 2013-11-17 15:32:24 -03:00
Matias Fontanini
a6655191d4 Fragmented IP packet's inner_pdu PDUs are not decoded now. 2013-11-16 19:40:08 -03:00
Matias Fontanini
dc6c37777b Updated configure.ac and README files. 2013-11-10 14:14:25 -03:00
Matias Fontanini
23552ea105 Fixed issue with relative include paths in dot11 headers. 2013-11-10 11:55:36 -03:00
Matias Fontanini
9962381fc7 Added the --disable-dot11 configure switch. 2013-11-09 14:41:08 -03:00
Matias Fontanini
93ab8d3b91 Removed useless include directives from ip.cpp and ipv6.cpp. 2013-11-04 23:31:46 -03:00
Matias Fontanini
5345b29f8c Added support for IPSec. 2013-11-04 23:05:00 -03:00
Matias Fontanini
de06fee5ab Fixed bug triggered when ifaddrs::ifa_addr was null. 2013-11-04 15:53:55 -03:00
Matias Fontanini
6d329424f1 Created an overload of Internals::pdu_from_flag for transport layer PDUs. 2013-11-04 13:46:25 -03:00
Matias Fontanini
dfbbea33d5 Added another overload of Utils::route_entries and fixed a bug in Utils::network_interfaces. 2013-11-02 19:19:55 -03:00
Matias Fontanini
0b02af616a Added ARP monitor example. 2013-10-29 21:10:11 -03:00
Matias Fontanini
a101ec9796 Added the missing WPS detector example. 2013-10-29 19:19:53 -03:00
Matias Fontanini
b0868b5d60 Added another Sniffer constructor. 2013-10-21 23:31:07 -03:00
Matias Fontanini
f57b8c189c Added WPS detector example. Updated configure files. 2013-10-21 22:54:18 -03:00
Matias Fontanini
a507355e27 Added tins_cast as a replacement for dynamic_cast when using it on PDU classes. 2013-10-18 09:28:43 -03:00
Matias Fontanini
87fdd62b57 Added some examples. 2013-10-17 20:44:54 -03:00
Matias Fontanini
3337335df2 Fixed compilation error on internals.h. 2013-10-16 14:45:03 -03:00
172 changed files with 8717 additions and 3788 deletions

117
CHANGES
View File

@@ -1,3 +1,120 @@
v3.0 - Thu Aug 7 21:39:09 ART 2014
- Timestamps can now be constructed from std::chrono::duration.
- Packets can now be constructed from a PDU pointer and take ownership
of it.
- All protocols now set the next layer protocol flag, regardless if
it was already set. This was not done in some protocols,
like EthernetII, and as a consequence if the network layer protocol
was replaced by other, the packet would be serialized incorrectly.
- Fixed invalid parsing of some unknown DNS records.
- Fixed unaligned memory accesses that were not supported under
ARMv4 and ARMv5.
- Added BaseSniffer::set_extract_raw_pdus.
- Reduced minimum automake version to 1.11.
- Added Utils::to_string(PDU::PDUType).
- Fixed error compilations on Windows.
- Fixed ICMPv6 checksum calculation.
- Added method in IP and TCP to emplace an option (C++11 only).
- Added small option optimization to PDUOption.
- Fixed error compilation on RSNInformation.
- Renamed ICMP::check to ICMP::checksum.
- Added Sniffer support to set interface to promiscuous mode.
- TCPStreamFollower now handles overlapping fragments correctly.
- Fixed bugs in TCPStreamFollower which didn't allow it to follow
stream correctly.
- TCPStreamFollower now doesn't clear its state after every call to
TCPStreamFollower::follow_streams.
- Added IPv6 flag check to pdu_flag_to_ip_type.
- Added DHCP::hostname to extract the hostname options.
- Removed extra qualifier on SessionKeys::decrypt_unicast which
produced compilation errors on some platforms.
- PacketSender::send now uses PDU::matches_flag to match specific
PDU types.
- Removed 'no newline at end of file' warnings.
- Fixed bug when calling BIOCIMMEDIATE on *BSD.
- Fixed bug on PacketSender::send_recv which didn't work under *BSD.
- Fixed bug triggered by not including the string header.
v2.0 - Thu Jan 23 11:09:38 ART 2014
- DNSResourceRecord was removed. Now DNS records are added using
DNS::Resource.
- tins.h now includes ppi.h.
- Done significant improvements in the speed of DNS parsing.
- Added PDUOption<>::to<> which converts a PDUOption to a specific type.
- Layer 3 packets sent using PacketSender::send_recv for which the
answer is a different PDU type.
- ICMP::gateway now uses IPv4Address.
- Added support for ICMP address mask request/reply.
- Fixed bug in PacketSender when using send_recv and a layer 2 PDU. The
interface in which the packet was sent was not the default_interface
set when the sender was constructed.
- IP packets sent using PacketSender::send_recv now match ICMP
responses.
- Added support for ICMP timestamp request/reply packets.
ICMP::matches_response now works with these types of packets as well.
- Added support for reassembling of fragmented IP packets via the
IPv4Reassembler class.
- Fragmented IP packet's inner_pdu PDUs are not decoded now.
- Added 1000ms as the default read timeout used when calling
pcap_open_live. Added BaseSniffer::set_timeout to modify this parameter.
- Added the --disable-dot11 configure switch.
- Added support for IPSec.
- Fixed bug triggered when ifaddrs::ifa_addr was null in
NetworkInterface::addresses.
- Added another overload of Utils::route_entries which returns the
result either than storing it in a parameter.
- Added ARP monitor, WPS detector, DNS queries sniffer and DNS spoofer
examples.
- Added another Sniffer constructor which doesn't expect the maximum
capture size.
- Added tins_cast as a replacement for dynamic_cast on PDUs.
v1.2 - Mon oct 7 23:33:49 ART 2013
- Added BaseSniffer::begin and BaseSniffer::end.

View File

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

View File

@@ -1,4 +1,4 @@
AUTOMAKE_OPTIONS=subdir-objects
AUTOMAKE_OPTIONS=subdir-objects 1.11
ACLOCAL_AMFLAGS=${ACLOCAL_FLAGS} -I m4
# pkg-config stuff
@@ -20,7 +20,6 @@ libtins_la_SOURCES=src/arp.cpp \
src/dhcp.cpp \
src/dhcpv6.cpp \
src/dns.cpp \
src/dns_record.cpp \
src/dot3.cpp \
src/dot1q.cpp \
src/eapol.cpp \
@@ -28,9 +27,12 @@ libtins_la_SOURCES=src/arp.cpp \
src/icmp.cpp \
src/icmpv6.cpp \
src/internals.cpp \
src/ip.cpp src/ip_address.cpp \
src/ip_reassembler.cpp \
src/ip.cpp \
src/ip_address.cpp \
src/ipv6.cpp \
src/ipv6_address.cpp \
src/ipsec.cpp \
src/llc.cpp \
src/loopback.cpp \
src/network_interface.cpp \
@@ -67,7 +69,7 @@ libtins_HEADERS = include/internals.h \
include/dot3.h \
include/small_uint.h \
include/ip.h \
include/dns_record.h \
include/ipsec.h \
include/eapol.h \
include/tcp_stream.h \
include/pppoe.h \
@@ -82,6 +84,7 @@ libtins_HEADERS = include/internals.h \
include/crypto.h \
include/packet.h \
include/llc.h \
include/ip_reassembler.h \
include/icmp.h \
include/hw_address.h \
include/packet_writer.h \

View File

@@ -1,9 +1,8 @@
# Makefile.in generated by automake 1.11.6 from Makefile.am.
# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
# Foundation, Inc.
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -18,23 +17,51 @@
VPATH = @srcdir@
am__make_dryrun = \
{ \
am__dry=no; \
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
| grep '^AM OK$$' >/dev/null || am__dry=yes;; \
*) \
for am__flg in $$MAKEFLAGS; do \
case $$am__flg in \
*=*|--*) ;; \
*n*) am__dry=yes; break;; \
esac; \
done;; \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
test $$am__dry = yes; \
}
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
@@ -55,12 +82,12 @@ build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
subdir = .
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
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/configure $(am__configure_deps) \
$(top_srcdir)/include/config.h.in $(srcdir)/libtins.pc.in \
depcomp $(libtins_HEADERS) $(libtins_dot11_HEADERS) AUTHORS \
README THANKS compile config.guess config.sub install-sh \
missing ltmain.sh
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 \
@@ -108,10 +135,10 @@ libtins_la_LIBADD =
am__dirstamp = $(am__leading_dot)dirstamp
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/crypto.lo src/dhcp.lo src/dhcpv6.lo src/dns.lo src/dot3.lo \
src/dot1q.lo src/eapol.lo src/ethernetII.lo src/icmp.lo \
src/icmpv6.lo src/internals.lo src/ip_reassembler.lo src/ip.lo \
src/ip_address.lo src/ipv6.lo src/ipv6_address.lo src/ipsec.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 \
@@ -122,22 +149,47 @@ am_libtins_la_OBJECTS = src/arp.lo src/bootp.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) \
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 =
libtins_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
$(CXXFLAGS) $(libtins_la_LDFLAGS) $(LDFLAGS) -o $@
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CXXFLAGS) $(CXXFLAGS)
AM_V_CXX = $(am__v_CXX_@AM_V@)
am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
am__v_CXX_0 = @echo " CXX " $@;
am__v_CXX_1 =
CXXLD = $(CXX)
CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
am__v_CXXLD_0 = @echo " CXXLD " $@;
am__v_CXXLD_1 =
SOURCES = $(libtins_la_SOURCES)
DIST_SOURCES = $(libtins_la_SOURCES)
am__can_run_installinfo = \
@@ -147,8 +199,27 @@ am__can_run_installinfo = \
esac
DATA = $(pkgconfig_DATA)
HEADERS = $(libtins_HEADERS) $(libtins_dot11_HEADERS)
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
CSCOPE = cscope
AM_RECURSIVE_TARGETS = cscope
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
@@ -158,14 +229,17 @@ am__remove_distdir = \
&& rm -rf "$(distdir)" \
|| { sleep 5 && rm -rf "$(distdir)"; }; \
else :; fi
am__post_remove_distdir = $(am__remove_distdir)
DIST_ARCHIVES = $(distdir).tar.gz
GZIP_ENV = --best
DIST_TARGETS = dist-gzip
distuninstallcheck_listfiles = find . -type f -print
am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
| sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
distcleancheck_listfiles = find . -type f -print
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
@@ -290,7 +364,7 @@ target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AUTOMAKE_OPTIONS = subdir-objects
AUTOMAKE_OPTIONS = subdir-objects 1.11
ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS} -I m4
# pkg-config stuff
@@ -308,7 +382,6 @@ libtins_la_SOURCES = src/arp.cpp \
src/dhcp.cpp \
src/dhcpv6.cpp \
src/dns.cpp \
src/dns_record.cpp \
src/dot3.cpp \
src/dot1q.cpp \
src/eapol.cpp \
@@ -316,9 +389,12 @@ libtins_la_SOURCES = src/arp.cpp \
src/icmp.cpp \
src/icmpv6.cpp \
src/internals.cpp \
src/ip.cpp src/ip_address.cpp \
src/ip_reassembler.cpp \
src/ip.cpp \
src/ip_address.cpp \
src/ipv6.cpp \
src/ipv6_address.cpp \
src/ipsec.cpp \
src/llc.cpp \
src/loopback.cpp \
src/network_interface.cpp \
@@ -354,7 +430,7 @@ libtins_HEADERS = include/internals.h \
include/dot3.h \
include/small_uint.h \
include/ip.h \
include/dns_record.h \
include/ipsec.h \
include/eapol.h \
include/tcp_stream.h \
include/pppoe.h \
@@ -369,6 +445,7 @@ libtins_HEADERS = include/internals.h \
include/crypto.h \
include/packet.h \
include/llc.h \
include/ip_reassembler.h \
include/icmp.h \
include/hw_address.h \
include/packet_writer.h \
@@ -453,8 +530,8 @@ $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
$(am__aclocal_m4_deps):
include/config.h: include/stamp-h1
@if test ! -f $@; then rm -f include/stamp-h1; else :; fi
@if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) include/stamp-h1; else :; fi
@test -f $@ || rm -f include/stamp-h1
@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) include/stamp-h1
include/stamp-h1: $(top_srcdir)/include/config.h.in $(top_builddir)/config.status
@rm -f include/stamp-h1
@@ -468,6 +545,7 @@ distclean-hdr:
-rm -f include/config.h include/stamp-h1
libtins.pc: $(top_builddir)/config.status $(srcdir)/libtins.pc.in
cd $(top_builddir) && $(SHELL) ./config.status $@
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
@$(NORMAL_INSTALL)
@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
@@ -494,12 +572,14 @@ uninstall-libLTLIBRARIES:
clean-libLTLIBRARIES:
-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
test "$$dir" != "$$p" || dir=.; \
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
@list='$(lib_LTLIBRARIES)'; \
locs=`for p in $$list; do echo $$p; done | \
sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
sort -u`; \
test -z "$$locs" || { \
echo rm -f $${locs}; \
rm -f $${locs}; \
}
src/$(am__dirstamp):
@$(MKDIR_P) src
@: > src/$(am__dirstamp)
@@ -516,7 +596,6 @@ src/crypto.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
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/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)
@@ -524,10 +603,13 @@ src/ethernetII.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/icmp.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/icmpv6.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/internals.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/ip_reassembler.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/ip.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/ip_address.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/ipv6.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/ipv6_address.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/ipsec.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/llc.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/loopback.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/network_interface.lo: src/$(am__dirstamp) \
@@ -573,105 +655,16 @@ 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)
$(AM_V_CXXLD)$(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)
-rm -f src/bootp.lo
-rm -f src/crypto.$(OBJEXT)
-rm -f src/crypto.lo
-rm -f src/dhcp.$(OBJEXT)
-rm -f src/dhcp.lo
-rm -f src/dhcpv6.$(OBJEXT)
-rm -f src/dhcpv6.lo
-rm -f src/dns.$(OBJEXT)
-rm -f src/dns.lo
-rm -f src/dns_record.$(OBJEXT)
-rm -f src/dns_record.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)
-rm -f src/dot3.lo
-rm -f src/eapol.$(OBJEXT)
-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)
-rm -f src/icmpv6.lo
-rm -f src/internals.$(OBJEXT)
-rm -f src/internals.lo
-rm -f src/ip.$(OBJEXT)
-rm -f src/ip.lo
-rm -f src/ip_address.$(OBJEXT)
-rm -f src/ip_address.lo
-rm -f src/ipv6.$(OBJEXT)
-rm -f src/ipv6.lo
-rm -f src/ipv6_address.$(OBJEXT)
-rm -f src/ipv6_address.lo
-rm -f src/llc.$(OBJEXT)
-rm -f src/llc.lo
-rm -f src/loopback.$(OBJEXT)
-rm -f src/loopback.lo
-rm -f src/network_interface.$(OBJEXT)
-rm -f src/network_interface.lo
-rm -f src/packet_sender.$(OBJEXT)
-rm -f src/packet_sender.lo
-rm -f src/packet_writer.$(OBJEXT)
-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)
-rm -f src/radiotap.lo
-rm -f src/rawpdu.$(OBJEXT)
-rm -f src/rawpdu.lo
-rm -f src/rsn_information.$(OBJEXT)
-rm -f src/rsn_information.lo
-rm -f src/sll.$(OBJEXT)
-rm -f src/sll.lo
-rm -f src/snap.$(OBJEXT)
-rm -f src/snap.lo
-rm -f src/sniffer.$(OBJEXT)
-rm -f src/sniffer.lo
-rm -f src/stp.$(OBJEXT)
-rm -f src/stp.lo
-rm -f src/tcp.$(OBJEXT)
-rm -f src/tcp.lo
-rm -f src/tcp_stream.$(OBJEXT)
-rm -f src/tcp_stream.lo
-rm -f src/udp.$(OBJEXT)
-rm -f src/udp.lo
-rm -f src/utils.$(OBJEXT)
-rm -f src/utils.lo
-rm -f src/*.$(OBJEXT)
-rm -f src/*.lo
-rm -f src/dot11/*.$(OBJEXT)
-rm -f src/dot11/*.lo
distclean-compile:
-rm -f *.tab.c
@@ -683,7 +676,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dhcp.Plo@am__quote@
@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)/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@
@@ -694,6 +686,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/internals.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/ip.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/ip_address.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/ip_reassembler.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/ipsec.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/ipv6.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/ipv6_address.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/llc.Plo@am__quote@
@@ -725,28 +719,28 @@ distclean-compile:
@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$$||'`;\
@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $<
.cpp.obj:
@am__fastdepCXX_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.cpp.lo:
@am__fastdepCXX_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
mostlyclean-libtool:
-rm -f *.lo
@@ -822,26 +816,15 @@ uninstall-libtins_dot11HEADERS:
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)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
@@ -853,15 +836,11 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$$unique; \
fi; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
ctags: ctags-am
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
@@ -870,9 +849,31 @@ GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscope: cscope.files
test ! -s cscope.files \
|| $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
clean-cscope:
-rm -f cscope.files
cscope.files: clean-cscope cscopelist
cscopelist: cscopelist-am
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
distdir: $(DISTFILES)
$(am__remove_distdir)
@@ -915,40 +916,42 @@ distdir: $(DISTFILES)
|| chmod -R a+r "$(distdir)"
dist-gzip: distdir
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
$(am__remove_distdir)
$(am__post_remove_distdir)
dist-bzip2: distdir
tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
$(am__remove_distdir)
$(am__post_remove_distdir)
dist-lzip: distdir
tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz
$(am__remove_distdir)
dist-lzma: distdir
tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma
$(am__remove_distdir)
$(am__post_remove_distdir)
dist-xz: distdir
tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
$(am__remove_distdir)
$(am__post_remove_distdir)
dist-tarZ: distdir
@echo WARNING: "Support for shar distribution archives is" \
"deprecated." >&2
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
$(am__remove_distdir)
$(am__post_remove_distdir)
dist-shar: distdir
@echo WARNING: "Support for distribution archives compressed with" \
"legacy program 'compress' is deprecated." >&2
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
$(am__remove_distdir)
$(am__post_remove_distdir)
dist-zip: distdir
-rm -f $(distdir).zip
zip -rq $(distdir).zip $(distdir)
$(am__remove_distdir)
$(am__post_remove_distdir)
dist dist-all: distdir
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
$(am__remove_distdir)
dist dist-all:
$(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:'
$(am__post_remove_distdir)
# This target untars the dist file and tries a VPATH configuration. Then
# it guarantees that the distribution is self-contained by making another
@@ -959,8 +962,6 @@ distcheck: dist
GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
*.tar.bz2*) \
bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
*.tar.lzma*) \
lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\
*.tar.lz*) \
lzip -dc $(distdir).tar.lz | $(am__untar) ;;\
*.tar.xz*) \
@@ -972,18 +973,19 @@ distcheck: dist
*.zip*) \
unzip $(distdir).zip ;;\
esac
chmod -R a-w $(distdir); chmod u+w $(distdir)
mkdir $(distdir)/_build
mkdir $(distdir)/_inst
chmod -R a-w $(distdir)
chmod u+w $(distdir)
mkdir $(distdir)/_build $(distdir)/_inst
chmod a-w $(distdir)
test -d $(distdir)/_build || exit 0; \
dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
&& am__cwd=`pwd` \
&& $(am__cd) $(distdir)/_build \
&& ../configure --srcdir=.. --prefix="$$dc_install_base" \
&& ../configure \
$(AM_DISTCHECK_CONFIGURE_FLAGS) \
$(DISTCHECK_CONFIGURE_FLAGS) \
--srcdir=.. --prefix="$$dc_install_base" \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) check \
@@ -1006,7 +1008,7 @@ distcheck: dist
&& $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
&& cd "$$am__cwd" \
|| exit 1
$(am__remove_distdir)
$(am__post_remove_distdir)
@(echo "$(distdir) archives ready for distribution: "; \
list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
@@ -1155,23 +1157,23 @@ uninstall-am: uninstall-libLTLIBRARIES uninstall-libtinsHEADERS \
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am am--refresh check check-am clean \
clean-generic clean-libLTLIBRARIES clean-libtool ctags dist \
dist-all dist-bzip2 dist-gzip dist-lzip dist-lzma dist-shar \
dist-tarZ dist-xz dist-zip distcheck distclean \
distclean-compile distclean-generic distclean-hdr \
distclean-libtool distclean-tags distcleancheck distdir \
distuninstallcheck dvi dvi-am html html-am info info-am \
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 \
.PHONY: CTAGS GTAGS TAGS all all-am am--refresh check check-am clean \
clean-cscope clean-generic clean-libLTLIBRARIES clean-libtool \
cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \
dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \
distcheck distclean distclean-compile distclean-generic \
distclean-hdr distclean-libtool distclean-tags distcleancheck \
distdir distuninstallcheck dvi dvi-am html html-am info \
info-am 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-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 \
pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \
uninstall-libLTLIBRARIES uninstall-libtinsHEADERS \
uninstall-libtins_dot11HEADERS uninstall-pkgconfigDATA

33
README
View File

@@ -1,24 +1,27 @@
------------------------------------------------------------------------
libtins v1.1
libtins v3.0
------------------------------------------------------------------------
-------------------------------- About ---------------------------------
libtins is a C++ library for crafting, sending, sniffing and
interpreting raw network packets.
libtins is a high-level, multiplatform C++ network packet sniffing and
crafting library.
Its main purpose is to provide the C++ developer an easy, efficient,
platform and endianess-independent way to create tools which need to
send, receive and manipulate specially crafted packets.
In order to read tutorials, examples and checkout some benchmarks which
show libtins' actual performance, please visit:
In order to read tutorials, examples and checkout some benchmarks of the
library, please visit:
http://libtins.sourceforge.net
http://libtins.github.io/
------------------------------- Compiling ------------------------------
libtins depends on libpcap and openssl, although the latter is not
necessary if some features of the library are disabled.
In order to compile, execute:
./configure
@@ -32,11 +35,23 @@ like to generate a static library file as well, run:
The generated static/shared library files will be located in the .libs
directory.
If you want to enable C++11 features, such as move semantics, use the
--enable-c++11 switch:
libtins is noticeable faster if you enable C++11 support. Therefore, if
your compiler supports this standard, then you should enable it. In
order to do so, use the --enable-c++11 switch:
./configure --enable-c++11
If you want to disable WPA2 decryption support, which will remove
openssl as a dependency for compilation, use the --disable-wpa2 switch:
./configure --disable-wpa2
If you want to disable IEEE 802.11 support(this will also disable
RadioTap and WPA2 decryption), which will reduce the size of the
resulting library in around 20%, use the --disable-dot11 switch:
./configure --disable-dot11
------------------------------ Installing-------------------------------
Once you're done, if you want to install the header files and the
@@ -55,4 +70,4 @@ ldconfig
You might want to have a look at the examples located in the "examples"
directory. The same samples can be found online at:
http://libtins.sourceforge.net/index.php?page=examples
http://libtins.github.io/examples/

85
README.md Normal file
View File

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

700
aclocal.m4 vendored

File diff suppressed because it is too large Load Diff

355
configure vendored
View File

@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for libtins 1.2.
# Generated by GNU Autoconf 2.69 for libtins 3.0.
#
# 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.2'
PACKAGE_STRING='libtins 1.2'
PACKAGE_VERSION='3.0'
PACKAGE_STRING='libtins 3.0'
PACKAGE_BUGREPORT='matias.fontanini@gmail.com'
PACKAGE_URL='http://libtins.sourceforge.net'
@@ -687,6 +687,10 @@ LDFLAGS
CFLAGS
CC
LIBTOOL
AM_BACKSLASH
AM_DEFAULT_VERBOSITY
AM_DEFAULT_V
AM_V
am__untar
am__tar
AMTAR
@@ -763,6 +767,7 @@ SHELL'
ac_subst_files=''
ac_user_opts='
enable_option_checking
enable_silent_rules
enable_static
enable_shared
with_pic
@@ -775,6 +780,7 @@ enable_maintainer_mode
with_pcap_include_path
with_pcap_lib_path
enable_c__11
enable_dot11
enable_wpa2
'
ac_precious_vars='build_alias
@@ -1330,7 +1336,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.2 to adapt to many kinds of systems.
\`configure' configures libtins 3.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1401,7 +1407,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of libtins 1.2:";;
short | recursive ) echo "Configuration of libtins 3.0:";;
esac
cat <<\_ACEOF
@@ -1409,16 +1415,22 @@ Optional Features:
--disable-option-checking ignore unrecognized --enable/--with options
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--enable-silent-rules less verbose build output (undo: "make V=1")
--disable-silent-rules verbose build output (undo: "make V=0")
--enable-static[=PKGS] build static libraries [default=no]
--enable-shared[=PKGS] build shared libraries [default=yes]
--enable-fast-install[=PKGS]
optimize for fast installation [default=yes]
--disable-dependency-tracking speeds up one-time build
--enable-dependency-tracking do not reject slow dependency extractors
--enable-dependency-tracking
do not reject slow dependency extractors
--disable-dependency-tracking
speeds up one-time build
--disable-libtool-lock avoid locking (might break parallel builds)
--disable-maintainer-mode disable make rules and dependencies not useful
(and sometimes confusing) to the casual installer
--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-dot11 disable IEEE 802.11 support
--disable-wpa2 disable WPA2 decryption features
Optional Packages:
@@ -1514,7 +1526,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
libtins configure 1.2
libtins configure 3.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2004,7 +2016,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.2, which was
It was created by libtins $as_me 3.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2591,9 +2603,6 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
$as_echo_n "checking whether build environment is sane... " >&6; }
# Just in case
sleep 1
echo timestamp > conftest.file
# Reject unsafe characters in $srcdir or the absolute working directory
# name. Accept space and tab only in the latter.
am_lf='
@@ -2604,32 +2613,40 @@ case `pwd` in
esac
case $srcdir in
*[\\\"\#\$\&\'\`$am_lf\ \ ]*)
as_fn_error $? "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;;
as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;;
esac
# Do `set' in a subshell so we don't clobber the current shell's
# Do 'set' in a subshell so we don't clobber the current shell's
# arguments. Must try -L first in case configure is actually a
# symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing
# directory).
if (
set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
if test "$*" = "X"; then
# -L didn't work.
set X `ls -t "$srcdir/configure" conftest.file`
fi
rm -f conftest.file
if test "$*" != "X $srcdir/configure conftest.file" \
&& test "$*" != "X conftest.file $srcdir/configure"; then
# If neither matched, then we have a broken ls. This can happen
# if, for instance, CONFIG_SHELL is bash and it inherits a
# broken ls alias from the environment. This has actually
# happened. Such a system could not be considered "sane".
as_fn_error $? "ls -t appears to fail. Make sure there is not a broken
alias in your environment" "$LINENO" 5
fi
am_has_slept=no
for am_try in 1 2; do
echo "timestamp, slept: $am_has_slept" > conftest.file
set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
if test "$*" = "X"; then
# -L didn't work.
set X `ls -t "$srcdir/configure" conftest.file`
fi
if test "$*" != "X $srcdir/configure conftest.file" \
&& test "$*" != "X conftest.file $srcdir/configure"; then
# If neither matched, then we have a broken ls. This can happen
# if, for instance, CONFIG_SHELL is bash and it inherits a
# broken ls alias from the environment. This has actually
# happened. Such a system could not be considered "sane".
as_fn_error $? "ls -t appears to fail. Make sure there is not a broken
alias in your environment" "$LINENO" 5
fi
if test "$2" = conftest.file || test $am_try -eq 2; then
break
fi
# Just in case.
sleep 1
am_has_slept=yes
done
test "$2" = conftest.file
)
then
@@ -2641,6 +2658,16 @@ Check your system clock" "$LINENO" 5
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
# If we didn't sleep, we still need to ensure time stamps of config.status and
# generated files are strictly newer.
am_sleep_pid=
if grep 'slept: no' conftest.file >/dev/null 2>&1; then
( sleep 1 ) &
am_sleep_pid=$!
fi
rm -f conftest.file
test "$program_prefix" != NONE &&
program_transform_name="s&^&$program_prefix&;$program_transform_name"
# Use a double $ so make ignores it.
@@ -2663,12 +2690,12 @@ if test x"${MISSING+set}" != xset; then
esac
fi
# Use eval to expand $SHELL
if eval "$MISSING --run true"; then
am_missing_run="$MISSING --run "
if eval "$MISSING --is-lightweight"; then
am_missing_run="$MISSING "
else
am_missing_run=
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5
$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5
$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;}
fi
if test x"${install_sh}" != xset; then
@@ -2680,10 +2707,10 @@ if test x"${install_sh}" != xset; then
esac
fi
# Installed binaries are usually stripped using `strip' when the user
# run `make install-strip'. However `strip' might not be the right
# Installed binaries are usually stripped using 'strip' when the user
# run "make install-strip". However 'strip' might not be the right
# tool to use in cross-compilation environments, therefore Automake
# will honor the `STRIP' environment variable to overrule this program.
# will honor the 'STRIP' environment variable to overrule this program.
if test "$cross_compiling" != no; then
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
@@ -2822,12 +2849,6 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
$as_echo "$MKDIR_P" >&6; }
mkdir_p="$MKDIR_P"
case $mkdir_p in
[\\/$]* | ?:[\\/]*) ;;
*/*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
esac
for ac_prog in gawk mawk nawk awk
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
@@ -2910,6 +2931,45 @@ else
fi
rmdir .tst 2>/dev/null
# Check whether --enable-silent-rules was given.
if test "${enable_silent_rules+set}" = set; then :
enableval=$enable_silent_rules;
fi
case $enable_silent_rules in # (((
yes) AM_DEFAULT_VERBOSITY=0;;
no) AM_DEFAULT_VERBOSITY=1;;
*) AM_DEFAULT_VERBOSITY=1;;
esac
am_make=${MAKE-make}
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
$as_echo_n "checking whether $am_make supports nested variables... " >&6; }
if ${am_cv_make_support_nested_variables+:} false; then :
$as_echo_n "(cached) " >&6
else
if $as_echo 'TRUE=$(BAR$(V))
BAR0=false
BAR1=true
V=1
am__doit:
@$(TRUE)
.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
am_cv_make_support_nested_variables=yes
else
am_cv_make_support_nested_variables=no
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
$as_echo "$am_cv_make_support_nested_variables" >&6; }
if test $am_cv_make_support_nested_variables = yes; then
AM_V='$(V)'
AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
else
AM_V=$AM_DEFAULT_VERBOSITY
AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
fi
AM_BACKSLASH='\'
if test "`cd $srcdir && pwd`" != "`pwd`"; then
# Use -I$(srcdir) only when $(srcdir) != ., so that make's output
# is not polluted with repeated "-I."
@@ -2932,7 +2992,7 @@ fi
# Define the identity of the package.
PACKAGE='libtins'
VERSION='1.2'
VERSION='3.0'
cat >>confdefs.h <<_ACEOF
@@ -2960,18 +3020,70 @@ AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
# For better backward compatibility. To be removed once Automake 1.9.x
# dies out for good. For more background, see:
# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
mkdir_p='$(MKDIR_P)'
# We need awk for the "check" target. The system "awk" is bad on
# some platforms.
# Always define AMTAR for backward compatibility. Yes, it's still used
# in the wild :-( We should find a proper way to deprecate it ...
AMTAR='$${TAR-tar}'
# We'll loop over all known methods to create a tar archive until one works.
_am_tools='gnutar pax cpio none'
am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
# POSIX will say in a future version that running "rm -f" with no argument
# is OK; and we want to be able to make that assumption in our Makefile
# recipes. So use an aggressive probe to check that the usage we want is
# actually supported "in the wild" to an acceptable degree.
# See automake bug#10828.
# To make any issue more visible, cause the running configure to be aborted
# by default if the 'rm' program in use doesn't match our expectations; the
# user can still override this though.
if rm -f && rm -fr && rm -rf; then : OK; else
cat >&2 <<'END'
Oops!
Your 'rm' program seems unable to run without file operands specified
on the command line, even when the '-f' option is present. This is contrary
to the behaviour of most rm programs out there, and not conforming with
the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
Please tell bug-automake@gnu.org about your system, including the value
of your $PATH and any error possibly output before this message. This
can help us improve future automake versions.
END
if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
echo 'Configuration will proceed anyway, since you have set the' >&2
echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
echo >&2
else
cat >&2 <<'END'
Aborting the configuration process, to ensure you take notice of the issue.
You can download and install GNU coreutils to get an 'rm' implementation
that behaves properly: <http://www.gnu.org/software/coreutils/>.
If you want to complete the configuration process using your problematic
'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
to "yes", and re-run configure.
END
as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5
fi
fi
case `pwd` in
*\ * | *\ *)
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
@@ -3085,7 +3197,7 @@ am__quote=
_am_result=none
# First try GNU make style include.
echo "include confinc" > confmf
# Ignore all kinds of additional output from `make'.
# Ignore all kinds of additional output from 'make'.
case `$am_make -s -f confmf 2> /dev/null` in #(
*the\ am__doit\ target*)
am__include=include
@@ -3918,6 +4030,65 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
if ${am_cv_prog_cc_c_o+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
;
return 0;
}
_ACEOF
# Make sure it works both with $CC and with simple cc.
# Following AC_PROG_CC_C_O, we do the test twice because some
# compilers refuse to overwrite an existing .o file with -o,
# though they will create one.
am_cv_prog_cc_c_o=yes
for am_i in 1 2; do
if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } \
&& test -f conftest2.$ac_objext; then
: OK
else
am_cv_prog_cc_c_o=no
break
fi
done
rm -f core conftest*
unset am_i
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
$as_echo "$am_cv_prog_cc_c_o" >&6; }
if test "$am_cv_prog_cc_c_o" != yes; then
# Losing compiler, so override with the script.
# FIXME: It is wrong to rewrite CC.
# But if we don't then we get into trouble of one sort or another.
# A longer-term fix would be to have automake use am__CC in this case,
# and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
CC="$am_aux_dir/compile $CC"
fi
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
depcc="$CC" am_compiler_list=
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
@@ -3929,8 +4100,8 @@ else
# We make a subdir and do the tests there. Otherwise we can end up
# making bogus files that we don't know about and never remove. For
# instance it was reported that on HP-UX the gcc test will end up
# making a dummy file named `D' -- because `-MD' means `put the output
# in D'.
# making a dummy file named 'D' -- because '-MD' means "put the output
# in D".
rm -rf conftest.dir
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
@@ -3965,16 +4136,16 @@ else
: > sub/conftest.c
for i in 1 2 3 4 5 6; do
echo '#include "conftst'$i'.h"' >> sub/conftest.c
# Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
# Solaris 8's {/usr,}/bin/sh.
touch sub/conftst$i.h
# Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
# Solaris 10 /bin/sh.
echo '/* dummy */' > sub/conftst$i.h
done
echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
# We check with `-c' and `-o' for the sake of the "dashmstdout"
# We check with '-c' and '-o' for the sake of the "dashmstdout"
# mode. It turns out that the SunPro C++ compiler does not properly
# handle `-M -o', and we need to detect this. Also, some Intel
# versions had trouble with output in subdirs
# handle '-M -o', and we need to detect this. Also, some Intel
# versions had trouble with output in subdirs.
am__obj=sub/conftest.${OBJEXT-o}
am__minus_obj="-o $am__obj"
case $depmode in
@@ -3983,8 +4154,8 @@ else
test "$am__universal" = false || continue
;;
nosideeffect)
# after this tag, mechanisms are not by side-effect, so they'll
# only be used when explicitly requested
# After this tag, mechanisms are not by side-effect, so they'll
# only be used when explicitly requested.
if test "x$enable_dependency_tracking" = xyes; then
continue
else
@@ -3992,7 +4163,7 @@ else
fi
;;
msvc7 | msvc7msys | msvisualcpp | msvcmsys)
# This compiler won't grok `-c -o', but also, the minuso test has
# This compiler won't grok '-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
am__obj=conftest.${OBJEXT-o}
@@ -11771,8 +11942,8 @@ else
# We make a subdir and do the tests there. Otherwise we can end up
# making bogus files that we don't know about and never remove. For
# instance it was reported that on HP-UX the gcc test will end up
# making a dummy file named `D' -- because `-MD' means `put the output
# in D'.
# making a dummy file named 'D' -- because '-MD' means "put the output
# in D".
rm -rf conftest.dir
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
@@ -11807,16 +11978,16 @@ else
: > sub/conftest.c
for i in 1 2 3 4 5 6; do
echo '#include "conftst'$i'.h"' >> sub/conftest.c
# Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
# Solaris 8's {/usr,}/bin/sh.
touch sub/conftst$i.h
# Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
# Solaris 10 /bin/sh.
echo '/* dummy */' > sub/conftst$i.h
done
echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
# We check with `-c' and `-o' for the sake of the "dashmstdout"
# We check with '-c' and '-o' for the sake of the "dashmstdout"
# mode. It turns out that the SunPro C++ compiler does not properly
# handle `-M -o', and we need to detect this. Also, some Intel
# versions had trouble with output in subdirs
# handle '-M -o', and we need to detect this. Also, some Intel
# versions had trouble with output in subdirs.
am__obj=sub/conftest.${OBJEXT-o}
am__minus_obj="-o $am__obj"
case $depmode in
@@ -11825,8 +11996,8 @@ else
test "$am__universal" = false || continue
;;
nosideeffect)
# after this tag, mechanisms are not by side-effect, so they'll
# only be used when explicitly requested
# After this tag, mechanisms are not by side-effect, so they'll
# only be used when explicitly requested.
if test "x$enable_dependency_tracking" = xyes; then
continue
else
@@ -11834,7 +12005,7 @@ else
fi
;;
msvc7 | msvc7msys | msvisualcpp | msvcmsys)
# This compiler won't grok `-c -o', but also, the minuso test has
# This compiler won't grok '-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
am__obj=conftest.${OBJEXT-o}
@@ -15331,12 +15502,22 @@ $as_echo "#define HAVE_CXX11 1" >>confdefs.h
fi
# Check whether --enable-wpa2 was given.
# Check whether --enable-dot11 was given.
if test "${enable_dot11+set}" = set; then :
enableval=$enable_dot11;
else
$as_echo "#define HAVE_DOT11 1" >>confdefs.h
# Only allow enabling WPA2 if Dot11 is enabled.
# 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
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"
@@ -15355,7 +15536,7 @@ fi
done
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PKCS5_PBKDF2_HMAC_SHA1 in -lcrypto" >&5
{ $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
@@ -15408,6 +15589,10 @@ $as_echo "#define HAVE_WPA2_DECRYPTION 1" >>confdefs.h
fi
fi
@@ -15416,7 +15601,7 @@ fi
LIBTINS_VERSION=1:1:0
LIBTINS_VERSION=3:0:0
ac_config_files="$ac_config_files Makefile libtins.pc"
@@ -15529,6 +15714,14 @@ LIBOBJS=$ac_libobjs
LTLIBOBJS=$ac_ltlibobjs
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5
$as_echo_n "checking that generated files are newer than configure... " >&6; }
if test -n "$am_sleep_pid"; then
# Hide warnings about reused PIDs.
wait $am_sleep_pid 2>/dev/null
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5
$as_echo "done" >&6; }
if test -n "$EXEEXT"; then
am__EXEEXT_TRUE=
am__EXEEXT_FALSE='#'
@@ -15950,7 +16143,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.2, which was
This file was extended by libtins $as_me 3.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -16017,7 +16210,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.2
libtins config.status 3.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
@@ -17122,7 +17315,7 @@ $as_echo "$as_me: executing $ac_file commands" >&6;}
case $ac_file$ac_mode in
"depfiles":C) test x"$AMDEP_TRUE" != x"" || {
# Autoconf 2.62 quotes --file arguments for eval, but not when files
# Older Autoconf quotes --file arguments for eval, but not when files
# are listed without --file. Let's play safe and only enable the eval
# if we detect the quoting.
case $CONFIG_FILES in
@@ -17135,7 +17328,7 @@ $as_echo "$as_me: executing $ac_file commands" >&6;}
# Strip MF so we end up with the name of the file.
mf=`echo "$mf" | sed -e 's/:.*$//'`
# Check whether this is an Automake generated Makefile or not.
# We used to match only the files named `Makefile.in', but
# We used to match only the files named 'Makefile.in', but
# some people rename them; so instead we look at the file content.
# Grep'ing the first line is not enough: some people post-process
# each Makefile.in and add a new line on top of each file to say so.
@@ -17169,21 +17362,19 @@ $as_echo X"$mf" |
continue
fi
# Extract the definition of DEPDIR, am__include, and am__quote
# from the Makefile without running `make'.
# from the Makefile without running 'make'.
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
test -z "$DEPDIR" && continue
am__include=`sed -n 's/^am__include = //p' < "$mf"`
test -z "am__include" && continue
test -z "$am__include" && continue
am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
# When using ansi2knr, U may be empty or an underscore; expand it
U=`sed -n 's/^U = //p' < "$mf"`
# Find all dependency output files, they are included files with
# $(DEPDIR) in their names. We invoke sed twice because it is the
# simplest approach to changing $(DEPDIR) to its actual value in the
# expansion.
for file in `sed -n "
s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
# Make sure the directory exists.
test -f "$dirpart/$file" && continue
fdir=`$as_dirname -- "$file" ||

View File

@@ -1,4 +1,4 @@
AC_INIT([libtins], [1.2], [matias.fontanini@gmail.com], [libtins], [http://libtins.sourceforge.net])
AC_INIT([libtins], [3.0], [matias.fontanini@gmail.com], [libtins], [http://libtins.sourceforge.net])
AC_CANONICAL_SYSTEM
AC_CONFIG_HEADER(include/config.h)
AM_INIT_AUTOMAKE([-Wall -Werror -Wno-extra-portability foreign])
@@ -45,23 +45,33 @@ AC_ARG_ENABLE(
)
AC_ARG_ENABLE(
wpa2,
[ --disable-wpa2 disable WPA2 decryption features],
dot11,
[ --disable-dot11 disable IEEE 802.11 support],
[],
[
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_DEFINE([HAVE_DOT11], 1, Have IEEE 802.11 support)
# Only allow enabling WPA2 if Dot11 is enabled.
AC_ARG_ENABLE(
wpa2,
[ --disable-wpa2 disable WPA2 decryption features],
[],
[
AC_CHECK_HEADERS(
[openssl/evp.h openssl/hmac.h openssl/aes.h],
[],
[AC_MSG_ERROR([openssl headers are missing! $wpa2_msg ])]
AC_DEFINE([HAVE_WPA2_DECRYPTION], 0, Have WPA2 decryption library)
)
AC_CHECK_LIB(
crypto,
PKCS5_PBKDF2_HMAC_SHA1,
[],
[AC_MSG_ERROR([openssl library is missing! $wpa2_msg ])]
)
AC_DEFINE([HAVE_WPA2_DECRYPTION], 1, Have WPA2 decryption library)
]
)
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)
]
)
@@ -70,6 +80,6 @@ AC_ARG_ENABLE(
AC_SUBST(CXXFLAGS)
AC_SUBST(LIBS)
AC_SUBST(LIBTINS_INCLUDE_DIR)
AC_SUBST([LIBTINS_VERSION], [1:1:0])
AC_SUBST([LIBTINS_VERSION], [3:0:0])
AC_CONFIG_FILES([Makefile libtins.pc])
AC_OUTPUT

View File

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

96
examples/arpmonitor.cpp Normal file
View File

@@ -0,0 +1,96 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <tins/tins.h>
#include <map>
#include <iostream>
#include <functional>
using namespace Tins;
class arp_monitor {
public:
void run(Sniffer &sniffer);
private:
bool callback(const PDU &pdu);
std::map<IPv4Address, HWAddress<6>> addresses;
};
void arp_monitor::run(Sniffer &sniffer)
{
sniffer.sniff_loop(
std::bind(
&arp_monitor::callback,
this,
std::placeholders::_1
)
);
}
bool arp_monitor::callback(const PDU &pdu)
{
// Retrieve the ARP layer
const ARP &arp = pdu.rfind_pdu<ARP>();
// Is it an ARP reply?
if(arp.opcode() == ARP::REPLY) {
// Let's check if there's already an entry for this address
auto iter = addresses.find(arp.sender_ip_addr());
if(iter == addresses.end()) {
// We haven't seen this address. Save it.
addresses.insert({ arp.sender_ip_addr(), arp.sender_hw_addr()});
std::cout << "[INFO] " << arp.sender_ip_addr() << " is at "
<< arp.sender_hw_addr() << std::endl;
}
else {
// We've seen this address. If it's not the same HW address, inform it
if(arp.sender_hw_addr() != iter->second) {
std::cout << "[WARNING] " << arp.sender_ip_addr() << " is at "
<< iter->second << " but also at " << arp.sender_hw_addr()
<< std::endl;
}
}
}
return true;
}
int main(int argc, char *argv[])
{
if(argc != 2) {
std::cout << "Usage: " << *argv << " <interface>\n";
return 1;
}
arp_monitor monitor;
// Sniff on the provided interface in promiscuous mode
Sniffer sniffer(argv[1], Sniffer::PROMISC);
// Only capture arp packets
sniffer.set_filter("arp");
monitor.run(sniffer);
}

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -47,7 +47,7 @@ private:
};
void BeaconSniffer::run(const std::string &iface) {
Sniffer sniffer(iface, 1500, true, "type mgt subtype beacon");
Sniffer sniffer(iface, Sniffer::PROMISC, "type mgt subtype beacon", true);
sniffer.sniff_loop(make_sniffer_handler(this, &BeaconSniffer::callback));
}

460
examples/configure vendored
View File

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

View File

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

65
examples/dns_queries.cpp Normal file
View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <tins/tins.h>
#include <iostream>
using namespace Tins;
bool callback(const PDU &pdu)
{
// The packet probably looks like this:
//
// EthernetII / IP / UDP / RawPDU
//
// So we retrieve the RawPDU layer, and construct a
// DNS PDU using its contents.
DNS dns = pdu.rfind_pdu<RawPDU>().to<DNS>();
// Retrieve the queries and print the domain name:
for(const auto &query : dns.queries())
std::cout << query.dname() << std::endl;
return true;
}
int main(int argc, char *argv[])
{
if(argc != 2) {
std::cout << "Usage: " << *argv << " <interface>" << std::endl;
return 1;
}
// Sniff on the provided interface in promiscuos mode
Sniffer sniffer(argv[1], Sniffer::PROMISC);
// Only capture udp packets sent to port 53
sniffer.set_filter("udp and dst port 53");
// Start the capture
sniffer.sniff_loop(callback);
}

103
examples/dns_spoof.cpp Normal file
View File

@@ -0,0 +1,103 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <tins/tins.h>
#include <iostream>
using namespace Tins;
PacketSender sender;
bool callback(const PDU &pdu)
{
// The packet probably looks like this:
//
// EthernetII / IP / UDP / RawPDU
//
// So we retrieve each layer, and construct a
// DNS PDU from the RawPDU layer contents.
EthernetII eth = pdu.rfind_pdu<EthernetII>();
IP ip = eth.rfind_pdu<IP>();
UDP udp = ip.rfind_pdu<UDP>();
DNS dns = udp.rfind_pdu<RawPDU>().to<DNS>();
// Is it a DNS query?
if(dns.type() == DNS::QUERY) {
// Let's see if there's any query for an "A" record.
for(const auto &query : dns.queries()) {
if(query.type() == DNS::A) {
// Here's one! Let's add an answer.
dns.add_answer(
DNS::Resource(
query.dname(),
"127.0.0.1",
DNS::A,
query.query_class(),
// 777 is just a random TTL
777
)
);
}
}
// Have we added some answers?
if(dns.answers_count() > 0) {
// It's a response now
dns.type(DNS::RESPONSE);
// Recursion is available(just in case)
dns.recursion_available(1);
// Build our packet
auto pkt = EthernetII(eth.src_addr(), eth.dst_addr()) /
IP(ip.src_addr(), ip.dst_addr()) /
UDP(udp.sport(), udp.dport()) /
dns;
// Send it!
sender.send(pkt);
}
}
return true;
}
int main(int argc, char *argv[])
{
if(argc != 2) {
std::cout << "Usage: " << *argv << " <interface>" << std::endl;
return 1;
}
// Sniff on the provided interface in promiscuos mode
Sniffer sniffer(argv[1], Sniffer::PROMISC);
// Only capture udp packets sent to port 53
sniffer.set_filter("udp and dst port 53");
// All packets will be sent through the provided interface
sender.default_interface(argv[1]);
// Start the capture
sniffer.sniff_loop(callback);
}

189
examples/dns_stats.cpp Normal file
View File

@@ -0,0 +1,189 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <iostream>
#include <mutex>
#include <chrono>
#include <map>
#include <thread>
#include <algorithm>
#include <tins/tins.h>
using namespace Tins;
// Holds the DNS response time statistics. The response time is
// represented using the Duration template parameter.
template<typename Duration>
class statistics {
public:
using duration_type = Duration;
using locker_type = std::lock_guard<std::mutex>;
struct information {
duration_type average, worst;
size_t count;
};
statistics()
: m_duration(), m_worst(duration_type::min()), m_count()
{
}
void add_response_time(const duration_type& duration)
{
locker_type _(m_lock);
m_duration += duration;
m_count++;
m_worst = std::max(m_worst, duration);
}
information get_information() const
{
locker_type _(m_lock);
if(m_count == 0)
return { };
else
return { m_duration / m_count, m_worst, m_count };
};
private:
duration_type m_duration, m_worst;
size_t m_count;
mutable std::mutex m_lock;
};
// Sniffs and tracks DNS queries. When a matching DNS response is found,
// the response time is added to a statistics object.
//
// This class performs *no cleanup* on data associated with queries that
// weren't answered.
class dns_monitor {
public:
// The response times are measured in milliseconds
using duration_type = std::chrono::milliseconds;
// The statistics type used.
using statistics_type = statistics<duration_type>;
void run(BaseSniffer& sniffer);
const statistics_type& stats() const {
return m_stats;
}
private:
using packet_info = std::tuple<IPv4Address, IPv4Address, uint16_t>;
using clock_type = std::chrono::steady_clock;
using time_point_type = std::chrono::time_point<clock_type>;
bool callback(const PDU& pdu);
static packet_info make_packet_info(const PDU& pdu, const DNS& dns);
statistics_type m_stats;
std::map<packet_info, time_point_type> m_packet_info;
};
void dns_monitor::run(BaseSniffer& sniffer)
{
sniffer.sniff_loop(
std::bind(
&dns_monitor::callback,
this,
std::placeholders::_1
)
);
}
bool dns_monitor::callback(const PDU& pdu)
{
auto now = clock_type::now();
auto dns = pdu.rfind_pdu<RawPDU>().to<DNS>();
auto info = make_packet_info(pdu, dns);
// If it's a query, add the sniff time to our map.
if(dns.type() == DNS::QUERY) {
m_packet_info.insert(
std::make_pair(info, now)
);
}
else {
// It's a response, we need to find the query in our map.
auto iter = m_packet_info.find(info);
if(iter != m_packet_info.end()) {
// We found the query, let's add the response time to the
// statistics object.
m_stats.add_response_time(
std::chrono::duration_cast<duration_type>(now - iter->second)
);
// Forget about the query.
m_packet_info.erase(iter);
}
}
return true;
}
// It is required that we can identify packets sent and received that
// hold the same DNS id as belonging to the same query.
//
// This function retrieves a tuple (addr, addr, id) that will achieve it.
auto dns_monitor::make_packet_info(const PDU& pdu, const DNS& dns) -> packet_info
{
const auto& ip = pdu.rfind_pdu<IP>();
return std::make_tuple(
// smallest address first
std::min(ip.src_addr(), ip.dst_addr()),
// largest address second
std::max(ip.src_addr(), ip.dst_addr()),
dns.id()
);
}
int main(int argc, char *argv[]) {
if(argc != 2) {
std::cout << "Usage: " << *argv << " <interface>\n";
return 1;
}
try {
Sniffer sniffer(argv[1], Sniffer::PROMISC);
sniffer.set_filter("udp and port 53");
dns_monitor monitor;
std::thread thread(
[&]() {
monitor.run(sniffer);
}
);
while(true) {
auto info = monitor.stats().get_information();
std::cout << "\rAverage " << info.average.count()
<< "ms. Worst: " << info.worst.count() << "ms. Count: "
<< info.count;
std::cout.flush();
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
catch(std::exception& ex) {
std::cout << "[-] Error: " << ex.what() << std::endl;
}
}

View File

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

View File

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

74
examples/wps_detect.cpp Normal file
View File

@@ -0,0 +1,74 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <tins/tins.h>
#include <iostream>
#include <set>
#include <string>
using namespace Tins;
// BSSIDs which we've already seen
std::set<HWAddress<6>> addrs;
// This will be the content of the OUI field in the vendor specific
// tagged option if it's a WPS tag.
const HWAddress<3> expected_oui("00:50:F2");
bool handler(const PDU& pdu) {
const Dot11Beacon &beacon = pdu.rfind_pdu<Dot11Beacon>();
// Only process it once
if(addrs.insert(beacon.addr3()).second) {
// Iterate the tagged options
for(const auto &opt : beacon.options()) {
// Is this a vendor-specific tag?
if(opt.option() == Dot11::VENDOR_SPECIFIC) {
// Make sure there's enough size for the OUI + identifier
if(opt.data_size() >= 4) {
// Retrieve the OUI field
HWAddress<3> addr = opt.data_ptr();
// Are we interested in this OUI and is it a WPS tag?
if(addr == expected_oui && opt.data_ptr()[3] == 0x04) {
std::cout << "[+] Access point: " << beacon.ssid() << " uses WPS\n";
}
}
}
}
}
return true;
}
int main(int argc, char *argv[]) {
if(argc != 2) {
std::cout << "Usage: " << *argv << " <DEVICE>\n";
return 1;
}
// Only sniff beacons
Sniffer sniffer(argv[1], 2000, true, "wlan type mgt subtype beacon");
sniffer.sniff_loop(handler);
}

View File

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

View File

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

View File

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

View File

@@ -6,6 +6,9 @@
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Have IEEE 802.11 support */
#undef HAVE_DOT11
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,7 +27,9 @@
*
*/
#ifndef TINS_CRYPTO_H
#include "config.h"
#if !defined(TINS_CRYPTO_H) && defined(HAVE_DOT11)
#define TINS_CRYPTO_H
#include <map>
@@ -38,7 +40,6 @@
#include "snap.h"
#include "rawpdu.h"
#include "handshake_capturer.h"
#include "config.h"
namespace Tins {
class PDU;
@@ -49,7 +50,7 @@ namespace Crypto {
/**
* \cond
*/
class RC4Key;
struct RC4Key;
#ifdef HAVE_WPA2_DECRYPTION
namespace WPA2 {
class invalid_handshake : public std::exception {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -38,7 +38,9 @@
#define TINS_CXXSTD_GCC_FIX 0
#endif // __GXX_EXPERIMENTAL_CXX0X__
#define TINS_IS_CXX11 (__cplusplus > 199711L || TINS_CXXSTD_GCC_FIX == 1)
#ifndef TINS_IS_CXX11
#define TINS_IS_CXX11 (__cplusplus > 199711L || TINS_CXXSTD_GCC_FIX == 1 || _MSC_VER >= 1800)
#endif // TINS_IS_CXX11
namespace Tins{
namespace Internals {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,6 +32,7 @@
#include <list>
#include <vector>
#include <string>
#include "bootp.h"
#include "pdu_option.h"
@@ -145,7 +146,7 @@ namespace Tins {
/**
* The DHCP option type.
*/
typedef PDUOption<uint8_t> option;
typedef PDUOption<uint8_t, DHCP> option;
/**
* The type used to store the DHCP options.
@@ -271,7 +272,7 @@ namespace Tins {
*
* \param routers A list of ip addresses.
*/
void routers(const std::list<ipaddress_type> &routers);
void routers(const std::vector<ipaddress_type> &routers);
/**
* \brief Adds a domain name servers option.
@@ -280,7 +281,7 @@ namespace Tins {
*
* \param dns A list of ip addresses.
*/
void domain_name_servers(const std::list<ipaddress_type> &dns);
void domain_name_servers(const std::vector<ipaddress_type> &dns);
/**
* \brief Adds a broadcast address option.
@@ -308,6 +309,15 @@ namespace Tins {
* \param name The domain name.
*/
void domain_name(const std::string &name);
/**
* \brief Adds a hostname option.
*
* The new option is appended at the end of the list.
*
* \param name The hostname.
*/
void hostname(const std::string &name);
// Option getters
@@ -377,10 +387,10 @@ namespace Tins {
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return std::list<ipaddress_type> Containing the routers
* \return std::vector<ipaddress_type> Containing the routers
* option data.
*/
std::list<ipaddress_type> routers() const;
std::vector<ipaddress_type> routers() const;
/**
* \brief Searchs for a dns option.
@@ -391,7 +401,7 @@ namespace Tins {
* \return std::list<ipaddress_type> Contanining the DNS servers
* provided.
*/
std::list<ipaddress_type> domain_name_servers() const;
std::vector<ipaddress_type> domain_name_servers() const;
/**
* \brief Searchs for a broadcast option.
@@ -422,6 +432,16 @@ namespace Tins {
* \return std::string Containing the domain name.
*/
std::string domain_name() const;
/**
* \brief Searchs for a hostname option.
*
* If the option is not found, an option_not_found exception
* is thrown.
*
* \return std::string Containing the hostname.
*/
std::string hostname() const;
/**
* \brief Getter for the options list.
@@ -450,27 +470,19 @@ namespace Tins {
}
private:
static const uint32_t MAX_DHCP_SIZE;
template<typename T>
struct type2type {};
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
template<class T>
T generic_search(OptionTypes opt, type2type<T>) const {
T search_and_convert(OptionTypes opt) const {
const option *option = search_option(opt);
if(option && option->data_size() == sizeof(T))
return *(const T*)option->data_ptr();
else
if(!option)
throw option_not_found();
return option->to<T>();
}
void internal_add_option(const option &opt);
std::list<ipaddress_type> generic_search(OptionTypes opt, type2type<std::list<ipaddress_type> >) const;
std::string generic_search(OptionTypes opt, type2type<std::string>) const;
ipaddress_type generic_search(OptionTypes opt, type2type<ipaddress_type>) const;
serialization_type serialize_list(const std::list<ipaddress_type> &ip_list);
serialization_type serialize_list(const std::vector<ipaddress_type> &ip_list);
options_type _options;
uint32_t _size;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,6 +30,7 @@
#ifndef TINS_DHCPV6_H
#define TINS_DHCPV6_H
#include <cstring>
#include <list>
#include "pdu.h"
#include "endianness.h"
@@ -46,7 +47,7 @@ public:
/**
* Represents a DHCPv6 option.
*/
typedef PDUOption<uint16_t> option;
typedef PDUOption<uint16_t, DHCPv6> option;
/**
* The message types.
@@ -179,6 +180,8 @@ public:
ia_na_type(uint32_t id = 0, uint32_t t1 = 0, uint32_t t2 = 0,
const options_type& options = options_type())
: id(id), t1(t1), t2(t2), options(options) {}
static ia_na_type from_option(const option &opt);
};
/**
@@ -194,6 +197,8 @@ public:
ia_ta_type(uint32_t id = 0,
const options_type& options = options_type())
: id(id), options(options) {}
static ia_ta_type from_option(const option &opt);
};
/**
@@ -211,6 +216,8 @@ public:
const options_type& options = options_type())
: address(address), preferred_lifetime(preferred_lifetime),
valid_lifetime(valid_lifetime), options(options) {}
static ia_address_type from_option(const option &opt);
};
/**
@@ -228,6 +235,8 @@ public:
const auth_info_type &auth_info = auth_info_type())
: protocol(protocol), algorithm(algorithm), rdm(rdm),
replay_detection(replay_detection), auth_info(auth_info) {}
static authentication_type from_option(const option &opt);
};
/**
@@ -239,6 +248,8 @@ public:
status_code_type(uint16_t code = 0, const std::string &message = "")
: code(code), message(message) { }
static status_code_type from_option(const option &opt);
};
/**
@@ -253,6 +264,8 @@ public:
vendor_info_type(uint32_t enterprise_number = 0,
const data_type &data = data_type())
: enterprise_number(enterprise_number), data(data) { }
static vendor_info_type from_option(const option &opt);
};
@@ -264,7 +277,19 @@ public:
/**
* The type used to store the User Class option.
*/
typedef std::vector<class_option_data_type> user_class_type;
//typedef std::vector<class_option_data_type> user_class_type;
struct user_class_type {
typedef std::vector<class_option_data_type> data_type;
data_type data;
user_class_type(const data_type &data = data_type())
: data(data)
{
}
static user_class_type from_option(const option &opt);
};
/**
* The type used to store the Vendor Class option.
@@ -279,6 +304,8 @@ public:
const class_data_type &vendor_class_data = class_data_type())
: enterprise_number(enterprise_number),
vendor_class_data(vendor_class_data) { }
static vendor_class_type from_option(const option &opt);
};
/**
@@ -361,12 +388,14 @@ public:
duid_type(const duid_ll &identifier)
: id(duid_en::duid_id), data(identifier.serialize()) {}
static duid_type from_option(const option &opt);
};
/**
* The type used to store the Option Request option.
*/
typedef std::vector<OptionTypes> option_request_type;
typedef std::vector<uint16_t> option_request_type;
/**
* The type used to store the Relay Message option.
@@ -837,52 +866,63 @@ private:
throw option_not_found();
return option;
}
template<typename InputIterator>
void class_option_data2option(InputIterator start, InputIterator end,
std::vector<uint8_t>& buffer, size_t start_index = 0)
{
size_t index = start_index;
while(start != end) {
buffer.resize(buffer.size() + sizeof(uint16_t) + start->size());
*(uint16_t*)&buffer[index] = Endian::host_to_be<uint16_t>(start->size());
index += sizeof(uint16_t);
std::copy(start->begin(), start->end(), buffer.begin() + index);
index += start->size();
start++;
}
}
template<typename OutputType>
OutputType option2class_option_data(const uint8_t *ptr, uint32_t total_sz) const
{
typedef typename OutputType::value_type value_type;
OutputType output;
size_t index = 0;
while(index + 2 < total_sz) {
uint16_t size = Endian::be_to_host(
*(const uint16_t*)(ptr + index)
);
index += sizeof(uint16_t);
if(index + size > total_sz)
throw option_not_found();
output.push_back(
value_type(ptr + index, ptr + index + size)
);
index += size;
}
if(index != total_sz)
template<typename T>
T search_and_convert(OptionTypes opt) const {
const option *option = search_option(opt);
if(!option)
throw option_not_found();
return output;
return option->to<T>();
}
uint8_t header_data[4];
uint32_t options_size;
ipaddress_type link_addr, peer_addr;
options_type options_;
};
};
namespace Internals {
template<typename InputIterator>
void class_option_data2option(InputIterator start, InputIterator end,
std::vector<uint8_t>& buffer, size_t start_index = 0)
{
size_t index = start_index;
uint16_t uint16_t_buffer;
while(start != end) {
buffer.resize(buffer.size() + sizeof(uint16_t) + start->size());
uint16_t_buffer = Endian::host_to_be<uint16_t>(start->size());
std::memcpy(&buffer[index], &uint16_t_buffer, sizeof(uint16_t));
index += sizeof(uint16_t);
std::copy(start->begin(), start->end(), buffer.begin() + index);
index += start->size();
start++;
}
}
template<typename OutputType>
OutputType option2class_option_data(const uint8_t *ptr, uint32_t total_sz)
{
typedef typename OutputType::value_type value_type;
OutputType output;
size_t index = 0;
while(index + 2 < total_sz) {
uint16_t size;
std::memcpy(&size, ptr + index, sizeof(uint16_t));
size = Endian::be_to_host(size);
index += sizeof(uint16_t);
if(index + size > total_sz)
throw option_not_found();
output.push_back(
value_type(ptr + index, ptr + index + size)
);
index += size;
}
if(index != total_sz)
throw malformed_option();
return output;
}
}
}
#endif // TINS_DHCPV6_H

View File

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

View File

@@ -1,272 +0,0 @@
/*
* 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_DNS_RECORD_H
#define TINS_DNS_RECORD_H
#include <string>
#include <vector>
#include <stdint.h>
#include "cxxstd.h"
#include "macros.h"
namespace Tins {
/**
* \cond
*/
class DNSRRImpl {
public:
virtual ~DNSRRImpl() {}
virtual uint32_t size() const = 0;
virtual uint32_t do_write(uint8_t *buffer) const = 0;
virtual bool matches(const std::string &dname) const { return false; }
virtual DNSRRImpl *clone() const = 0;
};
/**
* \brief Abstracts a DNS resource record.
*/
class DNSResourceRecord {
public:
/**
* \brief The type used to store resource records' information.
*/
TINS_BEGIN_PACK
struct info {
uint16_t type, qclass;
uint32_t ttl;
info(uint16_t tp, uint16_t qc, uint32_t tm)
: type(tp), qclass(qc), ttl(tm) { }
info() : type(), qclass(), ttl() {}
} TINS_END_PACK;
/**
* \brief Constructs a record.
* \param impl A pointer to the impl object.
* \param data A pointer to the start of the data buffer.
* \param len The length of the data.
*/
DNSResourceRecord(DNSRRImpl *impl = 0, const uint8_t *data = 0, uint16_t len = 0);
/**
* \brief Constructs a record.
*
* If the input data is malformed, a malformed_packet exception
* is thrown.
*
* \param buffer A pointer to the start of the data buffer.
* \param len The length of the data.
*/
DNSResourceRecord(const uint8_t *buffer, uint32_t size);
/**
* \brief Constructs a record from an input range.
* \param impl A pointer to the impl object.
* \param start The begining of the range.
* \param end The end of the range.
*/
template<typename ForwardIterator>
DNSResourceRecord(DNSRRImpl *impl, ForwardIterator start, ForwardIterator end)
: impl(impl), data(start, end)
{ }
/**
* \brief Copy constructor.
*
* This handles cloning the impl object.
* \param rhs The record which will be copied.
*/
DNSResourceRecord(const DNSResourceRecord &rhs);
/**
* \brief Copy assignment operator.
*
* This handles cloning the impl object.
* \param rhs The record which will be copied.
*/
DNSResourceRecord& operator=(const DNSResourceRecord &rhs);
#if TINS_IS_CXX11
/**
* Move constructor.
*/
DNSResourceRecord(DNSResourceRecord &&rhs) noexcept
: info_(rhs.info_), data(std::move(rhs.data)), impl(0) {
std::swap(impl, rhs.impl);
}
/**
* Move assignment operator.
*/
DNSResourceRecord& operator=(DNSResourceRecord &&rhs) noexcept
{
info_ = rhs.info_;
data = std::move(rhs.data);
delete impl;
impl = 0;
std::swap(impl, rhs.impl);
return *this;
}
#endif // TINS_IS_CXX11
/**
* \brief Destructor.
*
* This frees the impl object.
*/
~DNSResourceRecord();
/**
* \brief Writes this record to a buffer.
*
* \param buffer The buffer in which to store the serialization.
* \return uint32_t containing the number of bytes written.
*/
uint32_t write(uint8_t *buffer) const;
/**
* \brief Returns the size of the data in this record.
*/
uint32_t data_size() const {
return data.size();
}
/**
* \brief Returns the pointer to the start of the data buffer.
*/
const uint8_t *data_ptr() const {
return &data[0];
}
/**
* \brief Returns a bool indicating whether this record contains
* a domain name as the name being resolved.
*/
bool has_domain_name() const;
/**
* \brief Returns a pointer to the domain name stored in this record.
*
* This will throw a std::bad_cast exception if the impl object is
* not of the type NamedDNSRRImpl.
*/
const std::string *dname() const;
/**
* \brief Returns the offset stored in this record.
*
* This will throw a std::bad_cast exception if the impl object is
* not of the type OffsetedDNSRRImpl.
*/
uint16_t offset() const;
/**
* \brief Returns the size of this record.
*/
uint32_t size() const;
/**
* \brief Returns a reference to the info field.
*/
info &information() {
return info_;
}
/**
* \brief Returns a const reference to the info field.
*/
const info &information() const {
return info_;
}
/**
* \brief Checks if the domain name stored in this record matches
* the given one.
*
* This is a shortcut
*/
bool matches(const std::string &dname) const;
private:
DNSRRImpl *clone_impl() const;
size_t impl_size() const;
info info_;
std::vector<uint8_t> data;
DNSRRImpl *impl;
};
class OffsetedDNSRRImpl : public DNSRRImpl {
public:
OffsetedDNSRRImpl(uint16_t off);
uint32_t do_write(uint8_t *buffer) const;
uint32_t size() const;
OffsetedDNSRRImpl *clone() const;
uint16_t offset() const;
private:
uint16_t offset_;
};
class NamedDNSRRImpl : public DNSRRImpl {
public:
NamedDNSRRImpl(const std::string &nm);
template<typename ForwardIterator>
NamedDNSRRImpl(ForwardIterator start, ForwardIterator end)
: name(start, end)
{ }
uint32_t do_write(uint8_t *buffer) const;
uint32_t size() const;
bool matches(const std::string &dname) const;
const std::string *dname_pointer() const;
NamedDNSRRImpl *clone() const;
private:
std::string name;
};
/**
* \endcond
*/
inline DNSResourceRecord make_offseted_record(uint16_t offset, const uint8_t *data = 0, uint32_t size = 0) {
return DNSResourceRecord(new OffsetedDNSRRImpl(offset), data, size);
}
inline DNSResourceRecord make_named_record(const std::string &name, const uint8_t *data = 0, uint32_t size = 0) {
return DNSResourceRecord(new NamedDNSRRImpl(name), data, size);
}
}
#endif // TINS_DNS_RECORD_H

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,7 +27,9 @@
*
*/
#ifndef TINS_DOT11_DOT11_ASSOC_H
#include "../config.h"
#if !defined(TINS_DOT11_DOT11_ASSOC_H) && defined(HAVE_DOT11)
#define TINS_DOT11_DOT11_ASSOC_H
#include "../dot11/dot11_mgmt.h"
@@ -617,4 +619,4 @@ private:
};
} // namespace Tins
#endif // TINS_DOT11_DOT11_ASSOC_H
#endif // TINS_DOT11_DOT11_ASSOC_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,7 +27,9 @@
*
*/
#ifndef TINS_DOT11_DOT11_AUTH_H
#include "../config.h"
#if !defined(TINS_DOT11_DOT11_AUTH_H) && defined(HAVE_DOT11)
#define TINS_DOT11_DOT11_AUTH_H
#include "../dot11/dot11_mgmt.h"
@@ -255,4 +257,4 @@ private:
} // namespace Tins
#endif // TINS_DOT11_DOT11_AUTH_H
#endif // TINS_DOT11_DOT11_AUTH_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,7 +27,9 @@
*
*/
#ifndef TINS_DOT11_DOT11_H
#include "../config.h"
#if !defined(TINS_DOT11_DOT11_H) && defined(HAVE_DOT11)
#define TINS_DOT11_DOT11_H
#include <list>
@@ -55,7 +57,7 @@ public:
/**
* \brief IEEE 802.11 options struct.
*/
typedef PDUOption<uint8_t> option;
typedef PDUOption<uint8_t, Dot11> option;
/**
* The type used to store tagged options.
@@ -72,6 +74,11 @@ public:
*/
static const address_type BROADCAST;
/**
* The endianness used by Dot11.
*/
static const endian_type endianness = LE;
/**
* \brief Enum for the different types of 802.11 frames.
*

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,7 +27,9 @@
*
*/
#ifndef TINS_DOT11_DOT11_BEACON_H
#include "../config.h"
#if !defined(TINS_DOT11_DOT11_BEACON_H) && defined(HAVE_DOT11)
#define TINS_DOT11_DOT11_BEACON_H
#include "../dot11/dot11_mgmt.h"
@@ -161,4 +163,4 @@ namespace Tins {
};
} // namespace Tins
#endif // TINS_DOT11_DOT11_BEACON_H
#endif // TINS_DOT11_DOT11_BEACON_H

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,7 +27,10 @@
*
*/
#ifndef TINS_DOT11_DOT11_MGMT_H
#include "../config.h"
#if !defined(TINS_DOT11_DOT11_MGMT_H) && defined(HAVE_DOT11)
#define TINS_DOT11_DOT11_MGMT_H
#include <vector>
@@ -376,6 +379,8 @@ public:
uint8_t hop_pattern, uint8_t hop_index)
: dwell_time(dwell_time), hop_set(hop_set),
hop_pattern(hop_pattern), hop_index(hop_index) {}
static fh_params_set from_option(const option &opt);
};
/**
@@ -392,6 +397,8 @@ public:
: cfp_count(cfp_count), cfp_period(cfp_period),
cfp_max_duration(cfp_max_duration),
cfp_dur_remaining(cfp_dur_remaining) {}
static cf_params_set from_option(const option &opt);
};
/**
@@ -410,6 +417,8 @@ public:
uint8_t recovery_interval, const channels_type &channels)
: dfs_owner(addr), recovery_interval(recovery_interval),
channel_map(channels) {}
static ibss_dfs_params from_option(const option &opt);
};
/**
@@ -428,6 +437,8 @@ public:
const byte_array &number, const byte_array &max)
: country(country), first_channel(first), number_channels(number),
max_transmit_power(max) {}
static country_params from_option(const option &opt);
};
/**
@@ -445,6 +456,8 @@ public:
uint8_t offset, const byte_array& table)
: flag(flag), number_of_sets(sets), modulus(modulus),
offset(offset), random_table(table) {}
static fh_pattern_type from_option(const option &opt);
};
/**
@@ -457,6 +470,8 @@ public:
channel_switch_type(uint8_t mode, uint8_t channel, uint8_t count)
: switch_mode(mode), new_channel(channel), switch_count(count) { }
static channel_switch_type from_option(const option &opt);
};
/**
@@ -472,6 +487,8 @@ public:
uint16_t offset)
: quiet_count(count), quiet_period(period),
quiet_duration(duration), quiet_offset(offset) {}
static quiet_type from_option(const option &opt);
};
/**
@@ -488,6 +505,8 @@ public:
uint16_t capacity)
: station_count(count), available_capacity(capacity),
channel_utilization(utilization) {}
static bss_load_type from_option(const option &opt);
};
/**
@@ -503,6 +522,8 @@ public:
const byte_array &bitmap)
: dtim_count(count), dtim_period(period), bitmap_control(control),
partial_virtual_bitmap(bitmap) {}
static tim_type from_option(const option &opt);
};
/**
@@ -520,6 +541,11 @@ public:
static vendor_specific_type from_bytes(const uint8_t *buffer, uint32_t sz);
};
/**
* The type used to store the QOS capability tagged option data.
*/
typedef uint8_t qos_capability_type;
/**
* \brief Getter for the second address.
@@ -638,7 +664,7 @@ public:
*
* \param new_qos_capabilities uint8_t with the capabilities.
*/
void qos_capability(uint8_t new_qos_capability);
void qos_capability(qos_capability_type new_qos_capability);
/**
* \brief Helper method to set the power capabilities option.
@@ -848,7 +874,7 @@ public:
*
* \return uint8_t containing the QOS capability.
*/
uint8_t qos_capability() const;
qos_capability_type qos_capability() const;
/**
* \brief Helper method to get the power capability.
@@ -1117,6 +1143,14 @@ protected:
private:
static uint8_t *serialize_rates(const rates_type &rates);
static rates_type deserialize_rates(const option *option);
template<typename T>
T search_and_convert(OptionTypes opt_type) const {
const option *opt = search_option(opt_type);
if(!opt)
throw option_not_found();
return opt->to<T>();
}
ExtendedHeader _ext_header;
address_type _addr4;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,7 +27,10 @@
*
*/
#ifndef TINS_DOT11_DOT11_PROBE_H
#include "../config.h"
#if !defined(TINS_DOT11_DOT11_PROBE_H) && defined(HAVE_DOT11)
#define TINS_DOT11_DOT11_PROBE_H
#include "../dot11/dot11_mgmt.h"
@@ -227,4 +230,4 @@ private:
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
};
} // namespace Tins
#endif // TINS_DOT11_DOT11_PROBE_H
#endif // TINS_DOT11_DOT11_PROBE_H

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -55,6 +55,16 @@
namespace Tins {
namespace Endian {
/**
* \brief "Changes" a 8-bit integral value's endianess. This is an
* identity function.
*
* \param data The data to convert.
*/
inline uint8_t do_change_endian(uint8_t data) {
return data;
}
/**
* \brief Changes a 16-bit integral value's endianess.
*
@@ -100,6 +110,11 @@ namespace Endian {
template<size_t>
struct conversion_dispatcher;
template<>
struct conversion_dispatcher<sizeof(uint8_t)>
: public conversion_dispatch_helper<uint8_t>
{ };
template<>
struct conversion_dispatcher<sizeof(uint16_t)>
: public conversion_dispatch_helper<uint16_t>

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,6 +30,7 @@
#ifndef TINS_EXCEPTIONS_H
#define TINS_EXCEPTIONS_H
#include <string>
#include <stdexcept>
namespace Tins {
@@ -145,6 +146,28 @@ public:
return "Malformed option";
}
};
}
/**
* \brief Exception thrown when a call to tins_cast fails.
*/
class bad_tins_cast : public std::exception {
public:
const char *what() const throw() {
return "Bad Tins cast";
}
};
/**
* \brief Exception thrown when sniffing a protocol that
* has been disabled at compile time.
*/
class protocol_disabled : public std::exception {
public:
const char *what() const throw() {
return "Protocol disabled";
}
};
} // Tins
#endif // TINS_EXCEPTIONS_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,7 +27,9 @@
*
*/
#ifndef TINS_HANDSHAKE_CAPTURER_H
#include "config.h"
#if !defined(TINS_HANDSHAKE_CAPTURER_H) && defined(HAVE_DOT11)
#define TINS_HANDSHAKE_CAPTURER_H
#include <vector>
@@ -164,4 +166,4 @@ namespace Tins {
};
}
#endif // TINS_HANDSHAKE_CAPTURER_H
#endif // TINS_HANDSHAKE_CAPTURER_H

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,9 +30,22 @@
#ifndef TINS_ICMP_H
#define TINS_ICMP_H
// Windows likes to define macros with not-so-common-names, which break
// this code
#ifdef WIN32
#ifdef TIMESTAMP_REQUEST
#undef TIMESTAMP_REQUEST
#endif // TIMESTAMP_REQUEST
#ifdef TIMESTAMP_REPLY
#undef TIMESTAMP_REPLY
#endif // TIMESTAMP_REPLY
#endif // WIN32
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
#include "ip_address.h"
namespace Tins {
@@ -48,6 +61,11 @@ namespace Tins {
*/
static const PDU::PDUType pdu_flag = PDU::ICMP;
/**
* The type used to store addresses.
*/
typedef IPv4Address address_type;
/** \brief ICMP flags
*/
enum Flags {
@@ -58,8 +76,12 @@ namespace Tins {
ECHO_REQUEST = 8,
TIME_EXCEEDED = 11,
PARAM_PROBLEM = 12,
TIMESTAMP_REQUEST = 13,
TIMESTAMP_REPLY = 14,
INFO_REQUEST = 15,
INFO_REPLY = 16
INFO_REPLY = 16,
ADDRESS_MASK_REQUEST = 17,
ADDRESS_MASK_REPLY = 18
};
/**
@@ -113,9 +135,9 @@ namespace Tins {
/**
* \brief Setter for the gateway field.
*
* \param new_gw uint32_t with the new gateway.
* \param new_gw The new value for the gateway field.
*/
void gateway(uint32_t new_gw);
void gateway(address_type new_gw);
/**
* \brief Setter for the mtu field.
@@ -131,6 +153,34 @@ namespace Tins {
*/
void pointer(uint8_t new_pointer);
/**
* \brief Setter for the original timestamp field.
*
* \param new_timestamp the value to be set.
*/
void original_timestamp(uint32_t new_timestamp);
/**
* \brief Setter for the receive timestamp field.
*
* \param new_timestamp the value to be set.
*/
void receive_timestamp(uint32_t new_timestamp);
/**
* \brief Setter for the transmit timestamp field.
*
* \param new_timestamp the value to be set.
*/
void transmit_timestamp(uint32_t new_timestamp);
/**
* \brief Setter for the address mask field.
*
* \param new_mask the value to be set.
*/
void address_mask(address_type new_mask);
/**
* \brief Sets echo request flag for this PDU.
*
@@ -199,7 +249,7 @@ namespace Tins {
* \param address Address of the gateway to which traffic should
* be sent.
*/
void set_redirect(uint8_t icode, uint32_t address);
void set_redirect(uint8_t icode, address_type address);
/**
* \brief Getter for the ICMP type flag.
@@ -220,7 +270,7 @@ namespace Tins {
*
* \return Returns the checksum as an unit16_t.
*/
uint16_t check() const { return Endian::be_to_host(_icmp.check); }
uint16_t checksum() const { return Endian::be_to_host(_icmp.check); }
/**
* \brief Getter for the echo id.
@@ -239,24 +289,56 @@ namespace Tins {
/**
* \brief Getter for the gateway field.
*
* \return Returns the gateways in an unit32_t.
* \return Returns the gateway field value.
*/
uint32_t gateway() const { return Endian::be_to_host(_icmp.un.gateway); }
address_type gateway() const {
return address_type(Endian::be_to_host(_icmp.un.gateway));
}
/**
* \brief Getter for the pointer field.
*
* \return Returns the pointer value.
* \return Returns the pointer field value.
*/
uint8_t pointer() const { return this->_icmp.un.pointer; }
/**
* \brief Getter for the mtu field.
*
* \return Returns the mtu value in an uint16_t.
* \return Returns the mtu field value.
*/
uint16_t mtu() const { return Endian::be_to_host(_icmp.un.frag.mtu); }
/**
* \brief Getter for the original timestamp field.
*
* \return Returns the original timestamp value.
*/
uint32_t original_timestamp() const { return Endian::be_to_host(_orig_timestamp_or_address_mask); }
/**
* \brief Getter for the receive timestamp field.
*
* \return Returns the receive timestamp value.
*/
uint32_t receive_timestamp() const { return Endian::be_to_host(_recv_timestamp); }
/**
* \brief Getter for the transmit timestamp field.
*
* \return Returns the transmit timestamp value.
*/
uint32_t transmit_timestamp() const { return Endian::be_to_host(_trans_timestamp); }
/**
* \brief Getter for the address mask field.
*
* \return Returns the address mask value.
*/
address_type address_mask() const {
return address_type(Endian::be_to_host(_orig_timestamp_or_address_mask));
}
/**
* \brief Returns the header size.
*
@@ -307,7 +389,7 @@ namespace Tins {
} un;
} TINS_END_PACK;
void check(uint16_t new_check);
void checksum(uint16_t new_check);
/** \brief Serialices this ICMP PDU.
* \param buffer The buffer in which the PDU will be serialized.
@@ -317,6 +399,7 @@ namespace Tins {
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
icmphdr _icmp;
uint32_t _orig_timestamp_or_address_mask, _recv_timestamp, _trans_timestamp;
};
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -135,7 +135,7 @@ public:
/**
* The type used to represent ICMPv6 options.
*/
typedef PDUOption<uint8_t> option;
typedef PDUOption<uint8_t, ICMPv6> option;
/**
* The type used to store options.
@@ -145,30 +145,53 @@ public:
/**
* \brief The type used to store the new home agent information
* option data.
*
* The first member contains the home agent preference field, while
* the second one contains the home agent lifetime.
*/
typedef std::pair<uint16_t, uint16_t> new_ha_info_type;
typedef std::vector<uint16_t> new_ha_info_type;
/**
* The type used to store the source/target address list options.
*/
typedef std::vector<ipaddress_type> addr_list_type;
struct addr_list_type {
typedef std::vector<ipaddress_type> addresses_type;
uint8_t reserved[6];
addresses_type addresses;
addr_list_type(const addresses_type &addresses = addresses_type())
: addresses(addresses)
{
std::fill(reserved, reserved + sizeof(reserved), 0);
}
static addr_list_type from_option(const option &opt);
};
/**
* The type used to store the nonce option data.
*/
typedef std::vector<uint8_t> nonce_type;
/**
* The type used to store the MTU option.
*/
typedef std::pair<uint16_t, uint32_t> mtu_type;
/**
* \brief The type used to store the neighbour advertisement
* acknowledgement option data.
*
* The first member contains the option code field, while
* the second one contains the status.
*/
typedef std::pair<uint8_t, uint8_t> naack_type;
struct naack_type {
uint8_t code, status;
uint8_t reserved[4];
naack_type(uint8_t code = 0, uint8_t status = 0)
: code(code), status(status)
{
std::fill(reserved, reserved + 4, 0);
}
static naack_type from_option(const option &opt);
};
/**
* \brief The type used to store the link layer address option data.
@@ -207,6 +230,8 @@ public:
{
}
static lladdr_type from_option(const option &opt);
};
/**
@@ -226,6 +251,8 @@ public:
: prefix_len(prefix_len), A(A), L(L),
valid_lifetime(valid_lifetime), preferred_lifetime(preferred_lifetime),
prefix(prefix) { }
static prefix_info_type from_option(const option &opt);
};
/**
@@ -290,6 +317,8 @@ public:
{
std::fill(key_hash, key_hash + sizeof(key_hash), 0);
}
static rsa_sign_type from_option(const option &opt);
};
/**
@@ -303,6 +332,8 @@ public:
const ipaddress_type &address = ipaddress_type())
: option_code(option_code), prefix_len(prefix_len), address(address)
{}
static ip_prefix_type from_option(const option &opt);
};
/**
@@ -319,6 +350,8 @@ public:
const ipaddress_type &address = ipaddress_type())
: dist(dist), pref(pref), r(r), valid_lifetime(valid_lifetime),
address(address) { }
static map_type from_option(const option &opt);
};
/**
@@ -336,6 +369,8 @@ public:
uint32_t route_lifetime = 0, const prefix_type &prefix = prefix_type())
: prefix_len(prefix_len), pref(pref), route_lifetime(route_lifetime),
prefix(prefix) { }
static route_info_type from_option(const option &opt);
};
/**
@@ -350,6 +385,8 @@ public:
recursive_dns_type(uint32_t lifetime = 0,
const servers_type &servers = servers_type())
: lifetime(lifetime), servers(servers) {}
static recursive_dns_type from_option(const option &opt);
};
/**
@@ -364,6 +401,8 @@ public:
handover_key_req_type(small_uint<4> AT = 0,
const key_type &key = key_type())
: AT(AT), key(key) { }
static handover_key_req_type from_option(const option &opt);
};
/**
@@ -375,6 +414,8 @@ public:
handover_key_reply_type(uint16_t lifetime = 0, small_uint<4> AT = 0,
const key_type &key = key_type())
: handover_key_req_type(AT, key), lifetime(lifetime) { }
static handover_key_reply_type from_option(const option &opt);
};
/**
@@ -389,6 +430,8 @@ public:
handover_assist_info_type(uint8_t option_code=0,
const hai_type &hai = hai_type())
: option_code(option_code), hai(hai) { }
static handover_assist_info_type from_option(const option &opt);
};
/**
@@ -403,6 +446,8 @@ public:
mobile_node_id_type(uint8_t option_code=0,
const mn_type &mn = mn_type())
: option_code(option_code), mn(mn) { }
static mobile_node_id_type from_option(const option &opt);
};
/**
@@ -417,8 +462,58 @@ public:
dns_search_list_type(uint32_t lifetime = 0,
const domains_type &domains = domains_type())
: lifetime(lifetime), domains(domains) { }
static dns_search_list_type from_option(const option &opt);
};
/**
* The type used to store the timestamp option.
*/
struct timestamp_type {
uint8_t reserved[6];
uint64_t timestamp;
timestamp_type(uint64_t timestamp = 0)
: timestamp(timestamp)
{
std::fill(reserved, reserved + sizeof(reserved), 0);
}
static timestamp_type from_option(const option &opt);
};
/**
* The type used to store the shortcut limit option.
*/
struct shortcut_limit_type {
uint8_t limit, reserved1;
uint32_t reserved2;
shortcut_limit_type(uint8_t limit = 0)
: limit(limit), reserved1(), reserved2()
{
}
static shortcut_limit_type from_option(const option &opt);
};
/**
* The type used to store new advertisement interval option.
*/
struct new_advert_interval_type {
uint16_t reserved;
uint32_t interval;
new_advert_interval_type(uint32_t interval = 0)
: reserved(), interval(interval)
{
}
static new_advert_interval_type from_option(const option &opt);
};
/**
* \brief Constructs an ICMPv6 object.
*
@@ -820,33 +915,30 @@ public:
/**
* \brief Setter for the redirect header option.
*
* This method appends the 6 reserved bytes and inserts the
* necessary padding at the end.
*
* \param data The redirect header option data.
*/
void redirect_header(PDU::serialization_type data);
void redirect_header(const byte_array &data);
/**
* \brief Setter for the MTU option.
*
* \param value The MTU option data.
*/
void mtu(uint32_t value);
void mtu(const mtu_type& value);
/**
* \brief Setter for the shortcut limit option.
*
* \param value The shortcut limit option data.
*/
void shortcut_limit(uint8_t value);
void shortcut_limit(const shortcut_limit_type& value);
/**
* \brief Setter for the new advertisement interval option.
*
* \param value The new advertisement interval option data.
*/
void new_advert_interval(uint32_t value);
void new_advert_interval(const new_advert_interval_type &value);
/**
* \brief Setter for the new home agent information option.
@@ -881,7 +973,7 @@ public:
*
* \param value The new timestamp option data.
*/
void timestamp(uint64_t value);
void timestamp(const timestamp_type &value);
/**
* \brief Setter for the new nonce option.
@@ -1001,7 +1093,7 @@ public:
* This method will throw an option_not_found exception if the
* option is not found.
*/
PDU::serialization_type redirect_header() const;
byte_array redirect_header() const;
/**
* \brief Getter for the MTU option.
@@ -1009,7 +1101,7 @@ public:
* This method will throw an option_not_found exception if the
* option is not found.
*/
uint32_t mtu() const;
mtu_type mtu() const;
/**
* \brief Getter for the shortcut limit option.
@@ -1017,7 +1109,7 @@ public:
* This method will throw an option_not_found exception if the
* option is not found.
*/
uint8_t shortcut_limit() const;
shortcut_limit_type shortcut_limit() const;
/**
* \brief Getter for the new advertisement interval option.
@@ -1025,7 +1117,7 @@ public:
* This method will throw an option_not_found exception if the
* option is not found.
*/
uint32_t new_advert_interval() const;
new_advert_interval_type new_advert_interval() const;
/**
* \brief Getter for the new home agent information option.
@@ -1065,7 +1157,7 @@ public:
* This method will throw an option_not_found exception if the
* option is not found.
*/
uint64_t timestamp() const;
timestamp_type timestamp() const;
/**
* \brief Getter for the nonce option.
@@ -1225,6 +1317,14 @@ private:
return option;
}
template<typename T>
T search_and_convert(OptionTypes type) const {
const option *opt = search_option(type);
if(!opt)
throw option_not_found();
return opt->to<T>();
}
icmp6hdr _header;
ipaddress_type _target_address, _dest_address;
options_type _options;

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -57,7 +57,7 @@ public:
template<typename InputIterator>
byte_array(InputIterator start, InputIterator last) {
std::copy(start, end, data);
std::copy(start, last, data);
}
template<typename InputIterator>
@@ -99,22 +99,24 @@ private:
void skip_line(std::istream &input);
bool from_hex(const std::string &str, uint32_t &result);
template<bool, typename>
template<bool, typename T = void>
struct enable_if {
typedef T type;
};
template<typename T>
struct enable_if<true, T> {
typedef T type;
struct enable_if<false, T> {
};
PDU *pdu_from_flag(Constants::Ethernet::e flag, const uint8_t *buffer,
uint32_t size, bool rawpdu_on_no_match = true);
PDU *pdu_from_flag(Constants::IP::e flag, const uint8_t *buffer,
uint32_t size, bool rawpdu_on_no_match = true);
PDU *pdu_from_flag(PDU::PDUType type, const uint8_t *buffer, uint32_t size);
Constants::Ethernet::e pdu_flag_to_ether_type(PDU::PDUType flag);
Constants::IP::e pdu_flag_to_ip_type(PDU::PDUType flag);
template<typename T>
bool increment_buffer(T &addr) {
@@ -171,6 +173,31 @@ HWAddress<n> last_address_from_mask(HWAddress<n> addr, const HWAddress<n> &mask)
inline bool is_dot3(const uint8_t *ptr, size_t sz) {
return (sz >= 13 && ptr[12] < 8);
}
template<typename T>
struct is_unsigned_integral {
static const bool value = false;
};
template<>
struct is_unsigned_integral<uint8_t> {
static const bool value = true;
};
template<>
struct is_unsigned_integral<uint16_t> {
static const bool value = true;
};
template<>
struct is_unsigned_integral<uint32_t> {
static const bool value = true;
};
template<>
struct is_unsigned_integral<uint64_t> {
static const bool value = true;
};
} // namespace Internals
} // namespace Tins
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -169,7 +169,7 @@ namespace Tins {
/**
* The IP options type.
*/
typedef PDUOption<option_identifier> option;
typedef PDUOption<option_identifier, IP> option;
/**
* The type of the security option.
@@ -184,6 +184,8 @@ namespace Tins {
: security(sec), compartments(comp),
handling_restrictions(hand_res), transmission_control(tcc)
{}
static security_type from_option(const option &opt);
};
/**
@@ -198,6 +200,8 @@ namespace Tins {
generic_route_option_type(uint8_t ptr = 0,
routes_type rts = routes_type())
: pointer(ptr), routes(rts) {}
static generic_route_option_type from_option(const option &opt);
};
/**
@@ -364,6 +368,17 @@ namespace Tins {
/**
* \brief Setter for the protocol field.
*
* Note that this protocol will be overwritten using the
* inner_pdu's protocol type during serialization unless the IP
* datagram is fragmented.
*
* If the packet is fragmented and was originally sniffed, the
* original protocol type will be kept when serialized.
*
* If this packet has been crafted manually and the inner_pdu
* is, for example, a RawPDU, then setting the protocol yourself
* is necessary.
*
* \param new_protocol The new protocol.
*/
void protocol(uint8_t new_protocol);
@@ -411,6 +426,20 @@ namespace Tins {
internal_add_option(opt);
_ip_options.push_back(std::move(opt));
}
/**
* \brief Adds an IP option.
*
* The option is constructed from the provided parameters.
*
* \param args The arguments to be used in the option's
* constructor.
*/
template<typename... Args>
void add_option(Args&&... args) {
_ip_options.emplace_back(std::forward<Args>(args)...);
internal_add_option(_ip_options.back());
}
#endif
/**
@@ -568,6 +597,13 @@ namespace Tins {
*/
PDU *recv_response(PacketSender &sender, const NetworkInterface &);
/**
* Indicates whether this PDU is fragmented.
*
* \return true if this PDU is fragmented, false otherwise.
*/
bool is_fragmented() const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type

View File

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

216
include/ip_reassembler.h Normal file
View File

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

264
include/ipsec.h Normal file
View File

@@ -0,0 +1,264 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_IPSEC_H
#define TINS_IPSEC_H
#include "pdu.h"
#include "endianness.h"
#include "small_uint.h"
namespace Tins {
/**
* \brief Represents an IPSec Authentication Header.
*/
class IPSecAH : public PDU {
public:
/**
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::IPSEC_AH;
/**
* \brief Default constructor.
*
* The ICV field is initialized with four 0 bytes. The length
* field is initialized appropriately.
*/
IPSecAH();
/**
* \brief Constructs an IPSecAH object from a buffer and adds all
* identifiable PDUs found in the buffer as children of this
* one.
*
* If there is not enough size for an IPSecAH header, a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
IPSecAH(const uint8_t *buffer, uint32_t total_sz);
// Getters
/**
* \brief Getter for the Next header field.
* \return The stored Next header field value.
*/
uint8_t next_header() const {
return _header.next_header;
}
/**
* \brief Getter for the Length field.
* \return The stored Length field value.
*/
uint8_t length() const {
return _header.length;
}
/**
* \brief Getter for the Security Parameters Index field.
* \return The stored Security Parameters Index field value.
*/
uint32_t spi() const {
return Endian::be_to_host(_header.spi);
}
/**
* \brief Getter for the Sequence number field.
* \return The stored Sequence number field value.
*/
uint32_t seq_number() const {
return Endian::be_to_host(_header.seq_number);
}
/**
* \brief Getter for the ICV field.
* \return The stored ICV field value.
*/
const byte_array &icv() const {
return _icv;
}
// Setters
/**
* \brief Setter for the Next header field.
* \param new_next_header The new Next header field value.
*/
void next_header(uint8_t new_next_header);
/**
* \brief Setter for the Length field.
* \param new_length The new Length field value.
*/
void length(uint8_t new_length);
/**
* \brief Setter for the Security Parameters Index field.
* \param new_spi The new Security Parameters Index field value.
*/
void spi(uint32_t new_spi);
/**
* \brief Setter for the Sequence number field.
* \param new_seq_number The new Sequence number field value.
*/
void seq_number(uint32_t new_seq_number);
/**
* \brief Setter for the ICV field.
* \param new_icv The new ICV field value.
*/
void icv(const byte_array &new_icv);
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \sa PDU::clone
*/
IPSecAH *clone() const {
return new IPSecAH(*this);
}
private:
struct header {
uint8_t next_header, length;
uint32_t spi, seq_number;
};
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
header _header;
byte_array _icv;
};
/**
* \brief Represents an IPSec Authentication Header.
*/
class IPSecESP : public PDU {
public:
/**
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::IPSEC_ESP;
/**
* \brief Default constructor.
*/
IPSecESP();
/**
* \brief Constructs an IPSecESP object from a buffer and adds all
* identifiable PDUs found in the buffer as children of this
* one.
*
* If there is not enough size for an IPSecESP header, a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
IPSecESP(const uint8_t *buffer, uint32_t total_sz);
// Getters
/**
* \brief Getter for the Security Parameters Index field.
* \return The stored Security Parameters Index field value.
*/
uint32_t spi() const {
return Endian::be_to_host(_header.spi);
}
/**
* \brief Getter for the Sequence number field.
* \return The stored Sequence number field value.
*/
uint32_t seq_number() const {
return Endian::be_to_host(_header.seq_number);
}
// Setters
/**
* \brief Setter for the Security Parameters Index field.
* \param new_spi The new Security Parameters Index field value.
*/
void spi(uint32_t new_spi);
/**
* \brief Setter for the Sequence number field.
* \param new_seq_number The new Sequence number field value.
*/
void seq_number(uint32_t new_seq_number);
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \sa PDU::clone
*/
IPSecESP *clone() const {
return new IPSecESP(*this);
}
private:
struct header {
uint32_t spi, seq_number;
};
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
header _header;
};
}
#endif // TINS_IPSEC_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -60,7 +60,7 @@ public:
/**
* The type used to represent IPv6 extension headers.
*/
typedef PDUOption<uint8_t> ext_header;
typedef PDUOption<uint8_t, IPv6> ext_header;
/**
* The type used to store the extension headers.

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -40,11 +40,13 @@
#define TINS_END_PACK __pragma( pack(pop) )
#define TINS_PACKED(DECLARATION) __pragma( pack(push, 1) ) DECLARATION __pragma( pack(pop) )
#define TINS_DEPRECATED(func) __declspec(deprecated) func
#define NOEXCEPT
#else
#define TINS_BEGIN_PACK
#define TINS_END_PACK __attribute__((packed))
#define TINS_PACKED(DECLARATION) DECLARATION __attribute__((packed))
#define TINS_DEPRECATED(func) func __attribute__ ((deprecated))
#define NOEXCEPT noexcept
#endif
#endif

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -128,6 +128,13 @@ private:
*/
class Packet {
public:
/**
* Tag used to specify that a Packet should own a PDU pointer.
*/
struct own_pdu {
};
/**
* \brief Default constructs a Packet.
*
@@ -143,6 +150,17 @@ public:
*/
Packet(const PDU *apdu, const Timestamp &tstamp)
: pdu_(apdu->clone()), ts(tstamp) { }
/**
* \brief Constructs a Packet from a PDU* and a Timestamp.
*
* The PDU* will be owned by the Packet. This means you
* <b>do not</b> have to explicitly delete the pointer, that
* will be done automatically by the Packet when it goes out
* of scope.
*/
Packet(PDU *apdu, const Timestamp &tstamp, own_pdu)
: pdu_(apdu), ts(tstamp) { }
/**
* \brief Constructs a Packet from a const PDU&.
@@ -197,14 +215,14 @@ public:
/**
* Move constructor.
*/
Packet(Packet &&rhs) noexcept : pdu_(rhs.pdu()), ts(rhs.timestamp()) {
Packet(Packet &&rhs) NOEXCEPT : pdu_(rhs.pdu()), ts(rhs.timestamp()) {
rhs.pdu_ = nullptr;
}
/**
* Move assignment operator.
*/
Packet& operator=(Packet &&rhs) noexcept {
Packet& operator=(Packet &&rhs) NOEXCEPT {
if(this != &rhs) {
std::swap(pdu_, rhs.pdu_);
ts = rhs.timestamp();

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -87,7 +87,7 @@ namespace Tins {
* \brief Move constructor.
* \param rhs The sender to be moved.
*/
PacketSender(PacketSender &&rhs) noexcept {
PacketSender(PacketSender &&rhs) NOEXCEPT {
*this = std::move(rhs);
}
@@ -95,7 +95,7 @@ namespace Tins {
* \brief Move assignment operator.
* \param rhs The sender to be moved.
*/
PacketSender& operator=(PacketSender &&rhs) noexcept {
PacketSender& operator=(PacketSender &&rhs) NOEXCEPT {
_sockets = std::move(rhs._sockets);
rhs._sockets = std::vector<int>(SOCKETS_END, INVALID_RAW_SOCKET);
#ifndef WIN32
@@ -310,7 +310,8 @@ namespace Tins {
static_cast<T&>(pdu).send(*this, iface);
}
PDU *recv_match_loop(int sock, PDU &pdu, struct sockaddr* link_addr, uint32_t addrlen);
PDU *recv_match_loop(const std::vector<int>& sockets, PDU &pdu, struct sockaddr* link_addr,
uint32_t addrlen);
std::vector<int> _sockets;
#ifndef WIN32
@@ -324,6 +325,10 @@ namespace Tins {
SocketTypeMap _types;
uint32_t _timeout, _timeout_usec;
NetworkInterface default_iface;
// In BSD we need to store the buffer size, retrieved using BIOCGBLEN
#if defined(BSD) || defined(__FreeBSD_kernel__)
int buffer_size;
#endif
};
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -76,7 +76,7 @@ public:
*
* \param rhs The PacketWriter to be moved.
*/
PacketWriter(PacketWriter &&rhs) noexcept {
PacketWriter(PacketWriter &&rhs) NOEXCEPT {
*this = std::move(rhs);
}
@@ -88,7 +88,7 @@ public:
*
* \param rhs The PacketWriter to be moved.
*/
PacketWriter& operator=(PacketWriter &&rhs) noexcept {
PacketWriter& operator=(PacketWriter &&rhs) NOEXCEPT {
handle = 0;
dumper = 0;
std::swap(handle, rhs.handle);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -65,6 +65,14 @@ namespace Tins {
*/
typedef byte_array serialization_type;
/**
* The typep used to identify the endianness of every PDU.
*/
enum endian_type {
BE,
LE
};
/**
* \brief Enum which identifies each type of PDU.
*
@@ -119,8 +127,16 @@ namespace Tins {
PPPOE,
STP,
PPI,
IPSEC_AH,
IPSEC_ESP,
USER_DEFINED_PDU = 1000
};
/**
* The endianness used by this PDU. This can be overriden
* by subclasses.
*/
static const endian_type endianness = BE;
/**
* \brief Default constructor.
@@ -133,7 +149,7 @@ namespace Tins {
*
* \param rhs The PDU to be moved.
*/
PDU(PDU &&rhs) noexcept
PDU(PDU &&rhs) NOEXCEPT
: _inner_pdu(0)
{
std::swap(_inner_pdu, rhs._inner_pdu);
@@ -144,7 +160,7 @@ namespace Tins {
*
* \param rhs The PDU to be moved.
*/
PDU& operator=(PDU &&rhs) noexcept {
PDU& operator=(PDU &&rhs) NOEXCEPT {
std::swap(_inner_pdu, rhs._inner_pdu);
return *this;
}
@@ -456,6 +472,34 @@ namespace Tins {
*lop /= rop;
return lop;
}
namespace Internals {
template<typename T>
struct remove_pointer {
typedef T type;
};
template<typename T>
struct remove_pointer<T*> {
typedef T type;
};
}
template<typename T, typename U>
T tins_cast(U *pdu) {
typedef typename Internals::remove_pointer<T>::type TrueT;
return pdu && (TrueT::pdu_flag == pdu->pdu_type()) ?
static_cast<T>(pdu) :
0;
}
template<typename T, typename U>
T &tins_cast(U &pdu) {
T *ptr = tins_cast<T*>(&pdu);
if(!ptr)
throw bad_tins_cast();
return *ptr;
}
}
#endif // TINS_PDU_H

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,10 +32,260 @@
#include <vector>
#include <iterator>
#include <cstring>
#include <algorithm>
#include <string>
#include <stdint.h>
#include "exceptions.h"
#include "endianness.h"
#include "internals.h"
#include "ip_address.h"
#include "ipv6_address.h"
#include "hw_address.h"
namespace Tins {
/**
* \cond
*/
template<typename OptionType, class PDUType>
class PDUOption;
namespace Internals {
template<typename T, typename X, typename PDUType>
T convert_to_integral(const PDUOption<X, PDUType> & opt) {
if(opt.data_size() != sizeof(T))
throw malformed_option();
T data = *(T*)opt.data_ptr();
if(PDUType::endianness == PDUType::BE)
data = Endian::be_to_host(data);
else
data = Endian::le_to_host(data);
return data;
}
template<typename T, typename = void>
struct converter {
template<typename X, typename PDUType>
static T convert(const PDUOption<X, PDUType>& opt) {
return T::from_option(opt);
}
};
template<>
struct converter<uint8_t> {
template<typename X, typename PDUType>
static uint8_t convert(const PDUOption<X, PDUType>& opt) {
if(opt.data_size() != 1)
throw malformed_option();
return *opt.data_ptr();
}
};
template<>
struct converter<uint16_t> {
template<typename X, typename PDUType>
static uint16_t convert(const PDUOption<X, PDUType>& opt) {
return convert_to_integral<uint16_t>(opt);
}
};
template<>
struct converter<uint32_t> {
template<typename X, typename PDUType>
static uint32_t convert(const PDUOption<X, PDUType>& opt) {
return convert_to_integral<uint32_t>(opt);
}
};
template<>
struct converter<uint64_t> {
template<typename X, typename PDUType>
static uint64_t convert(const PDUOption<X, PDUType>& opt) {
return convert_to_integral<uint64_t>(opt);
}
};
template<size_t n>
struct converter<HWAddress<n> > {
template<typename X, typename PDUType>
static HWAddress<n> convert(const PDUOption<X, PDUType>& opt) {
if(opt.data_size() != n)
throw malformed_option();
return HWAddress<n>(opt.data_ptr());
}
};
template<>
struct converter<IPv4Address> {
template<typename X, typename PDUType>
static IPv4Address convert(const PDUOption<X, PDUType>& opt) {
if(opt.data_size() != sizeof(uint32_t))
throw malformed_option();
const uint32_t *ptr = (const uint32_t*)opt.data_ptr();
if(PDUType::endianness == PDUType::BE)
return IPv4Address(*ptr);
else
return IPv4Address(Endian::change_endian(*ptr));
}
};
template<>
struct converter<IPv6Address> {
template<typename X, typename PDUType>
static IPv6Address convert(const PDUOption<X, PDUType>& opt) {
if(opt.data_size() != IPv6Address::address_size)
throw malformed_option();
return IPv6Address(opt.data_ptr());
}
};
template<>
struct converter<std::string> {
template<typename X, typename PDUType>
static std::string convert(const PDUOption<X, PDUType>& opt) {
return std::string(
opt.data_ptr(),
opt.data_ptr() + opt.data_size()
);
}
};
template<>
struct converter<std::vector<float> > {
template<typename X, typename PDUType>
static std::vector<float> convert(const PDUOption<X, PDUType>& opt) {
std::vector<float> output;
const uint8_t *ptr = opt.data_ptr(), *end = ptr + opt.data_size();
while(ptr != end) {
output.push_back(float(*(ptr++) & 0x7f) / 2);
}
return output;
}
};
template<typename T>
struct converter<std::vector<T>, typename enable_if<is_unsigned_integral<T>::value>::type> {
template<typename X, typename PDUType>
static std::vector<T> convert(const PDUOption<X, PDUType>& opt) {
if(opt.data_size() % sizeof(T) != 0)
throw malformed_option();
const T *ptr = (const T*)opt.data_ptr();
const T *end = (const T*)(opt.data_ptr() + opt.data_size());
std::vector<T> output(std::distance(ptr, end));
typename std::vector<T>::iterator it = output.begin();
while(ptr < end) {
if(PDUType::endianness == PDUType::BE)
*it++ = Endian::be_to_host(*ptr++);
else
*it++ = Endian::le_to_host(*ptr++);
}
return output;
}
};
template<typename T, typename U>
struct converter<
std::vector<std::pair<T, U> >,
typename enable_if<
is_unsigned_integral<T>::value && is_unsigned_integral<U>::value
>::type
> {
template<typename X, typename PDUType>
static std::vector<std::pair<T, U> > convert(const PDUOption<X, PDUType>& opt) {
if(opt.data_size() % (sizeof(T) + sizeof(U)) != 0)
throw malformed_option();
const uint8_t *ptr = opt.data_ptr(), *end = ptr + opt.data_size();
std::vector<std::pair<T, U> > output;
while(ptr < end) {
std::pair<T, U> data;
data.first = *(const T*)ptr;
ptr += sizeof(T);
data.second = *(const U*)ptr;
ptr += sizeof(U);
if(PDUType::endianness == PDUType::BE) {
data.first = Endian::be_to_host(data.first);
data.second = Endian::be_to_host(data.second);
}
else {
data.first = Endian::le_to_host(data.first);
data.second = Endian::le_to_host(data.second);
}
output.push_back(data);
}
return output;
}
};
template<>
struct converter<std::vector<IPv4Address> > {
template<typename X, typename PDUType>
static std::vector<IPv4Address> convert(const PDUOption<X, PDUType>& opt) {
if(opt.data_size() % 4 != 0)
throw malformed_option();
const uint32_t *ptr = (const uint32_t*)opt.data_ptr();
const uint32_t *end = (const uint32_t*)(opt.data_ptr() + opt.data_size());
std::vector<IPv4Address> output(std::distance(ptr, end));
std::vector<IPv4Address>::iterator it = output.begin();
while(ptr < end) {
if(PDUType::endianness == PDUType::BE)
*it++ = IPv4Address(*ptr++);
else
*it++ = IPv4Address(Endian::change_endian(*ptr++));
}
return output;
}
};
template<>
struct converter<std::vector<IPv6Address> > {
template<typename X, typename PDUType>
static std::vector<IPv6Address> convert(const PDUOption<X, PDUType>& opt) {
if(opt.data_size() % IPv6Address::address_size != 0)
throw malformed_option();
const uint8_t *ptr = opt.data_ptr(), *end = opt.data_ptr() + opt.data_size();
std::vector<IPv6Address> output;
while(ptr < end) {
output.push_back(IPv6Address(ptr));
ptr += IPv6Address::address_size;
}
return output;
}
};
template<typename T, typename U>
struct converter<
std::pair<T, U>,
typename enable_if<
is_unsigned_integral<T>::value && is_unsigned_integral<U>::value
>::type
> {
template<typename X, typename PDUType>
static std::pair<T, U> convert(const PDUOption<X, PDUType>& opt) {
if(opt.data_size() != sizeof(T) + sizeof(U))
throw malformed_option();
std::pair<T, U> output;
std::memcpy(&output.first, opt.data_ptr(), sizeof(T));
std::memcpy(&output.second, opt.data_ptr() + sizeof(T), sizeof(U));
if(PDUType::endianness == PDUType::BE) {
output.first = Endian::be_to_host(output.first);
output.second = Endian::be_to_host(output.second);
}
else {
output.first = Endian::le_to_host(output.first);
output.second = Endian::le_to_host(output.second);
}
return output;
}
};
}
/**
* \endcond
*/
/**
* \class PDUOption
* \brief Represents a PDU option field.
@@ -46,17 +296,13 @@ namespace Tins {
*
* The OptionType template parameter indicates the type that will be
* used to store this option's identifier.
*
* The Container template parameter indicates the container which will
* be used to store this option's data. The container <b>must</b>
* store data sequentially. std::vector<uint8_t> is the default
* container.
*/
template<typename OptionType, class Container = std::vector<uint8_t> >
template<typename OptionType, class PDUType>
class PDUOption {
private:
static const int small_buffer_size = 8;
public:
typedef Container container_type;
typedef typename container_type::value_type data_type;
typedef uint8_t data_type;
typedef OptionType option_type;
/**
@@ -66,8 +312,79 @@ public:
* \param data The option's data(if any).
*/
PDUOption(option_type opt = option_type(), size_t length = 0, const data_type *data = 0)
: option_(opt), size_(length), value_(data, data + (data ? length : 0)) {
: option_(opt), size_(length) {
set_payload_contents(data, data + (data ? length : 0));
}
/**
* \brief Copy constructor.
* \param rhs The PDUOption to be copied.
*/
PDUOption(const PDUOption& rhs) {
real_size_ = 0;
*this = rhs;
}
#if TINS_IS_CXX11
/**
* \brief Move constructor.
* \param rhs The PDUOption to be moved.
*/
PDUOption(PDUOption&& rhs) {
real_size_ = 0;
*this = std::move(rhs);
}
/**
* \brief Move assignment operator.
* \param rhs The PDUOption to be moved.
*/
PDUOption& operator=(PDUOption&& rhs) {
option_ = rhs.option_;
size_ = rhs.size_;
if(real_size_ > small_buffer_size) {
delete[] payload_.big_buffer_ptr;
}
real_size_ = rhs.real_size_;
if(real_size_ > small_buffer_size) {
payload_.big_buffer_ptr = nullptr;
std::swap(payload_.big_buffer_ptr, rhs.payload_.big_buffer_ptr);
rhs.real_size_ = 0;
}
else {
std::copy(
rhs.data_ptr(),
rhs.data_ptr() + rhs.data_size(),
payload_.small_buffer
);
}
return *this;
}
#endif // TINS_IS_CXX11
/**
* \brief Copy assignment operator.
* \param rhs The PDUOption to be copied.
*/
PDUOption& operator=(const PDUOption& rhs) {
option_ = rhs.option_;
size_ = rhs.size_;
if(real_size_ > small_buffer_size) {
delete[] payload_.big_buffer_ptr;
}
real_size_ = rhs.real_size_;
set_payload_contents(rhs.data_ptr(), rhs.data_ptr() + rhs.data_size());
return *this;
}
/**
* \brief Destructor.
*/
~PDUOption() {
if(real_size_ > small_buffer_size) {
delete[] payload_.big_buffer_ptr;
}
}
/**
@@ -80,8 +397,8 @@ public:
*/
template<typename ForwardIterator>
PDUOption(option_type opt, ForwardIterator start, ForwardIterator end)
: option_(opt), size_(std::distance(start, end)), value_(start, end) {
: option_(opt), size_(std::distance(start, end)) {
set_payload_contents(start, end);
}
/**
@@ -101,8 +418,8 @@ public:
*/
template<typename ForwardIterator>
PDUOption(option_type opt, size_t length, ForwardIterator start, ForwardIterator end)
: option_(opt), size_(length), value_(start, end) {
: option_(opt), size_(length) {
set_payload_contents(start, end);
}
/**
@@ -131,7 +448,9 @@ public:
* \return const data_type& containing this option's value.
*/
const data_type *data_ptr() const {
return &*value_.begin();
return real_size_ <= small_buffer_size ?
payload_.small_buffer :
payload_.big_buffer_ptr;
}
/**
@@ -140,7 +459,7 @@ public:
* This is the actual size of the data.
*/
size_t data_size() const {
return value_.size();
return real_size_;
}
/**
@@ -158,10 +477,45 @@ public:
size_t length_field() const {
return size_;
}
/**
* \brief Constructs a T from this PDUOption.
*
* Use this method to convert a PDUOption to the specific type that
* represents it. For example, if you know an option is of type
* PDU::SACK, you could use option.to<TCP::sack_type>().
*/
template<typename T>
T to() const {
return Internals::converter<T>::convert(*this);
}
private:
template<typename ForwardIterator>
void set_payload_contents(ForwardIterator start, ForwardIterator end) {
real_size_ = std::distance(start, end);
if(real_size_ <= small_buffer_size) {
std::copy(
start,
end,
payload_.small_buffer
);
}
else {
payload_.big_buffer_ptr = new data_type[real_size_];
std::copy(
start,
end,
payload_.big_buffer_ptr
);
}
}
option_type option_;
uint16_t size_;
container_type value_;
uint16_t size_, real_size_;
union {
data_type small_buffer[small_buffer_size];
data_type* big_buffer_ptr;
} payload_;
};
} // namespace Tins
#endif // TINS_PDU_OPTION_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -85,7 +85,7 @@ public:
* \return The stored length field value.
*/
uint16_t length() const {
return _header.length;
return Endian::le_to_host(_header.length);
}
/**
@@ -93,7 +93,7 @@ public:
* \return The stored Data Link Type field value.
*/
uint32_t dlt() const {
return _header.dlt;
return Endian::le_to_host(_header.dlt);
}
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -72,7 +72,7 @@ public:
/**
* The type used to store a TLV option.
*/
typedef PDUOption<TagTypes> tag;
typedef PDUOption<TagTypes, PPPoE> tag;
/**
* The type used to store the options.
@@ -90,6 +90,8 @@ public:
vendor_spec_type(uint32_t vendor_id = 0, const data_type &data = data_type())
: vendor_id(vendor_id), data(data) { }
static vendor_spec_type from_option(const tag &opt);
};
/**
@@ -397,19 +399,11 @@ private:
}
template<typename T>
T retrieve_tag_iterable(TagTypes id) const {
const tag *tag = search_tag(id);
if(!tag)
T search_and_convert(TagTypes id) const {
const tag *t = search_tag(id);
if(!t)
throw option_not_found();
return T(tag->data_ptr(), tag->data_ptr() + tag->data_size());
}
template<template <typename> class Functor>
const tag *safe_search_tag(TagTypes opt, uint32_t size) const {
const tag *option = search_tag(opt);
if(!option || Functor<uint32_t>()(option->data_size(), size))
throw option_not_found();
return option;
return t->to<T>();
}
TINS_BEGIN_PACK

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,7 +27,9 @@
*
*/
#ifndef TINS_RADIOTAP_H
#include "config.h"
#if !defined(TINS_RADIOTAP_H) && defined(HAVE_DOT11)
#define TINS_RADIOTAP_H
#include "macros.h"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -38,17 +38,10 @@
#include <stdexcept>
#include <iterator>
#include "pdu.h"
#include "ethernetII.h"
#include "radiotap.h"
#include "packet.h"
#include "loopback.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;
@@ -75,7 +68,7 @@ namespace Tins {
* \brief Move constructor.
* This constructor is available only in C++11.
*/
BaseSniffer(BaseSniffer &&rhs) noexcept
BaseSniffer(BaseSniffer &&rhs) NOEXCEPT
: handle(nullptr), mask()
{
*this = std::move(rhs);
@@ -85,7 +78,7 @@ namespace Tins {
* \brief Move assignment operator.
* This operator is available only in C++11.
*/
BaseSniffer& operator=(BaseSniffer &&rhs) noexcept
BaseSniffer& operator=(BaseSniffer &&rhs) NOEXCEPT
{
using std::swap;
swap(handle, rhs.handle);
@@ -199,6 +192,30 @@ namespace Tins {
*/
int get_fd();
/**
* \brief Sets the read timeout for this sniffer.
*
* This calls pcap_set_timeout using the provided parameter.
* \param ms The amount of milliseconds.
*/
void set_timeout(int ms);
/**
* \brief Sets whether to extract RawPDUs or fully parsed packets.
*
* By default, packets will be parsed starting from link layer.
* However, if you're parsing a lot of traffic, then you might
* want to extract packets and push them into a queue,
* so a consumer can parse them when they're popped.
*
* This method allows doing that. If the parameter is true,
* then packets taken from this BaseSniffer will only contain
* a RawPDU which will have to entire contents of the packet.
*
* \param value Whether to extract RawPDUs or not.
*/
void set_extract_raw_pdus(bool value);
/**
* \brief Retrieves this sniffer's link type.
*
@@ -238,6 +255,7 @@ namespace Tins {
pcap_t *handle;
bpf_u_int32 mask;
bool extract_raw;
};
/**
@@ -246,15 +264,42 @@ namespace Tins {
*/
class Sniffer : public BaseSniffer {
public:
enum promisc_type {
NON_PROMISC,
PROMISC
};
/**
* \brief Constructs an instance of Sniffer.
* Constructs an instance of Sniffer.
*
* By default the interface won't be put into promiscuous mode, and won't
* be put into monitor mode.
*
* \param device The device which will be sniffed.
* \param max_packet_size The maximum packet size to be read.
* \param promisc bool indicating wether to put the interface in promiscuous mode.(optional)
* \param filter A capture filter to be used on the sniffing session.(optional);
* \param rfmon Indicates if the interface should be put in monitor mode.(optional);
*/
Sniffer(const std::string &device, unsigned max_packet_size,
bool promisc = false, const std::string &filter = "");
bool promisc = false, const std::string &filter = "", bool rfmon = false);
/**
* \brief Constructs an instance of Sniffer.
*
* The maximum capture size is set to 65535. By default the interface won't
* be put into promiscuous mode, and won't be put into monitor mode.
*
* \param device The device which will be sniffed.
* \param promisc Indicates if the interface should be put in promiscuous mode.
* \param filter A capture filter to be used on the sniffing session.(optional);
* \param rfmon Indicates if the interface should be put in monitor mode.(optional);
*/
Sniffer(const std::string &device, promisc_type promisc = NON_PROMISC,
const std::string &filter = "", bool rfmon = false);
private:
void init_sniffer(const std::string &device, unsigned max_packet_size,
bool promisc = false, const std::string &filter = "", bool rfmon = false);
};
/**

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -102,7 +102,7 @@ namespace Tins {
/**
* The type used to store TCP options.
*/
typedef PDUOption<uint8_t> option;
typedef PDUOption<uint8_t, TCP> option;
/**
* The type used to store the options.
@@ -409,6 +409,20 @@ namespace Tins {
internal_add_option(opt);
_options.push_back(std::move(opt));
}
/**
* \brief Adds a TCP option using the provided arguments.
*
* The option is constructed from the provided parameters.
*
* \param args The arguments to be used in the option's
* constructor.
*/
template<typename... Args>
void add_option(Args&&... args) {
_options.emplace_back(std::forward<Args>(args)...);
internal_add_option(_options.back());
}
#endif
/**
@@ -490,11 +504,11 @@ namespace Tins {
static const uint16_t DEFAULT_WINDOW;
template<class T>
T generic_search(OptionTypes opt) const {
const option *option = search_option(opt);
if(option && option->data_size() == sizeof(T))
return *(const T*)(&option->data_ptr()[0]);
throw option_not_found();
T generic_search(OptionTypes opt_type) const {
const option *opt = search_option(opt_type);
if(!opt)
throw option_not_found();
return opt->to<T>();
}
void internal_add_option(const option &option);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -185,7 +185,9 @@ private:
static fragments_type clone_fragments(const fragments_type &frags);
bool generic_process(uint32_t &my_seq, uint32_t &other_seq,
payload_type &pload, fragments_type &frags, TCP *tcp, RawPDU *raw);
payload_type &pload, fragments_type &frags, TCP *tcp);
void safe_insert(fragments_type &frags, uint32_t seq, RawPDU *raw);
uint32_t client_seq, server_seq;
@@ -298,11 +300,6 @@ private:
EndFunctor end_fun;
};
void clear_state() {
sessions.clear();
last_identifier = 0;
}
template<typename DataFunctor, typename EndFunctor>
bool callback(PDU &pdu, const DataFunctor &fun, const EndFunctor &end_fun);
static void dummy_function(TCPStream&) { }
@@ -315,7 +312,6 @@ template<typename DataFunctor, typename EndFunctor>
void TCPStreamFollower::follow_streams(BaseSniffer &sniffer, DataFunctor data_fun, EndFunctor end_fun) {
typedef proxy_caller<DataFunctor, EndFunctor> proxy_type;
proxy_type proxy = { this, data_fun, end_fun };
clear_state();
sniffer.sniff_loop(make_sniffer_handler(&proxy, &proxy_type::callback));
}
@@ -323,7 +319,6 @@ template<typename ForwardIterator, typename DataFunctor, typename EndFunctor>
void TCPStreamFollower::follow_streams(ForwardIterator start, ForwardIterator end,
DataFunctor data_fun, EndFunctor end_fun)
{
clear_state();
while(start != end) {
if(!callback(Utils::dereference_until_pdu(start), data_fun, end_fun))
return;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,6 @@
#define TINS_TIMESTAMP_H
#ifdef WIN32
#define NOMINMAX
#include <winsock2.h>
#else
#include <sys/time.h>
@@ -73,6 +72,22 @@ public:
* Default constructs the timestamp.
*/
Timestamp() : tv() {}
#if TINS_IS_CXX11
/**
* Constructs a Timestamp from a std::chrono::duration.
*/
template<typename Rep, typename Period>
Timestamp(const std::chrono::duration<Rep, Period>& ts) {
using std::chrono::duration_cast;
using std::chrono::microseconds;
using std::chrono::seconds;
tv.tv_sec = duration_cast<seconds>(ts).count();
tv.tv_usec = duration_cast<microseconds>(
ts - seconds(tv.tv_sec)).count();
}
#endif
/**
* Constructs a timestamp from a timeval object.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -70,5 +70,8 @@
#include "handshake_capturer.h"
#include "address_range.h"
#include "pdu_allocator.h"
#include "ipsec.h"
#include "ip_reassembler.h"
#include "ppi.h"
#endif // TINS_TINS_H

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,7 +33,6 @@
#ifndef WIN32
#include <ifaddrs.h>
#else
#define NOMINMAX
#include <winsock2.h>
#include <iphlpapi.h>
#undef interface
@@ -168,13 +167,20 @@ namespace Tins {
/**
* \brief Retrieves entries int the routing table.
* \brief Retrieves entries in the routing table.
*
* \brief output ForwardIterator in which entries will be stored.
*/
template<class ForwardIterator>
void route_entries(ForwardIterator output);
/**
* \brief Retrieves entries in the routing table.
*
* \return a vector which contains all of the route entries.
*/
std::vector<RouteEntry> route_entries();
/** \brief Returns the 32 bit crc of the given buffer.
*
* \param data The input buffer.
@@ -191,10 +197,17 @@ namespace Tins {
/**
* \brief Converts mhz units to the appropriate channel number.
* \param channel The mhz units to be converted.
* \param mhz The mhz units to be converted.
* \return The channel number.
*/
uint16_t mhz_to_channel(uint16_t mhz);
/**
* \brief Converts a PDUType to a string.
* \param pduType The PDUType to be converted.
* \return A string representation, for example "DOT11_QOS_DATA".
*/
std::string to_string(PDU::PDUType pduType);
/** \brief Does the 16 bits sum of all 2 bytes elements between start and end.
*

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,6 +28,9 @@
*/
#include "crypto.h"
#ifdef HAVE_DOT11
#ifdef HAVE_WPA2_DECRYPTION
#include <openssl/evp.h>
#include <openssl/hmac.h>
@@ -419,7 +422,7 @@ SNAP *SessionKeys::tkip_decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) con
return new SNAP(&pload[0], pload.size() - 20);
}
SNAP *SessionKeys::SessionKeys::decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const {
SNAP *SessionKeys::decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const {
return is_ccmp ?
ccmp_decrypt_unicast(dot11, raw) :
tkip_decrypt_unicast(dot11, raw);
@@ -542,3 +545,5 @@ bool WPA2Decrypter::decrypt(PDU &pdu) {
#endif // HAVE_WPA2_DECRYPTION
} // namespace Crypto
} // namespace Tins
#endif // HAVE_DOT11

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,6 +29,7 @@
#include <stdexcept>
#include <cassert>
#include <cstring>
#include "endianness.h"
#include "dhcp.h"
#include "ethernetII.h"
@@ -52,7 +53,9 @@ DHCP::DHCP(const uint8_t *buffer, uint32_t total_sz)
buffer += BootP::header_size() - vend().size();
total_sz -= BootP::header_size() - vend().size();
uint8_t args[2] = {0};
if(total_sz < sizeof(uint32_t) || *(uint32_t*)buffer != Endian::host_to_be<uint32_t>(0x63825363))
uint32_t uint32_t_buffer;
std::memcpy(&uint32_t_buffer, buffer, sizeof(uint32_t));
if(total_sz < sizeof(uint32_t) || uint32_t_buffer != Endian::host_to_be<uint32_t>(0x63825363))
throw malformed_packet();
buffer += sizeof(uint32_t);
total_sz -= sizeof(uint32_t);
@@ -104,7 +107,7 @@ void DHCP::end() {
}
uint8_t DHCP::type() const {
return generic_search(DHCP_MESSAGE_TYPE, type2type<uint8_t>());
return search_and_convert<uint8_t>(DHCP_MESSAGE_TYPE);
}
void DHCP::server_identifier(ipaddress_type ip) {
@@ -113,7 +116,7 @@ void DHCP::server_identifier(ipaddress_type ip) {
}
DHCP::ipaddress_type DHCP::server_identifier() const {
return generic_search(DHCP_SERVER_IDENTIFIER, type2type<ipaddress_type>());
return search_and_convert<ipaddress_type>(DHCP_SERVER_IDENTIFIER);
}
void DHCP::lease_time(uint32_t time) {
@@ -122,7 +125,7 @@ void DHCP::lease_time(uint32_t time) {
}
uint32_t DHCP::lease_time() const {
return Endian::host_to_be(generic_search(DHCP_LEASE_TIME, type2type<uint32_t>()));
return search_and_convert<uint32_t>(DHCP_LEASE_TIME);
}
void DHCP::renewal_time(uint32_t time) {
@@ -131,7 +134,7 @@ void DHCP::renewal_time(uint32_t time) {
}
uint32_t DHCP::renewal_time() const {
return Endian::host_to_be(generic_search(DHCP_RENEWAL_TIME, type2type<uint32_t>()));
return search_and_convert<uint32_t>(DHCP_RENEWAL_TIME);
}
void DHCP::subnet_mask(ipaddress_type mask) {
@@ -140,25 +143,25 @@ void DHCP::subnet_mask(ipaddress_type mask) {
}
DHCP::ipaddress_type DHCP::subnet_mask() const {
return generic_search(SUBNET_MASK, type2type<ipaddress_type>());
return search_and_convert<ipaddress_type>(SUBNET_MASK);
}
void DHCP::routers(const list<ipaddress_type> &routers) {
void DHCP::routers(const std::vector<ipaddress_type> &routers) {
serialization_type buffer = serialize_list(routers);
add_option(option(ROUTERS, buffer.begin(), buffer.end()));
}
std::list<DHCP::ipaddress_type> DHCP::routers() const {
return generic_search(ROUTERS, type2type<std::list<ipaddress_type> >());
std::vector<DHCP::ipaddress_type> DHCP::routers() const {
return search_and_convert<std::vector<DHCP::ipaddress_type> >(ROUTERS);
}
void DHCP::domain_name_servers(const list<ipaddress_type> &dns) {
void DHCP::domain_name_servers(const std::vector<ipaddress_type> &dns) {
serialization_type buffer = serialize_list(dns);
add_option(option(DOMAIN_NAME_SERVERS, buffer.begin(), buffer.end()));
}
std::list<DHCP::ipaddress_type> DHCP::domain_name_servers() const {
return generic_search(DOMAIN_NAME_SERVERS, type2type<std::list<ipaddress_type> >());
std::vector<DHCP::ipaddress_type> DHCP::domain_name_servers() const {
return search_and_convert<std::vector<DHCP::ipaddress_type> >(DOMAIN_NAME_SERVERS);
}
void DHCP::broadcast(ipaddress_type addr) {
@@ -167,7 +170,7 @@ void DHCP::broadcast(ipaddress_type addr) {
}
DHCP::ipaddress_type DHCP::broadcast() const {
return generic_search(BROADCAST_ADDRESS, type2type<ipaddress_type>());
return search_and_convert<ipaddress_type>(BROADCAST_ADDRESS);
}
void DHCP::requested_ip(ipaddress_type addr) {
@@ -176,7 +179,7 @@ void DHCP::requested_ip(ipaddress_type addr) {
}
DHCP::ipaddress_type DHCP::requested_ip() const {
return generic_search(DHCP_REQUESTED_ADDRESS, type2type<ipaddress_type>());
return search_and_convert<ipaddress_type>(DHCP_REQUESTED_ADDRESS);
}
void DHCP::domain_name(const string &name) {
@@ -184,7 +187,15 @@ void DHCP::domain_name(const string &name) {
}
std::string DHCP::domain_name() const {
return generic_search(DOMAIN_NAME, type2type<std::string>());
return search_and_convert<std::string>(DOMAIN_NAME);
}
void DHCP::hostname(const std::string &name) {
add_option(option(HOST_NAME, name.size(), (const uint8_t*)name.c_str()));
}
std::string DHCP::hostname() const {
return search_and_convert<std::string>(HOST_NAME);
}
void DHCP::rebind_time(uint32_t time) {
@@ -193,13 +204,13 @@ void DHCP::rebind_time(uint32_t time) {
}
uint32_t DHCP::rebind_time() const {
return Endian::host_to_be(generic_search(DHCP_REBINDING_TIME, type2type<uint32_t>()));
return search_and_convert<uint32_t>(DHCP_REBINDING_TIME);
}
PDU::serialization_type DHCP::serialize_list(const list<ipaddress_type> &ip_list) {
PDU::serialization_type DHCP::serialize_list(const std::vector<ipaddress_type> &ip_list) {
serialization_type buffer(ip_list.size() * sizeof(uint32_t));
uint32_t *ptr = (uint32_t*)&buffer[0];
for(list<ipaddress_type>::const_iterator it = ip_list.begin(); it != ip_list.end(); ++it)
for(std::vector<ipaddress_type>::const_iterator it = ip_list.begin(); it != ip_list.end(); ++it)
*(ptr++) = *it;
return buffer;
}
@@ -227,31 +238,4 @@ void DHCP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *pa
}
BootP::write_serialization(buffer, total_sz, parent);
}
std::list<DHCP::ipaddress_type> DHCP::generic_search(OptionTypes opt_type, type2type<std::list<ipaddress_type> >) const {
const option *opt = search_option(opt_type);
if(!opt)
throw option_not_found();
const uint32_t *ptr = (const uint32_t*)opt->data_ptr();
uint32_t len = opt->data_size();
if((len % sizeof(uint32_t)) != 0)
throw option_not_found();
std::list<ipaddress_type> container;
while(len) {
container.push_back(ipaddress_type(*(ptr++)));
len -= sizeof(uint32_t);
}
return container;
}
std::string DHCP::generic_search(OptionTypes opt_type, type2type<std::string>) const {
const option *opt = search_option(opt_type);
if(!opt)
throw option_not_found();
return string(opt->data_ptr(), opt->data_ptr() + opt->data_size());
}
DHCP::ipaddress_type DHCP::generic_search(OptionTypes opt, type2type<ipaddress_type>) const {
return ipaddress_type(generic_search(opt, type2type<uint32_t>()));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -63,10 +63,12 @@ DHCPv6::DHCPv6(const uint8_t *buffer, uint32_t total_sz)
if(total_sz < sizeof(uint16_t) * 2)
throw malformed_packet();
const uint16_t opt = Endian::be_to_host(*(const uint16_t*)buffer);
const uint16_t data_size = Endian::be_to_host(
*(const uint16_t*)(buffer + sizeof(uint16_t))
);
uint16_t opt;
std::memcpy(&opt, buffer, sizeof(uint16_t));
opt = Endian::be_to_host(opt);
uint16_t data_size;
std::memcpy(&data_size, buffer + sizeof(uint16_t), sizeof(uint16_t));
data_size = Endian::be_to_host(data_size);
if(total_sz - sizeof(uint16_t) * 2 < data_size)
throw malformed_packet();
buffer += sizeof(uint16_t) * 2;
@@ -91,8 +93,10 @@ const DHCPv6::option *DHCPv6::search_option(OptionTypes id) const {
}
uint8_t* DHCPv6::write_option(const option &opt, uint8_t* buffer) const {
*(uint16_t*)buffer = Endian::host_to_be(opt.option());
*(uint16_t*)&buffer[sizeof(uint16_t)] = Endian::host_to_be<uint16_t>(opt.length_field());
uint16_t uint16_t_buffer = Endian::host_to_be(opt.option());
std::memcpy(buffer, &uint16_t_buffer, sizeof(uint16_t));
uint16_t_buffer = Endian::host_to_be<uint16_t>(opt.length_field());
std::memcpy(&buffer[sizeof(uint16_t)], &uint16_t_buffer, sizeof(uint16_t));
return std::copy(
opt.data_ptr(),
opt.data_ptr() + opt.data_size(),
@@ -157,121 +161,43 @@ void DHCPv6::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *
// ********************************************************************
DHCPv6::ia_na_type DHCPv6::ia_na() const {
const option *opt = safe_search_option<std::less>(
IA_NA, sizeof(uint32_t) * 3
);
const uint8_t *ptr = opt->data_ptr() + sizeof(uint32_t) * 3;
const uint32_t *ptr_32 = (const uint32_t*)opt->data_ptr();
DHCPv6::ia_na_type output;
output.id = Endian::be_to_host(*ptr_32++);
output.t1 = Endian::be_to_host(*ptr_32++);
output.t2 = Endian::be_to_host(*ptr_32++);
output.options.assign(ptr, opt->data_ptr() + opt->data_size());
return output;
return search_and_convert<ia_na_type>(IA_NA);
}
DHCPv6::ia_ta_type DHCPv6::ia_ta() const {
const option *opt = safe_search_option<std::less>(
IA_TA, sizeof(uint32_t)
);
const uint8_t *ptr = opt->data_ptr() + sizeof(uint32_t);
const uint32_t *ptr_32 = (const uint32_t*)opt->data_ptr();
DHCPv6::ia_ta_type output;
output.id = Endian::be_to_host(*ptr_32++);
output.options.assign(ptr, opt->data_ptr() + opt->data_size());
return output;
return search_and_convert<ia_ta_type>(IA_TA);
}
DHCPv6::ia_address_type DHCPv6::ia_address() const {
const option *opt = safe_search_option<std::less>(
IA_ADDR, sizeof(uint32_t) * 2 + ipaddress_type::address_size
);
const uint8_t *ptr = opt->data_ptr() + sizeof(uint32_t) * 2 + ipaddress_type::address_size;
const uint32_t *ptr_32 = (const uint32_t*)(opt->data_ptr() + ipaddress_type::address_size);
DHCPv6::ia_address_type output;
output.address = opt->data_ptr();
output.preferred_lifetime = Endian::be_to_host(*ptr_32++);
output.valid_lifetime = Endian::be_to_host(*ptr_32++);
output.options.assign(ptr, opt->data_ptr() + opt->data_size());
return output;
return search_and_convert<ia_address_type>(IA_ADDR);
}
DHCPv6::option_request_type DHCPv6::option_request() const {
const option *opt = safe_search_option<std::less>(
OPTION_REQUEST, 2
);
const uint16_t *ptr = (const uint16_t*)opt->data_ptr(),
*end = (const uint16_t*)(opt->data_ptr() + opt->data_size());
option_request_type output;
while(ptr < end) {
output.push_back(
static_cast<OptionTypes>(Endian::be_to_host(*ptr++))
);
}
return output;
return search_and_convert<option_request_type>(OPTION_REQUEST);
}
uint8_t DHCPv6::preference() const {
const option *opt = safe_search_option<std::not_equal_to>(
PREFERENCE, 1
);
return *opt->data_ptr();
return search_and_convert<uint8_t>(PREFERENCE);
}
uint16_t DHCPv6::elapsed_time() const {
const option *opt = safe_search_option<std::not_equal_to>(
ELAPSED_TIME, 2
);
return Endian::be_to_host(
*(const uint16_t*)opt->data_ptr()
);
return search_and_convert<uint16_t>(ELAPSED_TIME);
}
DHCPv6::relay_msg_type DHCPv6::relay_message() const {
const option *opt = safe_search_option<std::less>(
RELAY_MSG, 1
);
return relay_msg_type(
opt->data_ptr(),
opt->data_ptr() + opt->data_size()
);
return search_and_convert<relay_msg_type>(RELAY_MSG);
}
DHCPv6::authentication_type DHCPv6::authentication() const {
const option *opt = safe_search_option<std::less>(
AUTH, sizeof(uint8_t) * 3 + sizeof(uint64_t)
);
const uint8_t *ptr = opt->data_ptr();
authentication_type output;
output.protocol = *ptr++;
output.algorithm = *ptr++;
output.rdm = *ptr++;
output.replay_detection = Endian::be_to_host(
*(const uint64_t*)ptr
);
ptr += sizeof(uint64_t);
output.auth_info.assign(ptr, opt->data_ptr() + opt->data_size());
return output;
return search_and_convert<authentication_type>(AUTH);
}
DHCPv6::ipaddress_type DHCPv6::server_unicast() const {
const option *opt = safe_search_option<std::not_equal_to>(
UNICAST, ipaddress_type::address_size
);
return ipaddress_type(opt->data_ptr());
return search_and_convert<ipaddress_type>(UNICAST);
}
DHCPv6::status_code_type DHCPv6::status_code() const {
const option *opt = safe_search_option<std::less>(
STATUS_CODE, sizeof(uint16_t)
);
status_code_type output;
output.code = Endian::be_to_host(*(const uint16_t*)opt->data_ptr());
output.message.assign(
opt->data_ptr() + sizeof(uint16_t),
opt->data_ptr() + opt->data_size()
);
return output;
return search_and_convert<status_code_type>(STATUS_CODE);
}
bool DHCPv6::has_rapid_commit() const {
@@ -279,60 +205,23 @@ bool DHCPv6::has_rapid_commit() const {
}
DHCPv6::user_class_type DHCPv6::user_class() const {
const option *opt = safe_search_option<std::less>(
USER_CLASS, sizeof(uint16_t)
);
return option2class_option_data<user_class_type>(
opt->data_ptr(), opt->data_size()
);
return search_and_convert<user_class_type>(USER_CLASS);
}
DHCPv6::vendor_class_type DHCPv6::vendor_class() const {
const option *opt = safe_search_option<std::less>(
VENDOR_CLASS, sizeof(uint32_t)
);
typedef vendor_class_type::class_data_type data_type;
vendor_class_type output;
output.enterprise_number = Endian::be_to_host(
*(const uint32_t*)opt->data_ptr()
);
output.vendor_class_data = option2class_option_data<data_type>(
opt->data_ptr() + sizeof(uint32_t),
opt->data_size() - sizeof(uint32_t)
);
return output;
return search_and_convert<vendor_class_type>(VENDOR_CLASS);
}
DHCPv6::vendor_info_type DHCPv6::vendor_info() const {
const option *opt = safe_search_option<std::less>(
VENDOR_OPTS, sizeof(uint32_t)
);
vendor_info_type output;
output.enterprise_number = Endian::be_to_host(
*(const uint32_t*)opt->data_ptr()
);
output.data.assign(
opt->data_ptr() + sizeof(uint32_t),
opt->data_ptr() + opt->data_size()
);
return output;
return search_and_convert<vendor_info_type>(VENDOR_OPTS);
}
DHCPv6::interface_id_type DHCPv6::interface_id() const {
const option *opt = safe_search_option<std::equal_to>(
INTERFACE_ID, 0
);
return interface_id_type(
opt->data_ptr(),
opt->data_ptr() + opt->data_size()
);
return search_and_convert<interface_id_type>(INTERFACE_ID);
}
uint8_t DHCPv6::reconfigure_msg() const {
return *safe_search_option<std::not_equal_to>(
RECONF_MSG, 1
)->data_ptr();
return search_and_convert<uint8_t>(RECONF_MSG);
}
bool DHCPv6::has_reconfigure_accept() const {
@@ -340,29 +229,11 @@ bool DHCPv6::has_reconfigure_accept() const {
}
DHCPv6::duid_type DHCPv6::client_id() const {
const option *opt = safe_search_option<std::less>(
CLIENTID, sizeof(uint16_t) + 1
);
return duid_type(
Endian::be_to_host(*(const uint16_t*)opt->data_ptr()),
serialization_type(
opt->data_ptr() + sizeof(uint16_t),
opt->data_ptr() + opt->data_size()
)
);
return search_and_convert<duid_type>(CLIENTID);
}
DHCPv6::duid_type DHCPv6::server_id() const {
const option *opt = safe_search_option<std::less>(
SERVERID, sizeof(uint16_t) + 1
);
return duid_type(
Endian::be_to_host(*(const uint16_t*)opt->data_ptr()),
serialization_type(
opt->data_ptr() + sizeof(uint16_t),
opt->data_ptr() + opt->data_size()
)
);
return search_and_convert<duid_type>(SERVERID);
}
// ********************************************************************
@@ -422,8 +293,11 @@ void DHCPv6::option_request(const option_request_type &value) {
std::vector<uint8_t> buffer(value.size() * sizeof(uint16_t));
size_t index = 0;
for(iterator it = value.begin(); it != value.end(); ++it, index += 2)
*(uint16_t*)&buffer[index] = Endian::host_to_be<uint16_t>(*it);
uint16_t uint16_t_buffer;
for(iterator it = value.begin(); it != value.end(); ++it, index += 2) {
uint16_t_buffer = Endian::host_to_be<uint16_t>(*it);
std::memcpy(&buffer[index], &uint16_t_buffer, sizeof(uint16_t));
}
add_option(
option(OPTION_REQUEST, buffer.begin(), buffer.end())
);
@@ -455,7 +329,8 @@ void DHCPv6::authentication(const authentication_type &value) {
buffer[0] = value.protocol;
buffer[1] = value.algorithm;
buffer[2] = value.rdm;
*(uint64_t*)&buffer[3] = Endian::host_to_be(value.replay_detection);
uint64_t uint64_t_buffer = Endian::host_to_be(value.replay_detection);
std::memcpy(&buffer[3], &uint64_t_buffer, sizeof(uint64_t));
std::copy(
value.auth_info.begin(),
value.auth_info.end(),
@@ -474,7 +349,8 @@ void DHCPv6::server_unicast(const ipaddress_type &value) {
void DHCPv6::status_code(const status_code_type &value) {
std::vector<uint8_t> buffer(sizeof(uint16_t) + value.message.size());
*(uint16_t*)&buffer[0] = Endian::host_to_be(value.code);
uint16_t uint16_t_buffer = Endian::host_to_be(value.code);
std::memcpy(&buffer[0], &uint16_t_buffer, sizeof(uint16_t));
std::copy(
value.message.begin(),
value.message.end(),
@@ -492,10 +368,10 @@ void DHCPv6::rapid_commit() {
}
void DHCPv6::user_class(const user_class_type &value) {
typedef user_class_type::const_iterator iterator;
typedef user_class_type::data_type::const_iterator iterator;
std::vector<uint8_t> buffer;
class_option_data2option(value.begin(), value.end(), buffer);
Internals::class_option_data2option(value.data.begin(), value.data.end(), buffer);
add_option(
option(USER_CLASS, buffer.begin(), buffer.end())
);
@@ -505,8 +381,9 @@ void DHCPv6::vendor_class(const vendor_class_type &value) {
std::vector<uint8_t> buffer(
sizeof(uint32_t)
);
*(uint32_t*)&buffer[0] = Endian::host_to_be(value.enterprise_number);
class_option_data2option(
uint32_t enterprise_number = Endian::host_to_be(value.enterprise_number);
std::memcpy(&buffer[0], &enterprise_number, sizeof(uint32_t));
Internals::class_option_data2option(
value.vendor_class_data.begin(),
value.vendor_class_data.end(),
buffer,
@@ -519,7 +396,8 @@ void DHCPv6::vendor_class(const vendor_class_type &value) {
void DHCPv6::vendor_info(const vendor_info_type &value) {
std::vector<uint8_t> buffer(sizeof(uint32_t) + value.data.size());
*(uint32_t*)&buffer[0] = Endian::host_to_be(value.enterprise_number);
uint32_t enterprise_number = Endian::host_to_be(value.enterprise_number);
std::memcpy(&buffer[0], &enterprise_number, sizeof(uint32_t));
std::copy(
value.data.begin(),
value.data.end(),
@@ -555,9 +433,11 @@ DHCPv6::duid_llt DHCPv6::duid_llt::from_bytes(const uint8_t *buffer, uint32_t to
if(total_sz < sizeof(uint16_t) + sizeof(uint32_t) + 1)
throw std::runtime_error("Not enough size for a DUID_LLT identifier");
duid_llt output;
output.hw_type = Endian::be_to_host(*(const uint16_t*)buffer);
std::memcpy(&output.hw_type, buffer, sizeof(uint16_t));
output.hw_type = Endian::be_to_host(output.hw_type);
buffer += sizeof(uint16_t);
output.time = Endian::be_to_host(*(const uint32_t*)buffer);
std::memcpy(&output.time, buffer, sizeof(uint32_t));
output.time = Endian::be_to_host(output.time);
buffer += sizeof(uint32_t);
total_sz -= sizeof(uint16_t) + sizeof(uint32_t);
output.lladdress.assign(buffer, buffer + total_sz);
@@ -566,8 +446,10 @@ DHCPv6::duid_llt DHCPv6::duid_llt::from_bytes(const uint8_t *buffer, uint32_t to
PDU::serialization_type DHCPv6::duid_llt::serialize() const {
serialization_type output(sizeof(uint16_t) + sizeof(uint32_t) + lladdress.size());
*(uint16_t*)&output[0] = Endian::host_to_be(hw_type);
*(uint32_t*)&output[sizeof(uint16_t)] = Endian::host_to_be(time);
uint16_t tmp_hw_type = Endian::host_to_be(hw_type);
uint32_t tmp_time = Endian::host_to_be(time);
std::memcpy(&output[0], &tmp_hw_type, sizeof(uint16_t));
std::memcpy(&output[sizeof(uint16_t)], &tmp_time, sizeof(uint32_t));
std::copy(
lladdress.begin(),
lladdress.end(),
@@ -582,7 +464,8 @@ DHCPv6::duid_en DHCPv6::duid_en::from_bytes(const uint8_t *buffer, uint32_t tota
if(total_sz < sizeof(uint32_t) + 1)
throw std::runtime_error("Not enough size for a DUID_en identifier");
duid_en output;
output.enterprise_number = Endian::be_to_host(*(const uint32_t*)buffer);
std::memcpy(&output.enterprise_number, buffer, sizeof(uint32_t));
output.enterprise_number = Endian::be_to_host(output.enterprise_number);
buffer += sizeof(uint32_t);
total_sz -= sizeof(uint32_t);
output.identifier.assign(buffer, buffer + total_sz);
@@ -591,7 +474,8 @@ DHCPv6::duid_en DHCPv6::duid_en::from_bytes(const uint8_t *buffer, uint32_t tota
PDU::serialization_type DHCPv6::duid_en::serialize() const {
serialization_type output(sizeof(uint32_t) + identifier.size());
*(uint32_t*)&output[0] = Endian::host_to_be(enterprise_number);
uint32_t tmp_enterprise_number = Endian::host_to_be(enterprise_number);
std::memcpy(&output[0], &tmp_enterprise_number, sizeof(uint32_t));
std::copy(
identifier.begin(),
identifier.end(),
@@ -606,7 +490,8 @@ DHCPv6::duid_ll DHCPv6::duid_ll::from_bytes(const uint8_t *buffer, uint32_t tota
if(total_sz < sizeof(uint16_t) + 1)
throw std::runtime_error("Not enough size for a DUID_en identifier");
duid_ll output;
output.hw_type = Endian::be_to_host(*(const uint16_t*)buffer);
std::memcpy(&output.hw_type, buffer, sizeof(uint16_t));
output.hw_type = Endian::be_to_host(output.hw_type);
buffer += sizeof(uint16_t);
total_sz -= sizeof(uint16_t);
output.lladdress.assign(buffer, buffer + total_sz);
@@ -615,7 +500,8 @@ DHCPv6::duid_ll DHCPv6::duid_ll::from_bytes(const uint8_t *buffer, uint32_t tota
PDU::serialization_type DHCPv6::duid_ll::serialize() const {
serialization_type output(sizeof(uint16_t) + lladdress.size());
*(uint16_t*)&output[0] = Endian::host_to_be(hw_type);
uint16_t tmp_hw_type = Endian::host_to_be(hw_type);
std::memcpy(&output[0], &tmp_hw_type, sizeof(uint16_t));
std::copy(
lladdress.begin(),
lladdress.end(),
@@ -626,7 +512,8 @@ PDU::serialization_type DHCPv6::duid_ll::serialize() const {
void DHCPv6::client_id(const duid_type &value) {
serialization_type buffer(sizeof(uint16_t) + value.data.size());
*(uint16_t*)&buffer[0] = Endian::host_to_be(value.id);
uint16_t tmp_id = Endian::host_to_be(value.id);
std::memcpy(&buffer[0], &tmp_id, sizeof(uint16_t));
std::copy(
value.data.begin(),
value.data.end(),
@@ -639,7 +526,8 @@ void DHCPv6::client_id(const duid_type &value) {
void DHCPv6::server_id(const duid_type &value) {
serialization_type buffer(sizeof(uint16_t) + value.data.size());
*(uint16_t*)&buffer[0] = Endian::host_to_be(value.id);
uint16_t tmp_id = Endian::host_to_be(value.id);
std::memcpy(&buffer[0], &tmp_id, sizeof(uint16_t));
std::copy(
value.data.begin(),
value.data.end(),
@@ -650,4 +538,132 @@ void DHCPv6::server_id(const duid_type &value) {
);
}
// Options
DHCPv6::ia_na_type DHCPv6::ia_na_type::from_option(const option &opt)
{
if(opt.data_size() < sizeof(uint32_t) * 3)
throw malformed_option();
const uint8_t *ptr = opt.data_ptr() + sizeof(uint32_t) * 3;
const uint32_t *ptr_32 = (const uint32_t*)opt.data_ptr();
DHCPv6::ia_na_type output;
output.id = Endian::be_to_host(*ptr_32++);
output.t1 = Endian::be_to_host(*ptr_32++);
output.t2 = Endian::be_to_host(*ptr_32++);
output.options.assign(ptr, opt.data_ptr() + opt.data_size());
return output;
}
DHCPv6::ia_ta_type DHCPv6::ia_ta_type::from_option(const option &opt)
{
if(opt.data_size() < sizeof(uint32_t))
throw malformed_option();
const uint8_t *ptr = opt.data_ptr() + sizeof(uint32_t);
const uint32_t *ptr_32 = (const uint32_t*)opt.data_ptr();
DHCPv6::ia_ta_type output;
output.id = Endian::be_to_host(*ptr_32++);
output.options.assign(ptr, opt.data_ptr() + opt.data_size());
return output;
}
DHCPv6::ia_address_type DHCPv6::ia_address_type::from_option(const option &opt)
{
if(opt.data_size() < sizeof(uint32_t) * 2 + DHCPv6::ipaddress_type::address_size)
throw malformed_option();
const uint8_t *ptr = opt.data_ptr() + sizeof(uint32_t) * 2 + ipaddress_type::address_size;
const uint32_t *ptr_32 = (const uint32_t*)(opt.data_ptr() + ipaddress_type::address_size);
DHCPv6::ia_address_type output;
output.address = opt.data_ptr();
output.preferred_lifetime = Endian::be_to_host(*ptr_32++);
output.valid_lifetime = Endian::be_to_host(*ptr_32++);
output.options.assign(ptr, opt.data_ptr() + opt.data_size());
return output;
}
DHCPv6::authentication_type DHCPv6::authentication_type::from_option(const option &opt)
{
if(opt.data_size() < sizeof(uint8_t) * 3 + sizeof(uint64_t))
throw malformed_option();
const uint8_t *ptr = opt.data_ptr();
authentication_type output;
output.protocol = *ptr++;
output.algorithm = *ptr++;
output.rdm = *ptr++;
std::memcpy(&output.replay_detection, ptr, sizeof(uint64_t));
output.replay_detection = Endian::be_to_host(output.replay_detection);
ptr += sizeof(uint64_t);
output.auth_info.assign(ptr, opt.data_ptr() + opt.data_size());
return output;
}
DHCPv6::status_code_type DHCPv6::status_code_type::from_option(const option &opt)
{
if(opt.data_size() < sizeof(uint16_t))
throw malformed_option();
status_code_type output;
std::memcpy(&output.code, opt.data_ptr(), sizeof(uint16_t));
output.code = Endian::be_to_host(output.code);
output.message.assign(
opt.data_ptr() + sizeof(uint16_t),
opt.data_ptr() + opt.data_size()
);
return output;
}
DHCPv6::vendor_info_type DHCPv6::vendor_info_type::from_option(const option &opt)
{
if(opt.data_size() < sizeof(uint32_t))
throw malformed_option();
vendor_info_type output;
std::memcpy(&output.enterprise_number, opt.data_ptr(), sizeof(uint32_t));
output.enterprise_number = Endian::be_to_host(output.enterprise_number);
output.data.assign(
opt.data_ptr() + sizeof(uint32_t),
opt.data_ptr() + opt.data_size()
);
return output;
}
DHCPv6::vendor_class_type DHCPv6::vendor_class_type::from_option(const option &opt)
{
if(opt.data_size() < sizeof(uint32_t))
throw malformed_option();
typedef vendor_class_type::class_data_type data_type;
vendor_class_type output;
std::memcpy(&output.enterprise_number, opt.data_ptr(), sizeof(uint32_t));
output.enterprise_number = Endian::be_to_host(output.enterprise_number);
output.vendor_class_data = Internals::option2class_option_data<data_type>(
opt.data_ptr() + sizeof(uint32_t),
opt.data_size() - sizeof(uint32_t)
);
return output;
}
DHCPv6::duid_type DHCPv6::duid_type::from_option(const option &opt)
{
if(opt.data_size() < sizeof(uint16_t) + 1)
throw malformed_option();
uint16_t uint16_t_buffer;
std::memcpy(&uint16_t_buffer, opt.data_ptr(), sizeof(uint16_t));
return duid_type(
Endian::be_to_host(uint16_t_buffer),
serialization_type(
opt.data_ptr() + sizeof(uint16_t),
opt.data_ptr() + opt.data_size()
)
);
}
DHCPv6::user_class_type DHCPv6::user_class_type::from_option(const option &opt)
{
if(opt.data_size() < sizeof(uint16_t))
throw malformed_option();
user_class_type output;
output.data = Internals::option2class_option_data<data_type>(
opt.data_ptr(), opt.data_size()
);
return output;
}
} // namespace Tins

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,6 +32,7 @@
#include <cassert>
#include <sstream>
#include <memory>
#include <cstdio>
#include "dns.h"
#include "ip_address.h"
#include "ipv6_address.h"
@@ -43,60 +44,77 @@ using std::list;
namespace Tins {
DNS::DNS() : extra_size(0) {
DNS::DNS()
: answers_idx(), authority_idx(), additional_idx()
{
std::memset(&dns, 0, sizeof(dns));
}
DNS::DNS(const uint8_t *buffer, uint32_t total_sz) : extra_size(0) {
DNS::DNS(const uint8_t *buffer, uint32_t total_sz)
: answers_idx(), authority_idx(), additional_idx()
{
if(total_sz < sizeof(dnshdr))
throw malformed_packet();
std::memcpy(&dns, buffer, sizeof(dnshdr));
const uint8_t *end(buffer + total_sz);
uint16_t nquestions(questions_count());
buffer += sizeof(dnshdr);
total_sz -= sizeof(dnshdr);
records_data.assign(
buffer + sizeof(dnshdr),
buffer + total_sz
);
buffer = &records_data[0];
const uint8_t *end = &records_data[0] + records_data.size(), *prev_start = buffer;
uint16_t nquestions = questions_count();
for(uint16_t i(0); i < nquestions; ++i) {
const uint8_t *ptr(buffer);
while(ptr < end && *ptr)
ptr++;
Query query;
if((ptr + (sizeof(uint16_t) * 2)) >= end)
buffer = find_dname_end(buffer);
if((buffer + (sizeof(uint16_t) * 2)) > end)
throw malformed_packet();
query.dname(string(buffer, ptr));
ptr++;
const uint16_t *opt_ptr = reinterpret_cast<const uint16_t*>(ptr);
query.type((QueryType)*(opt_ptr++));
query.query_class((QueryClass)*(opt_ptr++));
queries_.push_back(query);
total_sz -= reinterpret_cast<const uint8_t*>(opt_ptr) - buffer;
extra_size += reinterpret_cast<const uint8_t*>(opt_ptr) - buffer;
buffer = reinterpret_cast<const uint8_t*>(opt_ptr);
buffer += sizeof(uint16_t) * 2;
}
buffer = build_resource_list(ans, buffer, total_sz, answers_count());
buffer = build_resource_list(arity, buffer, total_sz, authority_count());
build_resource_list(addit, buffer, total_sz, additional_count());
if(total_sz)
inner_pdu(new RawPDU(buffer, total_sz));
answers_idx = buffer - prev_start;
authority_idx = find_section_end(&records_data[answers_idx], answers_count()) - &records_data[0];
additional_idx = find_section_end(&records_data[authority_idx], authority_count()) - &records_data[0];
}
const uint8_t *DNS::build_resource_list(ResourcesType &lst, const uint8_t *ptr, uint32_t &sz, uint16_t nrecs) {
const uint8_t *ptr_end(ptr + sz);
const uint8_t *parse_start(ptr);
for(uint16_t i(0); i < nrecs; ++i) {
const uint8_t *this_opt_start(ptr);
if(ptr + sizeof(uint16_t) > ptr_end)
throw malformed_packet();
lst.push_back(DNSResourceRecord(ptr, ptr_end - ptr));
ptr += lst.back().size();
extra_size += ptr - this_opt_start;
const uint8_t* DNS::find_dname_end(const uint8_t *ptr) const {
const uint8_t *end = &records_data[0] + records_data.size();
while(ptr < end) {
if(*ptr == 0) {
++ptr;
break;
}
else {
if((*ptr & 0xc0)) {
ptr += sizeof(uint16_t);
break;
}
else {
uint8_t size = *ptr;
ptr += size + 1;
}
}
}
return ptr;
}
const uint8_t *DNS::find_section_end(const uint8_t *ptr, const uint32_t num_records) const {
const uint8_t *end = &records_data[0] + records_data.size();
uint16_t uint16_t_buffer;
for(uint32_t i = 0; i < num_records; ++i) {
ptr = find_dname_end(ptr);
if(ptr + sizeof(uint16_t) * 3 + sizeof(uint32_t) > end)
throw malformed_packet();
ptr += sizeof(uint16_t) * 2 + sizeof(uint32_t);
std::memcpy(&uint16_t_buffer, ptr, sizeof(uint16_t));
uint16_t data_size = Endian::be_to_host(uint16_t_buffer); // Data size
ptr += sizeof(uint16_t);
if(ptr + data_size > end)
throw malformed_packet();
ptr += data_size;
}
sz -= ptr - parse_start;
return ptr;
}
uint32_t DNS::header_size() const {
return sizeof(dns) + extra_size;
return sizeof(dns) + records_data.size();
}
void DNS::id(uint16_t new_id) {
@@ -144,363 +162,407 @@ void DNS::rcode(uint8_t new_rcode) {
}
bool DNS::contains_dname(uint16_t type) {
type = Endian::be_to_host(type);
return type == MX || type == CNAME ||
type == PTR || type == NS;
}
void DNS::add_query(const Query &query) {
string new_str;
parse_domain_name(query.dname(), new_str);
queries_.push_back(
Query(
new_str,
(QueryType)Endian::host_to_be<uint16_t>(query.type()),
(QueryClass)Endian::host_to_be<uint16_t>(query.query_class())
)
string new_str = encode_domain_name(query.dname());
// Type (2 bytes) + Class (2 Bytes)
new_str.insert(new_str.end(), sizeof(uint16_t) * 2, ' ');
uint16_t uint16_t_buffer;
uint16_t_buffer = Endian::host_to_be<uint16_t>(query.type());
std::memcpy(&new_str[new_str.size() - 4], &uint16_t_buffer, sizeof(uint16_t));
uint16_t_buffer = Endian::host_to_be<uint16_t>(query.query_class());
std::memcpy(&new_str[new_str.size() - 2], &uint16_t_buffer, sizeof(uint16_t));
uint32_t offset = new_str.size(), threshold = answers_idx;
update_records(answers_idx, answers_count(), threshold, offset);
update_records(authority_idx, authority_count(), threshold, offset);
update_records(additional_idx, additional_count(), threshold, offset);
records_data.insert(
records_data.begin() + threshold,
new_str.begin(),
new_str.end()
);
dns.questions = Endian::host_to_be<uint16_t>(
questions_count() + 1
);
extra_size += new_str.size() + 1 + (sizeof(uint16_t) << 1);
dns.questions = Endian::host_to_be<uint16_t>(queries_.size());
}
void DNS::add_answer(const string &name, const DNSResourceRecord::info &info,
address_type ip)
{
ans.push_back(make_record(name, info, Endian::host_to_be((uint32_t)ip)));
dns.answers = Endian::host_to_be<uint16_t>(ans.size());
void DNS::add_answer(const Resource &resource) {
sections_type sections;
sections.push_back(std::make_pair(&authority_idx, authority_count()));
sections.push_back(std::make_pair(&additional_idx, additional_count()));
add_record(resource, sections);
dns.answers = Endian::host_to_be<uint16_t>(
answers_count() + 1
);
}
void DNS::add_answer(const string &name, const DNSResourceRecord::info &info,
address_v6_type ip)
{
ans.push_back(make_record(name, info, ip.begin(), address_v6_type::address_size));
dns.answers = Endian::host_to_be<uint16_t>(ans.size());
}
void DNS::add_answer(const std::string &name, const DNSResourceRecord::info &info,
const std::string &dname)
{
string new_str;
parse_domain_name(dname, new_str);
DNSResourceRecord res = make_record(name, info, new_str);
ans.push_back(res);
dns.answers = Endian::host_to_be<uint16_t>(ans.size());
}
void DNS::add_answer(const std::string &name, const DNSResourceRecord::info &info,
const uint8_t *data, uint32_t sz)
{
ans.push_back(make_record(name, info, data, sz));
dns.answers = Endian::host_to_be<uint16_t>(ans.size());
}
void DNS::add_authority(const string &name, const DNSResourceRecord::info &info,
const uint8_t *data, uint32_t sz)
{
arity.push_back(make_record(name, info, data, sz));
dns.authority = Endian::host_to_be<uint16_t>(arity.size());
}
void DNS::add_additional(const string &name, const DNSResourceRecord::info &info,
uint32_t ip)
{
addit.push_back(make_record(name, info, ip));
dns.additional = Endian::host_to_be<uint16_t>(addit.size());
}
DNSResourceRecord DNS::make_record(const std::string &name, const DNSResourceRecord::info &info, uint32_t ip) {
ip = Endian::host_to_be(ip);
return make_record(name, info, reinterpret_cast<uint8_t*>(&ip), sizeof(ip));
}
DNSResourceRecord DNS::make_record(const std::string &name,
const DNSResourceRecord::info &info, const std::string &dname)
{
return make_record(name, info, reinterpret_cast<const uint8_t*>(dname.c_str()), dname.size() + 1);
}
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();
void DNS::add_record(const Resource &resource, const sections_type &sections) {
// We need to check that the data provided is correct. Otherwise, the sections
// will end up being inconsistent.
IPv4Address v4_addr;
IPv6Address v6_addr;
std::string buffer = encode_domain_name(resource.dname()), encoded_data;
// By default the data size is the length of the data field.
uint32_t data_size = resource.data().size();
if(resource.type() == A) {
v4_addr = resource.data();
data_size = 4;
}
if(index)
res = make_offseted_record(Endian::host_to_be(index), ptr, len);
else
res = make_named_record(nm, ptr, len);
res.information().type = Endian::host_to_be<uint16_t>(info.type);
res.information().qclass = Endian::host_to_be<uint16_t>(info.qclass);
res.information().ttl = Endian::host_to_be(info.ttl);
extra_size += res.size();
return res;
}
uint32_t DNS::find_domain_name(const std::string &dname) {
uint16_t index(sizeof(dnshdr));
list<Query>::const_iterator it(queries_.begin());
for(; it != queries_.end() && it->dname() != dname; ++it)
index += it->dname().size() + 1 + (sizeof(uint16_t) << 1);
if(it != queries_.end() ||
find_domain_name(dname, ans, index) ||
find_domain_name(dname, arity, index) ||
find_domain_name(dname, addit, index))
return index;
else
return 0;
}
bool DNS::find_domain_name(const std::string &dname, const ResourcesType &lst, uint16_t &out) {
ResourcesType::const_iterator it(lst.begin());
while(it != lst.end()) {
if(it->matches(dname))
break;
out += it->size();
++it;
else if(resource.type() == AAAA) {
v6_addr = resource.data();
data_size = IPv6Address::address_size;
}
else if(contains_dname(resource.type())) {
encoded_data = encode_domain_name(resource.data());
data_size = encoded_data.size();
}
uint32_t offset = buffer.size() + sizeof(uint16_t) * 3 + sizeof(uint32_t) + data_size,
threshold = sections.empty() ? records_data.size() : *sections.front().first;
// Skip the preference field
if(resource.type() == MX) {
offset += sizeof(uint16_t);
}
for(size_t i = 0; i < sections.size(); ++i) {
update_records(*sections[i].first, sections[i].second, threshold, offset);
}
records_data.insert(
records_data.begin() + threshold,
offset,
0
);
uint8_t *ptr = std::copy(
buffer.begin(),
buffer.end(),
&records_data[threshold]
);
uint16_t uint16_t_buffer;
uint32_t uint32_t_buffer;
uint16_t_buffer = Endian::host_to_be(resource.type());
std::memcpy(ptr, &uint16_t_buffer, sizeof(uint16_t));
ptr += sizeof(uint16_t);
uint16_t_buffer = Endian::host_to_be(resource.query_class());
std::memcpy(ptr, &uint16_t_buffer, sizeof(uint16_t));
ptr += sizeof(uint16_t);
uint32_t_buffer = Endian::host_to_be(resource.ttl());
std::memcpy(ptr, &uint32_t_buffer, sizeof(uint32_t));
ptr += sizeof(uint32_t);
uint16_t_buffer = Endian::host_to_be<uint16_t>(
data_size + (resource.type() == MX ? 2 : 0)
);
std::memcpy(ptr, &uint16_t_buffer, sizeof(uint16_t));
ptr += sizeof(uint16_t);
if(resource.type() == MX) {
ptr += sizeof(uint16_t);
}
if(resource.type() == A) {
uint32_t ip_int = v4_addr;
std::memcpy(ptr, &ip_int, sizeof(ip_int));
}
else if(resource.type() == AAAA) {
std::copy(v6_addr.begin(), v6_addr.end(), ptr);
}
else if(!encoded_data.empty()) {
std::copy(encoded_data.begin(), encoded_data.end(), ptr);
}
else {
std::copy(resource.data().begin(), resource.data().end(), ptr);
}
return it != lst.end();
}
void DNS::parse_domain_name(const std::string &dn, std::string &out) const {
void DNS::add_authority(const Resource &resource) {
sections_type sections;
sections.push_back(std::make_pair(&additional_idx, additional_count()));
add_record(resource, sections);
dns.authority = Endian::host_to_be<uint16_t>(
authority_count() + 1
);
}
void DNS::add_additional(const Resource &resource){
add_record(resource, sections_type());
dns.additional = Endian::host_to_be<uint16_t>(
additional_count() + 1
);
}
std::string DNS::encode_domain_name(const std::string &dn) {
std::string output;
size_t last_index(0), index;
while((index = dn.find('.', last_index+1)) != string::npos) {
out.push_back(index - last_index);
out.append(dn.begin() + last_index, dn.begin() + index);
output.push_back(index - last_index);
output.append(dn.begin() + last_index, dn.begin() + index);
last_index = index + 1; //skip dot
}
out.push_back(dn.size() - last_index);
out.append(dn.begin() + last_index, dn.end());
output.push_back(dn.size() - last_index);
output.append(dn.begin() + last_index, dn.end());
output.push_back('\0');
return output;
}
void DNS::unparse_domain_name(const std::string &dn, std::string &out) const {
if(dn.size()) {
uint32_t index(1), len(dn[0]);
while(index + len < dn.size() && len) {
if(index != 1)
out.push_back('.');
out.append(dn.begin() + index, dn.begin() + index + len);
index += len;
if(index < dn.size() - 1)
len = dn[index];
index++;
// The output buffer should be at least 256 bytes long. This used to use
// a std::string but it worked about 50% slower, so this is somehow
// unsafe but a lot faster.
const uint8_t* DNS::compose_name(const uint8_t *ptr, char *out_ptr) const {
const uint8_t *end = &records_data[0] + records_data.size();
const uint8_t *end_ptr = 0;
char *current_out_ptr = out_ptr;
while(*ptr) {
// It's an offset
if((*ptr & 0xc0)) {
if(ptr + sizeof(uint16_t) > end)
throw malformed_packet();
uint16_t index;
std::memcpy(&index, ptr, sizeof(uint16_t));
index = Endian::be_to_host(index) & 0x3fff;
// Check that the offset is neither too low or too high
if(index < 0x0c || &records_data[index - 0x0c] >= ptr)
throw malformed_packet();
// We've probably found the end of the original domain name. Save it.
if(end_ptr == 0)
end_ptr = ptr + sizeof(uint16_t);
// Now this is our pointer
ptr = &records_data[index - 0x0c];
}
if(index < dn.size()) {
out.push_back('.');
out.append(dn.begin() + index, dn.end());
else {
// It's a label, grab its size.
uint8_t size = *ptr;
ptr++;
if(ptr + size > end || current_out_ptr - out_ptr + size + 1 > 255)
throw malformed_packet();
// Append a dot if it's not the first one.
if(current_out_ptr != out_ptr)
*current_out_ptr++ = '.';
std::copy(
ptr,
ptr + size,
current_out_ptr
);
current_out_ptr += size;
ptr += size;
}
}
// Add the null terminator.
*current_out_ptr = 0;
return end_ptr ? end_ptr : (ptr + 1);
}
void DNS::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
#ifdef TINS_DEBUG
assert(total_sz >= sizeof(dns) + extra_size);
assert(total_sz >= sizeof(dns) + records_data.size());//extra_size);
#endif
std::memcpy(buffer, &dns, sizeof(dns));
buffer += sizeof(dns);
for(list<Query>::const_iterator it(queries_.begin()); it != queries_.end(); ++it) {
std::copy(it->dname().begin(), it->dname().end(), buffer);
buffer += it->dname().size();
*buffer++ = 0;
*((uint16_t*)buffer) = it->type();
buffer += sizeof(uint16_t);
*((uint16_t*)buffer) = it->query_class();
buffer += sizeof(uint16_t);
}
buffer = serialize_list(ans, buffer);
buffer = serialize_list(arity, buffer);
buffer = serialize_list(addit, buffer);
std::copy(records_data.begin(), records_data.end(), buffer);
}
uint8_t *DNS::serialize_list(const ResourcesType &lst, uint8_t *buffer) const {
for(ResourcesType::const_iterator it(lst.begin()); it != lst.end(); ++it)
buffer += it->write(buffer);
return buffer;
// Optimization. Creating an IPv4Address and then using IPv4Address::to_string
// was quite slow. The output buffer should be able to hold an IPv4 address.
void DNS::inline_convert_v4(uint32_t value, char *output) {
output += sprintf(
output,
"%d.%d.%d.%d",
value & 0xff,
(value >> 8) & 0xff,
(value >> 16) & 0xff,
(value >> 24) & 0xff
);
*output = 0;
}
void DNS::add_suffix(uint32_t index, const uint8_t *data, uint32_t sz) const {
uint32_t i(0), suff_sz(data[0]);
SuffixMap::iterator it;
while((i + suff_sz + 1 <= sz || (suff_sz == 0xc0 && i + 1 < sz)) && suff_sz) {
if((suff_sz & 0xc0)) {
if((it = suffixes.find(data[i+1])) != suffixes.end())
suffix_indices[index + i] = data[i+1];
i += sizeof(uint16_t);
}
else {
++i;
suffixes.insert(std::make_pair(index + i - 1, string(data + i, data + i + suff_sz)));
i += suff_sz;
}
if(i < sz)
suff_sz = data[i];
}
}
uint32_t DNS::build_suffix_map(uint32_t index, const ResourcesType &lst) const {
const string *str;
for(ResourcesType::const_iterator it(lst.begin()); it != lst.end(); ++it) {
str = it->has_domain_name() ? it->dname() : 0;
if(str) {
add_suffix(index, (uint8_t*)str->c_str(), str->size());
index += str->size() + 1;
}
else
index += sizeof(uint16_t);
index += sizeof(DNSResourceRecord::info) + sizeof(uint16_t);
uint32_t sz(it->data_size());
const uint8_t *ptr = it->data_ptr();
if(Endian::be_to_host(it->information().type) == MX) {
ptr += 2;
sz -= 2;
index += 2;
}
if(contains_dname(it->information().type))
add_suffix(index, ptr, sz);
index += sz;
}
return index;
}
uint32_t DNS::build_suffix_map(uint32_t index, const list<Query> &lst) const {
for(list<Query>::const_iterator it(lst.begin()); it != lst.end(); ++it) {
add_suffix(index, (uint8_t*)it->dname().c_str(), it->dname().size());
index += it->dname().size() + 1 + (sizeof(uint16_t) << 1);
}
return index;
}
void DNS::build_suffix_map() const {
uint32_t index(sizeof(dnshdr));
index = build_suffix_map(index, queries_);
index = build_suffix_map(index, ans);
index = build_suffix_map(index, arity);
build_suffix_map(index, addit);
}
void DNS::compose_name(const uint8_t *ptr, uint32_t sz, std::string &out) const {
uint32_t i(0);
while(i < sz) {
if(i && ptr[i])
out.push_back('.');
if((ptr[i] & 0xc0)) {
uint16_t index = Endian::be_to_host(*((uint16_t*)(ptr + i)));
index &= 0x3fff;
SuffixMap::iterator it(suffixes.find(index));
SuffixIndices::iterator suff_it(suffix_indices.find(index));
// We need at least a suffix or a suffix index to compose
// the domain name
if(it == suffixes.end() && suff_it == suffix_indices.end())
throw malformed_packet();
bool first(true);
do {
if(it != suffixes.end()) {
if(!first)
out.push_back('.');
first = false;
out += it->second;
index += it->second.size() + 1;
}
else
index = suff_it->second;
it = suffixes.find(index);
if(it == suffixes.end())
suff_it = suffix_indices.find(index);
} while(it != suffixes.end() || suff_it != suffix_indices.end());
break;
}
else {
uint8_t suff_sz(ptr[i]);
i++;
if(i + suff_sz <= sz)
out.append(ptr + i, ptr + i + suff_sz);
i += suff_sz;
}
}
}
void DNS::convert_resources(const ResourcesType &lst, std::list<Resource> &res) const {
if(!suffixes.size())
build_suffix_map();
const string *str_ptr;
const uint8_t *ptr;
uint32_t sz;
for(ResourcesType::const_iterator it(lst.begin()); it != lst.end(); ++it) {
string dname, addr;
if(it->has_domain_name() && (str_ptr = it->dname()))
compose_name(reinterpret_cast<const uint8_t*>(str_ptr->c_str()), str_ptr->size(), dname);
else {
uint16_t offset = it->offset();
compose_name((uint8_t*)&offset, 2, dname);
}
ptr = it->data_ptr();
sz = it->data_size();
uint16_t record_type = Endian::be_to_host(it->information().type);
// Parses records in some section.
void DNS::convert_records(const uint8_t *ptr, const uint8_t *end, resources_type &res) const {
char dname[256], small_addr_buf[256];
while(ptr < end) {
std::string addr;
bool used_small_buffer = false;
// Retrieve the record's domain name.
ptr = compose_name(ptr, dname);
// 3 uint16_t fields: Type + Class + Data size
// 1 uint32_t field: TTL
if(ptr + sizeof(uint16_t) * 3 + sizeof(uint32_t) > end)
throw malformed_packet();
// Retrieve the following fields.
uint16_t type, qclass, data_size;
uint32_t ttl;
std::memcpy(&type, ptr, sizeof(uint16_t)); // Type
type = Endian::be_to_host(type);
ptr += sizeof(uint16_t);
std::memcpy(&qclass, ptr, sizeof(uint16_t)); // Class
qclass = Endian::be_to_host(qclass);
ptr += sizeof(uint16_t);
std::memcpy(&ttl, ptr, sizeof(uint32_t)); // TTL
ttl = Endian::be_to_host(ttl);
ptr += sizeof(uint32_t);
std::memcpy(&data_size, ptr, sizeof(uint16_t)); // Data size
data_size = Endian::be_to_host(data_size);
ptr += sizeof(uint16_t);
// Skip the preference field if it's MX
if(record_type == MX) {
if(type == MX) {
if(data_size < 2)
throw malformed_packet();
ptr += 2;
sz -= 2;
data_size -= 2;
}
switch(record_type) {
if(ptr + data_size > end)
throw malformed_packet();
switch(type) {
case AAAA:
if(sz != 16)
if(data_size != 16)
throw malformed_packet();
addr = IPv6Address(ptr).to_string();
break;
case A:
if(sz != 4)
if(data_size == 4) {
uint32_t uint32_t_buffer;
std::memcpy(&uint32_t_buffer, ptr, sizeof(uint32_t));
inline_convert_v4(uint32_t_buffer, small_addr_buf);
used_small_buffer = true;
}
else
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);
compose_name(ptr, small_addr_buf);
used_small_buffer = true;
break;
default:
addr.assign(ptr, ptr + sz);
if(data_size < sizeof(small_addr_buf) - 1) {
std::copy(
ptr,
ptr + data_size,
small_addr_buf
);
// null terminator
small_addr_buf[data_size] = 0;
used_small_buffer = true;
}
else
addr.assign(ptr, ptr + data_size);
break;
}
ptr += data_size;
res.push_back(
Resource(dname, addr, record_type,
Endian::host_to_be(it->information().qclass),
Endian::be_to_host(it->information().ttl)
Resource(
dname,
(used_small_buffer) ? small_addr_buf : addr,
type,
qclass,
ttl
)
);
}
}
// no length checks, records should already be valid
uint8_t *DNS::update_dname(uint8_t *ptr, uint32_t threshold, uint32_t offset) {
while(*ptr != 0) {
if((*ptr & 0xc0)) {
uint16_t index;
std::memcpy(&index, ptr, sizeof(uint16_t));
index = Endian::be_to_host(index) & 0x3fff;
if(index > threshold) {
index = Endian::host_to_be<uint16_t>((index + offset) | 0xc000);
std::memcpy(ptr, &index, sizeof(uint16_t));
}
ptr += sizeof(uint16_t);
break;
}
else {
ptr += *ptr + 1;
}
}
return ptr;
}
// Updates offsets in domain names inside records.
// No length checks, records are already valid.
void DNS::update_records(uint32_t &section_start, uint32_t num_records, uint32_t threshold, uint32_t offset) {
uint8_t *ptr = &records_data[section_start];
for(uint32_t i = 0; i < num_records; ++i) {
ptr = update_dname(ptr, threshold, offset);
uint16_t type;
std::memcpy(&type, ptr, sizeof(uint16_t));
type = Endian::be_to_host(type);
ptr += sizeof(uint16_t) * 2 + sizeof(uint32_t);
uint16_t size;
std::memcpy(&size, ptr, sizeof(uint16_t));
size = Endian::be_to_host(size);
ptr += sizeof(uint16_t);
if(type == MX) {
ptr += sizeof(uint16_t);
size -= sizeof(uint16_t);
}
if(contains_dname(type)) {
update_dname(ptr, threshold, offset);
}
ptr += size;
}
section_start += offset;
}
DNS::queries_type DNS::queries() const {
queries_type output;
for(std::list<Query>::const_iterator it(queries_.begin()); it != queries_.end(); ++it) {
string dn;
unparse_domain_name(it->dname(), dn);
const uint8_t *ptr = &records_data[0], *end = &records_data[answers_idx];
char buffer[256];
uint16_t tmp_query_type;
uint16_t tmp_query_class;
while(ptr < end) {
ptr = compose_name(ptr, buffer);
if(ptr + sizeof(uint16_t) * 2 > end)
throw malformed_packet();
std::memcpy(&tmp_query_type, ptr, sizeof(uint16_t));
std::memcpy(&tmp_query_class, ptr + 2, sizeof(uint16_t));
output.push_back(
Query(
dn,
(QueryType)Endian::be_to_host<uint16_t>(it->type()),
(QueryClass)Endian::be_to_host<uint16_t>(it->query_class())
buffer,
(QueryType)Endian::be_to_host(tmp_query_type),
(QueryClass)Endian::be_to_host(tmp_query_class)
)
);
ptr += sizeof(uint16_t) * 2;
}
return output;
}
DNS::resources_type DNS::answers() const {
resources_type res;
convert_resources(ans, res);
convert_records(
&records_data[answers_idx],
&records_data[authority_idx],
res
);
return res;
}
DNS::resources_type DNS::authority() const {
resources_type res;
convert_records(
&records_data[authority_idx],
&records_data[additional_idx],
res
);
return res;
}
DNS::resources_type DNS::additional() const {
resources_type res;
convert_records(
&records_data[additional_idx],
&records_data[records_data.size()],
res
);
return res;
}

View File

@@ -1,212 +0,0 @@
/*
* 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 <stdexcept>
#include <memory>
#include <typeinfo>
#include "dns_record.h"
#include "endianness.h"
#include "exceptions.h"
namespace Tins {
bool contains_dname(uint16_t type) {
type = Endian::be_to_host(type);
return type == 1 || type == 2 ||
type == 5 || type == 6 ||
type == 12 || type == 15 ||
type == 28 || type == 41;
}
DNSResourceRecord::DNSResourceRecord(DNSRRImpl *impl,
const uint8_t *d, uint16_t len) : impl(impl)
{
if(d && len)
data.assign(d, d + len);
}
DNSResourceRecord::DNSResourceRecord(const uint8_t *buffer, uint32_t size)
{
const uint8_t *buffer_end = buffer + size;
Internals::smart_ptr<DNSRRImpl>::type tmp_impl;
if((*buffer & 0xc0)) {
uint16_t offset(*reinterpret_cast<const uint16_t*>(buffer));
offset = Endian::be_to_host(offset) & 0x3fff;
tmp_impl.reset(new OffsetedDNSRRImpl(Endian::host_to_be(offset)));
buffer += sizeof(uint16_t);
}
else {
const uint8_t *str_end(buffer);
while(str_end < buffer_end && *str_end)
str_end++;
if(str_end == buffer_end)
throw malformed_packet();
//str_end++;
tmp_impl.reset(new NamedDNSRRImpl(buffer, str_end));
buffer = ++str_end;
}
if(buffer + sizeof(info_) > buffer_end)
throw malformed_packet();
std::memcpy(&info_, buffer, sizeof(info_));
buffer += sizeof(info_);
if(buffer + sizeof(uint16_t) > buffer_end)
throw malformed_packet();
// Store the option size.
data.resize(
Endian::be_to_host(*reinterpret_cast<const uint16_t*>(buffer))
);
buffer += sizeof(uint16_t);
if(buffer + data.size() > buffer_end)
throw malformed_packet();
if(contains_dname(info_.type) || data.size() != sizeof(uint32_t))
std::copy(buffer, buffer + data.size(), data.begin());
else if(data.size() == sizeof(uint32_t))
*(uint32_t*)&data[0] = *(uint32_t*)buffer;
impl = tmp_impl.release();
}
DNSResourceRecord::DNSResourceRecord(const DNSResourceRecord &rhs)
: info_(rhs.info_), data(rhs.data), impl(rhs.clone_impl())
{
}
DNSResourceRecord& DNSResourceRecord::operator=(const DNSResourceRecord &rhs)
{
delete impl;
info_ = rhs.info_;
data = rhs.data;
impl = rhs.clone_impl();
return *this;
}
DNSResourceRecord::~DNSResourceRecord() {
delete impl;
}
uint32_t DNSResourceRecord::write(uint8_t *buffer) const {
const uint32_t sz(impl ? impl->do_write(buffer) : 0);
buffer += sz;
std::memcpy(buffer, &info_, sizeof(info_));
buffer += sizeof(info_);
*((uint16_t*)buffer) = Endian::host_to_be<uint16_t>(data.size());
buffer += sizeof(uint16_t);
std::copy(data.begin(), data.end(), buffer);
return sz + sizeof(info_) + sizeof(uint16_t) + data.size();
}
DNSRRImpl *DNSResourceRecord::clone_impl() const {
return impl ? impl->clone() : 0;
}
bool DNSResourceRecord::has_domain_name() const {
if(!impl)
throw std::bad_cast();
return dynamic_cast<NamedDNSRRImpl*>(impl) != 0;
}
const std::string *DNSResourceRecord::dname() const {
if(!impl)
throw std::bad_cast();
return dynamic_cast<NamedDNSRRImpl&>(*impl).dname_pointer();
}
uint16_t DNSResourceRecord::offset() const {
return dynamic_cast<OffsetedDNSRRImpl&>(*impl).offset();
}
size_t DNSResourceRecord::impl_size() const {
return impl ? impl->size() : 0;
}
uint32_t DNSResourceRecord::size() const {
return sizeof(info_) + data.size() + sizeof(uint16_t) + impl_size();
}
bool DNSResourceRecord::matches(const std::string &dname) const {
return impl ? impl->matches(dname) : false;
}
// OffsetedRecord
OffsetedDNSRRImpl::OffsetedDNSRRImpl(uint16_t off)
: offset_(off | Endian::host_to_be<uint16_t>(0xc000))
{
}
uint32_t OffsetedDNSRRImpl::do_write(uint8_t *buffer) const {
std::memcpy(buffer, &offset_, sizeof(offset_));
return sizeof(offset_);
}
uint32_t OffsetedDNSRRImpl::size() const {
return sizeof(offset_);
}
OffsetedDNSRRImpl *OffsetedDNSRRImpl::clone() const {
return new OffsetedDNSRRImpl(*this);
}
uint16_t OffsetedDNSRRImpl::offset() const {
return offset_;
}
// NamedRecord
NamedDNSRRImpl::NamedDNSRRImpl(const std::string &nm)
: name(nm)
{
}
uint32_t NamedDNSRRImpl::size() const {
return name.size() + 1;
}
uint32_t NamedDNSRRImpl::do_write(uint8_t *buffer) const {
buffer = std::copy(name.begin(), name.end(), buffer);
*buffer = 0;
return name.size() + 1;
}
const std::string *NamedDNSRRImpl::dname_pointer() const {
return &name;
}
bool NamedDNSRRImpl::matches(const std::string &dname) const {
return dname == name;
}
NamedDNSRRImpl *NamedDNSRRImpl::clone() const {
return new NamedDNSRRImpl(*this);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,9 +27,11 @@
*
*/
#include "dot11/dot11_assoc.h"
#ifdef HAVE_DOT11
#include <cassert>
#include <cstring>
#include "dot11/dot11_assoc.h"
namespace Tins {
/* Diassoc */
@@ -246,4 +248,6 @@ uint32_t Dot11ReAssocResponse::write_fixed_parameters(uint8_t *buffer, uint32_t
memcpy(buffer, &this->_body, sz);
return sz;
}
} // namespace Tins
} // namespace Tins
#endif // HAVE_DOT11

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,9 +27,11 @@
*
*/
#include "dot11/dot11_auth.h"
#ifdef HAVE_DOT11
#include <cassert>
#include <cstring>
#include "dot11/dot11_auth.h"
namespace Tins {
/* Auth */
@@ -120,4 +122,6 @@ uint32_t Dot11Deauthentication::write_fixed_parameters(uint8_t *buffer, uint32_t
memcpy(buffer, &this->_body, sz);
return sz;
}
} // namespace Tins
} // namespace Tins
#endif // HAVE_DOT11

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,6 +27,9 @@
*
*/
#include "dot11/dot11_base.h"
#ifdef HAVE_DOT11
#include <cassert>
#include <cstring>
@@ -35,7 +38,6 @@
#include <utility>
#include "macros.h"
#include "exceptions.h"
#include "dot11/dot11_base.h"
#ifndef WIN32
#if defined(__FreeBSD_kernel__) || defined(BSD) || defined(__APPLE__)
@@ -272,4 +274,6 @@ Dot11 *Dot11::from_bytes(const uint8_t *buffer, uint32_t total_sz) {
ret = new Dot11(buffer, total_sz);
return ret;
}
} // namespace Tins
} // namespace Tins
#endif // HAVE_DOT11

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,9 +27,11 @@
*
*/
#include "dot11/dot11_beacon.h"
#ifdef HAVE_DOT11
#include <cstring>
#include <cassert>
#include "dot11/dot11_beacon.h"
namespace Tins {
/* Dot11Beacon */
@@ -76,4 +78,6 @@ uint32_t Dot11Beacon::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz)
std::memcpy(buffer, &this->_body, sz);
return sz;
}
} // namespace Tins
} // namespace Tins
#endif // HAVE_DOT11

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,9 +27,11 @@
*
*/
#include "dot11/dot11_control.h"
#ifdef HAVE_DOT11
#include <cassert>
#include <cstring>
#include "dot11/dot11_control.h"
namespace Tins {
/* Dot11Control */
@@ -280,4 +282,6 @@ uint32_t Dot11BlockAck::write_ext_header(uint8_t *buffer, uint32_t total_sz) {
uint32_t Dot11BlockAck::header_size() const {
return Dot11ControlTA::header_size() + sizeof(_start_sequence) + sizeof(_start_sequence) + sizeof(_bitmap);
}
} // namespace Tins
} // namespace Tins
#endif // HAVE_DOT11

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Matias Fontanini
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,9 +27,11 @@
*
*/
#include "dot11/dot11_data.h"
#ifdef HAVE_DOT11
#include <cstring>
#include <cassert>
#include "dot11/dot11_data.h"
#include "rawpdu.h"
#include "snap.h"
@@ -151,7 +153,7 @@ Dot11QoSData::Dot11QoSData(const uint8_t *buffer, uint32_t total_sz)
total_sz -= sz;
if(total_sz < sizeof(_qos_control))
throw malformed_packet();
_qos_control = *(uint16_t*)buffer;
std::memcpy(&_qos_control, buffer, sizeof(uint16_t));
total_sz -= sizeof(uint16_t);
buffer += sizeof(uint16_t);
if(total_sz) {
@@ -176,7 +178,9 @@ uint32_t Dot11QoSData::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz
#ifdef TINS_DEBUG
assert(sz <= total_sz);
#endif
*(uint16_t*)buffer = this->_qos_control;
std::memcpy(buffer, &this->_qos_control, sizeof(uint16_t));
return sz;
}
} // namespace Tins
#endif // HAVE_DOT11

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