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

69 Commits
v0.3 ... v1.0

Author SHA1 Message Date
Matias Fontanini
cf19c8758d UDP now calculates the checksum when the transport layer protocol is IPv6. 2013-04-23 23:00:43 -03:00
Matias Fontanini
5197e7f5f1 Sniffer now differentiates between EthernetII and Dot3 when sniffing. 2013-04-23 22:55:32 -03:00
Matias Fontanini
eb87b82c17 Fixed the CHANGES and README files. 2013-04-23 20:57:56 -03:00
Matias Fontanini
5064a9255b Fixed BSD notice. Updated AUTHORS file. 2013-04-23 20:33:00 -03:00
Matias Fontanini
bf604339f0 Removed the PDU* parameter in several PDU's constructors. 2013-04-23 20:03:08 -03:00
Matias Fontanini
7e85058ef1 Added another overload of Utils::resolv_hwaddr. 2013-04-23 15:19:48 -03:00
Matias Fontanini
ec05a49cce Done minor modifications on configure.ac 2013-04-23 14:46:56 -03:00
Matias Fontanini
b0eefe15f9 Modified the soname. 2013-04-23 13:43:12 -03:00
Matias Fontanini
0f2bc45059 Moved definitions inside TINS_IS_CXX11 into header files. 2013-04-23 13:04:57 -03:00
Matias Fontanini
f8134be8b7 Done some modifications on the configure script. 2013-04-23 13:03:00 -03:00
Matias Fontanini
8afbe14c82 PacketSender is not copyable and movable. 2013-04-23 11:05:44 -03:00
Matias Fontanini
fdfb8b0dea Fixed compilation issues triggered in GNU/kFreeBSD. 2013-04-22 23:48:53 -03:00
Matias Fontanini
9be4f0ca37 Removed IP, UDP and IP checksum setters. Added some checksum tests. 2013-04-22 20:06:35 -03:00
Matias Fontanini
66ff604580 assert() is only called when TINS_DEBUG is defined. 2013-04-22 18:45:56 -03:00
Matias Fontanini
7e0e85db65 Added AC_CANONICAL_SYSTEM to configure.ac. 2013-04-22 13:58:42 -03:00
Matias Fontanini
ed39eb36f5 Dot11BlockAck and Dot11BlockAckRequests' frag_seq, start_sequence and bar_control now use small_uint rather than uintX_t. 2013-04-22 12:54:27 -03:00
Matias Fontanini
7da8de6ea7 Added another test case for RadioTap's constructor from buffer. 2013-04-22 12:53:01 -03:00
Matias Fontanini
d1b64ec48e PDU::matches_response is now const. 2013-04-21 20:03:47 -03:00
Matias Fontanini
69968cbc5c Removed deprecated methods/types. 2013-04-21 19:52:39 -03:00
Matias Fontanini
9e20c0241f Added a default interface to PacketSender. 2013-04-21 19:40:17 -03:00
Matias Fontanini
97f049580b Link layer PDUs no longer contain a NetworkInterface. 2013-04-21 18:50:08 -03:00
Matias Fontanini
6f04329fbe All tests now run successfully on big endian architectures. 2013-04-21 15:40:28 -03:00
Matias Fontanini
077b54bbed Added STP root_id and bridge_id setters/getters. 2013-04-21 13:22:15 -03:00
Matias Fontanini
759e92706f Sniffer::sniff_loop now catches malformed_packet and pdu_not_found, when thrown by the functor argument. 2013-04-21 13:21:47 -03:00
Matias Fontanini
2ea952d6ab Added PDU::rfind_pdu. 2013-04-19 22:27:48 -03:00
Matias Fontanini
91bdcca577 Dot11 now uses option_not_found. Sniffer catches malformed_packet rather than std::runtime_error while sniffing. 2013-04-19 14:06:59 -03:00
Matias Fontanini
75bd445bd3 Dot11 now uses malformed_packet. 2013-04-19 02:05:28 -03:00
Matias Fontanini
9812ad441f Added missing exceptions.h file. 2013-04-18 17:52:53 -03:00
Matias Fontanini
3fd1b3d37d Added malformed_packet exception. Every class except Dot11* use it. 2013-04-18 00:12:20 -03:00
Matias Fontanini
923f51ae15 Fixed bug triggered when parsing Dot11 QoS packets. 2013-04-16 15:01:48 -03:00
Matias Fontanini
804ea411fc Fixed bug in RadioTap when using FCS at the end. 2013-04-16 13:45:30 -03:00
Piotr Haber
9bcfd07896 fix radiotap header parsing
Signed-off-by: Matias Fontanini <matias.fontanini@gmail.com>
2013-04-16 13:37:31 -03:00
Matias Fontanini
58c8eccc46 Makefile issue fix. 2013-04-16 13:15:35 -03:00
Matias F
a674640ef2 Now hopefully make problems are fixed. 2013-04-16 13:00:12 -03:00
Matias F
dde890b24b Fixed make issues. 2013-04-16 12:51:07 -03:00
Matias Fontanini
38ccb4413b STP is now serialized correctly. LLC behaves correctly when it contains an STP is its inner pdu. 2013-04-16 01:05:06 -03:00
Matias F
9631734805 Added STP class. 2013-04-15 14:01:44 -03:00
Matias Fontanini
7faf514496 Merge branch 'master' of ssh://git.code.sf.net/p/libtins/code 2013-04-15 08:49:25 -03:00
Matias Fontanini
08091fc7c2 Added missing the deprecated header ieee802_3.h to Makefile.am. 2013-04-15 08:48:51 -03:00
Matias Fontanini
1450c8cf26 Fixed missing header in Makefile.in as well. 2013-04-15 08:41:21 -03:00
Matias Fontanini
b533775cb4 Added missing the deprecated header ieee802_3.h to Makefile.am. 2013-04-15 08:35:34 -03:00
Matias Fontanini
3f4c48ad9f Fixed bug triggered when parsing EOL and NOP options in IP. 2013-04-15 00:23:29 -03:00
Matias Fontanini
30d6a4f2e0 UDP checksum is now calculated always inside write_serialization. 2013-04-12 13:42:11 -03:00
Matias Fontanini
f4522acd44 IP and TCP now calculate checksums always inside write_serialization. 2013-04-11 00:57:36 -03:00
Matias Fontanini
1fbef641da TCP options now use PDUOption<>::length_field when it is != from data_size. 2013-04-10 18:44:00 -03:00
Matias Fontanini
fee938b46d Added move constructor/assignment operator to PDU. 2013-04-10 18:43:24 -03:00
Matias Fontanini
ae1e1c2ce2 Modified some protocols' internal type names. 2013-04-09 15:40:58 -03:00
Matias Fontanini
20054e6c73 Several classes now use PDUOption::length_field instead of data_size. 2013-04-08 11:58:12 -03:00
Matias Fontanini
f7f5a9bc9a Added PPPoE. 2013-04-07 20:57:43 -03:00
Matias Fontanini
f2a5f73337 Implemented matches_response on several PDUs. Added some test cases. 2013-04-02 21:05:53 -03:00
Matias Fontanini
97049140af Added some helper methods to Dot1Q. 2013-03-26 23:42:43 -03:00
Matias Fontanini
dfc0498b70 DNS, RadioTap and Dot1Q work when using PacketSender::send_recv. 2013-03-26 14:54:24 -03:00
Matias Fontanini
1cec099c0e Dot3::matches_response now works as expected. 2013-03-26 00:25:47 -03:00
Matias Fontanini
3989566608 Renamed IEEE802_3 to Dot3. 2013-03-25 15:35:30 -03:00
Matias Fontanini
b32586e739 Fixed compilation error on IP and TCP. 2013-03-25 15:17:26 -03:00
Matias Fontanini
82ef41dd92 IP now fills automatically the sender address when no link layer PDU is present. Made some protocols work when using PacketSender::send_recv. 2013-03-25 14:08:59 -03:00
Matias Fontanini
b0dc376494 Fixed compilation error in pdu_cacher.h. 2013-03-25 09:55:15 -03:00
Matias Fontanini
8be0c4c23c Marked PDU::clone_packet as deprecated. 2013-03-24 16:08:09 -03:00
Matias Fontanini
d7dd1e131f Added an overload of add_option that takes an rvalue-ref in IP, TCP, DHCP, ICMPv6 and Dot11. 2013-03-24 00:08:53 -03:00
Matias Fontanini
584fe81f04 Optimized TCP, IP and PDUOption<>. 2013-03-23 13:44:33 -03:00
Matias Fontanini
16a99ef35b Added an overload of PacketSender::send that takes a NetworkInterface. 2013-03-20 23:24:43 -03:00
Matias Fontanini
247273e086 Added constructor from buffer test for Dot11BlockAckRequest. 2013-03-18 13:32:34 -03:00
Matias Fontanini
0f27b04a92 Fixed lots of warnings in test cases, due to narrowing conversions. 2013-03-18 11:32:34 -03:00
Matias Fontanini
a8edc2af74 Added serialization test for Dot1Q. 2013-03-18 10:17:43 -03:00
Matias Fontanini
f5ecaa3faa Added Dot1Q class. 2013-03-17 23:27:34 -03:00
Matias Fontanini
b5f9f5095e Added Utils::resolve_domain and resolve_domain6. 2013-03-15 15:43:42 -03:00
Matias Fontanini
02a53da361 Fixed bug triggered when parsing RadioTap in BE architectures. 2013-03-15 15:13:00 -03:00
Matias Fontanini
f86f727810 Added RadioTap::iface. 2013-02-06 14:10:21 -03:00
Matias Fontanini
836dbd8955 Fixed compilation issue in 2 examples. 2013-02-01 13:55:29 -03:00
152 changed files with 16080 additions and 11618 deletions

11
AUTHORS
View File

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

40
CHANGES
View File

@@ -1,3 +1,43 @@
v1.0 - Tue Apr 23 20:40:57 ART 2013
- Link layer protocol PDUs now don't hold a NetworkInterface. This led
to changes in their constructors.
- Removed the obsolete PDU* parameter taken by several classes'
constructors.
- IP now sets the sender's address automatically when no link layer
PDU is used.
- IP, TCP and UDP now calculate the checksum everytime they're
serialized.
- Added PDU::rfind_pdu.
- Defined several exception types.
- Implemented matches_response on several protocols.
- PacketSender is now movable.
- Added an overload of add_option that takes an rvalue-reference in IP,
TCP, DHCP, ICMPv6 and Dot11.
- Added support for GNU/kFreeBSD.
- Removed several deprecated methods, such as PDU::clone_packet.
- Added PacketSender::send(PDU&, NetworkInterface).
- Normalized the TLV options naming conventions in all of the classes
that used them.
- Added support for Dot1Q, STP, PPPoE protocols.
- Made some important optimizations on PDUOption<>'s constructors.
- Added Utils::resolve_domain and Utils::resolve_domain6
v0.3 - Thu Jan 31 16:47:27 ART 2013
- Added IPv6, ICMPv6 and DHCPv6 classes.

View File

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

View File

@@ -13,17 +13,20 @@ AM_CXXFLAGS = -Wall -pedantic -I@LIBTINS_INCLUDE_DIR@
libtins_la_SOURCES=src/arp.cpp \
src/bootp.cpp \
src/stp.cpp \
src/pppoe.cpp \
src/crypto.cpp \
src/dhcp.cpp \
src/dhcpv6.cpp \
src/dns.cpp \
src/dns_record.cpp \
src/dot11.cpp \
src/dot3.cpp \
src/dot1q.cpp \
src/eapol.cpp \
src/ethernetII.cpp \
src/icmp.cpp \
src/icmpv6.cpp \
src/ieee802_3.cpp \
src/internals.cpp \
src/ip.cpp src/ip_address.cpp \
src/ipv6.cpp \
@@ -49,17 +52,20 @@ libtins_includedir = $(includedir)/tins
libtins_include_HEADERS = include/internals.h \
include/dhcpv6.h \
include/dot11.h \
include/dot1q.h \
include/dot3.h \
include/small_uint.h \
include/ip.h \
include/dns_record.h \
include/eapol.h \
include/tcp_stream.h \
include/pppoe.h \
include/ipv6.h \
include/icmpv6.h \
include/ieee802_3.h \
include/endianness.h \
include/rsn_information.h \
include/loopback.h \
include/ieee802_3.h \
include/ethernetII.h \
include/crypto.h \
include/packet.h \
@@ -90,4 +96,6 @@ libtins_include_HEADERS = include/internals.h \
include/ipv6_address.h \
include/constants.h \
include/utils.h \
include/cxxstd.h
include/cxxstd.h \
include/stp.h \
include/exceptions.h

View File

@@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.11.3 from Makefile.am.
# Makefile.in generated by automake 1.11.6 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -18,6 +18,23 @@
VPATH = @srcdir@
am__make_dryrun = \
{ \
am__dry=no; \
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;; \
esac; \
test $$am__dry = yes; \
}
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
@@ -36,19 +53,24 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
subdir = .
DIST_COMMON = README $(am__configure_deps) $(libtins_include_HEADERS) \
$(srcdir)/Makefile.am $(srcdir)/Makefile.in \
$(srcdir)/libtins.pc.in $(top_srcdir)/configure AUTHORS THANKS \
TODO config.guess config.sub depcomp install-sh ltmain.sh \
missing
$(srcdir)/libtins.pc.in $(top_srcdir)/configure \
$(top_srcdir)/include/config.h.in AUTHORS THANKS TODO \
config.guess config.sub depcomp install-sh ltmain.sh missing
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
configure.lineno config.status.lineno
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/include/config.h
CONFIG_CLEAN_FILES = libtins.pc
CONFIG_CLEAN_VPATH_FILES =
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
@@ -83,12 +105,13 @@ am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" \
LTLIBRARIES = $(lib_LTLIBRARIES)
libtins_la_LIBADD =
am__dirstamp = $(am__leading_dot)dirstamp
am_libtins_la_OBJECTS = src/arp.lo src/bootp.lo src/crypto.lo \
src/dhcp.lo src/dhcpv6.lo src/dns.lo src/dns_record.lo \
src/dot11.lo src/eapol.lo src/ethernetII.lo src/icmp.lo \
src/icmpv6.lo src/ieee802_3.lo src/internals.lo src/ip.lo \
src/ip_address.lo src/ipv6.lo src/ipv6_address.lo src/llc.lo \
src/loopback.lo src/network_interface.lo src/packet_sender.lo \
am_libtins_la_OBJECTS = src/arp.lo src/bootp.lo src/stp.lo \
src/pppoe.lo src/crypto.lo src/dhcp.lo src/dhcpv6.lo \
src/dns.lo src/dns_record.lo src/dot11.lo src/dot3.lo \
src/dot1q.lo src/eapol.lo src/ethernetII.lo src/icmp.lo \
src/icmpv6.lo src/internals.lo src/ip.lo src/ip_address.lo \
src/ipv6.lo src/ipv6_address.lo src/llc.lo src/loopback.lo \
src/network_interface.lo src/packet_sender.lo \
src/packet_writer.lo src/pdu.lo src/radiotap.lo src/rawpdu.lo \
src/rsn_information.lo src/sll.lo src/snap.lo src/sniffer.lo \
src/tcp.lo src/tcp_stream.lo src/udp.lo src/utils.lo
@@ -96,7 +119,7 @@ libtins_la_OBJECTS = $(am_libtins_la_OBJECTS)
libtins_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
$(CXXFLAGS) $(libtins_la_LDFLAGS) $(LDFLAGS) -o $@
DEFAULT_INCLUDES = -I.@am__isrc@
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -111,6 +134,11 @@ CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(libtins_la_SOURCES)
DIST_SOURCES = $(libtins_la_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
DATA = $(pkgconfig_DATA)
HEADERS = $(libtins_include_HEADERS)
ETAGS = etags
@@ -159,6 +187,7 @@ EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
HAVE_CXX11 = @HAVE_CXX11@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -247,7 +276,11 @@ sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
@@ -262,17 +295,20 @@ libtins_la_LDFLAGS = -version-info @LIBTINS_VERSION@
AM_CXXFLAGS = -Wall -pedantic -I@LIBTINS_INCLUDE_DIR@
libtins_la_SOURCES = src/arp.cpp \
src/bootp.cpp \
src/stp.cpp \
src/pppoe.cpp \
src/crypto.cpp \
src/dhcp.cpp \
src/dhcpv6.cpp \
src/dns.cpp \
src/dns_record.cpp \
src/dot11.cpp \
src/dot3.cpp \
src/dot1q.cpp \
src/eapol.cpp \
src/ethernetII.cpp \
src/icmp.cpp \
src/icmpv6.cpp \
src/ieee802_3.cpp \
src/internals.cpp \
src/ip.cpp src/ip_address.cpp \
src/ipv6.cpp \
@@ -298,17 +334,20 @@ libtins_includedir = $(includedir)/tins
libtins_include_HEADERS = include/internals.h \
include/dhcpv6.h \
include/dot11.h \
include/dot1q.h \
include/dot3.h \
include/small_uint.h \
include/ip.h \
include/dns_record.h \
include/eapol.h \
include/tcp_stream.h \
include/pppoe.h \
include/ipv6.h \
include/icmpv6.h \
include/ieee802_3.h \
include/endianness.h \
include/rsn_information.h \
include/loopback.h \
include/ieee802_3.h \
include/ethernetII.h \
include/crypto.h \
include/packet.h \
@@ -339,7 +378,9 @@ libtins_include_HEADERS = include/internals.h \
include/ipv6_address.h \
include/constants.h \
include/utils.h \
include/cxxstd.h
include/cxxstd.h \
include/stp.h \
include/exceptions.h
all: all-am
@@ -379,11 +420,25 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
$(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
include/stamp-h1: $(top_srcdir)/include/config.h.in $(top_builddir)/config.status
@rm -f include/stamp-h1
cd $(top_builddir) && $(SHELL) ./config.status include/config.h
$(top_srcdir)/include/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
($(am__cd) $(top_srcdir) && $(AUTOHEADER))
rm -f include/stamp-h1
touch $@
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)
test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
list2=; for p in $$list; do \
if test -f $$p; then \
@@ -391,6 +446,8 @@ install-libLTLIBRARIES: $(lib_LTLIBRARIES)
else :; fi; \
done; \
test -z "$$list2" || { \
echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
$(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
}
@@ -420,17 +477,20 @@ src/$(DEPDIR)/$(am__dirstamp):
@: > src/$(DEPDIR)/$(am__dirstamp)
src/arp.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/bootp.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/stp.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/pppoe.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/crypto.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/dhcp.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/dhcpv6.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/dns.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/dns_record.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/dot11.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/dot3.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/dot1q.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/eapol.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
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/ieee802_3.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/internals.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)
@@ -477,6 +537,10 @@ mostlyclean-compile:
-rm -f src/dns_record.lo
-rm -f src/dot11.$(OBJEXT)
-rm -f src/dot11.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)
@@ -485,8 +549,6 @@ mostlyclean-compile:
-rm -f src/icmp.lo
-rm -f src/icmpv6.$(OBJEXT)
-rm -f src/icmpv6.lo
-rm -f src/ieee802_3.$(OBJEXT)
-rm -f src/ieee802_3.lo
-rm -f src/internals.$(OBJEXT)
-rm -f src/internals.lo
-rm -f src/ip.$(OBJEXT)
@@ -509,6 +571,8 @@ mostlyclean-compile:
-rm -f src/packet_writer.lo
-rm -f src/pdu.$(OBJEXT)
-rm -f src/pdu.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)
@@ -521,6 +585,8 @@ mostlyclean-compile:
-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)
@@ -541,11 +607,12 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dns.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dns_record.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dot11.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dot1q.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dot3.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/eapol.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/ethernetII.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/icmp.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/icmpv6.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/ieee802_3.Plo@am__quote@
@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@
@@ -557,12 +624,14 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/packet_sender.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/packet_writer.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/pdu.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/pppoe.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/radiotap.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/rawpdu.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/rsn_information.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/sll.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/snap.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/sniffer.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/stp.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/tcp.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/tcp_stream.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/udp.Plo@am__quote@
@@ -603,8 +672,11 @@ distclean-libtool:
-rm -f libtool config.lt
install-pkgconfigDATA: $(pkgconfig_DATA)
@$(NORMAL_INSTALL)
test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)"
@list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \
$(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \
fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
@@ -621,8 +693,11 @@ uninstall-pkgconfigDATA:
dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir)
install-libtins_includeHEADERS: $(libtins_include_HEADERS)
@$(NORMAL_INSTALL)
test -z "$(libtins_includedir)" || $(MKDIR_P) "$(DESTDIR)$(libtins_includedir)"
@list='$(libtins_include_HEADERS)'; test -n "$(libtins_includedir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(libtins_includedir)'"; \
$(MKDIR_P) "$(DESTDIR)$(libtins_includedir)" || exit 1; \
fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
@@ -788,7 +863,7 @@ distcheck: dist
*.zip*) \
unzip $(distdir).zip ;;\
esac
chmod -R a-w $(distdir); chmod a+w $(distdir)
chmod -R a-w $(distdir); chmod u+w $(distdir)
mkdir $(distdir)/_build
mkdir $(distdir)/_inst
chmod a-w $(distdir)
@@ -901,7 +976,7 @@ distclean: distclean-am
-rm -rf src/$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-libtool distclean-tags
distclean-hdr distclean-libtool distclean-tags
dvi: dvi-am
@@ -972,20 +1047,20 @@ uninstall-am: uninstall-libLTLIBRARIES \
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-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-libtins_includeHEADERS install-man install-pdf \
install-pdf-am install-pkgconfigDATA install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
pdf pdf-am ps ps-am tags uninstall uninstall-am \
uninstall-libLTLIBRARIES uninstall-libtins_includeHEADERS \
uninstall-pkgconfigDATA
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-libtins_includeHEADERS \
install-man install-pdf install-pdf-am install-pkgconfigDATA \
install-ps install-ps-am install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags uninstall uninstall-am uninstall-libLTLIBRARIES \
uninstall-libtins_includeHEADERS uninstall-pkgconfigDATA
# Tell versions [3.59,3.63) of GNU make to not export all variables.

2
README
View File

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

3
THANKS
View File

@@ -1,7 +1,4 @@
We'd like to thank the following people, who have been of great help
through the development of libtins:
- Bruno Nery <brunonery@brunonery.com> - For several bug reports and new
feature requests.
- Raúl Benencia <rbenencia@gmail.com> - For creating the Debian package.

8622
aclocal.m4 vendored

File diff suppressed because it is too large Load Diff

11
config.sub vendored
View File

@@ -4,7 +4,7 @@
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
# 2011, 2012 Free Software Foundation, Inc.
timestamp='2012-02-10'
timestamp='2012-04-18'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
@@ -225,6 +225,12 @@ case $os in
-isc*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-lynx*178)
os=-lynxos178
;;
-lynx*5)
os=-lynxos5
;;
-lynx*)
os=-lynxos
;;
@@ -1537,6 +1543,9 @@ case $basic_machine in
c4x-* | tic4x-*)
os=-coff
;;
hexagon-*)
os=-elf
;;
tic54x-*)
os=-coff
;;

872
configure vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,7 @@
AC_INIT([libtins], [0.3], [matias.fontanini@gmail.com], [libtins], [http://libtins.sourceforge.net])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AC_INIT([libtins], [1.0], [matias.fontanini@gmail.com], [libtins], [http://libtins.sourceforge.net])
AC_CANONICAL_SYSTEM
AC_CONFIG_HEADER(include/config.h)
AM_INIT_AUTOMAKE([-Wall -Werror])
LT_INIT([disable-static])
AC_CONFIG_MACRO_DIR([m4])
AM_MAINTAINER_MODE([enable])
@@ -9,25 +11,8 @@ AC_LANG(C++)
AC_PROG_LIBTOOL
if test -n "$debug"
then
CXXFLAGS="$CXXFLAGS -DTINS_DEBUG -g"
else
CXXFLAGS="$CXXFLAGS -O3"
fi
CXXFLAGS="$CXXFLAGS -Iinclude"
AC_ARG_ENABLE(
c++11,
[ --enable-c++11 enable C++11 features],
[CXXFLAGS="$CXXFLAGS -std=c++0x"]
)
# Check that libpcap exists
# Get libpcap library and include locations
AC_ARG_WITH([pcap-include-path],
[AS_HELP_STRING([--with-pcap-include-path],
[location of the libpcap headers, defaults to /usr/include/pcap])],
@@ -49,11 +34,19 @@ AC_CHECK_HEADERS([pcap.h], [], [AC_MSG_ERROR([libpcap headers are missing!])])
CPPFLAGS=$old_cppflags
# Options
AC_ARG_ENABLE(
c++11,
[ --enable-c++11 enable C++11 features],
[AX_CXX_COMPILE_STDCXX_11(noext)]
)
# Substitute options
AC_SUBST(CXXFLAGS)
AC_SUBST(LIBS)
AC_SUBST(LIBTINS_INCLUDE_DIR)
AC_SUBST([LIBTINS_VERSION], [0:3:0])
AC_SUBST([LIBTINS_VERSION], [1:0:0])
AC_CONFIG_FILES([Makefile libtins.pc])
AC_OUTPUT

124
depcomp
View File

@@ -1,10 +1,10 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2011-12-04.11; # UTC
scriptversion=2012-03-27.16; # UTC
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010,
# 2011 Free Software Foundation, Inc.
# 2011, 2012 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -28,7 +28,7 @@ scriptversion=2011-12-04.11; # UTC
case $1 in
'')
echo "$0: No command. Try \`$0 --help' for more information." 1>&2
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
@@ -40,8 +40,8 @@ as side-effects.
Environment variables:
depmode Dependency tracking mode.
source Source file read by `PROGRAMS ARGS'.
object Object file output by `PROGRAMS ARGS'.
source Source file read by 'PROGRAMS ARGS'.
object Object file output by 'PROGRAMS ARGS'.
DEPDIR directory where to store dependencies.
depfile Dependency file to output.
tmpdepfile Temporary file to use when outputting dependencies.
@@ -57,6 +57,12 @@ EOF
;;
esac
# A tabulation character.
tab=' '
# A newline character.
nl='
'
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
@@ -102,6 +108,12 @@ if test "$depmode" = msvc7msys; then
depmode=msvc7
fi
if test "$depmode" = xlc; then
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency informations.
gccflag=-qmakedep=gcc,-MF
depmode=gcc
fi
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
@@ -156,15 +168,14 @@ gcc)
## The second -e expression handles DOS-style file names with drive letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
## This next piece of magic avoids the `deleted header file' problem.
## This next piece of magic avoids the "deleted header file" problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
tr ' ' '
' < "$tmpdepfile" |
## Some versions of gcc put a space before the `:'. On the theory
tr ' ' "$nl" < "$tmpdepfile" |
## Some versions of gcc put a space before the ':'. On the theory
## that the space means something, we add a space to the output as
## well. hp depmode also adds that space, but also prefixes the VPATH
## to the object. Take care to not repeat it in the output.
@@ -203,18 +214,15 @@ sgi)
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
# the IRIX cc adds comments like `#:fec' to the end of the
# the IRIX cc adds comments like '#:fec' to the end of the
# dependency line.
tr ' ' '
' < "$tmpdepfile" \
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
tr '
' ' ' >> "$depfile"
tr "$nl" ' ' >> "$depfile"
echo >> "$depfile"
# The second pass generates a dummy entry for each header file.
tr ' ' '
' < "$tmpdepfile" \
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> "$depfile"
else
@@ -226,10 +234,17 @@ sgi)
rm -f "$tmpdepfile"
;;
xlc)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
# current directory. Also, the AIX compiler puts `$object:' at the
# current directory. Also, the AIX compiler puts '$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
@@ -259,12 +274,11 @@ aix)
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
# Each line is of the form `foo.o: dependent.h'.
# Each line is of the form 'foo.o: dependent.h'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
# '$object: dependent.h' and one to simply 'dependent.h:'.
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
# That's a tab and a space in the [].
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
@@ -275,23 +289,26 @@ aix)
;;
icc)
# Intel's C compiler understands `-MD -MF file'. However on
# icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
# Intel's C compiler anf tcc (Tiny C Compiler) understand '-MD -MF file'.
# However on
# $CC -MD -MF foo.d -c -o sub/foo.o sub/foo.c
# ICC 7.0 will fill foo.d with something like
# foo.o: sub/foo.c
# foo.o: sub/foo.h
# which is wrong. We want:
# which is wrong. We want
# sub/foo.o: sub/foo.c
# sub/foo.o: sub/foo.h
# sub/foo.c:
# sub/foo.h:
# ICC 7.1 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using \ :
# and will wrap long lines using '\':
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
# tcc 0.9.26 (FIXME still under development at the moment of writing)
# will emit a similar output, but also prepend the continuation lines
# with horizontal tabulation characters.
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
@@ -300,15 +317,21 @@ icc)
exit $stat
fi
rm -f "$depfile"
# Each line is of the form `foo.o: dependent.h',
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
# Each line is of the form 'foo.o: dependent.h',
# or 'foo.o: dep1.h dep2.h \', or ' dep3.h dep4.h \'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
sed -e 's/$/ :/' >> "$depfile"
# '$object: dependent.h' and one to simply 'dependent.h:'.
sed -e "s/^[ $tab][ $tab]*/ /" -e "s,^[^:]*:,$object :," \
< "$tmpdepfile" > "$depfile"
sed '
s/[ '"$tab"'][ '"$tab"']*/ /g
s/^ *//
s/ *\\*$//
s/^[^:]*: *//
/^$/d
/:$/d
s/$/ :/
' < "$tmpdepfile" >> "$depfile"
rm -f "$tmpdepfile"
;;
@@ -344,7 +367,7 @@ hp2)
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
# Add `dependent.h:' lines.
# Add 'dependent.h:' lines.
sed -ne '2,${
s/^ *//
s/ \\*$//
@@ -359,9 +382,9 @@ hp2)
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in `foo.d' instead, so we check for that too.
# dependencies in 'foo.d' instead, so we check for that too.
# Subdirectories are respected.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
@@ -407,8 +430,7 @@ tru64)
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
# That's a tab and a space in the [].
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
echo "#dummy" > "$depfile"
fi
@@ -443,11 +465,11 @@ msvc7)
p
}' | $cygpath_u | sort -u | sed -n '
s/ /\\ /g
s/\(.*\)/ \1 \\/p
s/\(.*\)/'"$tab"'\1 \\/p
s/.\(.*\) \\/\1:/
H
$ {
s/.*/ /
s/.*/'"$tab"'/
G
p
}' >> "$depfile"
@@ -478,7 +500,7 @@ dashmstdout)
shift
fi
# Remove `-o $object'.
# Remove '-o $object'.
IFS=" "
for arg
do
@@ -498,15 +520,14 @@ dashmstdout)
done
test -z "$dashmflag" && dashmflag=-M
# Require at least two characters before searching for `:'
# Require at least two characters before searching for ':'
# in the target name. This is to cope with DOS-style filenames:
# a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
"$@" $dashmflag |
sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
sed 's:^['"$tab"' ]*[^:'"$tab"' ][^:][^:]*\:['"$tab"' ]*:'"$object"'\: :' > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
tr ' ' '
' < "$tmpdepfile" | \
tr ' ' "$nl" < "$tmpdepfile" | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
@@ -562,8 +583,7 @@ makedepend)
# makedepend may prepend the VPATH from the source file name to the object.
# No need to regex-escape $object, excess matching of '.' is harmless.
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
sed '1,2d' "$tmpdepfile" | tr ' ' '
' | \
sed '1,2d' "$tmpdepfile" | tr ' ' "$nl" | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
@@ -583,7 +603,7 @@ cpp)
shift
fi
# Remove `-o $object'.
# Remove '-o $object'.
IFS=" "
for arg
do
@@ -652,8 +672,8 @@ msvisualcpp)
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
echo " " >> "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
echo "$tab" >> "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;

View File

@@ -32,6 +32,7 @@
#include <string>
#include <stdexcept>
#include <cstdlib>
#include <unistd.h>
#include <tins/arp.h>
#include <tins/network_interface.h>
#include <tins/utils.h>
@@ -42,23 +43,18 @@ using namespace std;
using namespace Tins;
int do_arp_spoofing(NetworkInterface iface, IPv4Address gw, IPv4Address victim,
void do_arp_spoofing(NetworkInterface iface, IPv4Address gw, IPv4Address victim,
const NetworkInterface::Info &info)
{
PacketSender sender;
EthernetII::address_type gw_hw, victim_hw;
// Resolves gateway's hardware address.
if(!Utils::resolve_hwaddr(iface, gw, &gw_hw, sender)) {
cout << "Could not resolve gateway's ip address.\n";
return 5;
}
gw_hw = Utils::resolve_hwaddr(iface, gw, sender);
// Resolves victim's hardware address.
if(!Utils::resolve_hwaddr(iface, victim, &victim_hw, sender)) {
cout << "Could not resolve victim's ip address.\n";
return 6;
}
victim_hw = Utils::resolve_hwaddr(iface, victim, sender);
// Print out the hw addresses we're using.
cout << " Using gateway hw address: " << gw_hw << "\n";
cout << " Using victim hw address: " << victim_hw << "\n";
@@ -76,12 +72,12 @@ int do_arp_spoofing(NetworkInterface iface, IPv4Address gw, IPv4Address victim,
* We include our hw address as the source address
* in ethernet layer, to avoid possible packet dropping
* performed by any routers. */
EthernetII to_gw(iface, gw_hw, info.hw_addr, gw_arp);
EthernetII to_victim(iface, victim_hw, info.hw_addr, victim_arp);
EthernetII to_gw(gw_hw, info.hw_addr, gw_arp);
EthernetII to_victim(victim_hw, info.hw_addr, victim_arp);
while(true) {
// Just send them once every 5 seconds.
sender.send(to_gw);
sender.send(to_victim);
sender.send(to_gw, iface);
sender.send(to_victim, iface);
sleep(5);
}
}
@@ -115,7 +111,7 @@ int main(int argc, char *argv[]) {
return 3;
}
try {
return do_arp_spoofing(iface, gw, victim, info);
do_arp_spoofing(iface, gw, victim, info);
}
catch(std::runtime_error &ex) {
std::cout << "Runtime error: " << ex.what() << std::endl;

View File

@@ -33,6 +33,7 @@
#include <string>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h>
#include <tins/ip.h>
#include <tins/tcp.h>
#include <tins/ip_address.h>
@@ -96,8 +97,8 @@ void send_syns(const NetworkInterface &iface, IPv4Address dest_ip, const vector<
// Pretend we're the scanned host...
ip.src_addr(dest_ip);
// We use an ethernet pdu, otherwise the kernel will drop it.
EthernetII eth(iface, info.hw_addr, info.hw_addr, ip.clone());
sender.send(eth);
EthernetII eth(info.hw_addr, info.hw_addr, ip.clone());
sender.send(eth, iface);
}
void *thread_proc(void *param) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -82,8 +82,14 @@ namespace Tins {
const hwaddress_type &sender_hw = hwaddress_type());
/**
* \brief Constructor which creates an ARP object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \brief Constructs an ARP object from a buffer.
*
* If there is not enough size for an ARP header in the buffer,
* a malformed_packet exception is thrown.
*
* If the buffer is bigger than the size of the ARP header,
* then the extra data is stored in a RawPDU.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
@@ -230,34 +236,32 @@ namespace Tins {
PDUType pdu_type() const { return PDU::ARP; }
/**
* \brief Creates an ARP Request within a Layer 2 PDU using uint32_t for target and sender.
* \brief Creates an ARP Request within an EthernetII PDU.
*
* Creates an ARP Request PDU and embeds it within a Layer 2 PDU ready to be
* sent. The target and sender's protocol address are given using uint32_t.
* sent.
*
* \param iface string with the interface from where to send the ARP.
* \param target IPv4Address with the target's IP.
* \param sender IPv4Address with the sender's IP.
* \param hw_snd uint8_t array of 6 bytes containing the sender's hardware address.
* \return Returns a EthernetII containing the ARP Request.
*/
static EthernetII make_arp_request(const NetworkInterface& iface, ipaddress_type target,
static EthernetII make_arp_request(ipaddress_type target,
ipaddress_type sender, const hwaddress_type &hw_snd = hwaddress_type());
/**
* \brief Creates an ARP Reply within a Layer 2 PDU using uint32_t for target and sender.
* \brief Creates an ARP Reply within an EthernetII PDU.
*
* Creates an ARP Reply PDU and embeds it within a Layer 2 PDU ready to be
* sent. The target and sender's protocol address are given using uint32_t.
* sent.
*
* \param iface string with the interface from where to send the ARP.
* \param target IPv4Address with the target's IP.
* \param sender IPv4Address with the sender's IP.
* \param hw_tgt uint8_t array of 6 bytes containing the target's hardware address.
* \param hw_snd uint8_t array of 6 bytes containing the sender's hardware address.
* \return Returns an EthetnetII containing the ARP Replay.
*/
static EthernetII make_arp_reply(const NetworkInterface& iface, ipaddress_type target,
static EthernetII make_arp_reply(ipaddress_type target,
ipaddress_type sender, const hwaddress_type &hw_tgt = hwaddress_type(),
const hwaddress_type &hw_snd = hwaddress_type());
@@ -267,17 +271,7 @@ namespace Tins {
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(uint8_t *ptr, uint32_t total_sz);
/** \brief Clones this pdu, filling the corresponding header with data
* extracted from a buffer.
*
* \param ptr The pointer to the from from which the data will be extracted.
* \param total_sz The size of the buffer.
* \return The cloned PDU.
* \sa PDU::clone_packet
*/
PDU *clone_packet(const uint8_t *ptr, uint32_t total_sz);
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \sa PDU::clone

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -84,8 +84,11 @@ namespace Tins {
BootP();
/**
* \brief Constructor which creates a BootP object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \brief Constructs a BootP object from a buffer .
*
* If there's not enough size for a BootP header, then a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
* \param vend_field_size The vend field size to allocate.
@@ -293,6 +296,17 @@ namespace Tins {
*/
void vend(const vend_type &new_vend);
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* This returns true, if the xid field is equal.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type

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

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -84,6 +84,7 @@ namespace Tins {
VLAN = 0x8100, /* IEEE 802.1Q VLAN tagging */
IPX = 0x8137, /* IPX */
IPV6 = 0x86dd, /* IP protocol version 6 */
PPPOED = 0x8863, /* PPPoE Discovery */
EAPOL = 0x888e, /* EAPOL */
LOOPBACK = 0x9000 /* used to test interfaces */
};

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,6 +30,8 @@
#ifndef TINS_CXXSTD_H
#define TINS_CXXSTD_H
#include <memory>
#ifdef __GXX_EXPERIMENTAL_CXX0X__
#define TINS_CXXSTD_GCC_FIX 1
#else
@@ -38,4 +40,17 @@
#define TINS_IS_CXX11 (__cplusplus > 199711L || TINS_CXXSTD_GCC_FIX == 1)
namespace Tins{
namespace Internals {
template<typename T>
struct smart_ptr {
#if TINS_IS_CXX11
typedef std::unique_ptr<T> type;
#else
typedef std::auto_ptr<T> type;
#endif
};
}
}
#endif // TINS_CXXSTD_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,6 +35,7 @@
#include <string>
#include "bootp.h"
#include "pdu_option.h"
#include "cxxstd.h"
namespace Tins {
/**
@@ -66,7 +67,7 @@ namespace Tins {
/**
* \brief DHCP options enum.
*/
enum Options {
enum OptionTypes {
PAD,
SUBNET_MASK,
TIME_OFFSET,
@@ -142,12 +143,12 @@ namespace Tins {
/**
* The DHCP option type.
*/
typedef PDUOption<uint8_t> dhcp_option;
typedef PDUOption<uint8_t> option;
/**
* The type used to store the DHCP options.
*/
typedef std::list<dhcp_option> options_type;
typedef std::list<option> options_type;
/**
* \brief Creates an instance of DHCP.
@@ -158,8 +159,12 @@ namespace Tins {
DHCP();
/**
* \brief Constructor which creates a DHCP object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \brief Constructs a DHCP object from a buffer.
*
* If there is not enough size for a BootP header, or any of
* the TLV options contain an invalid size field, then a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
* Subclasses might use 0 to provide their own interpretation of this field.
@@ -168,16 +173,30 @@ namespace Tins {
/**
* \brief Adds a new option to this DHCP PDU.
* \param option The option to be added.
* \param opt The option to be added.
*/
void add_option(const dhcp_option &option);
void add_option(const option &opt);
#if TINS_IS_CXX11
/**
* \brief Adds a new option to this DHCP PDU.
*
* The option is move-constructed.
*
* \param opt The option to be added.
*/
void add_option(option &&opt) {
internal_add_option(opt);
_options.push_back(std::move(opt));
}
#endif
/**
* \brief Searchs for an option that matchs the given flag.
* \param opt_flag The flag to be searched.
* \return A pointer to the option, or 0 if it was not found.
*/
const dhcp_option *search_option(Options opt) const;
const option *search_option(OptionTypes opt) const;
/**
* \brief Adds a type option the the option list.
@@ -401,17 +420,18 @@ namespace Tins {
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
template<class T>
T generic_search(Options opt, type2type<T>) const {
const dhcp_option *option = search_option(opt);
T generic_search(OptionTypes opt, type2type<T>) const {
const option *option = search_option(opt);
if(option && option->data_size() == sizeof(T))
return *(const T*)option->data_ptr();
else
throw option_not_found();
}
std::list<ipaddress_type> generic_search(Options opt, type2type<std::list<ipaddress_type> >) const;
std::string generic_search(Options opt, type2type<std::string>) const;
ipaddress_type generic_search(Options opt, type2type<ipaddress_type>) const;
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);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -46,79 +46,7 @@ public:
/**
* Represents a DHCPv6 option.
*/
class dhcpv6_option {
public:
typedef std::vector<uint8_t> container_type;
typedef container_type::value_type data_type;
typedef uint16_t option_type;
/**
* \brief Constructs a PDUOption.
* \param opt The option type.
* \param length The option's data length.
* \param data The option's data(if any).
*/
dhcpv6_option(option_type opt = 0, size_t length = 0, const data_type *data = 0)
: option_(opt), option_size_(length) {
if(data)
value_.insert(value_.end(), data, data + length);
}
/**
* \brief Constructs a PDUOption from iterators, which
* indicate the data to be stored in it.
*
* \param opt The option type.
* \param start The beginning of the option data.
* \param end The end of the option data.
*/
template<typename ForwardIterator>
dhcpv6_option(option_type opt, ForwardIterator start, ForwardIterator end)
: option_(opt), option_size_(std::distance(start, end))
{
value_.insert(value_.end(), start, end);
}
/**
* Retrieves this option's type.
* \return uint8_t containing this option's size.
*/
uint16_t option() const {
return option_;
}
/**
* Sets this option's type
* \param opt The option type to be set.
*/
void option(uint16_t opt) {
option_ = opt;
}
/**
* Retrieves this option's data.
*
* If this method is called when data_size() == 0,
* dereferencing the returned pointer will result in undefined
* behaviour.
*
* \return const data_type& containing this option's value.
*/
const data_type *data_ptr() const {
return &*value_.begin();
}
/**
* Retrieves the length of this option's data.
*/
uint16_t data_size() const {
return option_size_;
}
private:
option_type option_;
uint16_t option_size_;
container_type value_;
};
typedef PDUOption<uint16_t> option;
/**
* The message types.
@@ -146,7 +74,7 @@ public:
/**
* The DHCPv6 options.
*/
enum Option {
enum OptionTypes {
CLIENTID = 1,
SERVERID,
IA_NA,
@@ -226,7 +154,7 @@ public:
/**
* The type used to store the DHCPv6 options.
*/
typedef std::list<dhcpv6_option> options_type;
typedef std::list<option> options_type;
/**
* The type used to store IP addresses.
@@ -438,7 +366,7 @@ public:
/**
* The type used to store the Option Request option.
*/
typedef std::vector<Option> option_request_type;
typedef std::vector<OptionTypes> option_request_type;
/**
* The type used to store the Relay Message option.
@@ -456,9 +384,12 @@ public:
DHCPv6();
/**
* \brief Constructor which constructs a DHCPv6 object from a buffer
* and adds all identifiable PDUs found in the buffer as children
* of this one.
* \brief Constructs a DHCPv6 object from a buffer.
*
* If there is not enough size for the DHCPv6 header, or any
* of the TLV options contains an invalid size field, a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
@@ -851,9 +782,9 @@ public:
* The option is added after the last option in the option
* fields.
*
* \param option The option to be added
* \param opt The option to be added
*/
void add_option(const dhcpv6_option &option);
void add_option(const option &opt);
/**
* \brief Searchs for an option that matchs the given flag.
@@ -864,7 +795,7 @@ public:
*
* \param id The option identifier to be searched.
*/
const dhcpv6_option *search_option(Option id) const;
const option *search_option(OptionTypes id) const;
// PDU stuff
@@ -875,6 +806,15 @@ public:
*/
uint32_t header_size() const;
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
@@ -889,11 +829,11 @@ public:
}
private:
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
uint8_t* write_option(const dhcpv6_option &option, uint8_t* buffer) const;
uint8_t* write_option(const option &option, uint8_t* buffer) const;
template<template <typename> class Functor>
const dhcpv6_option *safe_search_option(Option opt, uint32_t size) const {
const dhcpv6_option *option = search_option(opt);
const option *safe_search_option(OptionTypes opt, uint32_t size) const {
const option *option = search_option(opt);
if(!option || Functor<uint32_t>()(option->data_size(), size))
throw option_not_found();
return option;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -252,7 +252,11 @@ namespace Tins {
DNS();
/**
* \brief Constructor which creates a DNS object from a buffer.
* \brief Constructs a DNS object from a buffer.
*
* If there's not enough size for the DNS header, or any of the
* records are malformed, a malformed_packet is be thrown.
*
* \param buffer The buffer from which this PDU will be
* constructed.
* \param total_sz The total size of the buffer.
@@ -566,6 +570,15 @@ namespace Tins {
*/
resources_type answers() const;
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \sa PDU::clone
*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,7 +37,17 @@
#include "macros.h"
namespace Tins {
class DNSRRImpl;
/**
* \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.
@@ -68,6 +78,10 @@ public:
/**
* \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.
*/
@@ -104,12 +118,23 @@ public:
/**
* Move constructor.
*/
DNSResourceRecord(DNSResourceRecord &&rhs) noexcept;
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;
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
/**
@@ -198,18 +223,6 @@ private:
DNSRRImpl *impl;
};
/**
* \cond
*/
class DNSRRImpl {
public:
virtual ~DNSRRImpl() {}
virtual uint32_t size() const = 0;
virtual uint32_t do_write(uint8_t *buffer) const = 0;
virtual bool matches(const std::string &dname) const { return false; }
virtual DNSRRImpl *clone() const = 0;
};
class OffsetedDNSRRImpl : public DNSRRImpl {
public:
OffsetedDNSRRImpl(uint16_t off);

File diff suppressed because it is too large Load Diff

209
include/dot1q.h Normal file
View File

@@ -0,0 +1,209 @@
/*
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_DOT1Q_H
#define TINS_DOT1Q_H
#include "pdu.h"
#include "endianness.h"
#include "small_uint.h"
namespace Tins {
class Dot1Q : public PDU {
public:
/**
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::DOT1Q;
/**
* Default constructor
*/
Dot1Q(small_uint<12> tag_id = 0, bool append_pad = true);
/**
* \brief Constructs a Dot1Q object from a buffer and adds all
* identifiable PDUs found in the buffer as children of this
* one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for a Dot1Q header in the buffer,
* a malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
Dot1Q(const uint8_t *buffer, uint32_t total_sz);
// Getters
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \brief Returns the frame's trailer size.
* \return The trailer's size.
*/
uint32_t trailer_size() const;
/**
* \brief Getter for the priority field.
* \return The stored priority field value.
*/
small_uint<3> priority() const {
return _header.priority;
}
/**
* \brief Getter for the cfi field.
* \return The stored cfi field value.
*/
small_uint<1> cfi() const {
return _header.cfi;
}
/**
* \brief Getter for the id field.
* \return The stored id field value.
*/
small_uint<12> id() const {
#if TINS_IS_LITTLE_ENDIAN
return _header.idL | (_header.idH << 8);
#else
return _header.id;
#endif
}
/**
* \brief Getter for the payload type field.
* \return The stored type field value.
*/
uint16_t payload_type() const {
return Endian::be_to_host(_header.type);
}
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \sa PDU::clone
*/
Dot1Q *clone() const {
return new Dot1Q(*this);
}
/**
* \brief Retrieves the flag indicating whether padding will be
* appended at the end of this packet.
*/
bool append_padding() const {
return _append_padding;
}
// Setters
/**
* \brief Setter for the priority field.
* \param new_priority The new priority field value.
*/
void priority(small_uint<3> new_priority);
/**
* \brief Setter for the cfi field.
* \param new_cfi The new cfi field value.
*/
void cfi(small_uint<1> new_cfi);
/**
* \brief Setter for the id field.
* \param new_id The new id field value.
*/
void id(small_uint<12> new_id);
/**
* \brief Setter for the payload type field.
* \param new_type The new type field value.
*/
void payload_type(uint16_t new_type);
/**
* \brief Indicates whether the appropriate padding will be
* at the end of the packet.
*
* This flag could be disabled in case two or more contiguous Dot1Q
* PDUs are added to a packet. In that case, only the Dot1Q which is
* closer to the link layer should add the padding at the end.
*
* \param value A boolean indicating whether padding will be appended.
*/
void append_padding(bool value);
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
private:
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
TINS_BEGIN_PACK
struct dot1q_hdr {
#if TINS_IS_BIG_ENDIAN
uint16_t priority:3,
cfi:1,
id:12;
uint16_t type;
#else
uint16_t idH:4,
cfi:1,
priority:3,
idL:8;
uint16_t type;
#endif
} TINS_END_PACK;
static uint16_t get_id(const dot1q_hdr *hdr);
dot1q_hdr _header;
bool _append_padding;
};
}
#endif // TINS_DOT1Q_H

193
include/dot3.h Normal file
View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -67,6 +67,12 @@ namespace Tins {
/**
* \brief Static method to instantiate the correct EAPOL subclass
* based on a raw buffer.
*
* If no valid EAPOL type is detected, a null pointer is returned.
*
* \sa RC4EAPOL
* \sa RSNEAPOL
*
* \param buffer The buffer from which the data will be taken.
* \param total_sz The total size of the buffer.
*/
@@ -197,12 +203,16 @@ namespace Tins {
static const size_t key_sign_size = 16;
/**
* \brief Creates an instance of RC4EAPOL
* \brief Default constructor.
*/
RC4EAPOL();
/**
* \brief Constructor which creates an RC4EAPOL object from a buffer.
* \brief Constructs a RC4EAPOL object from a buffer.
*
* If there is not enough size for a RC4EAPOL header in the
* buffer, a malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
@@ -396,7 +406,11 @@ namespace Tins {
RSNEAPOL();
/**
* \brief Constructor which creates an RSNEAPOL object from a buffer.
* \brief Constructs a RSNEAPOL object from a buffer.
*
* If there is not enough size for the RSNEAPOL header, a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,7 +35,6 @@
#include "pdu.h"
#include "endianness.h"
#include "hw_address.h"
#include "network_interface.h"
namespace Tins {
@@ -60,24 +59,23 @@ namespace Tins {
static const address_type BROADCAST;
/**
* \brief Constructor for creating an ethernet PDU
* \brief Constructs an ethernet II PDU.
*
* Constructor that builds an ethernet PDU taking the interface name,
* destination's and source's MAC.
*
* \param iface string containing the interface's name from where to send the packet.
* \param dst_hw_addr address_type containing the destination's MAC(optional).
* \param src_hw_addr address_type containing the source's MAC(optional).
* \param child PDU* with the PDU contained by the ethernet PDU (optional).
* \param dst_hw_addr address_type containing the destination's MAC.
* \param src_hw_addr address_type containing the source's MAC.
*/
EthernetII(const NetworkInterface& iface = NetworkInterface(),
const address_type &dst_hw_addr = address_type(),
const address_type &src_hw_addr = address_type(),
PDU* child = 0);
EthernetII(const address_type &dst_hw_addr = address_type(),
const address_type &src_hw_addr = address_type());
/**
* \brief Constructor which creates an EthernetII object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \brief Constructs a EthernetII object from a buffer and adds
* all identifiable PDUs found in the buffer as children of
* this one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for a EthernetII header in the
* buffer, a malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
@@ -100,13 +98,6 @@ namespace Tins {
*/
address_type src_addr() const { return _eth.src_mac; }
/**
* \brief Getter for the interface.
*
* \return Returns the interface in which this PDU will be sent.
*/
const NetworkInterface &iface() const { return _iface; }
/**
* \brief Getter for the payload_type
* \return The payload type.
@@ -129,13 +120,6 @@ namespace Tins {
*/
void src_addr(const address_type &new_src_addr);
/**
* \brief Setter for the interface.
*
* \param new_iface the interface to be set.
*/
void iface(const NetworkInterface& new_iface);
/**
* \brief Setter for the payload type.
*
@@ -157,24 +141,25 @@ namespace Tins {
/**
* \sa PDU::send()
*/
void send(PacketSender &sender);
void send(PacketSender &sender, const NetworkInterface &iface);
#endif // WIN32
/** \brief Check wether ptr points to a valid response for this PDU.
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(uint8_t *ptr, uint32_t total_sz);
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
#ifndef WIN32
/** \brief Receives a matching response for this packet.
/**
* \brief Receives a matching response for this packet.
*
* \sa PDU::recv_response
* \param sender The packet sender which will receive the packet.
*/
PDU *recv_response(PacketSender &sender);
PDU *recv_response(PacketSender &sender, const NetworkInterface &iface);
#endif // WIN32
/**
@@ -183,16 +168,6 @@ namespace Tins {
*/
PDUType pdu_type() const { return PDU::ETHERNET_II; }
/** \brief Clones this pdu, filling the corresponding header with data
* extracted from a buffer.
*
* \param ptr The pointer to the from from which the data will be extracted.
* \param total_sz The size of the buffer.
* \return The cloned PDU.
* \sa PDU::clone_packet
*/
PDU *clone_packet(const uint8_t *ptr, uint32_t total_sz);
/**
* \sa PDU::clone
*/
@@ -213,7 +188,6 @@ namespace Tins {
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
ethhdr _eth;
NetworkInterface _iface;
};
}

129
include/exceptions.h Normal file
View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -71,8 +71,13 @@ namespace Tins {
ICMP(Flags flag = ECHO_REQUEST);
/**
* \brief Constructor which creates an ICMP object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \brief Constructs an ICMP object from a buffer.
*
* If there is not enough size for an ICMP header, a
* malformed_packet exception is thrown.
*
* Any extra data in the buffer will be stored in a RawPDU.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
@@ -274,7 +279,7 @@ namespace Tins {
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(uint8_t *ptr, uint32_t total_sz);
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \brief Getter for the PDU's type.
@@ -282,17 +287,6 @@ namespace Tins {
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::ICMP; }
/**
* \brief Clones this pdu, filling the corresponding header with data
* extracted from a buffer.
*
* \param ptr The pointer to the from from which the data will be extracted.
* \param total_sz The size of the buffer.
* \return The cloned PDU.
* \sa PDU::clone_packet
*/
PDU *clone_packet(const uint8_t *ptr, uint32_t total_sz);
/**
* \sa PDU::clone

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,7 @@
#include "small_uint.h"
#include "hw_address.h"
#include "small_uint.h"
#include "cxxstd.h"
namespace Tins {
/**
@@ -83,7 +84,7 @@ public:
/**
* The types of ICMPv6 options.
*/
enum Options {
enum OptionTypes {
SOURCE_ADDRESS = 1,
TARGET_ADDRESS,
PREFIX_INFO,
@@ -134,12 +135,12 @@ public:
/**
* The type used to represent ICMPv6 options.
*/
typedef PDUOption<uint8_t> icmpv6_option;
typedef PDUOption<uint8_t> option;
/**
* The type used to store options.
*/
typedef std::list<icmpv6_option> options_type;
typedef std::list<option> options_type;
/**
* \brief The type used to store the new home agent information
@@ -429,8 +430,12 @@ public:
ICMPv6(Types tp = ECHO_REQUEST);
/**
* \brief Constructor which creates an ICMP object from a buffer and
* adds all identifiable PDUs found in the buffer as children of this one.
* \brief Constructs an ICMPv6 object from a buffer.
*
* If there is not enough size for an ICMPv6 header, a
* malformed_packet exception is thrown.
*
* Any extra data is stored in a RawPDU.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
@@ -736,7 +741,21 @@ public:
*
* \param option The option to be added
*/
void add_option(const icmpv6_option &option);
void add_option(const option &option);
#if TINS_IS_CXX11
/**
* \brief Adds an ICMPv6 option.
*
* The option is move-constructed.
*
* \param option The option to be added.
*/
void add_option(option &&option) {
internal_add_option(option);
_options.push_back(std::move(option));
}
#endif
/**
* \brief Returns the header size.
@@ -745,6 +764,15 @@ public:
* payload and options size. \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \brief Searchs for an option that matchs the given flag.
@@ -755,7 +783,7 @@ public:
*
* \param id The option identifier to be searched.
*/
const icmpv6_option *search_option(Options id) const;
const option *search_option(OptionTypes id) const;
/**
* \sa PDU::clone
@@ -1181,16 +1209,17 @@ private:
};
} TINS_END_PACK;
void internal_add_option(const option &option);
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
bool has_options() const;
uint8_t *write_option(const icmpv6_option &opt, uint8_t *buffer);
uint8_t *write_option(const option &opt, uint8_t *buffer);
void parse_options(const uint8_t *&buffer, uint32_t &total_sz);
void add_addr_list(uint8_t type, const addr_list_type &value);
addr_list_type search_addr_list(Options type) const;
addr_list_type search_addr_list(OptionTypes type) const;
template<template <typename> class Functor>
const icmpv6_option *safe_search_option(Options opt, uint32_t size) const {
const icmpv6_option *option = search_option(opt);
const option *safe_search_option(OptionTypes opt, uint32_t size) const {
const option *option = search_option(opt);
if(!option || Functor<uint32_t>()(option->data_size(), size))
throw option_not_found();
return option;

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -57,6 +57,8 @@ namespace Internals {
PDU *pdu_from_flag(Constants::Ethernet::e flag, const uint8_t *buffer,
uint32_t size, bool rawpdu_on_no_match = true);
PDU *pdu_from_flag(PDU::PDUType type, const uint8_t *buffer, uint32_t size);
Constants::Ethernet::e pdu_flag_to_ether_type(PDU::PDUType flag);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,6 +37,7 @@
#include "ip_address.h"
#include "pdu_option.h"
#include "macros.h"
#include "cxxstd.h"
namespace Tins {
@@ -168,7 +169,7 @@ namespace Tins {
/**
* The IP options type.
*/
typedef PDUOption<option_identifier> ip_option;
typedef PDUOption<option_identifier> option;
/**
* The type of the security option.
@@ -217,7 +218,7 @@ namespace Tins {
/**
* The type used to store IP options.
*/
typedef std::list<ip_option> options_type;
typedef std::list<option> options_type;
/**
* \brief Constructor for building the IP PDU.
@@ -228,17 +229,18 @@ namespace Tins {
*
* \param ip_dst The destination ip address(optional).
* \param ip_src The source ip address(optional).
* \param child pointer to a PDU which will be set as the inner_pdu
* for the packet being constructed(optional).
*/
IP(address_type ip_dst = address_type(),
address_type ip_src = address_type(),
PDU *child = 0);
address_type ip_src = address_type());
/**
* \brief Constructor which constructs an IP object from a buffer
* and adds all identifiable PDUs found in the buffer as children
* of this one.
* \brief Constructs an IP object from a buffer and adds all
* identifiable PDUs found in the buffer as children of this
* one.
*
* If there is not enough size for an IP header, a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
@@ -302,7 +304,7 @@ namespace Tins {
*
* \return The checksum for this IP PDU.
*/
uint16_t check() const { return Endian::be_to_host(_ip.check); }
uint16_t checksum() const { return Endian::be_to_host(_ip.check); }
/**
* \brief Getter for the source address field.
@@ -380,13 +382,6 @@ namespace Tins {
*/
void protocol(uint8_t new_protocol);
/**
* \brief Setter for the checksum field.
*
* \param new_check The new checksum.
*/
void check(uint16_t new_check);
/**
* \brief Setter for the source address field.
*
@@ -414,9 +409,23 @@ namespace Tins {
* The option is added after the last option in the option
* fields.
*
* \param option The option to be added
* \param opt The option to be added
*/
void add_option(const ip_option &option);
void add_option(const option &opt);
#if TINS_IS_CXX11
/**
* \brief Adds an IP option.
*
* The option is move-constructed.
*
* \param opt The option to be added.
*/
void add_option(option &&opt) {
internal_add_option(opt);
_ip_options.push_back(std::move(opt));
}
#endif
/**
* \brief Searchs for an option that matchs the given flag.
@@ -427,7 +436,7 @@ namespace Tins {
*
* \param id The option identifier to be searched.
*/
const ip_option *search_option(option_identifier id) const;
const option *search_option(option_identifier id) const;
// Option setters
@@ -554,7 +563,7 @@ namespace Tins {
/**
* \sa PDU::send()
*/
void send(PacketSender &sender);
void send(PacketSender &sender, const NetworkInterface &);
/**
* \brief Check wether ptr points to a valid response for this PDU.
@@ -563,7 +572,7 @@ namespace Tins {
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(uint8_t *ptr, uint32_t total_sz);
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \brief Receives a matching response for this packet.
@@ -571,7 +580,7 @@ namespace Tins {
* \sa PDU::recv_response
* \param sender The packet sender which will receive the packet.
*/
PDU *recv_response(PacketSender &sender);
PDU *recv_response(PacketSender &sender, const NetworkInterface &);
/**
* \brief Getter for the PDU's type.
@@ -579,17 +588,6 @@ namespace Tins {
*/
PDUType pdu_type() const { return PDU::IP; }
/**
* \brief Clones this pdu, filling the corresponding header with data
* extracted from a buffer.
*
* \param ptr The pointer to the from from which the data will be extracted.
* \param total_sz The size of the buffer.
* \return The cloned PDU.
* \sa PDU::clone_packet
*/
PDU *clone_packet(const uint8_t *ptr, uint32_t total_sz);
/**
* \sa PDU::clone
*/
@@ -620,15 +618,18 @@ namespace Tins {
/*The options start here. */
} TINS_END_PACK;
void prepare_for_serialize(const PDU *parent);
void internal_add_option(const option &option);
void init_ip_fields();
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
uint8_t* write_option(const ip_option &opt, uint8_t* buffer);
uint8_t* write_option(const option &opt, uint8_t* buffer);
void add_route_option(option_identifier id, const generic_route_option_type &data);
generic_route_option_type search_route_option(option_identifier id) const;
void checksum(uint16_t new_check);
iphdr _ip;
uint16_t _options_size, _padded_options_size;
options_type _ip_options;
uint32_t _options_size, _padded_options_size;
};
}

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -60,12 +60,12 @@ public:
/**
* The type used to represent IPv6 extension headers.
*/
typedef PDUOption<uint8_t> ipv6_ext_header;
typedef PDUOption<uint8_t> ext_header;
/**
* The type used to store the extension headers.
*/
typedef std::list<ipv6_ext_header> headers_type;
typedef std::list<ext_header> headers_type;
/**
* The values used to identify extension headers.
@@ -82,17 +82,6 @@ public:
NO_NEXT_HEADER = 59
};
/**
* Exception thrown when an invalid extension header size is
* encountered.
*/
class header_size_error : public std::exception {
public:
const char *what() const throw() {
return "Not enough size for an extension header";
}
};
/**
* \brief Constructs an IPv6 object.
*
@@ -106,9 +95,11 @@ public:
PDU *child = 0);
/**
* \brief Constructor which creates an IPv6 object from a buffer and
* adds all identifiable PDUs found in the buffer as children of this
* one.
* \brief Constructs an IPv6 object from a buffer and adds all
* identifiable PDUs found in the buffer as children of this one.
*
* If there is not enough size for an IPv6 header, a malformed_packet
* exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
@@ -257,6 +248,15 @@ public:
*/
uint32_t header_size() const;
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \sa PDU::clone
*/
@@ -274,7 +274,7 @@ public:
/**
* \sa PDU::send()
*/
void send(PacketSender &sender);
void send(PacketSender &sender, const NetworkInterface &);
#endif
/**
@@ -282,7 +282,7 @@ public:
*
* \param header The extension header to be added.
*/
void add_ext_header(const ipv6_ext_header &header);
void add_ext_header(const ext_header &header);
/**
* \brief Searchs for an extension header that matchs the given
@@ -294,11 +294,11 @@ public:
*
* \param id The header identifier to be searched.
*/
const ipv6_ext_header *search_header(ExtensionHeader id) const;
const ext_header *search_header(ExtensionHeader id) const;
private:
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
void set_last_next_header(uint8_t value);
static uint8_t *write_header(const ipv6_ext_header &header, uint8_t *buffer);
static uint8_t *write_header(const ext_header &header, uint8_t *buffer);
static bool is_extension_header(uint8_t header_id);
TINS_BEGIN_PACK

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -90,22 +90,25 @@ namespace Tins {
};
/**
* \brief Creates an instance of LLC
* \param child The child PDU.(optional)
* \brief Default constructor.
*/
LLC(PDU *child = 0);
LLC();
/**
* \brief Creates an instance of LLC, setting the dsap and ssap.
* The control field is set all to 0.
* @param dsap The dsap value to be set.
* @param ssap The ssap value to be set.
* \brief Constructs an instance of LLC, setting the dsap and ssap.
* The control field is set to 0.
* \param dsap The dsap value to be set.
* \param ssap The ssap value to be set.
*/
LLC(uint8_t dsap, uint8_t ssap, PDU* child = 0);
LLC(uint8_t dsap, uint8_t ssap);
/**
* \brief Constructor which creates a LLC object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \brief Constructs a LLC object from a buffer and adds all
* identifiable PDUs found in the buffer as children of this one.
*
* If there is not enough size for a LLC header, a malformed_packet
* exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
@@ -376,7 +379,6 @@ namespace Tins {
typedef std::vector<uint8_t> field_type;
void copy_fields(const LLC *other);
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
llchdr _header;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,7 +32,6 @@
#include "pdu.h"
#include "macros.h"
#include "network_interface.h"
namespace Tins {
class Loopback : public PDU {
@@ -48,20 +47,16 @@ public:
* The family identifier is left as zero.
*/
Loopback();
/**
* \brief Construct a Loopback object.
*
* The NetworkInterface object will only be used in *BSD, where
* Null/Loopback PDUs can actually be sent.
*
* \param iface The network interface in which to send this PDU.
* \param inner_pdu The inner pdu to be set.
*/
Loopback(const NetworkInterface &iface, PDU *inner_pdu = 0);
/**
* \brief Construct a Loopback object from a buffer.
* \brief Construct a Loopback object from a buffer and adds
* all identifiable PDUs found in the buffer as children of
* this one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for a Loopback header, a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
@@ -91,18 +86,6 @@ public:
*/
PDUType pdu_type() const { return PDU::IP; }
/**
* \brief Getter for the interface member.
*/
const NetworkInterface &iface() const { return _iface; }
/**
* \brief Setter for the interface member.
*
* \param new_iface The new interface to be set.
*/
void iface(const NetworkInterface &new_iface);
/**
* \sa PDU::clone
*/
@@ -114,13 +97,12 @@ public:
/**
* \sa PDU::send()
*/
void send(PacketSender &sender);
void send(PacketSender &sender, const NetworkInterface &iface);
#endif // BSD
private:
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
uint32_t _family;
NetworkInterface _iface;
};
}

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -38,6 +38,7 @@
#include <map>
#include "network_interface.h"
#include "macros.h"
#include "cxxstd.h"
struct timeval;
struct sockaddr;
@@ -63,7 +64,9 @@ namespace Tins {
*/
enum SocketType {
ETHER_SOCKET,
IP_SOCKET,
IP_TCP_SOCKET,
IP_UDP_SOCKET,
IP_RAW_SOCKET,
ARP_SOCKET,
ICMP_SOCKET,
IPV6_SOCKET,
@@ -75,7 +78,40 @@ namespace Tins {
*
* \param recv_timeout The timeout which will be used when receiving responses.
*/
PacketSender(uint32_t recv_timeout = DEFAULT_TIMEOUT, uint32_t usec = 0);
PacketSender(const NetworkInterface &iface = NetworkInterface(),
uint32_t recv_timeout = DEFAULT_TIMEOUT, uint32_t usec = 0);
#if TINS_IS_CXX11
/**
* \brief Move constructor.
* \param rhs The sender to be moved.
*/
PacketSender(PacketSender &&rhs) noexcept {
*this = std::move(rhs);
}
/**
* \brief Move assignment operator.
* \param rhs The sender to be moved.
*/
PacketSender& operator=(PacketSender &&rhs) noexcept {
_sockets = std::move(rhs._sockets);
rhs._sockets = std::vector<int>(SOCKETS_END, INVALID_RAW_SOCKET);
#ifndef WIN32
#if defined(BSD) || defined(__FreeBSD_kernel__)
_ether_socket = std::move(rhs._ether_socket);
#else
_ether_socket = rhs._ether_socket;
rhs._ether_socket = INVALID_RAW_SOCKET;
#endif
#endif
_types = rhs._types; // no move
_timeout = rhs._timeout;
_timeout_usec = rhs._timeout_usec;
default_iface = rhs.default_iface;
return *this;
}
#endif
/**
* \brief PacketSender destructor.
@@ -88,7 +124,7 @@ namespace Tins {
/**
* \brief Opens a layer 2 socket.
*
* If this operation fails, then a SocketOpenError will be thrown.
* If this operation fails, then a socket_open_error will be thrown.
*/
void open_l2_socket(const NetworkInterface& iface = NetworkInterface());
#endif // WIN32
@@ -97,9 +133,9 @@ namespace Tins {
* \brief Opens a layer 3 socket, using the corresponding protocol
* for the given flag.
*
* If this operation fails, then a SocketOpenError will be thrown.
* If the provided socket type is not valid, a InvalidSocketTypeError
* will be throw.
* If this operation fails, then a socket_open_error will be thrown.
* If the provided socket type is not valid, an invalid_socket_type
* exception will be throw.
*
* \param type The type of socket which will be used to pick the protocol flag
* for this socket.
@@ -110,26 +146,63 @@ namespace Tins {
* \brief Closes the socket associated with the given flag.
*
* If the provided type is invalid, meaning no such open socket
* exists, a InvalidSocketTypeError is thrown.
* exists, an invalid_socket_type exception is thrown.
*
* If any socket close errors are encountered, a SocketCloseError
* If any socket close errors are encountered, a socket_close_error
* is thrown.
*
* \param type The type of the socket to be closed.
*/
void close_socket(SocketType type, const NetworkInterface &iface = NetworkInterface());
/**
* \brief Sets the default interface.
*
* The interface will be used whenever PacketSender::send(PDU&)
* is called.
*/
void default_interface(const NetworkInterface &iface);
/**
* \brief Gets the default interface.
*
* \sa PacketSender::default_interface
*/
const NetworkInterface& default_interface();
/**
* \brief Sends a PDU.
*
* This method opens the appropriate socket, if it's not open yet,
* and sends the PDU on the open socket.
*
* If any send error occurs, then a SocketWriteError is thrown.
* If any send error occurs, then a socket_write_error is thrown.
*
* If the PDU contains a link layer protocol, then default_interface
* is used.
*
* \sa PacketSender::default_interface
*
* \param pdu The PDU to be sent.
*/
void send(PDU &pdu);
/**
* \brief Sends a PDU.
*
* \sa PacketSender::send
*
* This overload takes a NetworkInterface. The packet is sent
* through that interface if a link-layer PDU is present,
* otherwise this call is equivalent to send(PDU&).
*
* The interface stored in the link layer PDU(if any), is restored
* after this method ends.
*
* \param pdu The PDU to be sent.
* \param iface The network interface to use.
*/
void send(PDU &pdu, const NetworkInterface &iface);
/**
* \brief Sends a PDU and waits for its response.
@@ -143,6 +216,20 @@ namespace Tins {
* \return Returns the response PDU, 0 if not response was received.
*/
PDU *send_recv(PDU &pdu);
/**
* \brief Sends a PDU and waits for its response.
*
* This method is used to send PDUs and receive their response.
* It opens the required socket(if it's not open yet). This can be used
* to expect responses for ICMP, ARP, and such packets that are normally
* answered by the host that receives the packet.
*
* \param pdu The PDU to send.
* \param iface The network interface in which to send and receive.
* \return Returns the response PDU, 0 if not response was received.
*/
PDU *send_recv(PDU &pdu, const NetworkInterface &iface);
#ifndef WIN32
/**
@@ -166,7 +253,7 @@ namespace Tins {
* using the corresponding flag, according to the given type of
* protocol.
*
* If any socket write error occurs, a SocketWriteError is thrown.
* If any socket write error occurs, a socket_write_error is thrown.
*
* \param pdu The PDU to send.
* \param link_addr The sockaddr struct which will be used to send the PDU.
@@ -196,7 +283,7 @@ namespace Tins {
* This method sends a layer 3 PDU, using a raw socket, open using the corresponding flag,
* according to the given type of protocol.
*
* If any socket write error occurs, a SocketWriteError is thrown.
* If any socket write error occurs, a socket_write_error is thrown.
*
* \param pdu The PDU to send.
* \param link_addr The sockaddr struct which will be used to send the PDU.
@@ -209,18 +296,24 @@ namespace Tins {
typedef std::map<SocketType, int> SocketTypeMap;
PacketSender(const PacketSender&);
PacketSender& operator=(const PacketSender&);
int find_type(SocketType type);
int timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y);
#ifndef WIN32
bool ether_socket_initialized(const NetworkInterface& iface = NetworkInterface()) const;
int get_ether_socket(const NetworkInterface& iface = NetworkInterface());
bool ether_socket_initialized(const NetworkInterface& iface = NetworkInterface()) const;
int get_ether_socket(const NetworkInterface& iface = NetworkInterface());
#endif
template<typename T>
void send(PDU &pdu, const NetworkInterface &iface) {
static_cast<T&>(pdu).send(*this, iface);
}
PDU *recv_match_loop(int sock, PDU &pdu, struct sockaddr* link_addr, uint32_t addrlen);
std::vector<int> _sockets;
#ifndef WIN32
#ifdef BSD
#if defined(BSD) || defined(__FreeBSD_kernel__)
typedef std::map<uint32_t, int> BSDEtherSockets;
BSDEtherSockets _ether_socket;
#else
@@ -229,32 +322,7 @@ namespace Tins {
#endif
SocketTypeMap _types;
uint32_t _timeout, _timeout_usec;
};
class SocketOpenError : public std::runtime_error {
public:
SocketOpenError(const std::string &msg)
: std::runtime_error(msg) { }
};
class SocketCloseError : public std::runtime_error {
public:
SocketCloseError(const std::string &msg)
: std::runtime_error(msg) { }
};
class SocketWriteError : public std::runtime_error {
public:
SocketWriteError(const std::string &msg)
: std::runtime_error(msg) { }
};
class InvalidSocketTypeError : public std::exception {
public:
const char *what() const throw() {
return "The provided socket type is invalid";
}
NetworkInterface default_iface;
};
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -55,6 +55,7 @@ public:
RADIOTAP = DLT_IEEE802_11_RADIO,
DOT11 = DLT_IEEE802_11,
ETH2 = DLT_EN10MB,
DOT3 = DLT_EN10MB,
SLL = DLT_LINUX_SLL
};
@@ -75,7 +76,9 @@ public:
*
* \param rhs The PacketWriter to be moved.
*/
PacketWriter(PacketWriter &&rhs) noexcept;
PacketWriter(PacketWriter &&rhs) noexcept {
*this = std::move(rhs);
}
/**
* \brief Move assignment operator.
@@ -85,7 +88,13 @@ 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);
std::swap(dumper, rhs.dumper);
return *this;
}
#endif
/**
@@ -98,6 +107,18 @@ public:
*/
void write(PDU &pdu);
/**
* \brief Writes a PDU to this file.
*
* The template parameter T must at some point yield a PDU& after
* applying operator* one or more than one time. This accepts both
* raw and smartpointers.
*/
template<typename T>
void write(T &pdu) {
write(Utils::dereference_until_pdu(pdu));
}
/**
* \brief Writes all the PDUs in the range [start, end)
* \param start A forward iterator pointing to the first PDU

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,12 +33,21 @@
#include <stdint.h>
#include <vector>
#include "macros.h"
#include "cxxstd.h"
#include "exceptions.h"
/** \brief The Tins namespace.
*/
namespace Tins {
class PacketSender;
class NetworkInterface;
/**
* The type used to store several PDU option values.
*/
typedef std::vector<uint8_t> byte_array;
/** \brief Base class for protocol data units.
*
@@ -54,7 +63,7 @@ namespace Tins {
/**
* The type that will be returned when serializing PDUs.
*/
typedef std::vector<uint8_t> serialization_type;
typedef byte_array serialization_type;
/**
* \brief Enum which identifies each type of PDU.
@@ -105,18 +114,42 @@ namespace Tins {
IPv6,
ICMPv6,
SLL,
DHCPv6
DHCPv6,
DOT1Q,
PPPOE,
STP
};
/** \brief PDU constructor
*
* Must be called by subclasses in their constructors.
* \param flag The flag identifier for the subclass' PDU.
* \param next_pdu The child PDU. Can be obviated.
/**
* \brief Default constructor.
*/
PDU(PDU *next_pdu = 0);
PDU();
#if TINS_IS_CXX11
/**
* \brief Move constructor.
*
* \param rhs The PDU to be moved.
*/
PDU(PDU &&rhs) noexcept
: _inner_pdu(0)
{
std::swap(_inner_pdu, rhs._inner_pdu);
}
/**
* \brief Move assignment operator.
*
* \param rhs The PDU to be moved.
*/
PDU& operator=(PDU &&rhs) noexcept {
std::swap(_inner_pdu, rhs._inner_pdu);
return *this;
}
#endif
/** \brief PDU destructor.
/**
* \brief PDU destructor.
*
* Deletes the inner pdu, as a consequence every child pdu is
* deleted.
@@ -163,11 +196,21 @@ namespace Tins {
/**
* \brief Sets the child PDU.
*
* \param next_pdu The new child PDU.
* When setting a new inner_pdu, the instance takesownership of
* the object, therefore deleting it when it's no longer required.
*
* \param next_pdu The new child PDU.
*/
void inner_pdu(PDU *next_pdu);
/**
* \brief Sets the child PDU.
*
* The PDU parameter is cloned using PDU::clone.
*
* \param next_pdu The new child PDU.
*/
void inner_pdu(const PDU &next_pdu);
/**
@@ -182,14 +225,14 @@ namespace Tins {
serialization_type serialize();
/**
* \brief Find and returns the first PDU that matches the given flag.
* \brief Finds and returns the first PDU that matches the given flag.
*
* This method searches for the first PDU which has the same type flag as
* the given one. If the first PDU matches that flag, it is returned.
* If no PDU matches, 0 is returned.
* \param flag The flag which being searched.
*/
template<class T>
template<typename T>
T *find_pdu(PDUType type = T::pdu_flag) {
PDU *pdu = this;
while(pdu) {
@@ -201,15 +244,42 @@ namespace Tins {
}
/**
* \brief Find and returns the first PDU that matches the given flag.
* \brief Finds and returns the first PDU that matches the given flag.
*
* \param flag The flag which being searched.
*/
template<class T>
template<typename T>
const T *find_pdu(PDUType type = T::pdu_flag) const {
return const_cast<PDU*>(this)->find_pdu<T>();
}
/**
* \brief Finds and returns the first PDU that matches the given flag.
*
* If the PDU is not found, a pdu_not_found exception is thrown.
*
* \sa PDU::find_pdu
*
* \param flag The flag which being searched.
*/
template<typename T>
T &rfind_pdu(PDUType type = T::pdu_flag) {
T *ptr = find_pdu<T>(type);
if(!ptr)
throw pdu_not_found();
return *ptr;
}
/**
* \brief Finds and returns the first PDU that matches the given flag.
*
* \param flag The flag which being searched.
*/
template<typename T>
const T &rfind_pdu(PDUType type = T::pdu_flag) const {
return const_cast<PDU*>(this)->rfind_pdu<T>();
}
/**
* \brief Clones this packet.
*
@@ -220,25 +290,37 @@ namespace Tins {
*/
virtual PDU *clone() const = 0;
/** \brief Send the stack of PDUs through a PacketSender.
/**
* \brief Send the stack of PDUs through a PacketSender.
*
* This method will be called only for the PDU on the bottom of the stack,
* therefore it should only implement this method if it can be sent.
*
* PacketSender implements specific methods to send packets which start
* on every valid TCP/IP stack layer; this should only be a proxy for
* those methods.
*
* If this PDU does not represent a link layer protocol, then
* the interface argument will be ignored.
*
* \param sender The PacketSender which will send the packet.
* \param iface The network interface in which this packet will
* be sent.
*/
virtual void send(PacketSender &sender);
virtual void send(PacketSender &sender, const NetworkInterface &iface);
/** \brief Receives a matching response for this packet.
/**
* \brief Receives a matching response for this packet.
*
* This method should act as a proxy for PacketSender::recv_lX methods.
*
* \param sender The packet sender which will receive the packet.
* \param iface The interface in which to expect the response.
*/
virtual PDU *recv_response(PacketSender &sender);
virtual PDU *recv_response(PacketSender &sender, const NetworkInterface &iface);
/** \brief Check wether ptr points to a valid response for this PDU.
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* This method must check wether the buffer pointed by ptr is a valid
* response for this PDU. If it is valid, then it might want to propagate
@@ -247,7 +329,9 @@ namespace Tins {
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
virtual bool matches_response(uint8_t *ptr, uint32_t total_sz) { return false; }
virtual bool matches_response(const uint8_t *ptr, uint32_t total_sz) const {
return false;
}
/**
* \brief Check wether this PDU matches the specified flag.
@@ -267,15 +351,6 @@ namespace Tins {
* \return Returns the PDUType corresponding to the PDU.
*/
virtual PDUType pdu_type() const = 0;
/** \brief Clones this pdu, filling the corresponding header with data
* extracted from a buffer.
*
* \param ptr The pointer to the from from which the data will be extracted.
* \param total_sz The size of the buffer.
* \return The cloned PDU.
*/
virtual PDU *clone_packet(const uint8_t *ptr, uint32_t total_sz) { return 0; }
protected:
/**
* \brief Copy constructor.
@@ -293,6 +368,20 @@ namespace Tins {
*/
void copy_inner_pdu(const PDU &pdu);
/**
* \brief Prepares this PDU for serialization.
*
* This method is called before the inner PDUs are serialized.
* It's useful in situations such as when serializing IP PDUs,
* which don't contain any link layer encapsulation, and therefore
* require to set the source IP address before the TCP/UDP checksum
* is calculated.
*
* By default, this method does nothing
*
* \param parent The parent PDU.
*/
virtual void prepare_for_serialize(const PDU *parent) { }
/**
* \brief Serializes this PDU and propagates this action to child PDUs.
@@ -303,16 +392,6 @@ namespace Tins {
*/
void serialize(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
/**
* \brief Clones the inner pdu(if any).
*
* This method clones the inner pdu using data from a buffer.
* \param ptr The pointer from which the child PDU must be cloned.
* \param total_sz The total size of the buffer.
* \return Returns the cloned PDU. Will be 0 if cloning failed.
*/
PDU *clone_inner_pdu(const uint8_t *ptr, uint32_t total_sz);
/**
* \brief Serializes this TCP PDU.
*

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,18 +33,9 @@
#include <vector>
#include <iterator>
#include <stdint.h>
#include "exceptions.h"
namespace Tins {
/**
* \brief Exception thrown when an option is not found.
*/
class option_not_found : public std::exception {
public:
const char* what() const throw() {
return "Option not found";
}
};
/**
* \class PDUOption
* \brief Represents a PDU option field.
@@ -75,10 +66,8 @@ public:
* \param data The option's data(if any).
*/
PDUOption(option_type opt = option_type(), size_t length = 0, const data_type *data = 0)
: option_(opt) {
value_.push_back(length);
if(data)
value_.insert(value_.end(), data, data + length);
: option_(opt), size_(length), value_(data, data + (data ? length : 0)) {
}
/**
@@ -91,9 +80,29 @@ public:
*/
template<typename ForwardIterator>
PDUOption(option_type opt, ForwardIterator start, ForwardIterator end)
: option_(opt) {
value_.push_back(std::distance(start, end));
value_.insert(value_.end(), start, end);
: option_(opt), size_(std::distance(start, end)), value_(start, end) {
}
/**
* \brief Constructs a PDUOption from iterators, which
* indicate the data to be stored in it.
*
* The length parameter indicates the contents of the length field
* when this option is serialized. Note that this can be different
* to std::distance(start, end).
*
* \sa length_field
*
* \param opt The option type.
* \param length The length of this option.
* \param start The beginning of the option data.
* \param end The end of the option data.
*/
template<typename ForwardIterator>
PDUOption(option_type opt, size_t length, ForwardIterator start, ForwardIterator end)
: option_(opt), size_(length), value_(start, end) {
}
/**
@@ -122,17 +131,36 @@ public:
* \return const data_type& containing this option's value.
*/
const data_type *data_ptr() const {
return &*(++value_.begin());
return &*value_.begin();
}
/**
* Retrieves the length of this option's data.
* \brief Retrieves the length of this option's data.
*
* This is the actual size of the data.
*/
size_t data_size() const {
return value_.empty() ? 0 : (value_.size() - 1);
return value_.size();
}
/**
* \brief Retrieves the data length field.
*
* This is what the size field will contain when this option is
* serialized. It can differ from the actual data size.
*
* This will be equal to data_size unless the constructor that takes
* both a data length and two iterators is used.
*
* \sa data_size.
*/
size_t length_field() const {
return size_;
}
private:
option_type option_;
uint16_t size_;
container_type value_;
};
} // namespace Tins

436
include/pppoe.h Normal file
View File

@@ -0,0 +1,436 @@
/*
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_PPPoE_H
#define TINS_PPPoE_H
#include <list>
#include <string>
#include <vector>
#include "pdu.h"
#include "endianness.h"
#include "small_uint.h"
#include "pdu_option.h"
#include "cxxstd.h"
namespace Tins {
class PPPoE : public PDU {
public:
/**
* The tag types enum.
*/
enum TagTypes {
END_OF_LIST = 0,
SERVICE_NAME = 0x101,
#if TINS_IS_LITTLE_ENDIAN
AC_NAME = 0x201,
HOST_UNIQ = 0x301,
AC_COOKIE = 0x401,
VENDOR_SPECIFIC = 0x501,
RELAY_SESSION_ID = 0x101,
SERVICE_NAME_ERROR = 0x201,
AC_SYSTEM_ERROR = 0x202,
GENERIC_ERROR = 0x302
#else
AC_NAME = 0x102,
HOST_UNIQ = 0x103,
AC_COOKIE = 0x104,
VENDOR_SPECIFIC = 0x105,
RELAY_SESSION_ID = 0x110,
SERVICE_NAME_ERROR = 0x201,
AC_SYSTEM_ERROR = 0x202,
GENERIC_ERROR = 0x203
#endif
};
/**
* The type used to store a TLV option.
*/
typedef PDUOption<TagTypes> tag;
/**
* The type used to store the options.
*/
typedef std::list<tag> tags_type;
/**
* The type used to store the Vendor-Specific tag's value.
*/
struct vendor_spec_type {
typedef std::vector<uint8_t> data_type;
uint32_t vendor_id;
data_type data;
vendor_spec_type(uint32_t vendor_id = 0, const data_type &data = data_type())
: vendor_id(vendor_id), data(data) { }
};
/**
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::PPPOE;
/**
* \brief Default constructor.
*
* This sets the version and type fields to 0x1.
*/
PPPoE();
/**
* \brief Constructor which creates an PPPoE object from a buffer.
*
* If there is not enough size for a PPPoE header, a malformed_packet
* exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
PPPoE(const uint8_t *buffer, uint32_t total_sz);
// Getters
/**
* \brief Getter for the version field.
* \return The stored version field value.
*/
small_uint<4> version() const {
return _header.version;
}
/**
* \brief Getter for the type field.
* \return The stored type field value.
*/
small_uint<4> type() const {
return _header.type;
}
/**
* \brief Getter for the code field.
* \return The stored code field value.
*/
uint8_t code() const {
return _header.code;
}
/**
* \brief Getter for the session_id field.
* \return The stored session_id field value.
*/
uint16_t session_id() const {
return Endian::be_to_host(_header.session_id);
}
/**
* \brief Getter for the payload_length field.
* \return The stored payload_length field value.
*/
uint16_t payload_length() const {
return Endian::be_to_host(_header.payload_length);
}
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \brief Returns the list of tags.
*/
const tags_type &tags() const {
return _tags;
}
/**
* \sa PDU::clone
*/
PPPoE *clone() const {
return new PPPoE(*this);
}
const tag *search_tag(TagTypes identifier) const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
// Setters
/**
* \brief Setter for the version field.
* \param new_version The new version field value.
*/
void version(small_uint<4> new_version);
/**
* \brief Setter for the type field.
* \param new_type The new type field value.
*/
void type(small_uint<4> new_type);
/**
* \brief Setter for the code field.
* \param new_code The new code field value.
*/
void code(uint8_t new_code);
/**
* \brief Setter for the session_id field.
* \param new_session_id The new session_id field value.
*/
void session_id(uint16_t new_session_id);
/**
* \brief Setter for the payload_length field.
* \param new_payload_length The new payload_length field value.
*/
void payload_length(uint16_t new_payload_length);
/**
* \brief Adds a PPPoE tag.
*
* \param option The option to be added.
*/
void add_tag(const tag &option);
#if TINS_IS_CXX11
/**
* \brief Adds a PPPoE tag.
*
* This move-constructs the option.
*
* \param option The option to be added.
*/
void add_tag(tag &&option) {
_tags_size += option.data_size() + sizeof(uint16_t) * 2;
_tags.push_back(std::move(option));
}
#endif
// Option setters
/**
* \brief Adds an end-of-list tag.
*/
void end_of_list();
/**
* \brief Adds a service-name tag.
*
* \param value The service name.
*/
void service_name(const std::string &value);
/**
* \brief Adds a AC-name tag.
*
* \param value The AC name.
*/
void ac_name(const std::string &value);
/**
* \brief Adds a host-uniq tag.
*
* \param value The tag's value.
*/
void host_uniq(const byte_array &value);
/**
* \brief Adds a AC-Cookie tag.
*
* \param value The tag's value.
*/
void ac_cookie(const byte_array &value);
/**
* \brief Adds a Vendor-Specific tag.
*
* \param value The tag's value.
*/
void vendor_specific(const vendor_spec_type &value);
/**
* \brief Adds a Relay-Session-Id tag.
*
* \param value The tag's value.
*/
void relay_session_id(const byte_array &value);
/**
* \brief Adds a Service-Name-Error tag.
*
* \param value The tag's value.
*/
void service_name_error(const std::string &value);
/**
* \brief Adds a AC-System-Error tag.
*
* \param value The tag's value.
*/
void ac_system_error(const std::string &value);
/**
* \brief Adds a Generic-Error tag.
*
* \param value The tag's value.
*/
void generic_error(const std::string &value);
// Option getters
/**
* \brief Getter for the service-name tag.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
std::string service_name() const;
/**
* \brief Getter for the AC-name tag.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
std::string ac_name() const;
/**
* \brief Getter for the host-uniq tag.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
byte_array host_uniq() const;
/**
* \brief Getter for the AC-Cookie tag.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
byte_array ac_cookie() const;
/**
* \brief Getter for the Vendor-Specific tag.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
vendor_spec_type vendor_specific() const;
/**
* \brief Getter for the Vendor-Specific tag.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
byte_array relay_session_id() const;
/**
* \brief Getter for the Service-Name-Error tag.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
std::string service_name_error() const;
/**
* \brief Getter for the AC-System-Error tag.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
std::string ac_system_error() const;
/**
* \brief Getter for the Generic-Error tag.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
std::string generic_error() const;
private:
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
template<typename T>
void add_tag_iterable(TagTypes id, const T &data) {
add_tag(
tag(
id,
data.begin(),
data.end()
)
);
}
template<typename T>
T retrieve_tag_iterable(TagTypes id) const {
const tag *tag = search_tag(id);
if(!tag)
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;
}
TINS_BEGIN_PACK
struct pppoe_hdr {
#if TINS_IS_LITTLE_ENDIAN
uint8_t version:4,
type:4;
uint8_t code;
#else
uint16_t version:4,
type:4,
code:8;
#endif
uint16_t session_id;
uint16_t payload_length;
} TINS_END_PACK;
pppoe_hdr _header;
tags_type _tags;
uint16_t _tags_size;
};
}
#endif // TINS_PPPoE_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,7 +33,6 @@
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
#include "network_interface.h"
namespace Tins {
class PacketSender;
@@ -108,16 +107,17 @@ namespace Tins {
};
/**
* \brief Creates an instance of RadioTap.
* \param iface The interface in which to send this PDU.
* \param child The child PDU.(optional)
* \brief Default constructor.
*/
RadioTap(const NetworkInterface &iface = NetworkInterface(),
PDU *child = 0);
RadioTap();
/**
* \brief Constructor which creates a RadioTap object from a buffer and adds all
* \brief Constructs a RadioTap object from a buffer and adds all
* identifiable PDUs found in the buffer as children of this one.
*
* If there is not enough size for a RadioTap header, a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
@@ -129,7 +129,7 @@ namespace Tins {
/**
* \sa PDU::send()
*/
void send(PacketSender &sender);
void send(PacketSender &sender, const NetworkInterface &iface);
#endif
/**
@@ -292,6 +292,14 @@ namespace Tins {
return (PresentFlags)*(uint32_t*)(&_radio.it_len + 1);
}
/** \brief Check wether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \brief Returns the RadioTap frame's header length.
*
@@ -357,13 +365,13 @@ namespace Tins {
flags:1,
tsft:1,
reserved3:1,
tx_attenuation:1,
rx_flags:1,
db_tx_attenuation:1,
dbm_tx_attenuation:1,
antenna:1,
db_signal:1,
db_noise:1,
rx_flags:1,
tx_attenuation:1,
reserved2:5,
channel_plus:1,
reserved1:2,
@@ -377,7 +385,6 @@ namespace Tins {
radiotap_hdr _radio;
NetworkInterface _iface;
// present fields...
uint64_t _tsft;
uint32_t _channel_type;

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -89,7 +89,10 @@ namespace Tins{
RSNInformation(const serialization_type &buffer);
/**
* \brief Constructor from 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.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -54,9 +54,14 @@ public:
SLL();
/**
* \brief Constructor which constructs an SLL object from a buffer
* and adds all identifiable PDUs found in the buffer as children
* of this one.
* \brief Constructs a SLL object from a buffer and adds all
* identifiable PDUs found in the buffer as children of this one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for a SLL header in the
* buffer, a malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -56,13 +56,18 @@ namespace Tins {
* \brief Creates an instance of SNAP
* This constructor sets the dsap and ssap fields to 0xaa, and
* the id field to 3.
* \param child The child PDU.(optional)
*/
SNAP(PDU *child = 0);
SNAP();
/**
* \brief Constructor which creates a SNAP object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \brief Constructs a SNAP object from a buffer and adds all
* identifiable PDUs found in the buffer as children of this one.
*
* If the next PDU is not recognized, then a RawPDU is used.
*
* If there is not enough size for a SNAP header in the
* buffer, a malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -42,8 +42,10 @@
#include "packet.h"
#include "loopback.h"
#include "dot11.h"
#include "dot3.h"
#include "sll.h"
#include "cxxstd.h"
#include "exceptions.h"
namespace Tins {
/**
@@ -63,13 +65,25 @@ namespace Tins {
* \brief Move constructor.
* This constructor is available only in C++11.
*/
BaseSniffer(BaseSniffer &&rhs) noexcept;
BaseSniffer(BaseSniffer &&rhs) noexcept
{
*this = std::move(rhs);
}
/**
* \brief Move assignment operator.
* This opeartor is available only in C++11.
*/
BaseSniffer& operator=(BaseSniffer &&rhs) noexcept;
BaseSniffer& operator=(BaseSniffer &&rhs) noexcept
{
handle = 0;
mask = rhs.mask;
iface_type = rhs.iface_type;
actual_filter.bf_insns = 0;
std::swap(handle, rhs.handle);
std::swap(actual_filter, rhs.actual_filter);
return *this;
}
#endif
/**
@@ -192,9 +206,25 @@ namespace Tins {
: handle(_handle), c_handler(_handler), iface_type(if_type)
{ }
};
struct PCapLoopBreaker {
bool &went_well;
pcap_t *handle;
PCapLoopBreaker(bool &went_well, pcap_t *handle)
: went_well(went_well), handle(handle) { }
~PCapLoopBreaker() {
if(!went_well)
pcap_breakloop(handle);
}
};
BaseSniffer(const BaseSniffer&);
BaseSniffer &operator=(const BaseSniffer&);
static bool is_dot3(const uint8_t *ptr, size_t sz) {
return (sz >= 13 && ptr[12] < 8);
}
template<class ConcretePDU, class Functor>
static bool call_functor(LoopData<Functor> *data, const u_char *packet, const struct pcap_pkthdr *header);
@@ -268,16 +298,22 @@ namespace Tins {
template<class Functor>
void Tins::BaseSniffer::callback_handler(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) {
bool ret_val(true);
LoopData<Functor> *data = reinterpret_cast<LoopData<Functor>*>(args);
PCapLoopBreaker _(ret_val, data->handle);
try {
std::auto_ptr<PDU> pdu;
LoopData<Functor> *data = reinterpret_cast<LoopData<Functor>*>(args);
bool ret_val(false);
if(data->iface_type == DLT_EN10MB)
ret_val = call_functor<Tins::EthernetII>(data, packet, header);
Internals::smart_ptr<PDU>::type pdu;
if(data->iface_type == DLT_EN10MB) {
ret_val = is_dot3((const uint8_t*)packet, header->caplen) ?
call_functor<Tins::Dot3>(data, packet, header) :
call_functor<Tins::EthernetII>(data, packet, header);
}
else if(data->iface_type == DLT_IEEE802_11_RADIO)
ret_val = call_functor<Tins::RadioTap>(data, packet, header);
else if(data->iface_type == DLT_IEEE802_11) {
std::auto_ptr<PDU> pdu(Tins::Dot11::from_bytes((const uint8_t*)packet, header->caplen));
Internals::smart_ptr<PDU>::type pdu(
Tins::Dot11::from_bytes((const uint8_t*)packet, header->caplen)
);
if(pdu.get()) {
RefPacket pck(*pdu, header->ts);
ret_val = data->c_handler(pck);
@@ -287,12 +323,12 @@ namespace Tins {
ret_val = call_functor<Tins::Loopback>(data, packet, header);
else if(data->iface_type == DLT_LINUX_SLL)
ret_val = call_functor<Tins::SLL>(data, packet, header);
if(!ret_val)
pcap_breakloop(data->handle);
}
catch(std::runtime_error&) {
catch(malformed_packet&) {
ret_val = true;
}
catch(pdu_not_found&) {
ret_val = true;
}
}

307
include/stp.h Normal file
View File

@@ -0,0 +1,307 @@
/*
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_STP_H
#define TINS_STP_H
#include "pdu.h"
#include "endianness.h"
#include "hw_address.h"
#include "small_uint.h"
namespace Tins {
class STP : public PDU {
public:
/**
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::STP;
/**
* The type used to store BPDU identifier addresses.
*/
typedef HWAddress<6> address_type;
/**
* The type used to store the BPDU identifiers.
*/
struct bpdu_id_type {
small_uint<4> priority;
small_uint<12> ext_id;
address_type id;
bpdu_id_type(small_uint<4> priority=0, small_uint<12> ext_id=0,
const address_type& id=address_type())
: priority(priority), ext_id(ext_id), id(id) { }
};
/**
* \brief Default constructor.
*/
STP();
/**
* \brief Constructs a STP object from a buffer.
*
* If there is not enough size for a STP header, a malformed_packet
* exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
STP(const uint8_t *buffer, uint32_t total_sz);
// Getters
/**
* \brief Getter for the proto_id field.
* \return The stored proto_id field value.
*/
uint16_t proto_id() const {
return Endian::be_to_host(_header.proto_id);
}
/**
* \brief Getter for the proto_version field.
* \return The stored proto_version field value.
*/
uint8_t proto_version() const {
return _header.proto_version;
}
/**
* \brief Getter for the bpdu_type field.
* \return The stored bpdu_type field value.
*/
uint8_t bpdu_type() const {
return _header.bpdu_type;
}
/**
* \brief Getter for the bpdu_flags field.
* \return The stored bpdu_flags field value.
*/
uint8_t bpdu_flags() const {
return _header.bpdu_flags;
}
/**
* \brief Getter for the root_path_cost field.
* \return The stored root_path_cost field value.
*/
uint32_t root_path_cost() const {
return Endian::be_to_host(_header.root_path_cost);
}
/**
* \brief Getter for the port_id field.
* \return The stored port_id field value.
*/
uint16_t port_id() const {
return Endian::be_to_host(_header.port_id);
}
/**
* \brief Getter for the msg_age field.
* \return The stored msg_age field value.
*/
uint16_t msg_age() const {
return Endian::be_to_host(_header.msg_age) / 256;
}
/**
* \brief Getter for the max_age field.
* \return The stored max_age field value.
*/
uint16_t max_age() const {
return Endian::be_to_host(_header.max_age) / 256;
}
/**
* \brief Getter for the hello_time field.
* \return The stored hello_time field value.
*/
uint16_t hello_time() const {
return Endian::be_to_host(_header.hello_time) / 256;
}
/**
* \brief Getter for the fwd_delay field.
* \return The stored fwd_delay field value.
*/
uint16_t fwd_delay() const {
return Endian::be_to_host(_header.fwd_delay) / 256;
}
/**
* \brief Getter for the root id field.
* \return The stored root id field value.
*/
bpdu_id_type root_id() const;
/**
* \brief Getter for the bridge id field.
* \return The stored bridge id field value.
*/
bpdu_id_type bridge_id() const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \sa PDU::clone
*/
STP *clone() const {
return new STP(*this);
}
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;
// Setters
/**
* \brief Setter for the proto_id field.
* \param new_proto_id The new proto_id field value.
*/
void proto_id(uint16_t new_proto_id);
/**
* \brief Setter for the proto_version field.
* \param new_proto_version The new proto_version field value.
*/
void proto_version(uint8_t new_proto_version);
/**
* \brief Setter for the bpdu_type field.
* \param new_bpdu_type The new bpdu_type field value.
*/
void bpdu_type(uint8_t new_bpdu_type);
/**
* \brief Setter for the bpdu_flags field.
* \param new_bpdu_flags The new bpdu_flags field value.
*/
void bpdu_flags(uint8_t new_bpdu_flags);
/**
* \brief Setter for the root_path_cost field.
* \param new_root_path_cost The new root_path_cost field value.
*/
void root_path_cost(uint32_t new_root_path_cost);
/**
* \brief Setter for the port_id field.
* \param new_port_id The new port_id field value.
*/
void port_id(uint16_t new_port_id);
/**
* \brief Setter for the msg_age field.
* \param new_msg_age The new msg_age field value.
*/
void msg_age(uint16_t new_msg_age);
/**
* \brief Setter for the max_age field.
* \param new_max_age The new max_age field value.
*/
void max_age(uint16_t new_max_age);
/**
* \brief Setter for the hello_time field.
* \param new_hello_time The new hello_time field value.
*/
void hello_time(uint16_t new_hello_time);
/**
* \brief Setter for the fwd_delay field.
* \param new_fwd_delay The new fwd_delay field value.
*/
void fwd_delay(uint16_t new_fwd_delay);
/**
* \brief Setter for the root id field.
* \param new_fwd_delay The new root id field value.
*/
void root_id(const bpdu_id_type &id);
/**
* \brief Setter for the bridge id field.
* \param new_fwd_delay The new bridge id field value.
*/
void bridge_id(const bpdu_id_type &id);
private:
TINS_BEGIN_PACK
struct pvt_bpdu_id {
#if TINS_IS_LITTLE_ENDIAN
// fixme
uint16_t ext_id:4,
priority:4,
ext_idL:8;
#else
uint16_t priority:4,
ext_id:12;
#endif
uint8_t id[6];
} TINS_END_PACK;
TINS_BEGIN_PACK
struct stphdr {
uint16_t proto_id;
uint8_t proto_version;
uint8_t bpdu_type;
uint8_t bpdu_flags;
pvt_bpdu_id root_id;
uint32_t root_path_cost;
pvt_bpdu_id bridge_id;
uint16_t port_id;
uint16_t msg_age;
uint16_t max_age;
uint16_t hello_time;
uint16_t fwd_delay;
} TINS_END_PACK;
static bpdu_id_type convert(const pvt_bpdu_id &id);
static pvt_bpdu_id convert(const bpdu_id_type &id);
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
stphdr _header;
};
}
#endif // TINS_STP_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -41,6 +41,7 @@
#include "endianness.h"
#include "small_uint.h"
#include "pdu_option.h"
#include "cxxstd.h"
namespace Tins {
/**
@@ -78,8 +79,7 @@ namespace Tins {
*
* This enum identifies valid options supported by TCP PDU.
*/
enum Option {
enum OptionTypes {
EOL = 0,
NOP = 1,
MSS = 2,
@@ -99,12 +99,15 @@ namespace Tins {
CHK_16FLETCHER
};
typedef PDUOption<uint8_t> tcp_option;
/**
* The type used to store TCP options.
*/
typedef PDUOption<uint8_t> option;
/**
* The type used to store the options.
*/
typedef std::list<tcp_option> options_type;
typedef std::list<option> options_type;
/**
* The type used to store the sack option.
@@ -122,9 +125,14 @@ namespace Tins {
TCP(uint16_t dport = 0, uint16_t sport = 0);
/**
* \brief Constructor which creates an TCP object from a buffer
* and adds all identifiable PDUs found in the buffer as children
* of this one.
* \brief Constructs TCP object from a buffer.
*
* If there is not enough size for a TCP header, or any of the
* TLV options are malformed a malformed_packet exception is
* thrown.
*
* Any extra data will be stored in a RawPDU.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
@@ -170,7 +178,7 @@ namespace Tins {
*
* \return The checksum field in an uint16_t.
*/
uint16_t check() const { return Endian::be_to_host(_tcp.check); }
uint16_t checksum() const { return Endian::be_to_host(_tcp.check); }
/**
* \brief Getter for the urgent pointer field.
@@ -238,13 +246,6 @@ namespace Tins {
*/
void window(uint16_t new_window);
/**
* \brief Setter for the checksum field.
*
* \param new_check The new checksum.
*/
void check(uint16_t new_check);
/**
* \brief Setter for the urgent pointer field.
*
@@ -351,15 +352,27 @@ namespace Tins {
* \param value The new value for this flag. Must be 0 or 1.
*/
void set_flag(Flags tcp_flag, small_uint<1> value);
/**
* \brief Adds a TCP option.
*
* \param option The option type flag to be set.
* \param length The length of this option(optional).
* \param data Pointer to this option's data(optional).
* \param option The option to be added.
*/
void add_option(Option option, uint8_t length = 0, const uint8_t *data = 0);
void add_option(const option &opt);
#if TINS_IS_CXX11
/**
* \brief Adds a TCP option.
*
* This move-constructs the option.
*
* \param option The option to be added.
*/
void add_option(option &&opt) {
internal_add_option(opt);
_options.push_back(std::move(opt));
}
#endif
/**
* \brief Returns the header size.
@@ -370,6 +383,15 @@ namespace Tins {
* \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \brief Getter for the PDU's type.
@@ -383,7 +405,7 @@ namespace Tins {
* \param opt_flag The flag to be searched.
* \return A pointer to the option, or 0 if it was not found.
*/
const tcp_option *search_option(Option opt) const;
const option *search_option(OptionTypes opt) const;
/**
* \sa PDU::clone
@@ -431,20 +453,22 @@ namespace Tins {
static const uint16_t DEFAULT_WINDOW;
template<class T>
T generic_search(Option opt) const {
const tcp_option *option = search_option(opt);
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();
}
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
uint8_t *write_option(const tcp_option &opt, uint8_t *buffer);
void internal_add_option(const option &option);
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
void checksum(uint16_t new_check);
uint8_t *write_option(const option &opt, uint8_t *buffer);
tcphdr _tcp;
uint16_t _options_size, _total_options_size;
options_type _options;
uint32_t _options_size, _total_options_size;
};
}

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -41,6 +41,8 @@
#include "icmp.h"
#include "icmpv6.h"
#include "dot11.h"
#include "dot1q.h"
#include "dot3.h"
#include "ip.h"
#include "ipv6.h"
#include "packet_sender.h"
@@ -63,5 +65,7 @@
#include "timestamp.h"
#include "sll.h"
#include "dhcpv6.h"
#include "pppoe.h"
#include "stp.h"
#endif // TINS_TINS_H

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -39,7 +39,7 @@
#undef interface
#endif
#include "macros.h"
#ifdef BSD
#if defined(BSD) || defined(__FreeBSD_kernel__)
#include <sys/file.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
@@ -95,7 +95,7 @@ namespace Tins {
*/
IPv4Address mask;
};
/**
* \brief Resolves a domain name and returns its corresponding ip address.
*
@@ -104,20 +104,17 @@ namespace Tins {
*
* \param to_resolve The domain name/ip address to resolve.
*/
IPv4Address resolve_ip(const std::string &to_resolve);
IPv4Address resolve_domain(const std::string &to_resolve);
/**
* \brief Resolves the hardware address for a given ip.
* \brief Resolves a domain name and returns its corresponding ip address.
*
* \param iface The interface in which the packet will be sent.
* \param ip The ip to resolve, in integer format.
* \param buffer The buffer in which the host's hardware address will be stored.
* \param sender The sender to use to send and receive the ARP requests.
* \return Returns true if the hardware address was resolved successfully,
* false otherwise.
* If an ip address is given, its integer representation is returned.
* Otherwise, the domain name is resolved and its ip address is returned.
*
* \param to_resolve The domain name/ip address to resolve.
*/
bool resolve_hwaddr(const NetworkInterface &iface, IPv4Address ip,
HWAddress<6> *address, PacketSender &sender);
IPv6Address resolve_domain6(const std::string &to_resolve);
/**
* \brief Resolves the hardware address for a given ip.
@@ -132,6 +129,21 @@ namespace Tins {
*/
HWAddress<6> resolve_hwaddr(const NetworkInterface &iface,
IPv4Address ip, PacketSender &sender);
/**
* \brief Resolves the hardware address for a given ip.
*
* If the address can't be resolved, a std::runtime_error
* exception is thrown.
*
* This method sends and receives the packet through
* PacketSender::default_interface.
*
* \param ip The ip to resolve, in integer format.
* \param sender The sender to use to send and receive the ARP requests.
* \return HWAddress<6> containing the resolved hardware address.
*/
HWAddress<6> resolve_hwaddr(IPv4Address ip, PacketSender &sender);
/** \brief List all network interfaces.
*
@@ -283,7 +295,7 @@ namespace Tins {
dereference_until_pdu(T &value) {
return dereference_until_pdu(*value);
}
#ifdef BSD
#if defined(BSD) || defined(__FreeBSD_kernel__)
inline std::vector<char> query_route_table() {
int mib[6];
std::vector<char> buf;
@@ -325,7 +337,7 @@ namespace Tins {
#endif
}
}
#ifdef BSD
#if defined(BSD) || defined(__FreeBSD_kernel__)
template<class ForwardIterator>
void Tins::Utils::route_entries(ForwardIterator output) {
std::vector<char> buffer = query_route_table();

View File

@@ -70,7 +70,7 @@
# compiler: $LTCC
# compiler flags: $LTCFLAGS
# linker: $LD (gnu? $with_gnu_ld)
# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1ubuntu1
# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1ubuntu2
# automake: $automake_version
# autoconf: $autoconf_version
#
@@ -80,7 +80,7 @@
PROGRAM=libtool
PACKAGE=libtool
VERSION="2.4.2 Debian-2.4.2-1ubuntu1"
VERSION="2.4.2 Debian-2.4.2-1ubuntu2"
TIMESTAMP=""
package_revision=1.3337

View File

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

1
m4/libtool.m4 vendored
View File

@@ -1 +0,0 @@
/usr/share/aclocal/libtool.m4

8001
m4/libtool.m4 vendored Normal file

File diff suppressed because it is too large Load Diff

1
m4/ltoptions.m4 vendored
View File

@@ -1 +0,0 @@
/usr/share/aclocal/ltoptions.m4

384
m4/ltoptions.m4 vendored Normal file
View File

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

1
m4/ltsugar.m4 vendored
View File

@@ -1 +0,0 @@
/usr/share/aclocal/ltsugar.m4

123
m4/ltsugar.m4 vendored Normal file
View File

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

1
m4/ltversion.m4 vendored
View File

@@ -1 +0,0 @@
/usr/share/aclocal/ltversion.m4

23
m4/ltversion.m4 vendored Normal file
View File

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

1
m4/lt~obsolete.m4 vendored
View File

@@ -1 +0,0 @@
/usr/share/aclocal/lt~obsolete.m4

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

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,6 +36,7 @@
#include "rawpdu.h"
#include "constants.h"
#include "network_interface.h"
#include "exceptions.h"
using std::runtime_error;
@@ -59,7 +60,7 @@ ARP::ARP(ipaddress_type target_ip, ipaddress_type sender_ip,
ARP::ARP(const uint8_t *buffer, uint32_t total_sz)
{
if(total_sz < sizeof(arphdr))
throw runtime_error("Not enough size for an ARP header in the buffer.");
throw malformed_packet();
memcpy(&_arp, buffer, sizeof(arphdr));
total_sz -= sizeof(arphdr);
if(total_sz)
@@ -107,54 +108,41 @@ uint32_t ARP::header_size() const {
}
void ARP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) {
#ifdef TINS_DEBUG
assert(total_sz >= sizeof(arphdr));
#endif
memcpy(buffer, &_arp, sizeof(arphdr));
}
bool ARP::matches_response(uint8_t *ptr, uint32_t total_sz) {
bool ARP::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
if(total_sz < sizeof(arphdr))
return false;
arphdr *arp_ptr = (arphdr*)ptr;
const arphdr *arp_ptr = (const arphdr*)ptr;
return arp_ptr->ar_sip == _arp.ar_tip && arp_ptr->ar_tip == _arp.ar_sip;
}
PDU *ARP::clone_packet(const uint8_t *ptr, uint32_t total_sz) {
if(total_sz < sizeof(arphdr))
return 0;
PDU *child = 0, *cloned;
if(total_sz > sizeof(arphdr)) {
child = PDU::clone_inner_pdu(ptr + sizeof(arphdr), total_sz - sizeof(arphdr));
if(!child)
return 0;
}
cloned = new ARP(ptr, std::min(total_sz, (uint32_t)sizeof(_arp)));
cloned->inner_pdu(child);
return cloned;
}
EthernetII ARP::make_arp_request(const NetworkInterface& iface,
ipaddress_type target, ipaddress_type sender, const hwaddress_type &hw_snd)
EthernetII ARP::make_arp_request(ipaddress_type target, ipaddress_type sender,
const hwaddress_type &hw_snd)
{
/* Create ARP packet and set its attributes */
ARP* arp = new ARP();
arp->target_ip_addr(target);
arp->sender_ip_addr(sender);
arp->sender_hw_addr(hw_snd);
arp->opcode(REQUEST);
ARP arp;
arp.target_ip_addr(target);
arp.sender_ip_addr(sender);
arp.sender_hw_addr(hw_snd);
arp.opcode(REQUEST);
/* Create the EthernetII PDU with the ARP PDU as its inner PDU */
return EthernetII(iface, EthernetII::BROADCAST, hw_snd, arp);
return EthernetII(EthernetII::BROADCAST, hw_snd) / arp;
}
EthernetII ARP::make_arp_reply(const NetworkInterface& iface,
ipaddress_type target, ipaddress_type sender, const hwaddress_type &hw_tgt,
const hwaddress_type &hw_snd)
EthernetII ARP::make_arp_reply(ipaddress_type target, ipaddress_type sender,
const hwaddress_type &hw_tgt, const hwaddress_type &hw_snd)
{
/* Create ARP packet and set its attributes */
ARP* arp = new ARP(target, sender, hw_tgt, hw_snd);
arp->opcode(REPLY);
ARP arp(target, sender, hw_tgt, hw_snd);
arp.opcode(REPLY);
/* Create the EthernetII PDU with the ARP PDU as its inner PDU */
return EthernetII(iface, hw_tgt, hw_snd, arp);
return EthernetII(hw_tgt, hw_snd) / arp;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,6 +31,7 @@
#include <cstring>
#include <cassert>
#include "bootp.h"
#include "exceptions.h"
namespace Tins{
BootP::BootP()
@@ -42,7 +43,7 @@ BootP::BootP(const uint8_t *buffer, uint32_t total_sz, uint32_t vend_field_size)
: _vend(vend_field_size)
{
if(total_sz < sizeof(bootphdr) + vend_field_size)
throw std::runtime_error("Not enough size for a BootP header in the buffer.");
throw malformed_packet();
std::memcpy(&_bootp, buffer, sizeof(bootphdr));
buffer += sizeof(bootphdr);
total_sz -= sizeof(bootphdr);
@@ -113,8 +114,17 @@ void BootP::vend(const vend_type &new_vend) {
}
void BootP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
#ifdef TINS_DEBUG
assert(total_sz >= sizeof(bootphdr) + _vend.size());
#endif
std::memcpy(buffer, &_bootp, sizeof(bootphdr));
std::copy(_vend.begin(), _vend.end(), buffer + sizeof(bootphdr));
}
bool BootP::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
if(total_sz < sizeof(bootphdr))
return false;
const bootphdr *bootp_ptr = (const bootphdr *)ptr;
return bootp_ptr->xid == _bootp.xid;
}
}

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,6 +32,7 @@
#include "endianness.h"
#include "dhcp.h"
#include "ethernetII.h"
#include "exceptions.h"
using std::string;
using std::list;
@@ -52,7 +53,7 @@ DHCP::DHCP(const uint8_t *buffer, uint32_t total_sz)
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))
throw std::runtime_error("Not enough size for a DHCP header in the buffer.");
throw malformed_packet();
buffer += sizeof(uint32_t);
total_sz -= sizeof(uint32_t);
while(total_sz) {
@@ -64,22 +65,28 @@ DHCP::DHCP(const uint8_t *buffer, uint32_t total_sz)
i = 2;
}
else if(!total_sz)
throw std::runtime_error("Not enough size for a DHCP header in the buffer.");
throw malformed_packet();
}
if(total_sz < args[1])
throw std::runtime_error("Not enough size for a DHCP header in the buffer.");
add_option(dhcp_option((Options)args[0], args[1], buffer));
throw malformed_packet();
add_option(
option((OptionTypes)args[0], args[1], buffer)
);
buffer += args[1];
total_sz -= args[1];
}
}
void DHCP::add_option(const dhcp_option &option) {
_options.push_back(option);
_size += option.data_size() + (sizeof(uint8_t) << 1);
void DHCP::add_option(const option &opt) {
internal_add_option(opt);
_options.push_back(opt);
}
const DHCP::dhcp_option *DHCP::search_option(Options opt) const {
void DHCP::internal_add_option(const option &opt) {
_size += opt.data_size() + (sizeof(uint8_t) << 1);
}
const DHCP::option *DHCP::search_option(OptionTypes opt) const {
for(options_type::const_iterator it = _options.begin(); it != _options.end(); ++it) {
if(it->option() == opt)
return &(*it);
@@ -89,11 +96,11 @@ const DHCP::dhcp_option *DHCP::search_option(Options opt) const {
void DHCP::type(Flags type) {
uint8_t int_type = type;
add_option(dhcp_option(DHCP_MESSAGE_TYPE, sizeof(uint8_t), &int_type));
add_option(option(DHCP_MESSAGE_TYPE, sizeof(uint8_t), &int_type));
}
void DHCP::end() {
add_option(dhcp_option(DHCP_MESSAGE_TYPE));
add_option(option(DHCP_MESSAGE_TYPE));
}
uint8_t DHCP::type() const {
@@ -102,7 +109,7 @@ uint8_t DHCP::type() const {
void DHCP::server_identifier(ipaddress_type ip) {
uint32_t ip_int = ip;
add_option(dhcp_option(DHCP_SERVER_IDENTIFIER, sizeof(uint32_t), (const uint8_t*)&ip_int));
add_option(option(DHCP_SERVER_IDENTIFIER, sizeof(uint32_t), (const uint8_t*)&ip_int));
}
DHCP::ipaddress_type DHCP::server_identifier() const {
@@ -111,7 +118,7 @@ DHCP::ipaddress_type DHCP::server_identifier() const {
void DHCP::lease_time(uint32_t time) {
time = Endian::host_to_be(time);
add_option(dhcp_option(DHCP_LEASE_TIME, sizeof(uint32_t), (const uint8_t*)&time));
add_option(option(DHCP_LEASE_TIME, sizeof(uint32_t), (const uint8_t*)&time));
}
uint32_t DHCP::lease_time() const {
@@ -120,7 +127,7 @@ uint32_t DHCP::lease_time() const {
void DHCP::renewal_time(uint32_t time) {
time = Endian::host_to_be(time);
add_option(dhcp_option(DHCP_RENEWAL_TIME, sizeof(uint32_t), (const uint8_t*)&time));
add_option(option(DHCP_RENEWAL_TIME, sizeof(uint32_t), (const uint8_t*)&time));
}
uint32_t DHCP::renewal_time() const {
@@ -129,7 +136,7 @@ uint32_t DHCP::renewal_time() const {
void DHCP::subnet_mask(ipaddress_type mask) {
uint32_t mask_int = mask;
add_option(dhcp_option(SUBNET_MASK, sizeof(uint32_t), (const uint8_t*)&mask_int));
add_option(option(SUBNET_MASK, sizeof(uint32_t), (const uint8_t*)&mask_int));
}
DHCP::ipaddress_type DHCP::subnet_mask() const {
@@ -138,7 +145,7 @@ DHCP::ipaddress_type DHCP::subnet_mask() const {
void DHCP::routers(const list<ipaddress_type> &routers) {
serialization_type buffer = serialize_list(routers);
add_option(dhcp_option(ROUTERS, buffer.begin(), buffer.end()));
add_option(option(ROUTERS, buffer.begin(), buffer.end()));
}
std::list<DHCP::ipaddress_type> DHCP::routers() const {
@@ -147,7 +154,7 @@ std::list<DHCP::ipaddress_type> DHCP::routers() const {
void DHCP::domain_name_servers(const list<ipaddress_type> &dns) {
serialization_type buffer = serialize_list(dns);
add_option(dhcp_option(DOMAIN_NAME_SERVERS, buffer.begin(), buffer.end()));
add_option(option(DOMAIN_NAME_SERVERS, buffer.begin(), buffer.end()));
}
std::list<DHCP::ipaddress_type> DHCP::domain_name_servers() const {
@@ -156,7 +163,7 @@ std::list<DHCP::ipaddress_type> DHCP::domain_name_servers() const {
void DHCP::broadcast(ipaddress_type addr) {
uint32_t int_addr = addr;
add_option(dhcp_option(BROADCAST_ADDRESS, sizeof(uint32_t), (uint8_t*)&int_addr));
add_option(option(BROADCAST_ADDRESS, sizeof(uint32_t), (uint8_t*)&int_addr));
}
DHCP::ipaddress_type DHCP::broadcast() const {
@@ -165,7 +172,7 @@ DHCP::ipaddress_type DHCP::broadcast() const {
void DHCP::requested_ip(ipaddress_type addr) {
uint32_t int_addr = addr;
add_option(dhcp_option(DHCP_REQUESTED_ADDRESS, sizeof(uint32_t), (uint8_t*)&int_addr));
add_option(option(DHCP_REQUESTED_ADDRESS, sizeof(uint32_t), (uint8_t*)&int_addr));
}
DHCP::ipaddress_type DHCP::requested_ip() const {
@@ -173,7 +180,7 @@ DHCP::ipaddress_type DHCP::requested_ip() const {
}
void DHCP::domain_name(const string &name) {
add_option(dhcp_option(DOMAIN_NAME, name.size(), (const uint8_t*)name.c_str()));
add_option(option(DOMAIN_NAME, name.size(), (const uint8_t*)name.c_str()));
}
std::string DHCP::domain_name() const {
@@ -182,7 +189,7 @@ std::string DHCP::domain_name() const {
void DHCP::rebind_time(uint32_t time) {
time = Endian::host_to_be(time);
add_option(dhcp_option(DHCP_REBINDING_TIME, sizeof(uint32_t), (uint8_t*)&time));
add_option(option(DHCP_REBINDING_TIME, sizeof(uint32_t), (uint8_t*)&time));
}
uint32_t DHCP::rebind_time() const {
@@ -202,7 +209,9 @@ uint32_t DHCP::header_size() const {
}
void DHCP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
#ifdef TINS_DEBUG
assert(total_sz >= header_size());
#endif
if(_size) {
vend_type &result(BootP::vend());
result.resize(_size);
@@ -211,7 +220,7 @@ void DHCP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *pa
*((uint32_t*)&result[0]) = Endian::host_to_be<uint32_t>(0x63825363);
for(options_type::const_iterator it = _options.begin(); it != _options.end(); ++it) {
*(ptr++) = it->option();
*(ptr++) = it->data_size();
*(ptr++) = it->length_field();
std::copy(it->data_ptr(), it->data_ptr() + it->data_size(), ptr);
ptr += it->data_size();
}
@@ -219,12 +228,12 @@ 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(Options opt, type2type<std::list<ipaddress_type> >) const {
const dhcp_option *option = search_option(opt);
if(!option)
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*)option->data_ptr();
uint32_t len = option->data_size();
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;
@@ -235,14 +244,14 @@ std::list<DHCP::ipaddress_type> DHCP::generic_search(Options opt, type2type<std:
return container;
}
std::string DHCP::generic_search(Options opt, type2type<std::string>) const {
const dhcp_option *option = search_option(opt);
if(!option)
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(option->data_ptr(), option->data_ptr() + option->data_size());
return string(opt->data_ptr(), opt->data_ptr() + opt->data_size());
}
DHCP::ipaddress_type DHCP::generic_search(Options opt, type2type<ipaddress_type>) const {
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, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,10 +27,10 @@
*
*/
#include <iostream> //borrame
#include <vector>
#include <algorithm>
#include "dhcpv6.h"
#include "exceptions.h"
namespace Tins {
DHCPv6::DHCPv6() : options_size() {
@@ -40,21 +40,19 @@ DHCPv6::DHCPv6() : options_size() {
DHCPv6::DHCPv6(const uint8_t *buffer, uint32_t total_sz)
: options_size()
{
const char *err_msg = "Not enough size for a DHCPv6 header",
*opt_err_msg = "Not enough size for a DHCPv6 option";
if(total_sz == 0)
throw std::runtime_error(err_msg);
throw malformed_packet();
// Relay Agent/Server Messages
bool is_relay_msg = (buffer[0] == 12 || buffer[0] == 13);
uint32_t required_size = is_relay_msg ? 2 : 4;
if(total_sz < required_size)
throw std::runtime_error(err_msg);
throw malformed_packet();
std::copy(buffer, buffer + required_size, header_data);
buffer += required_size;
total_sz -= required_size;
if(is_relay_message()) {
if(total_sz < ipaddress_type::address_size * 2)
throw std::runtime_error(err_msg);
throw malformed_packet();
link_addr = buffer;
peer_addr = buffer + ipaddress_type::address_size;
buffer += ipaddress_type::address_size * 2;
@@ -63,28 +61,28 @@ DHCPv6::DHCPv6(const uint8_t *buffer, uint32_t total_sz)
options_size = total_sz;
while(total_sz) {
if(total_sz < sizeof(uint16_t) * 2)
throw std::runtime_error(opt_err_msg);
throw malformed_packet();
const uint16_t option = Endian::be_to_host(*(const uint16_t*)buffer);
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))
);
if(total_sz - sizeof(uint16_t) * 2 < data_size)
throw std::runtime_error(opt_err_msg);
throw malformed_packet();
buffer += sizeof(uint16_t) * 2;
add_option(
dhcpv6_option(option, buffer, buffer + data_size)
option(opt, buffer, buffer + data_size)
);
buffer += data_size;
total_sz -= sizeof(uint16_t) * 2 + data_size;
}
}
void DHCPv6::add_option(const dhcpv6_option &option) {
options_.push_back(option);
void DHCPv6::add_option(const option &opt) {
options_.push_back(opt);
}
const DHCPv6::dhcpv6_option *DHCPv6::search_option(Option id) const {
const DHCPv6::option *DHCPv6::search_option(OptionTypes id) const {
for(options_type::const_iterator it = options_.begin(); it != options_.end(); ++it) {
if(it->option() == static_cast<uint16_t>(id))
return &*it;
@@ -92,12 +90,12 @@ const DHCPv6::dhcpv6_option *DHCPv6::search_option(Option id) const {
return 0;
}
uint8_t* DHCPv6::write_option(const dhcpv6_option &option, uint8_t* buffer) const {
*(uint16_t*)buffer = Endian::host_to_be(option.option());
*(uint16_t*)&buffer[sizeof(uint16_t)] = Endian::host_to_be(option.data_size());
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());
return std::copy(
option.data_ptr(),
option.data_ptr() + option.data_size(),
opt.data_ptr(),
opt.data_ptr() + opt.data_size(),
buffer + sizeof(uint16_t) * 2
);
}
@@ -133,6 +131,15 @@ uint32_t DHCPv6::header_size() const {
return (is_relay_message() ? (2 + ipaddress_type::address_size * 2) : 4) + options_size;
}
bool DHCPv6::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
if(!is_relay_message()) {
if(total_sz < 4 || (ptr[0] == 12 || ptr[0] == 13))
return false;
return std::equal(header_data + 1, header_data + 4, ptr + 1);
}
return false;
}
void DHCPv6::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) {
const uint32_t required_size = is_relay_message() ? 2 : 4;
buffer = std::copy(header_data, header_data + required_size, buffer);
@@ -150,7 +157,7 @@ void DHCPv6::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *
// ********************************************************************
DHCPv6::ia_na_type DHCPv6::ia_na() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
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;
@@ -164,7 +171,7 @@ DHCPv6::ia_na_type DHCPv6::ia_na() const {
}
DHCPv6::ia_ta_type DHCPv6::ia_ta() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
const option *opt = safe_search_option<std::less>(
IA_TA, sizeof(uint32_t)
);
const uint8_t *ptr = opt->data_ptr() + sizeof(uint32_t);
@@ -176,7 +183,7 @@ DHCPv6::ia_ta_type DHCPv6::ia_ta() const {
}
DHCPv6::ia_address_type DHCPv6::ia_address() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
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;
@@ -190,7 +197,7 @@ DHCPv6::ia_address_type DHCPv6::ia_address() const {
}
DHCPv6::option_request_type DHCPv6::option_request() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
const option *opt = safe_search_option<std::less>(
OPTION_REQUEST, 2
);
const uint16_t *ptr = (const uint16_t*)opt->data_ptr(),
@@ -198,21 +205,21 @@ DHCPv6::option_request_type DHCPv6::option_request() const {
option_request_type output;
while(ptr < end) {
output.push_back(
static_cast<Option>(Endian::be_to_host(*ptr++))
static_cast<OptionTypes>(Endian::be_to_host(*ptr++))
);
}
return output;
}
uint8_t DHCPv6::preference() const {
const dhcpv6_option *opt = safe_search_option<std::not_equal_to>(
const option *opt = safe_search_option<std::not_equal_to>(
PREFERENCE, 1
);
return *opt->data_ptr();
}
uint16_t DHCPv6::elapsed_time() const {
const dhcpv6_option *opt = safe_search_option<std::not_equal_to>(
const option *opt = safe_search_option<std::not_equal_to>(
ELAPSED_TIME, 2
);
return Endian::be_to_host(
@@ -221,7 +228,7 @@ uint16_t DHCPv6::elapsed_time() const {
}
DHCPv6::relay_msg_type DHCPv6::relay_message() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
const option *opt = safe_search_option<std::less>(
RELAY_MSG, 1
);
return relay_msg_type(
@@ -231,7 +238,7 @@ DHCPv6::relay_msg_type DHCPv6::relay_message() const {
}
DHCPv6::authentication_type DHCPv6::authentication() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
const option *opt = safe_search_option<std::less>(
AUTH, sizeof(uint8_t) * 3 + sizeof(uint64_t)
);
const uint8_t *ptr = opt->data_ptr();
@@ -248,14 +255,14 @@ DHCPv6::authentication_type DHCPv6::authentication() const {
}
DHCPv6::ipaddress_type DHCPv6::server_unicast() const {
const dhcpv6_option *opt = safe_search_option<std::not_equal_to>(
const option *opt = safe_search_option<std::not_equal_to>(
UNICAST, ipaddress_type::address_size
);
return ipaddress_type(opt->data_ptr());
}
DHCPv6::status_code_type DHCPv6::status_code() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
const option *opt = safe_search_option<std::less>(
STATUS_CODE, sizeof(uint16_t)
);
status_code_type output;
@@ -272,7 +279,7 @@ bool DHCPv6::has_rapid_commit() const {
}
DHCPv6::user_class_type DHCPv6::user_class() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
const option *opt = safe_search_option<std::less>(
USER_CLASS, sizeof(uint16_t)
);
return option2class_option_data<user_class_type>(
@@ -281,7 +288,7 @@ DHCPv6::user_class_type DHCPv6::user_class() const {
}
DHCPv6::vendor_class_type DHCPv6::vendor_class() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
const option *opt = safe_search_option<std::less>(
VENDOR_CLASS, sizeof(uint32_t)
);
typedef vendor_class_type::class_data_type data_type;
@@ -298,7 +305,7 @@ DHCPv6::vendor_class_type DHCPv6::vendor_class() const {
}
DHCPv6::vendor_info_type DHCPv6::vendor_info() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
const option *opt = safe_search_option<std::less>(
VENDOR_OPTS, sizeof(uint32_t)
);
vendor_info_type output;
@@ -313,7 +320,7 @@ DHCPv6::vendor_info_type DHCPv6::vendor_info() const {
}
DHCPv6::interface_id_type DHCPv6::interface_id() const {
const dhcpv6_option *opt = safe_search_option<std::equal_to>(
const option *opt = safe_search_option<std::equal_to>(
INTERFACE_ID, 0
);
return interface_id_type(
@@ -333,7 +340,7 @@ bool DHCPv6::has_reconfigure_accept() const {
}
DHCPv6::duid_type DHCPv6::client_id() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
const option *opt = safe_search_option<std::less>(
CLIENTID, sizeof(uint16_t) + 1
);
return duid_type(
@@ -346,7 +353,7 @@ DHCPv6::duid_type DHCPv6::client_id() const {
}
DHCPv6::duid_type DHCPv6::server_id() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
const option *opt = safe_search_option<std::less>(
SERVERID, sizeof(uint16_t) + 1
);
return duid_type(
@@ -374,7 +381,7 @@ void DHCPv6::ia_na(const ia_na_type &value) {
buffer.begin() + sizeof(uint32_t) * 3
);
add_option(
dhcpv6_option(IA_NA, buffer.begin(), buffer.end())
option(IA_NA, buffer.begin(), buffer.end())
);
}
@@ -388,7 +395,7 @@ void DHCPv6::ia_ta(const ia_ta_type &value) {
buffer.begin() + sizeof(uint32_t)
);
add_option(
dhcpv6_option(IA_TA, buffer.begin(), buffer.end())
option(IA_TA, buffer.begin(), buffer.end())
);
}
@@ -406,7 +413,7 @@ void DHCPv6::ia_address(const ia_address_type &value) {
buffer.begin() + sizeof(uint32_t) * 2 + ipaddress_type::address_size
);
add_option(
dhcpv6_option(IA_ADDR, buffer.begin(), buffer.end())
option(IA_ADDR, buffer.begin(), buffer.end())
);
}
@@ -418,26 +425,26 @@ void DHCPv6::option_request(const option_request_type &value) {
for(iterator it = value.begin(); it != value.end(); ++it, index += 2)
*(uint16_t*)&buffer[index] = Endian::host_to_be<uint16_t>(*it);
add_option(
dhcpv6_option(OPTION_REQUEST, buffer.begin(), buffer.end())
option(OPTION_REQUEST, buffer.begin(), buffer.end())
);
}
void DHCPv6::preference(uint8_t value) {
add_option(
dhcpv6_option(PREFERENCE, 1, &value)
option(PREFERENCE, 1, &value)
);
}
void DHCPv6::elapsed_time(uint16_t value) {
value = Endian::host_to_be(value);
add_option(
dhcpv6_option(ELAPSED_TIME, 2, (const uint8_t*)&value)
option(ELAPSED_TIME, 2, (const uint8_t*)&value)
);
}
void DHCPv6::relay_message(const relay_msg_type &value) {
add_option(
dhcpv6_option(RELAY_MSG, value.begin(), value.end())
option(RELAY_MSG, value.begin(), value.end())
);
}
@@ -455,13 +462,13 @@ void DHCPv6::authentication(const authentication_type &value) {
buffer.begin() + sizeof(uint8_t) * 3 + sizeof(uint64_t)
);
add_option(
dhcpv6_option(AUTH, buffer.begin(), buffer.end())
option(AUTH, buffer.begin(), buffer.end())
);
}
void DHCPv6::server_unicast(const ipaddress_type &value) {
add_option(
dhcpv6_option(UNICAST, value.begin(), value.end())
option(UNICAST, value.begin(), value.end())
);
}
@@ -474,7 +481,7 @@ void DHCPv6::status_code(const status_code_type &value) {
buffer.begin() + sizeof(uint16_t)
);
add_option(
dhcpv6_option(STATUS_CODE, buffer.begin(), buffer.end())
option(STATUS_CODE, buffer.begin(), buffer.end())
);
}
@@ -490,7 +497,7 @@ void DHCPv6::user_class(const user_class_type &value) {
std::vector<uint8_t> buffer;
class_option_data2option(value.begin(), value.end(), buffer);
add_option(
dhcpv6_option(USER_CLASS, buffer.begin(), buffer.end())
option(USER_CLASS, buffer.begin(), buffer.end())
);
}
@@ -506,7 +513,7 @@ void DHCPv6::vendor_class(const vendor_class_type &value) {
sizeof(uint32_t)
);
add_option(
dhcpv6_option(VENDOR_CLASS, buffer.begin(), buffer.end())
option(VENDOR_CLASS, buffer.begin(), buffer.end())
);
}
@@ -519,19 +526,19 @@ void DHCPv6::vendor_info(const vendor_info_type &value) {
buffer.begin() + sizeof(uint32_t)
);
add_option(
dhcpv6_option(VENDOR_OPTS, buffer.begin(), buffer.end())
option(VENDOR_OPTS, buffer.begin(), buffer.end())
);
}
void DHCPv6::interface_id(const interface_id_type &value) {
add_option(
dhcpv6_option(INTERFACE_ID, value.begin(), value.end())
option(INTERFACE_ID, value.begin(), value.end())
);
}
void DHCPv6::reconfigure_msg(uint8_t value) {
add_option(
dhcpv6_option(RECONF_MSG, 1, &value)
option(RECONF_MSG, 1, &value)
);
}
@@ -626,7 +633,7 @@ void DHCPv6::client_id(const duid_type &value) {
buffer.begin() + sizeof(uint16_t)
);
add_option(
dhcpv6_option(CLIENTID, buffer.begin(), buffer.end())
option(CLIENTID, buffer.begin(), buffer.end())
);
}
@@ -639,7 +646,7 @@ void DHCPv6::server_id(const duid_type &value) {
buffer.begin() + sizeof(uint16_t)
);
add_option(
dhcpv6_option(SERVERID, buffer.begin(), buffer.end())
option(SERVERID, buffer.begin(), buffer.end())
);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,6 +35,8 @@
#include "dns.h"
#include "ip_address.h"
#include "ipv6_address.h"
#include "exceptions.h"
#include "rawpdu.h"
using std::string;
using std::list;
@@ -47,7 +49,7 @@ DNS::DNS() : extra_size(0) {
DNS::DNS(const uint8_t *buffer, uint32_t total_sz) : extra_size(0) {
if(total_sz < sizeof(dnshdr))
throw std::runtime_error("Not enough size for a DNS header in the buffer.");
throw malformed_packet();
std::memcpy(&dns, buffer, sizeof(dnshdr));
const uint8_t *end(buffer + total_sz);
uint16_t nquestions(questions_count());
@@ -59,7 +61,7 @@ DNS::DNS(const uint8_t *buffer, uint32_t total_sz) : extra_size(0) {
ptr++;
Query query;
if((ptr + (sizeof(uint16_t) * 2)) >= end)
throw std::runtime_error("Not enough size for a given query.");
throw malformed_packet();
query.dname(string(buffer, ptr));
ptr++;
const uint16_t *opt_ptr = reinterpret_cast<const uint16_t*>(ptr);
@@ -73,6 +75,8 @@ DNS::DNS(const uint8_t *buffer, uint32_t total_sz) : extra_size(0) {
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));
}
const uint8_t *DNS::build_resource_list(ResourcesType &lst, const uint8_t *ptr, uint32_t &sz, uint16_t nrecs) {
@@ -81,7 +85,7 @@ const uint8_t *DNS::build_resource_list(ResourcesType &lst, const uint8_t *ptr,
for(uint16_t i(0); i < nrecs; ++i) {
const uint8_t *this_opt_start(ptr);
if(ptr + sizeof(uint16_t) > ptr_end)
throw std::runtime_error("Not enough size for a given resource.");
throw malformed_packet();
lst.push_back(DNSResourceRecord(ptr, ptr_end - ptr));
ptr += lst.back().size();
extra_size += ptr - this_opt_start;
@@ -290,7 +294,9 @@ void DNS::unparse_domain_name(const std::string &dn, std::string &out) const {
}
void DNS::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
#ifdef TINS_DEBUG
assert(total_sz >= sizeof(dns) + extra_size);
#endif
std::memcpy(buffer, &dns, sizeof(dns));
buffer += sizeof(dns);
for(list<Query>::const_iterator it(queries_.begin()); it != queries_.end(); ++it) {
@@ -386,7 +392,7 @@ void DNS::compose_name(const uint8_t *ptr, uint32_t sz, std::string &out) const
// 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 std::runtime_error("Malformed DNS packet");
throw malformed_packet();
bool first(true);
do {
if(it != suffixes.end()) {
@@ -476,4 +482,11 @@ DNS::resources_type DNS::answers() const {
convert_resources(ans, res);
return res;
}
bool DNS::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
if(total_sz < sizeof(dnshdr))
return false;
const dnshdr *hdr = (const dnshdr*)ptr;
return hdr->id == dns.id;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,6 +33,7 @@
#include <typeinfo>
#include "dns_record.h"
#include "endianness.h"
#include "exceptions.h"
namespace Tins {
bool contains_dname(uint16_t type) {
@@ -53,7 +54,7 @@ DNSResourceRecord::DNSResourceRecord(DNSRRImpl *impl,
DNSResourceRecord::DNSResourceRecord(const uint8_t *buffer, uint32_t size)
{
const uint8_t *buffer_end = buffer + size;
std::auto_ptr<DNSRRImpl> tmp_impl;
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;
@@ -65,17 +66,17 @@ DNSResourceRecord::DNSResourceRecord(const uint8_t *buffer, uint32_t size)
while(str_end < buffer_end && *str_end)
str_end++;
if(str_end == buffer_end)
throw std::runtime_error("Not enough size for a resource domain name.");
throw malformed_packet();
//str_end++;
tmp_impl.reset(new NamedDNSRRImpl(buffer, str_end));
buffer = ++str_end;
}
if(buffer + sizeof(info_) > buffer_end)
throw std::runtime_error("Not enough size for a resource info.");
throw malformed_packet();
std::memcpy(&info_, buffer, sizeof(info_));
buffer += sizeof(info_);
if(buffer + sizeof(uint16_t) > buffer_end)
throw std::runtime_error("Not enough size for resource data size.");
throw malformed_packet();
// Store the option size.
data.resize(
@@ -83,7 +84,7 @@ DNSResourceRecord::DNSResourceRecord(const uint8_t *buffer, uint32_t size)
);
buffer += sizeof(uint16_t);
if(buffer + data.size() > buffer_end)
throw std::runtime_error("Not enough size for resource data");
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))
@@ -106,24 +107,6 @@ DNSResourceRecord& DNSResourceRecord::operator=(const DNSResourceRecord &rhs)
return *this;
}
#if TINS_IS_CXX11
DNSResourceRecord::DNSResourceRecord(DNSResourceRecord &&rhs) noexcept
: info_(rhs.info_), data(std::move(rhs.data)), impl(0) {
std::swap(impl, rhs.impl);
}
DNSResourceRecord& 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
DNSResourceRecord::~DNSResourceRecord() {
delete impl;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,9 +33,10 @@
#include <algorithm>
#include <utility>
#include "macros.h"
#include "exceptions.h"
#ifndef WIN32
#if defined(BSD) || defined(__APPLE__)
#if defined(__FreeBSD_kernel__) || defined(BSD) || defined(__APPLE__)
#include <sys/types.h>
#include <net/if_dl.h>
#else
@@ -59,8 +60,8 @@ using std::runtime_error;
namespace Tins {
const Dot11::address_type Dot11::BROADCAST = "ff:ff:ff:ff:ff:ff";
Dot11::Dot11(const address_type &dst_hw_addr, PDU* child)
: PDU(child), _options_size(0)
Dot11::Dot11(const address_type &dst_hw_addr)
: _options_size(0)
{
memset(&_header, 0, sizeof(ieee80211_header));
addr1(dst_hw_addr);
@@ -75,7 +76,7 @@ Dot11::Dot11(const uint8_t *buffer, uint32_t total_sz)
: _options_size(0)
{
if(total_sz < sizeof(_header))
throw runtime_error("Not enough size for an Dot11 header in the buffer.");
throw malformed_packet();
std::memcpy(&_header, buffer, sizeof(_header));
}
@@ -88,28 +89,32 @@ void Dot11::parse_tagged_parameters(const uint8_t *buffer, uint32_t total_sz) {
buffer += 2;
total_sz -= 2;
if(length > total_sz) {
throw std::runtime_error("Malformed option encountered");
throw malformed_packet();
}
add_tagged_option((TaggedOption)opcode, length, buffer);
add_tagged_option((OptionTypes)opcode, length, buffer);
buffer += length;
total_sz -= length;
}
}
}
void Dot11::add_tagged_option(TaggedOption opt, uint8_t len, const uint8_t *val) {
void Dot11::add_tagged_option(OptionTypes opt, uint8_t len, const uint8_t *val) {
uint32_t opt_size = len + sizeof(uint8_t) * 2;
_options.push_back(dot11_option((uint8_t)opt, len, val));
_options.push_back(option((uint8_t)opt, len, val));
_options_size += opt_size;
}
void Dot11::add_tagged_option(const dot11_option &opt) {
_options.push_back(opt);
void Dot11::internal_add_option(const option &opt) {
_options_size += opt.data_size() + sizeof(uint8_t) * 2;
}
const Dot11::dot11_option *Dot11::search_option(TaggedOption opt) const {
for(std::list<dot11_option>::const_iterator it = _options.begin(); it != _options.end(); ++it)
void Dot11::add_option(const option &opt) {
internal_add_option(opt);
_options.push_back(opt);
}
const Dot11::option *Dot11::search_option(OptionTypes opt) const {
for(std::list<option>::const_iterator it = _options.begin(); it != _options.end(); ++it)
if(it->option() == (uint8_t)opt)
return &(*it);
return 0;
@@ -163,21 +168,17 @@ void Dot11::addr1(const address_type &new_addr1) {
std::copy(new_addr1.begin(), new_addr1.end(), _header.addr1);
}
void Dot11::iface(const NetworkInterface &new_iface) {
this->_iface = new_iface;
}
uint32_t Dot11::header_size() const {
uint32_t sz = sizeof(ieee80211_header) + _options_size;
return sz;
}
#ifndef WIN32
void Dot11::send(PacketSender &sender) {
if(!_iface)
throw std::runtime_error("Interface has not been set");
void Dot11::send(PacketSender &sender, const NetworkInterface &iface) {
if(!iface)
throw invalid_interface();
#ifndef BSD
#if !defined(BSD) && !defined(__FreeBSD_kernel__)
sockaddr_ll addr;
memset(&addr, 0, sizeof(struct sockaddr_ll));
@@ -185,18 +186,19 @@ void Dot11::send(PacketSender &sender) {
addr.sll_family = Endian::host_to_be<uint16_t>(PF_PACKET);
addr.sll_protocol = Endian::host_to_be<uint16_t>(ETH_P_ALL);
addr.sll_halen = 6;
addr.sll_ifindex = _iface.id();
addr.sll_ifindex = iface.id();
memcpy(&(addr.sll_addr), _header.addr1, 6);
sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
#else
sender.send_l2(*this, 0, 0, _iface);
sender.send_l2(*this, 0, 0, iface);
#endif
}
#endif // WIN32
void Dot11::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
uint32_t my_sz = header_size();
assert(total_sz >= my_sz);
#ifdef TINS_DEBUG
assert(total_sz >= header_size());
#endif
memcpy(buffer, &_header, sizeof(_header));
buffer += sizeof(_header);
total_sz -= sizeof(_header);
@@ -207,10 +209,12 @@ void Dot11::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *p
uint32_t child_len = write_fixed_parameters(buffer, total_sz - _options_size);
buffer += child_len;
#ifdef TINS_DEBUG
assert(total_sz >= child_len + _options_size);
for(std::list<dot11_option>::const_iterator it = _options.begin(); it != _options.end(); ++it) {
#endif
for(std::list<option>::const_iterator it = _options.begin(); it != _options.end(); ++it) {
*(buffer++) = it->option();
*(buffer++) = it->data_size();
*(buffer++) = it->length_field();
std::copy(it->data_ptr(), it->data_ptr() + it->data_size(), buffer);
buffer += it->data_size();
}
@@ -221,7 +225,7 @@ Dot11 *Dot11::from_bytes(const uint8_t *buffer, uint32_t total_sz) {
// This should be sizeof(ieee80211_header::control), but gcc 4.2 complains
if(total_sz < 2)
throw runtime_error("Not enough size for a IEEE 802.11 header in the buffer.");
throw malformed_packet();
const ieee80211_header *hdr = (const ieee80211_header*)buffer;
Dot11 *ret = 0;
if(hdr->control.type == MANAGEMENT) {
@@ -280,14 +284,14 @@ Dot11ManagementFrame::Dot11ManagementFrame(const uint8_t *buffer, uint32_t total
buffer += sizeof(ieee80211_header);
total_sz -= sizeof(ieee80211_header);
if(total_sz < sizeof(_ext_header))
throw runtime_error("Not enough size for an Dot11ManagementFrame header in the buffer.");
throw malformed_packet();
std::memcpy(&_ext_header, buffer, sizeof(_ext_header));
total_sz -= sizeof(_ext_header);
if(from_ds() && to_ds()) {
if(total_sz >= _addr4.size())
_addr4 = buffer + sizeof(_ext_header);
else
throw runtime_error("Not enough size for an Dot11ManagementFrame header in the buffer.");
throw malformed_packet();
}
}
@@ -366,9 +370,9 @@ uint8_t *Dot11ManagementFrame::serialize_rates(const rates_type &rates) {
return buffer;
}
Dot11ManagementFrame::rates_type Dot11ManagementFrame::deserialize_rates(const dot11_option *option) {
Dot11ManagementFrame::rates_type Dot11ManagementFrame::deserialize_rates(const option *opt) {
rates_type output;
const uint8_t *ptr = option->data_ptr(), *end = ptr + option->data_size();
const uint8_t *ptr = opt->data_ptr(), *end = ptr + opt->data_size();
while(ptr != end) {
output.push_back(float(*(ptr++) & 0x7f) / 2);
}
@@ -598,52 +602,52 @@ void Dot11ManagementFrame::challenge_text(const std::string &text) {
// Getters
RSNInformation Dot11ManagementFrame::rsn_information() {
const Dot11::dot11_option *option = search_option(RSN);
const Dot11::option *option = search_option(RSN);
if(!option || option->data_size() < (sizeof(uint16_t) << 1) + sizeof(uint32_t))
throw std::runtime_error("RSN information not set");
throw option_not_found();
return RSNInformation(option->data_ptr(), option->data_size());
}
string Dot11ManagementFrame::ssid() const {
const Dot11::dot11_option *option = search_option(SSID);
const Dot11::option *option = search_option(SSID);
if(!option || option->data_size() == 0)
throw std::runtime_error("SSID not set");
throw option_not_found();
return string((const char*)option->data_ptr(), option->data_size());
}
Dot11ManagementFrame::rates_type Dot11ManagementFrame::supported_rates() const {
const Dot11::dot11_option *option = search_option(SUPPORTED_RATES);
const Dot11::option *option = search_option(SUPPORTED_RATES);
if(!option || option->data_size() == 0)
throw std::runtime_error("Supported rates not set");
throw option_not_found();
return deserialize_rates(option);
}
Dot11ManagementFrame::rates_type Dot11ManagementFrame::extended_supported_rates() const {
const Dot11::dot11_option *option = search_option(EXT_SUPPORTED_RATES);
const Dot11::option *option = search_option(EXT_SUPPORTED_RATES);
if(!option || option->data_size() == 0)
throw std::runtime_error("Extended supported rates not set");
throw option_not_found();
return deserialize_rates(option);
}
uint8_t Dot11ManagementFrame::qos_capability() const {
const Dot11::dot11_option *option = search_option(QOS_CAPABILITY);
const Dot11::option *option = search_option(QOS_CAPABILITY);
if(!option || option->data_size() != 1)
throw std::runtime_error("QOS capability not set");
throw option_not_found();
return *option->data_ptr();
}
std::pair<uint8_t, uint8_t> Dot11ManagementFrame::power_capability() const {
const Dot11::dot11_option *option = search_option(POWER_CAPABILITY);
const Dot11::option *option = search_option(POWER_CAPABILITY);
if(!option || option->data_size() != 2)
throw std::runtime_error("Power capability not set");
throw option_not_found();
return std::make_pair(*option->data_ptr(), *(option->data_ptr() + 1));
}
Dot11ManagementFrame::channels_type Dot11ManagementFrame::supported_channels() const {
const Dot11::dot11_option *option = search_option(SUPPORTED_CHANNELS);
const Dot11::option *option = search_option(SUPPORTED_CHANNELS);
// We need a multiple of two
if(!option || ((option->data_size() & 0x1) == 1))
throw std::runtime_error("Supported channels not set");
throw option_not_found();
channels_type output;
const uint8_t *ptr = option->data_ptr(), *end = ptr + option->data_size();
while(ptr != end) {
@@ -654,9 +658,9 @@ Dot11ManagementFrame::channels_type Dot11ManagementFrame::supported_channels() c
}
Dot11ManagementFrame::request_info_type Dot11ManagementFrame::request_information() const {
const Dot11::dot11_option *option = search_option(REQUEST_INFORMATION);
const Dot11::option *option = search_option(REQUEST_INFORMATION);
if(!option || option->data_size() == 0)
throw std::runtime_error("Request information not set");
throw option_not_found();
request_info_type output;
const uint8_t *ptr = option->data_ptr(), *end = ptr + option->data_size();
output.assign(ptr, end);
@@ -664,9 +668,9 @@ Dot11ManagementFrame::request_info_type Dot11ManagementFrame::request_informatio
}
Dot11ManagementFrame::fh_params_set Dot11ManagementFrame::fh_parameter_set() const {
const Dot11::dot11_option *option = search_option(FH_SET);
const Dot11::option *option = search_option(FH_SET);
if(!option || option->data_size() != sizeof(fh_params_set))
throw std::runtime_error("FH parameters set not set");
throw option_not_found();
fh_params_set output = *reinterpret_cast<const fh_params_set*>(option->data_ptr());
output.dwell_time = Endian::le_to_host(output.dwell_time);
output.hop_set = output.hop_set;
@@ -676,23 +680,23 @@ Dot11ManagementFrame::fh_params_set Dot11ManagementFrame::fh_parameter_set() con
}
uint8_t Dot11ManagementFrame::ds_parameter_set() const {
const Dot11::dot11_option *option = search_option(DS_SET);
const Dot11::option *option = search_option(DS_SET);
if(!option || option->data_size() != sizeof(uint8_t))
throw std::runtime_error("DS parameters set not set");
throw option_not_found();
return *option->data_ptr();
}
uint16_t Dot11ManagementFrame::ibss_parameter_set() const {
const Dot11::dot11_option *option = search_option(IBSS_SET);
const Dot11::option *option = search_option(IBSS_SET);
if(!option || option->data_size() != sizeof(uint16_t))
throw std::runtime_error("IBSS parameters set not set");
throw option_not_found();
return Endian::le_to_host(*reinterpret_cast<const uint16_t*>(option->data_ptr()));
}
Dot11ManagementFrame::ibss_dfs_params Dot11ManagementFrame::ibss_dfs() const {
const Dot11::dot11_option *option = search_option(IBSS_DFS);
const Dot11::option *option = search_option(IBSS_DFS);
if(!option || option->data_size() < ibss_dfs_params::minimum_size)
throw std::runtime_error("IBSS DFS set not set");
throw option_not_found();
ibss_dfs_params output;
const uint8_t *ptr = option->data_ptr(), *end = ptr + option->data_size();
output.dfs_owner = ptr;
@@ -701,16 +705,16 @@ Dot11ManagementFrame::ibss_dfs_params Dot11ManagementFrame::ibss_dfs() const {
while(ptr != end) {
uint8_t first = *(ptr++);
if(ptr == end)
throw std::runtime_error("Malformed channel data");
throw option_not_found();
output.channel_map.push_back(std::make_pair(first, *(ptr++)));
}
return output;
}
Dot11ManagementFrame::country_params Dot11ManagementFrame::country() const {
const Dot11::dot11_option *option = search_option(COUNTRY);
const Dot11::option *option = search_option(COUNTRY);
if(!option || option->data_size() < country_params::minimum_size)
throw std::runtime_error("Country option not set");
throw option_not_found();
country_params output;
const uint8_t *ptr = option->data_ptr(), *end = ptr + option->data_size();
std::copy(ptr, ptr + 3, std::back_inserter(output.country));
@@ -721,23 +725,23 @@ Dot11ManagementFrame::country_params Dot11ManagementFrame::country() const {
output.max_transmit_power.push_back(*(ptr++));
}
if(ptr != end)
throw std::runtime_error("Malformed option");
throw option_not_found();
return output;
}
std::pair<uint8_t, uint8_t> Dot11ManagementFrame::fh_parameters() const {
const Dot11::dot11_option *option = search_option(HOPPING_PATTERN_PARAMS);
const Dot11::option *option = search_option(HOPPING_PATTERN_PARAMS);
if(!option || option->data_size() != sizeof(uint8_t) * 2)
throw std::runtime_error("FH parameters option not set");
throw option_not_found();
const uint8_t *ptr = option->data_ptr();
uint8_t first = *(ptr++);
return std::make_pair(first, *ptr);
}
Dot11ManagementFrame::fh_pattern_type Dot11ManagementFrame::fh_pattern_table() const {
const Dot11::dot11_option *option = search_option(HOPPING_PATTERN_TABLE);
const Dot11::option *option = search_option(HOPPING_PATTERN_TABLE);
if(!option || option->data_size() < fh_pattern_type::minimum_size)
throw std::runtime_error("FH pattern option not set");
throw option_not_found();
fh_pattern_type output;
const uint8_t *ptr = option->data_ptr(), *end = ptr + option->data_size();
@@ -751,16 +755,16 @@ Dot11ManagementFrame::fh_pattern_type Dot11ManagementFrame::fh_pattern_table() c
}
uint8_t Dot11ManagementFrame::power_constraint() const {
const Dot11::dot11_option *option = search_option(POWER_CONSTRAINT);
const Dot11::option *option = search_option(POWER_CONSTRAINT);
if(!option || option->data_size() != 1)
throw std::runtime_error("Power constraint option not set");
throw option_not_found();
return *option->data_ptr();
}
Dot11ManagementFrame::channel_switch_type Dot11ManagementFrame::channel_switch() const {
const Dot11::dot11_option *option = search_option(CHANNEL_SWITCH);
const Dot11::option *option = search_option(CHANNEL_SWITCH);
if(!option || option->data_size() != sizeof(uint8_t) * 3)
throw std::runtime_error("Channel switch option not set");
throw option_not_found();
const uint8_t *ptr = option->data_ptr();
channel_switch_type output;
output.switch_mode = *(ptr++);
@@ -770,9 +774,9 @@ Dot11ManagementFrame::channel_switch_type Dot11ManagementFrame::channel_switch()
}
Dot11ManagementFrame::quiet_type Dot11ManagementFrame::quiet() const {
const Dot11::dot11_option *option = search_option(QUIET);
const Dot11::option *option = search_option(QUIET);
if(!option || option->data_size() != (sizeof(uint8_t) * 2 + sizeof(uint16_t) * 2))
throw std::runtime_error("Quiet option not set");
throw option_not_found();
const uint8_t *ptr = option->data_ptr();
quiet_type output;
@@ -785,25 +789,25 @@ Dot11ManagementFrame::quiet_type Dot11ManagementFrame::quiet() const {
}
std::pair<uint8_t, uint8_t> Dot11ManagementFrame::tpc_report() const {
const Dot11::dot11_option *option = search_option(TPC_REPORT);
const Dot11::option *option = search_option(TPC_REPORT);
if(!option || option->data_size() != sizeof(uint8_t) * 2)
throw std::runtime_error("TPC Report option not set");
throw option_not_found();
const uint8_t *ptr = option->data_ptr();
uint8_t first = *(ptr++);
return std::make_pair(first, *ptr);
}
uint8_t Dot11ManagementFrame::erp_information() const {
const Dot11::dot11_option *option = search_option(ERP_INFORMATION);
const Dot11::option *option = search_option(ERP_INFORMATION);
if(!option || option->data_size() != sizeof(uint8_t))
throw std::runtime_error("ERP Information option not set");
throw option_not_found();
return *option->data_ptr();
}
Dot11ManagementFrame::bss_load_type Dot11ManagementFrame::bss_load() const {
const Dot11::dot11_option *option = search_option(BSS_LOAD);
const Dot11::option *option = search_option(BSS_LOAD);
if(!option || option->data_size() != sizeof(uint8_t) + 2 * sizeof(uint16_t))
throw std::runtime_error("BSS Load option not set");
throw option_not_found();
bss_load_type output;
const uint8_t *ptr = option->data_ptr();
@@ -814,9 +818,9 @@ Dot11ManagementFrame::bss_load_type Dot11ManagementFrame::bss_load() const {
}
Dot11ManagementFrame::tim_type Dot11ManagementFrame::tim() const {
const Dot11::dot11_option *option = search_option(TIM);
const Dot11::option *option = search_option(TIM);
if(!option || option->data_size() < 4 * sizeof(uint8_t))
throw std::runtime_error("TIM option not set");
throw option_not_found();
const uint8_t *ptr = option->data_ptr(), *end = ptr + option->data_size();
tim_type output;
@@ -829,9 +833,9 @@ Dot11ManagementFrame::tim_type Dot11ManagementFrame::tim() const {
}
std::string Dot11ManagementFrame::challenge_text() const {
const Dot11::dot11_option *option = search_option(CHALLENGE_TEXT);
const Dot11::option *option = search_option(CHALLENGE_TEXT);
if(!option || option->data_size() == 0)
throw std::runtime_error("Challenge text option not set");
throw option_not_found();
return std::string(option->data_ptr(), option->data_ptr() + option->data_size());
}
@@ -852,7 +856,7 @@ Dot11Beacon::Dot11Beacon(const uint8_t *buffer, uint32_t total_sz)
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(_body))
throw runtime_error("Not enough size for a IEEE 802.11 beacon header in the buffer.");
throw malformed_packet();
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
@@ -873,7 +877,9 @@ uint32_t Dot11Beacon::header_size() const {
uint32_t Dot11Beacon::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) {
uint32_t sz = sizeof(_body);
#ifdef TINS_DEBUG
assert(sz <= total_sz);
#endif
memcpy(buffer, &this->_body, sz);
return sz;
}
@@ -894,7 +900,7 @@ Dot11Disassoc::Dot11Disassoc(const uint8_t *buffer, uint32_t total_sz)
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(_body))
throw runtime_error("Not enough size for a IEEE 802.11 disassociation header in the buffer.");
throw malformed_packet();
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
@@ -911,7 +917,9 @@ uint32_t Dot11Disassoc::header_size() const {
uint32_t Dot11Disassoc::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) {
uint32_t sz = sizeof(DisassocBody);
#ifdef TINS_DEBUG
assert(sz <= total_sz);
#endif
memcpy(buffer, &this->_body, sz);
return sz;
}
@@ -926,12 +934,14 @@ const address_type &src_hw_addr)
memset(&_body, 0, sizeof(_body));
}
Dot11AssocRequest::Dot11AssocRequest(const uint8_t *buffer, uint32_t total_sz) : Dot11ManagementFrame(buffer, total_sz) {
Dot11AssocRequest::Dot11AssocRequest(const uint8_t *buffer, uint32_t total_sz)
: Dot11ManagementFrame(buffer, total_sz)
{
uint32_t sz = management_frame_size();
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(_body))
throw runtime_error("Not enough size for an IEEE 802.11 association request header in the buffer.");
throw malformed_packet();
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
@@ -948,7 +958,9 @@ uint32_t Dot11AssocRequest::header_size() const {
uint32_t Dot11AssocRequest::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) {
uint32_t sz = sizeof(AssocReqBody);
#ifdef TINS_DEBUG
assert(sz <= total_sz);
#endif
memcpy(buffer, &this->_body, sz);
return sz;
}
@@ -970,7 +982,7 @@ Dot11AssocResponse::Dot11AssocResponse(const uint8_t *buffer, uint32_t total_sz)
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(_body))
throw runtime_error("Not enough size for an IEEE 802.11 association response header in the buffer.");
throw malformed_packet();
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
@@ -991,7 +1003,9 @@ uint32_t Dot11AssocResponse::header_size() const {
uint32_t Dot11AssocResponse::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) {
uint32_t sz = sizeof(AssocRespBody);
#ifdef TINS_DEBUG
assert(sz <= total_sz);
#endif
memcpy(buffer, &this->_body, sz);
return sz;
}
@@ -1013,7 +1027,7 @@ Dot11ReAssocRequest::Dot11ReAssocRequest(const uint8_t *buffer, uint32_t total_s
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(_body))
throw runtime_error("Not enough size for an IEEE 802.11 reassociation request header in the buffer.");
throw malformed_packet();
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
@@ -1034,7 +1048,9 @@ uint32_t Dot11ReAssocRequest::header_size() const {
uint32_t Dot11ReAssocRequest::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) {
uint32_t sz = sizeof(this->_body);
#ifdef TINS_DEBUG
assert(sz <= total_sz);
#endif
memcpy(buffer, &this->_body, sz);
return sz;
}
@@ -1055,7 +1071,7 @@ Dot11ReAssocResponse::Dot11ReAssocResponse(const uint8_t *buffer, uint32_t total
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(_body))
throw runtime_error("Not enough size for an IEEE 802.11 reassociation response header in the buffer.");
throw malformed_packet();
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
@@ -1076,7 +1092,9 @@ uint32_t Dot11ReAssocResponse::header_size() const {
uint32_t Dot11ReAssocResponse::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) {
uint32_t sz = sizeof(this->_body);
#ifdef TINS_DEBUG
assert(sz <= total_sz);
#endif
memcpy(buffer, &this->_body, sz);
return sz;
}
@@ -1099,7 +1117,7 @@ Dot11Authentication::Dot11Authentication(const uint8_t *buffer, uint32_t total_s
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(_body))
throw runtime_error("Not enough size for an IEEE 802.11 authentication header in the buffer.");
throw malformed_packet();
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
@@ -1124,7 +1142,9 @@ uint32_t Dot11Authentication::header_size() const {
uint32_t Dot11Authentication::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) {
uint32_t sz = sizeof(this->_body);
#ifdef TINS_DEBUG
assert(sz <= total_sz);
#endif
memcpy(buffer, &this->_body, sz);
return sz;
}
@@ -1145,7 +1165,7 @@ Dot11Deauthentication::Dot11Deauthentication(const uint8_t *buffer, uint32_t tot
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(_body))
throw runtime_error("Not enough size for a IEEE 802.11 deauthentication header in the buffer.");
throw malformed_packet();
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
@@ -1162,7 +1182,9 @@ uint32_t Dot11Deauthentication::header_size() const {
uint32_t Dot11Deauthentication::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) {
uint32_t sz = sizeof(this->_body);
#ifdef TINS_DEBUG
assert(sz <= total_sz);
#endif
memcpy(buffer, &this->_body, sz);
return sz;
}
@@ -1202,7 +1224,7 @@ Dot11ProbeResponse::Dot11ProbeResponse(const uint8_t *buffer, uint32_t total_sz)
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(_body))
throw runtime_error("Not enough size for an IEEE 802.11 probe response header in the buffer.");
throw malformed_packet();
memcpy(&_body, buffer, sizeof(_body));
buffer += sizeof(_body);
total_sz -= sizeof(_body);
@@ -1223,7 +1245,9 @@ uint32_t Dot11ProbeResponse::header_size() const {
uint32_t Dot11ProbeResponse::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) {
uint32_t sz = sizeof(this->_body);
#ifdef TINS_DEBUG
assert(sz <= total_sz);
#endif
memcpy(buffer, &this->_body, sz);
return sz;
}
@@ -1231,22 +1255,11 @@ uint32_t Dot11ProbeResponse::write_fixed_parameters(uint8_t *buffer, uint32_t to
/* Dot11Data */
Dot11Data::Dot11Data(const uint8_t *buffer, uint32_t total_sz)
: Dot11(buffer, total_sz) {
uint32_t sz = Dot11::header_size();
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(_ext_header))
throw runtime_error("Not enough size for an IEEE 802.11 data header in the buffer.");
std::memcpy(&_ext_header, buffer, sizeof(_ext_header));
buffer += sizeof(_ext_header);
total_sz -= sizeof(_ext_header);
if(from_ds() && to_ds()) {
if(total_sz < _addr4.size())
throw runtime_error("Not enough size for an IEEE 802.11 data header in the buffer.");
_addr4 = buffer;
buffer += _addr4.size();
total_sz -= _addr4.size();
}
: Dot11(buffer, total_sz)
{
const uint32_t offset = init(buffer, total_sz);
buffer += offset;
total_sz -= offset;
if(total_sz) {
// If the wep bit is on, then just use a RawPDU
if(wep())
@@ -1256,10 +1269,35 @@ Dot11Data::Dot11Data(const uint8_t *buffer, uint32_t total_sz)
}
}
Dot11Data::Dot11Data(const uint8_t *buffer, uint32_t total_sz, no_inner_pdu)
: Dot11(buffer, total_sz)
{
init(buffer, total_sz);
}
uint32_t Dot11Data::init(const uint8_t *buffer, uint32_t total_sz) {
const uint8_t *start_ptr = buffer;
uint32_t sz = Dot11::header_size();
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(_ext_header))
throw malformed_packet();
std::memcpy(&_ext_header, buffer, sizeof(_ext_header));
buffer += sizeof(_ext_header);
total_sz -= sizeof(_ext_header);
if(from_ds() && to_ds()) {
if(total_sz < _addr4.size())
throw malformed_packet();
_addr4 = buffer;
buffer += _addr4.size();
total_sz -= _addr4.size();
}
return buffer - start_ptr;
}
Dot11Data::Dot11Data(const address_type &dst_hw_addr,
const address_type &src_hw_addr, PDU* child)
: Dot11(dst_hw_addr, child)
const address_type &src_hw_addr)
: Dot11(dst_hw_addr)
{
type(Dot11::DATA);
memset(&_ext_header, 0, sizeof(_ext_header));
@@ -1316,8 +1354,8 @@ uint32_t Dot11Data::write_ext_header(uint8_t *buffer, uint32_t total_sz) {
/* QoS data. */
Dot11QoSData::Dot11QoSData(const address_type &dst_hw_addr,
const address_type &src_hw_addr, PDU* child)
: Dot11Data(dst_hw_addr, src_hw_addr, child)
const address_type &src_hw_addr)
: Dot11Data(dst_hw_addr, src_hw_addr)
{
subtype(Dot11::QOS_DATA_DATA);
_qos_control = 0;
@@ -1325,13 +1363,12 @@ Dot11QoSData::Dot11QoSData(const address_type &dst_hw_addr,
Dot11QoSData::Dot11QoSData(const uint8_t *buffer, uint32_t total_sz)
// Am I breaking something? :S
//: Dot11Data(buffer, std::min(data_frame_size(), total_sz)) {
: Dot11Data(buffer, total_sz) {
: Dot11Data(buffer, total_sz, no_inner_pdu()) {
uint32_t sz = data_frame_size();
buffer += sz;
total_sz -= sz;
if(total_sz < sizeof(this->_qos_control))
throw runtime_error("Not enough size for an IEEE 802.11 data header in the buffer.");
if(total_sz < sizeof(_qos_control))
throw malformed_packet();
_qos_control = *(uint16_t*)buffer;
total_sz -= sizeof(uint16_t);
buffer += sizeof(uint16_t);
@@ -1349,15 +1386,17 @@ uint32_t Dot11QoSData::header_size() const {
uint32_t Dot11QoSData::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) {
uint32_t sz = sizeof(this->_qos_control);
#ifdef TINS_DEBUG
assert(sz <= total_sz);
#endif
*(uint16_t*)buffer = this->_qos_control;
return sz;
}
/* Dot11Control */
Dot11Control::Dot11Control(const address_type &dst_addr, PDU* child)
: Dot11(dst_addr, child)
Dot11Control::Dot11Control(const address_type &dst_addr)
: Dot11(dst_addr)
{
type(CONTROL);
}
@@ -1370,8 +1409,8 @@ Dot11Control::Dot11Control(const uint8_t *buffer, uint32_t total_sz)
/* Dot11ControlTA */
Dot11ControlTA::Dot11ControlTA(const address_type &dst_addr,
const address_type &target_address, PDU* child)
: Dot11Control(dst_addr, child)
const address_type &target_address)
: Dot11Control(dst_addr)
{
target_addr(target_address);
}
@@ -1390,7 +1429,9 @@ uint32_t Dot11ControlTA::header_size() const {
}
uint32_t Dot11ControlTA::write_ext_header(uint8_t *buffer, uint32_t total_sz) {
#ifdef TINS_DEBUG
assert(total_sz >= sizeof(_taddr));
#endif
//std::memcpy(buffer, _taddr, sizeof(_taddr));
_taddr.copy(buffer);
return sizeof(_taddr);
@@ -1403,8 +1444,8 @@ void Dot11ControlTA::target_addr(const address_type &addr) {
/* Dot11RTS */
Dot11RTS::Dot11RTS(const address_type &dst_addr,
const address_type &target_addr, PDU* child)
: Dot11ControlTA(dst_addr, target_addr, child)
const address_type &target_addr)
: Dot11ControlTA(dst_addr, target_addr)
{
subtype(RTS);
}
@@ -1417,8 +1458,8 @@ Dot11RTS::Dot11RTS(const uint8_t *buffer, uint32_t total_sz)
/* Dot11PSPoll */
Dot11PSPoll::Dot11PSPoll(const address_type &dst_addr,
const address_type &target_addr, PDU* child)
: Dot11ControlTA(dst_addr, target_addr, child)
const address_type &target_addr)
: Dot11ControlTA(dst_addr, target_addr)
{
subtype(PS);
}
@@ -1431,8 +1472,8 @@ Dot11PSPoll::Dot11PSPoll(const uint8_t *buffer, uint32_t total_sz)
/* Dot11CFEnd */
Dot11CFEnd::Dot11CFEnd(const address_type &dst_addr,
const address_type &target_addr, PDU* child)
: Dot11ControlTA(dst_addr, target_addr, child)
const address_type &target_addr)
: Dot11ControlTA(dst_addr, target_addr)
{
subtype(CF_END);
}
@@ -1445,8 +1486,8 @@ Dot11CFEnd::Dot11CFEnd(const uint8_t *buffer, uint32_t total_sz)
/* Dot11EndCFAck */
Dot11EndCFAck::Dot11EndCFAck(const address_type &dst_addr,
const address_type &target_addr, PDU* child)
: Dot11ControlTA(dst_addr, target_addr, child)
const address_type &target_addr)
: Dot11ControlTA(dst_addr, target_addr)
{
subtype(CF_END_ACK);
}
@@ -1458,26 +1499,30 @@ Dot11EndCFAck::Dot11EndCFAck(const uint8_t *buffer, uint32_t total_sz)
/* Dot11Ack */
Dot11Ack::Dot11Ack(const address_type &dst_addr, PDU* child)
: Dot11Control(dst_addr, child)
Dot11Ack::Dot11Ack(const address_type &dst_addr)
: Dot11Control(dst_addr)
{
subtype(ACK);
}
Dot11Ack::Dot11Ack(const uint8_t *buffer, uint32_t total_sz) : Dot11Control(buffer, total_sz) {
Dot11Ack::Dot11Ack(const uint8_t *buffer, uint32_t total_sz)
: Dot11Control(buffer, total_sz)
{
}
/* Dot11BlockAck */
Dot11BlockAckRequest::Dot11BlockAckRequest(const address_type &dst_addr,
const address_type &target_addr, PDU* child)
: Dot11ControlTA(dst_addr, target_addr, child)
const address_type &target_addr)
: Dot11ControlTA(dst_addr, target_addr)
{
init_block_ack();
}
Dot11BlockAckRequest::Dot11BlockAckRequest(const uint8_t *buffer, uint32_t total_sz) : Dot11ControlTA(buffer, total_sz) {
Dot11BlockAckRequest::Dot11BlockAckRequest(const uint8_t *buffer, uint32_t total_sz)
: Dot11ControlTA(buffer, total_sz)
{
uint32_t padding = controlta_size();
buffer += padding;
total_sz -= padding;
@@ -1503,18 +1548,28 @@ uint32_t Dot11BlockAckRequest::write_ext_header(uint8_t *buffer, uint32_t total_
return parent_size + sizeof(_start_sequence) + sizeof(_bar_control);
}
void Dot11BlockAckRequest::bar_control(uint16_t bar) {
//std::memcpy(&_bar_control, &bar, sizeof(bar));
_bar_control.tid = Endian::host_to_le(bar);
void Dot11BlockAckRequest::bar_control(small_uint<4> bar) {
#if TINS_IS_LITTLE_ENDIAN
_bar_control = bar | (_bar_control & 0xfff0);
#else
_bar_control = (bar << 8) | (_bar_control & 0xf0ff);
#endif
}
void Dot11BlockAckRequest::start_sequence(uint16_t seq) {
//std::memcpy(&_start_sequence, &seq, sizeof(seq));
_start_sequence.seq = Endian::host_to_le(seq);
void Dot11BlockAckRequest::start_sequence(small_uint<12> seq) {
#if TINS_IS_LITTLE_ENDIAN
_start_sequence = (seq << 4) | (_start_sequence & 0xf);
#else
_start_sequence = Endian::host_to_le<uint16_t>(seq << 4) | (_start_sequence & 0xf00);
#endif
}
void Dot11BlockAckRequest::fragment_number(uint8_t frag) {
_start_sequence.frag = frag;
void Dot11BlockAckRequest::fragment_number(small_uint<4> frag) {
#if TINS_IS_LITTLE_ENDIAN
_start_sequence = frag | (_start_sequence & 0xfff0);
#else
_start_sequence = (frag << 8) | (_start_sequence & 0xf0ff);
#endif
}
uint32_t Dot11BlockAckRequest::header_size() const {
@@ -1524,8 +1579,8 @@ uint32_t Dot11BlockAckRequest::header_size() const {
/* Dot11BlockAck */
Dot11BlockAck::Dot11BlockAck(const address_type &dst_addr,
const address_type &target_addr, PDU* child)
: Dot11ControlTA(dst_addr, target_addr, child)
const address_type &target_addr)
: Dot11ControlTA(dst_addr, target_addr)
{
subtype(BLOCK_ACK);
std::memset(_bitmap, 0, sizeof(_bitmap));
@@ -1544,12 +1599,28 @@ Dot11BlockAck::Dot11BlockAck(const uint8_t *buffer, uint32_t total_sz) : Dot11Co
std::memcpy(&_bitmap, buffer, sizeof(_bitmap));
}
void Dot11BlockAck::bar_control(uint16_t bar) {
std::memcpy(&_bar_control, &bar, sizeof(bar));
void Dot11BlockAck::bar_control(small_uint<4> bar) {
#if TINS_IS_LITTLE_ENDIAN
_bar_control = bar | (_bar_control & 0xfff0);
#else
_bar_control = (bar << 8) | (_bar_control & 0xf0ff);
#endif
}
void Dot11BlockAck::start_sequence(uint16_t seq) {
std::memcpy(&_start_sequence, &seq, sizeof(seq));
void Dot11BlockAck::start_sequence(small_uint<12> seq) {
#if TINS_IS_LITTLE_ENDIAN
_start_sequence = (seq << 4) | (_start_sequence & 0xf);
#else
_start_sequence = Endian::host_to_le<uint16_t>(seq << 4) | (_start_sequence & 0xf00);
#endif
}
void Dot11BlockAck::fragment_number(small_uint<4> frag) {
#if TINS_IS_LITTLE_ENDIAN
_start_sequence = frag | (_start_sequence & 0xfff0);
#else
_start_sequence = (frag << 8) | (_start_sequence & 0xf0ff);
#endif
}
void Dot11BlockAck::bitmap(const uint8_t *bit) {

144
src/dot1q.cpp Normal file
View File

@@ -0,0 +1,144 @@
/*
* 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 <stdexcept>
#include <cstring>
#include <cassert>
#include "dot1q.h"
#include "internals.h"
#include "exceptions.h"
namespace Tins {
Dot1Q::Dot1Q(small_uint<12> tag_id, bool append_pad)
: _header(), _append_padding(append_pad)
{
id(tag_id);
}
Dot1Q::Dot1Q(const uint8_t *buffer, uint32_t total_sz)
: _append_padding()
{
if(total_sz < sizeof(_header))
throw malformed_packet();
std::memcpy(&_header, buffer, sizeof(_header));
buffer += sizeof(_header);
total_sz -= sizeof(_header);
if(total_sz) {
inner_pdu(
Internals::pdu_from_flag(
(Constants::Ethernet::e)payload_type(),
buffer,
total_sz
)
);
}
}
void Dot1Q::priority(small_uint<3> new_priority) {
_header.priority = new_priority;
}
void Dot1Q::cfi(small_uint<1> new_cfi) {
_header.cfi = new_cfi;
}
void Dot1Q::id(small_uint<12> new_id) {
#if TINS_IS_LITTLE_ENDIAN
_header.idL = new_id & 0xff;
_header.idH = new_id >> 8;
#else
_header.id = new_id;
#endif
}
void Dot1Q::payload_type(uint16_t new_type) {
_header.type = Endian::host_to_be(new_type);
}
uint32_t Dot1Q::header_size() const {
return sizeof(_header);
}
uint32_t Dot1Q::trailer_size() const {
if(_append_padding) {
uint32_t total_size = sizeof(_header);
if(inner_pdu())
total_size += inner_pdu()->size();
return (total_size > 50) ? 0 : (50 - total_size);
}
else
return 0;
}
void Dot1Q::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) {
uint32_t trailer = trailer_size();
#ifdef TINS_DEBUG
assert(total_sz >= sizeof(_header) + trailer);
#endif
if ((payload_type() == 0) && inner_pdu()) {
Constants::Ethernet::e flag = Internals::pdu_flag_to_ether_type(
inner_pdu()->pdu_type()
);
payload_type(static_cast<uint16_t>(flag));
}
std::memcpy(buffer, &_header, sizeof(_header));
buffer += sizeof(_header) + inner_pdu()->size();
std::fill(buffer, buffer + trailer, 0);
}
#if TINS_IS_LITTLE_ENDIAN
uint16_t Dot1Q::get_id(const dot1q_hdr *hdr) {
return hdr->idL | (hdr->idH << 8);
}
#else
uint16_t Dot1Q::get_id(const dot1q_hdr *hdr) {
return hdr->id;
}
#endif
void Dot1Q::append_padding(bool value) {
_append_padding = value;
}
bool Dot1Q::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
if(total_sz < sizeof(_header))
return false;
const dot1q_hdr *dot1q_ptr = (const dot1q_hdr*)ptr;
if(get_id(dot1q_ptr) == get_id(&_header)) {
ptr += sizeof(_header);
total_sz -= sizeof(_header);
return inner_pdu() ? inner_pdu()->matches_response(ptr, total_sz) : true;
}
return false;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,13 +27,15 @@
*
*/
#ifdef TINS_DEBUG
#include <cassert>
#endif
#include <cstring>
#include <stdexcept>
#include <algorithm>
#include "macros.h"
#ifndef WIN32
#ifdef BSD
#if defined(BSD) || defined(__FreeBSD_kernel__)
#include <net/if_dl.h>
#else
#include <netpacket/packet.h>
@@ -41,30 +43,27 @@
#include <net/ethernet.h>
#include <netinet/in.h>
#endif
#include "ieee802_3.h"
#include "dot3.h"
#include "packet_sender.h"
#include "llc.h"
#include "exceptions.h"
namespace Tins {
const IEEE802_3::address_type IEEE802_3::BROADCAST("ff:ff:ff:ff:ff:ff");
const Dot3::address_type Dot3::BROADCAST("ff:ff:ff:ff:ff:ff");
IEEE802_3::IEEE802_3(const NetworkInterface& iface,
const address_type &dst_hw_addr, const address_type &src_hw_addr,
PDU* child)
: PDU(child)
Dot3::Dot3(const address_type &dst_hw_addr, const address_type &src_hw_addr)
{
memset(&_eth, 0, sizeof(ethhdr));
this->dst_addr(dst_hw_addr);
this->src_addr(src_hw_addr);
this->iface(iface);
this->_eth.length = 0;
}
IEEE802_3::IEEE802_3(const uint8_t *buffer, uint32_t total_sz)
Dot3::Dot3(const uint8_t *buffer, uint32_t total_sz)
{
if(total_sz < sizeof(ethhdr))
throw std::runtime_error("Not enough size for an ethernetII header in the buffer.");
throw malformed_packet();
memcpy(&_eth, buffer, sizeof(ethhdr));
buffer += sizeof(ethhdr);
total_sz -= sizeof(ethhdr);
@@ -72,32 +71,28 @@ IEEE802_3::IEEE802_3(const uint8_t *buffer, uint32_t total_sz)
inner_pdu(new Tins::LLC(buffer, total_sz));
}
void IEEE802_3::dst_addr(const address_type &new_dst_mac) {
void Dot3::dst_addr(const address_type &new_dst_mac) {
std::copy(new_dst_mac.begin(), new_dst_mac.end(), _eth.dst_mac);
}
void IEEE802_3::src_addr(const address_type &new_src_mac) {
void Dot3::src_addr(const address_type &new_src_mac) {
std::copy(new_src_mac.begin(), new_src_mac.end(), _eth.src_mac);
}
void IEEE802_3::iface(const NetworkInterface &new_iface) {
_iface = new_iface;
}
void IEEE802_3::length(uint16_t new_length) {
void Dot3::length(uint16_t new_length) {
this->_eth.length = Endian::host_to_be(new_length);
}
uint32_t IEEE802_3::header_size() const {
uint32_t Dot3::header_size() const {
return sizeof(ethhdr);
}
#ifndef WIN32
void IEEE802_3::send(PacketSender &sender) {
if(!_iface)
throw std::runtime_error("Interface has not been set");
void Dot3::send(PacketSender &sender, const NetworkInterface &iface) {
if(!iface)
throw invalid_interface();
#ifndef BSD
#if !defined(BSD) && !defined(__FreeBSD_kernel__)
struct sockaddr_ll addr;
memset(&addr, 0, sizeof(struct sockaddr_ll));
@@ -105,30 +100,37 @@ void IEEE802_3::send(PacketSender &sender) {
addr.sll_family = Endian::host_to_be<uint16_t>(PF_PACKET);
addr.sll_protocol = Endian::host_to_be<uint16_t>(ETH_P_ALL);
addr.sll_halen = address_type::address_size;
addr.sll_ifindex = _iface.id();
addr.sll_ifindex = iface.id();
memcpy(&(addr.sll_addr), _eth.dst_mac, sizeof(_eth.dst_mac));
sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
#else
sender.send_l2(*this, 0, 0, _iface);
sender.send_l2(*this, 0, 0, iface);
#endif
}
#endif // WIN32
bool IEEE802_3::matches_response(uint8_t *ptr, uint32_t total_sz) {
bool Dot3::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
if(total_sz < sizeof(ethhdr))
return false;
ethhdr *eth_ptr = (ethhdr*)ptr;
if(!memcmp(eth_ptr->dst_mac, _eth.src_mac, sizeof(_eth.src_mac))) {
return true;
const size_t addr_sz = address_type::address_size;
const ethhdr *eth_ptr = (const ethhdr*)ptr;
if(std::equal(_eth.src_mac, _eth.src_mac + addr_sz, eth_ptr->dst_mac)) {
if(std::equal(_eth.src_mac, _eth.src_mac + addr_sz, eth_ptr->dst_mac) || dst_addr() == BROADCAST)
{
ptr += sizeof(ethhdr);
total_sz -= sizeof(ethhdr);
return inner_pdu() ? inner_pdu()->matches_response(ptr, total_sz) : true;
}
}
return false;
}
void IEEE802_3::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
uint32_t my_sz = header_size();
void Dot3::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
bool set_length = _eth.length == 0;
assert(total_sz >= my_sz);
#ifdef TINS_DEBUG
assert(total_sz >= header_size());
#endif
if (set_length)
_eth.length = Endian::host_to_be(size() - sizeof(_eth));
@@ -140,36 +142,23 @@ void IEEE802_3::write_serialization(uint8_t *buffer, uint32_t total_sz, const PD
}
#ifndef WIN32
PDU *IEEE802_3::recv_response(PacketSender &sender) {
if(!_iface)
throw std::runtime_error("Interface has not been set");
#ifndef BSD
PDU *Dot3::recv_response(PacketSender &sender, const NetworkInterface &iface) {
if(!iface)
throw invalid_interface();
#if !defined(BSD) && !defined(__FreeBSD_kernel__)
struct sockaddr_ll addr;
memset(&addr, 0, sizeof(struct sockaddr_ll));
addr.sll_family = Endian::host_to_be<uint16_t>(PF_PACKET);
addr.sll_protocol = Endian::host_to_be<uint16_t>(ETH_P_802_3);
addr.sll_halen = address_type::address_size;
addr.sll_ifindex = _iface.id();
addr.sll_ifindex = iface.id();
memcpy(&(addr.sll_addr), _eth.dst_mac, sizeof(_eth.dst_mac));
return sender.recv_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
#else
return sender.recv_l2(*this, 0, 0, _iface);
return sender.recv_l2(*this, 0, 0, iface);
#endif
}
#endif // WIN32
PDU *IEEE802_3::clone_packet(const uint8_t *ptr, uint32_t total_sz) {
if(total_sz < sizeof(_eth))
return 0;
PDU *child = 0, *cloned;
if(total_sz > sizeof(_eth)) {
if((child = PDU::clone_inner_pdu(ptr + sizeof(_eth), total_sz - sizeof(_eth))) == 0)
return 0;
}
cloned = new IEEE802_3(ptr, std::min(total_sz, (uint32_t)sizeof(_eth)));
cloned->inner_pdu(child);
return cloned;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,12 +28,14 @@
*/
#include <cstring>
#ifdef TINS_DEBUG
#include <cassert>
#endif
#include <stdexcept>
#include "eapol.h"
#include "dot11.h"
#include "rsn_information.h"
#include "exceptions.h"
namespace Tins {
EAPOL::EAPOL(uint8_t packet_type, EAPOLTYPE type)
@@ -47,13 +49,13 @@ EAPOL::EAPOL(uint8_t packet_type, EAPOLTYPE type)
EAPOL::EAPOL(const uint8_t *buffer, uint32_t total_sz)
{
if(total_sz < sizeof(_header))
throw std::runtime_error("Not enough size for an EAPOL header in the buffer.");
throw malformed_packet();
std::memcpy(&_header, buffer, sizeof(_header));
}
EAPOL *EAPOL::from_bytes(const uint8_t *buffer, uint32_t total_sz) {
if(total_sz < sizeof(eapolhdr))
throw std::runtime_error("Not enough size for an EAPOL header in the buffer.");
throw malformed_packet();
const eapolhdr *ptr = (const eapolhdr*)buffer;
switch(ptr->type) {
case RC4:
@@ -84,10 +86,9 @@ void EAPOL::type(uint8_t new_type) {
}
void EAPOL::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) {
uint32_t sz = header_size();
assert(total_sz >= sz);
//if(!_header.length)
// length(sz - sizeof(_header.version) - sizeof(_header.length) - sizeof(_header.type));
#ifdef TINS_DEBUG
assert(total_sz >= header_size());
#endif
std::memcpy(buffer, &_header, sizeof(_header));
write_body(buffer + sizeof(_header), total_sz - sizeof(_header));
}
@@ -106,7 +107,7 @@ RC4EAPOL::RC4EAPOL(const uint8_t *buffer, uint32_t total_sz)
buffer += sizeof(eapolhdr);
total_sz -= sizeof(eapolhdr);
if(total_sz < sizeof(_header))
throw std::runtime_error("Not enough size for an EAPOL header in the buffer.");
throw malformed_packet();
std::memcpy(&_header, buffer, sizeof(_header));
buffer += sizeof(_header);
total_sz -= sizeof(_header);
@@ -147,8 +148,9 @@ uint32_t RC4EAPOL::header_size() const {
}
void RC4EAPOL::write_body(uint8_t *buffer, uint32_t total_sz) {
uint32_t sz = sizeof(_header) + _key.size();
assert(total_sz >= sz);
#ifdef TINS_DEBUG
assert(total_sz >= sizeof(_header) + _key.size());
#endif
if(_key.size())
_header.key_length = Endian::host_to_be(_key.size());
std::memcpy(buffer, &_header, sizeof(_header));
@@ -171,7 +173,7 @@ RSNEAPOL::RSNEAPOL(const uint8_t *buffer, uint32_t total_sz)
buffer += sizeof(eapolhdr);
total_sz -= sizeof(eapolhdr);
if(total_sz < sizeof(_header))
throw std::runtime_error("Not enough size for an EAPOL header in the buffer.");
throw malformed_packet();
std::memcpy(&_header, buffer, sizeof(_header));
buffer += sizeof(_header);
total_sz -= sizeof(_header);
@@ -261,8 +263,9 @@ uint32_t RSNEAPOL::header_size() const {
}
void RSNEAPOL::write_body(uint8_t *buffer, uint32_t total_sz) {
uint32_t sz = header_size() - sizeof(eapolhdr);
assert(total_sz >= sz);
#ifdef TINS_DEBUG
assert(total_sz >= header_size() - sizeof(eapolhdr));
#endif
if(_key.size()) {
if(!_header.key_t) {
_header.key_length = Endian::host_to_be<uint16_t>(32);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,13 +27,15 @@
*
*/
#ifdef TINS_DEBUG
#include <cassert>
#endif
#include <cstring>
#include <stdexcept>
#include <algorithm>
#include "macros.h"
#ifndef WIN32
#ifdef BSD
#if defined(BSD) || defined(__FreeBSD_kernel__)
#include <net/if_dl.h>
#else
#include <netpacket/packet.h>
@@ -49,19 +51,17 @@
#include "arp.h"
#include "constants.h"
#include "internals.h"
#include "exceptions.h"
namespace Tins {
const EthernetII::address_type EthernetII::BROADCAST("ff:ff:ff:ff:ff:ff");
EthernetII::EthernetII(const NetworkInterface& iface,
const address_type &dst_hw_addr, const address_type &src_hw_addr,
PDU* child)
: PDU(child)
EthernetII::EthernetII(const address_type &dst_hw_addr,
const address_type &src_hw_addr)
{
memset(&_eth, 0, sizeof(ethhdr));
dst_addr(dst_hw_addr);
src_addr(src_hw_addr);
this->iface(iface);
_eth.payload_type = 0;
}
@@ -69,7 +69,7 @@ EthernetII::EthernetII(const NetworkInterface& iface,
EthernetII::EthernetII(const uint8_t *buffer, uint32_t total_sz)
{
if(total_sz < sizeof(ethhdr))
throw std::runtime_error("Not enough size for an ethernetII header in the buffer.");
throw malformed_packet();
memcpy(&_eth, buffer, sizeof(ethhdr));
buffer += sizeof(ethhdr);
total_sz -= sizeof(ethhdr);
@@ -92,10 +92,6 @@ void EthernetII::src_addr(const address_type &new_src_addr) {
new_src_addr.copy(_eth.src_mac);
}
void EthernetII::iface(const NetworkInterface& new_iface) {
_iface = new_iface;
}
void EthernetII::payload_type(uint16_t new_payload_type) {
this->_eth.payload_type = Endian::host_to_be(new_payload_type);
}
@@ -105,11 +101,11 @@ uint32_t EthernetII::header_size() const {
}
#ifndef WIN32
void EthernetII::send(PacketSender &sender) {
if(!_iface)
throw std::runtime_error("Interface has not been set");
void EthernetII::send(PacketSender &sender, const NetworkInterface &iface) {
if(!iface)
throw invalid_interface();
#ifndef BSD
#if !defined(BSD) && !defined(__FreeBSD_kernel__)
struct sockaddr_ll addr;
memset(&addr, 0, sizeof(struct sockaddr_ll));
@@ -117,30 +113,35 @@ void EthernetII::send(PacketSender &sender) {
addr.sll_family = Endian::host_to_be<uint16_t>(PF_PACKET);
addr.sll_protocol = Endian::host_to_be<uint16_t>(ETH_P_ALL);
addr.sll_halen = address_type::address_size;
addr.sll_ifindex = _iface.id();
addr.sll_ifindex = iface.id();
memcpy(&(addr.sll_addr), _eth.dst_mac, address_type::address_size);
sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
#else
sender.send_l2(*this, 0, 0, _iface);
sender.send_l2(*this, 0, 0, iface);
#endif
}
#endif // WIN32
bool EthernetII::matches_response(uint8_t *ptr, uint32_t total_sz) {
bool EthernetII::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
if(total_sz < sizeof(ethhdr))
return false;
ethhdr *eth_ptr = (ethhdr*)ptr;
if(!memcmp(eth_ptr->dst_mac, _eth.src_mac, address_type::address_size)) {
// chequear broadcast en destino original...
return (inner_pdu()) ? inner_pdu()->matches_response(ptr + sizeof(_eth), total_sz - sizeof(_eth)) : true;
const size_t addr_sz = address_type::address_size;
const ethhdr *eth_ptr = (const ethhdr*)ptr;
if(std::equal(_eth.src_mac, _eth.src_mac + addr_sz, eth_ptr->dst_mac)) {
if(std::equal(_eth.src_mac, _eth.src_mac + addr_sz, eth_ptr->dst_mac) || dst_addr() == BROADCAST ||
(_eth.src_mac[0] == 0x33 && _eth.src_mac[1] == 0x33))
{
return (inner_pdu()) ? inner_pdu()->matches_response(ptr + sizeof(_eth), total_sz - sizeof(_eth)) : true;
}
}
return false;
}
void EthernetII::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
uint32_t my_sz = header_size();
assert(total_sz >= my_sz);
#ifdef TINS_DEBUG
assert(total_sz >= header_size());
#endif
/* Inner type defaults to IP */
if ((_eth.payload_type == 0) && inner_pdu()) {
@@ -153,34 +154,21 @@ void EthernetII::write_serialization(uint8_t *buffer, uint32_t total_sz, const P
}
#ifndef WIN32
PDU *EthernetII::recv_response(PacketSender &sender) {
#ifndef BSD
PDU *EthernetII::recv_response(PacketSender &sender, const NetworkInterface &iface) {
#if !defined(BSD) && !defined(__FreeBSD_kernel__)
struct sockaddr_ll addr;
memset(&addr, 0, sizeof(struct sockaddr_ll));
addr.sll_family = Endian::host_to_be<uint16_t>(PF_PACKET);
addr.sll_protocol = Endian::host_to_be<uint16_t>(ETH_P_ALL);
addr.sll_halen = address_type::address_size;
addr.sll_ifindex = _iface.id();
addr.sll_ifindex = iface.id();
memcpy(&(addr.sll_addr), _eth.dst_mac, address_type::address_size);
return sender.recv_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
#else
return sender.recv_l2(*this, 0, 0, _iface);
return sender.recv_l2(*this, 0, 0, iface);
#endif
}
#endif // WIN32
PDU *EthernetII::clone_packet(const uint8_t *ptr, uint32_t total_sz) {
if(total_sz < sizeof(_eth))
return 0;
PDU *child = 0, *cloned;
if(total_sz > sizeof(_eth)) {
if((child = PDU::clone_inner_pdu(ptr + sizeof(_eth), total_sz - sizeof(_eth))) == 0)
return 0;
}
cloned = new EthernetII(ptr, std::min(total_sz, (uint32_t)sizeof(_eth)));
cloned->inner_pdu(child);
return cloned;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,7 +29,9 @@
#include <stdexcept>
#include <cstring>
#ifdef TINS_DEBUG
#include <cassert>
#endif
#ifndef WIN32
#define NOMINMAX
#include <netinet/in.h>
@@ -37,95 +39,97 @@
#include "icmp.h"
#include "rawpdu.h"
#include "utils.h"
#include "exceptions.h"
Tins::ICMP::ICMP(Flags flag)
namespace Tins {
ICMP::ICMP(Flags flag)
{
std::memset(&_icmp, 0, sizeof(icmphdr));
type(flag);
}
Tins::ICMP::ICMP(const uint8_t *buffer, uint32_t total_sz)
ICMP::ICMP(const uint8_t *buffer, uint32_t total_sz)
{
if(total_sz < sizeof(icmphdr))
throw std::runtime_error("Not enough size for an ICMP header in the buffer.");
throw malformed_packet();
std::memcpy(&_icmp, buffer, sizeof(icmphdr));
total_sz -= sizeof(icmphdr);
if(total_sz)
inner_pdu(new RawPDU(buffer + sizeof(icmphdr), total_sz));
}
void Tins::ICMP::code(uint8_t new_code) {
void ICMP::code(uint8_t new_code) {
_icmp.code = new_code;
}
void Tins::ICMP::type(Flags new_type) {
void ICMP::type(Flags new_type) {
_icmp.type = new_type;
}
void Tins::ICMP::check(uint16_t new_check) {
void ICMP::check(uint16_t new_check) {
_icmp.check = Endian::host_to_be(new_check);
}
void Tins::ICMP::id(uint16_t new_id) {
void ICMP::id(uint16_t new_id) {
_icmp.un.echo.id = Endian::host_to_be(new_id);
}
void Tins::ICMP::sequence(uint16_t new_seq) {
void ICMP::sequence(uint16_t new_seq) {
_icmp.un.echo.sequence = Endian::host_to_be(new_seq);
}
void Tins::ICMP::gateway(uint32_t new_gw) {
void ICMP::gateway(uint32_t new_gw) {
_icmp.un.gateway = Endian::host_to_be(new_gw);
}
void Tins::ICMP::mtu(uint16_t new_mtu) {
void ICMP::mtu(uint16_t new_mtu) {
_icmp.un.frag.mtu = Endian::host_to_be(new_mtu);
}
void Tins::ICMP::pointer(uint8_t new_pointer) {
void ICMP::pointer(uint8_t new_pointer) {
_icmp.un.pointer = new_pointer;
}
uint32_t Tins::ICMP::header_size() const {
uint32_t ICMP::header_size() const {
return sizeof(icmphdr);
}
void Tins::ICMP::set_echo_request(uint16_t id, uint16_t seq) {
void ICMP::set_echo_request(uint16_t id, uint16_t seq) {
type(ECHO_REQUEST);
this->id(id);
sequence(seq);
}
void Tins::ICMP::set_echo_reply(uint16_t id, uint16_t seq) {
void ICMP::set_echo_reply(uint16_t id, uint16_t seq) {
type(ECHO_REPLY);
this->id(id);
sequence(seq);
}
void Tins::ICMP::set_info_request(uint16_t id, uint16_t seq) {
void ICMP::set_info_request(uint16_t id, uint16_t seq) {
type(INFO_REQUEST);
code(0);
this->id(id);
sequence(seq);
}
void Tins::ICMP::set_info_reply(uint16_t id, uint16_t seq) {
void ICMP::set_info_reply(uint16_t id, uint16_t seq) {
type(INFO_REPLY);
code(0);
this->id(id);
sequence(seq);
}
void Tins::ICMP::set_dest_unreachable() {
void ICMP::set_dest_unreachable() {
type(DEST_UNREACHABLE);
}
void Tins::ICMP::set_time_exceeded(bool ttl_exceeded) {
void ICMP::set_time_exceeded(bool ttl_exceeded) {
type(TIME_EXCEEDED);
code((ttl_exceeded) ? 0 : 1);
}
void Tins::ICMP::set_param_problem(bool set_pointer, uint8_t bad_octet) {
void ICMP::set_param_problem(bool set_pointer, uint8_t bad_octet) {
type(PARAM_PROBLEM);
if(set_pointer) {
code(0);
@@ -135,18 +139,20 @@ void Tins::ICMP::set_param_problem(bool set_pointer, uint8_t bad_octet) {
code(1);
}
void Tins::ICMP::set_source_quench() {
void ICMP::set_source_quench() {
type(SOURCE_QUENCH);
}
void Tins::ICMP::set_redirect(uint8_t icode, uint32_t address) {
void ICMP::set_redirect(uint8_t icode, uint32_t address) {
type(REDIRECT);
code(icode);
gateway(address);
}
void Tins::ICMP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) {
void ICMP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) {
#ifdef TINS_DEBUG
assert(total_sz >= sizeof(icmphdr));
#endif
if(!_icmp.check) {
uint32_t checksum = Utils::do_checksum(buffer + sizeof(icmphdr), buffer + total_sz) +
Utils::do_checksum((uint8_t*)&_icmp, ((uint8_t*)&_icmp) + sizeof(icmphdr));
@@ -158,25 +164,13 @@ void Tins::ICMP::write_serialization(uint8_t *buffer, uint32_t total_sz, const P
_icmp.check = 0;
}
bool Tins::ICMP::matches_response(uint8_t *ptr, uint32_t total_sz) {
bool ICMP::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
if(total_sz < sizeof(icmphdr))
return false;
icmphdr *icmp_ptr = (icmphdr*)ptr;
if(_icmp.type == ECHO_REQUEST) {
return icmp_ptr->type == ECHO_REPLY && icmp_ptr->un.echo.id == _icmp.un.echo.id && icmp_ptr->un.echo.sequence == _icmp.un.echo.sequence;
const icmphdr *icmp_ptr = (const icmphdr*)ptr;
if(_icmp.type == ECHO_REQUEST && icmp_ptr->type == ECHO_REPLY) {
return icmp_ptr->un.echo.id == _icmp.un.echo.id && icmp_ptr->un.echo.sequence == _icmp.un.echo.sequence;
}
return false;
}
Tins::PDU *Tins::ICMP::clone_packet(const uint8_t *ptr, uint32_t total_sz) {
if(total_sz < sizeof(icmphdr))
return 0;
PDU *child = 0, *cloned;
if(total_sz > sizeof(icmphdr)) {
if((child = PDU::clone_inner_pdu(ptr + sizeof(icmphdr), total_sz - sizeof(icmphdr))) == 0)
return 0;
}
cloned = new ICMP(ptr, std::min(total_sz, (uint32_t)sizeof(_icmp)));
cloned->inner_pdu(child);
return cloned;
}
} // namespace Tins

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,13 +27,16 @@
*
*/
#ifdef TINS_DEBUG
#include <cassert>
#endif
#include <cstring>
#include "icmpv6.h"
#include "ipv6.h"
#include "rawpdu.h"
#include "utils.h"
#include "constants.h"
#include "exceptions.h"
namespace Tins {
@@ -48,27 +51,27 @@ ICMPv6::ICMPv6(const uint8_t *buffer, uint32_t total_sz)
: _options_size(), reach_time(0), retrans_timer(0)
{
if(total_sz < sizeof(_header))
throw std::runtime_error("Not enough size for an ICMPv6 header");
throw malformed_packet();
std::memcpy(&_header, buffer, sizeof(_header));
buffer += sizeof(_header);
total_sz -= sizeof(_header);
if(has_target_addr()) {
if(total_sz < ipaddress_type::address_size)
throw std::runtime_error("Not enough size for the target address");
throw malformed_packet();
target_addr(buffer);
buffer += ipaddress_type::address_size;
total_sz -= ipaddress_type::address_size;
}
if(has_dest_addr()) {
if(total_sz < ipaddress_type::address_size)
throw std::runtime_error("Not enough size for the destination address");
throw malformed_packet();
dest_addr(buffer);
buffer += ipaddress_type::address_size;
total_sz -= ipaddress_type::address_size;
}
if(type() == ROUTER_ADVERT) {
if(total_sz < sizeof(uint32_t) * 2)
throw std::runtime_error("Not enough size for router advert fields");
throw malformed_packet();
const uint32_t *ptr_32 = (const uint32_t*)buffer;
reach_time = *ptr_32++;
retrans_timer = *ptr_32++;
@@ -85,9 +88,15 @@ ICMPv6::ICMPv6(const uint8_t *buffer, uint32_t total_sz)
void ICMPv6::parse_options(const uint8_t *&buffer, uint32_t &total_sz) {
while(total_sz > 0) {
if(total_sz < 8 || (static_cast<uint32_t>(buffer[1]) * 8) > total_sz || buffer[1] < 1)
throw std::runtime_error("Not enough size for options");
throw malformed_packet();
// size(option) = option_size - identifier_size - length_identifier_size
add_option(icmpv6_option(buffer[0], static_cast<uint32_t>(buffer[1]) * 8 - sizeof(uint8_t) * 2, buffer + 2));
add_option(
option(
buffer[0],
static_cast<uint32_t>(buffer[1]) * 8 - sizeof(uint8_t) * 2,
buffer + 2
)
);
total_sz -= buffer[1] * 8;
buffer += buffer[1] * 8;
}
@@ -174,6 +183,16 @@ uint32_t ICMPv6::header_size() const {
(has_dest_addr() ? ipaddress_type::address_size : 0);
}
bool ICMPv6::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
if(total_sz < sizeof(icmp6hdr))
return false;
const icmp6hdr *hdr_ptr = (const icmp6hdr*)ptr;
if(type() == ECHO_REQUEST && hdr_ptr->type == ECHO_REPLY)
return hdr_ptr->u_echo.identifier == _header.u_echo.identifier &&
hdr_ptr->u_echo.sequence == _header.u_echo.sequence;
return false;
}
void ICMPv6::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
#ifdef TINS_DEBUG
assert(total_sz >= header_size());
@@ -200,6 +219,7 @@ void ICMPv6::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *
for(options_type::const_iterator it = _options.begin(); it != _options.end(); ++it) {
#ifdef TINS_DEBUG
assert(total_sz >= it->data_size() + sizeof(uint8_t) * 2);
// total_sz is only used if TINS_DEBUG is defined.
total_sz -= it->data_size() + sizeof(uint8_t) * 2;
#endif
buffer = write_option(*it, buffer);
@@ -226,18 +246,22 @@ bool ICMPv6::has_options() const {
type() == ROUTER_ADVERT;
}
void ICMPv6::add_option(const icmpv6_option &option) {
void ICMPv6::add_option(const option &option) {
internal_add_option(option);
_options.push_back(option);
}
void ICMPv6::internal_add_option(const option &option) {
_options_size += option.data_size() + sizeof(uint8_t) * 2;
}
uint8_t *ICMPv6::write_option(const icmpv6_option &opt, uint8_t *buffer) {
uint8_t *ICMPv6::write_option(const option &opt, uint8_t *buffer) {
*buffer++ = opt.option();
*buffer++ = (opt.data_size() + sizeof(uint8_t) * 2) / 8;
*buffer++ = (opt.length_field() + sizeof(uint8_t) * 2) / 8;
return std::copy(opt.data_ptr(), opt.data_ptr() + opt.data_size(), buffer);
}
const ICMPv6::icmpv6_option *ICMPv6::search_option(Options id) const {
const ICMPv6::option *ICMPv6::search_option(OptionTypes id) const {
for(options_type::const_iterator it = _options.begin(); it != _options.end(); ++it) {
if(it->option() == id)
return &*it;
@@ -250,11 +274,11 @@ const ICMPv6::icmpv6_option *ICMPv6::search_option(Options id) const {
// ********************************************************************
void ICMPv6::source_link_layer_addr(const hwaddress_type &addr) {
add_option(icmpv6_option(SOURCE_ADDRESS, addr.begin(), addr.end()));
add_option(option(SOURCE_ADDRESS, addr.begin(), addr.end()));
}
void ICMPv6::target_link_layer_addr(const hwaddress_type &addr) {
add_option(icmpv6_option(TARGET_ADDRESS, addr.begin(), addr.end()));
add_option(option(TARGET_ADDRESS, addr.begin(), addr.end()));
}
void ICMPv6::prefix_info(prefix_info_type info) {
@@ -266,7 +290,7 @@ void ICMPv6::prefix_info(prefix_info_type info) {
*(uint32_t*)(buffer + 2 + sizeof(uint32_t) * 2) = 0;
info.prefix.copy(buffer + 2 + sizeof(uint32_t) * 3);
add_option(
icmpv6_option(PREFIX_INFO, buffer, buffer + sizeof(buffer))
option(PREFIX_INFO, buffer, buffer + sizeof(buffer))
);
}
@@ -278,32 +302,32 @@ void ICMPv6::redirect_header(PDU::serialization_type data) {
if(padding == 8)
padding = 0;
data.insert(data.end(), padding, 0);
add_option(icmpv6_option(REDIRECT_HEADER, data.begin(), data.end()));
add_option(option(REDIRECT_HEADER, data.begin(), data.end()));
}
void ICMPv6::mtu(uint32_t value) {
uint8_t buffer[sizeof(uint16_t) + sizeof(uint32_t)] = {0};
*((uint32_t*)(buffer + sizeof(uint16_t))) = Endian::host_to_be(value);
add_option(icmpv6_option(MTU, sizeof(buffer), buffer));
add_option(option(MTU, sizeof(buffer), buffer));
}
void ICMPv6::shortcut_limit(uint8_t value) {
uint8_t buffer[sizeof(uint16_t) + sizeof(uint32_t)] = {0};
buffer[0] = value;
add_option(icmpv6_option(NBMA_SHORT_LIMIT, sizeof(buffer), buffer));
add_option(option(NBMA_SHORT_LIMIT, sizeof(buffer), buffer));
}
void ICMPv6::new_advert_interval(uint32_t value) {
uint8_t buffer[sizeof(uint16_t) + sizeof(uint32_t)] = {0};
*((uint32_t*)(buffer + sizeof(uint16_t))) = Endian::host_to_be(value);
add_option(icmpv6_option(ADVERT_INTERVAL, sizeof(buffer), buffer));
add_option(option(ADVERT_INTERVAL, sizeof(buffer), buffer));
}
void ICMPv6::new_home_agent_info(const new_ha_info_type &value) {
uint8_t buffer[sizeof(uint16_t) + sizeof(uint32_t)] = {0};
*((uint16_t*)(buffer + sizeof(uint16_t))) = Endian::host_to_be(value.first);
*((uint16_t*)(buffer + sizeof(uint16_t) * 2)) = Endian::host_to_be(value.second);
add_option(icmpv6_option(HOME_AGENT_INFO, sizeof(buffer), buffer));
add_option(option(HOME_AGENT_INFO, sizeof(buffer), buffer));
}
void ICMPv6::source_addr_list(const addr_list_type &value) {
@@ -320,7 +344,7 @@ void ICMPv6::add_addr_list(uint8_t type, const addr_list_type &value) {
buffer.insert(buffer.end(), 6, 0);
for(addr_list_type::const_iterator it(value.begin()); it != value.end(); ++it)
buffer.insert(buffer.end(), it->begin(), it->end());
add_option(icmpv6_option(type, buffer.begin(), buffer.end()));
add_option(option(type, buffer.begin(), buffer.end()));
}
void ICMPv6::rsa_signature(const rsa_sign_type &value) {
@@ -334,18 +358,18 @@ void ICMPv6::rsa_signature(const rsa_sign_type &value) {
buffer.insert(buffer.end(), value.key_hash, value.key_hash + sizeof(value.key_hash));
buffer.insert(buffer.end(), value.signature.begin(), value.signature.end());
buffer.insert(buffer.end(), padding, 0);
add_option(icmpv6_option(RSA_SIGN, buffer.begin(), buffer.end()));
add_option(option(RSA_SIGN, buffer.begin(), buffer.end()));
}
void ICMPv6::timestamp(uint64_t value) {
std::vector<uint8_t> buffer(6 + sizeof(uint64_t));
buffer.insert(buffer.begin(), 6, 0);
*((uint64_t*)&buffer[6]) = Endian::host_to_be(value);
add_option(icmpv6_option(TIMESTAMP, buffer.begin(), buffer.end()));
add_option(option(TIMESTAMP, buffer.begin(), buffer.end()));
}
void ICMPv6::nonce(const nonce_type &value) {
add_option(icmpv6_option(NONCE, value.begin(), value.end()));
add_option(option(NONCE, value.begin(), value.end()));
}
void ICMPv6::ip_prefix(const ip_prefix_type &value) {
@@ -356,7 +380,7 @@ void ICMPv6::ip_prefix(const ip_prefix_type &value) {
// reserved
buffer.insert(buffer.end(), sizeof(uint32_t), 0);
buffer.insert(buffer.end(), value.address.begin(), value.address.end());
add_option(icmpv6_option(IP_PREFIX, buffer.begin(), buffer.end()));
add_option(option(IP_PREFIX, buffer.begin(), buffer.end()));
}
void ICMPv6::link_layer_addr(lladdr_type value) {
@@ -365,14 +389,14 @@ void ICMPv6::link_layer_addr(lladdr_type value) {
if(padding == 8)
padding = 0;
value.address.insert(value.address.end(), padding, 0);
add_option(icmpv6_option(LINK_ADDRESS, value.address.begin(), value.address.end()));
add_option(option(LINK_ADDRESS, value.address.begin(), value.address.end()));
}
void ICMPv6::naack(const naack_type &value) {
uint8_t buffer[6];
buffer[0] = value.first;
buffer[1] = value.second;
add_option(icmpv6_option(NAACK, buffer, buffer + sizeof(buffer)));
add_option(option(NAACK, buffer, buffer + sizeof(buffer)));
}
void ICMPv6::map(const map_type &value) {
@@ -381,7 +405,7 @@ void ICMPv6::map(const map_type &value) {
buffer[1] = value.r << 7;
*(uint32_t*)(buffer + 2) = Endian::host_to_be(value.valid_lifetime);
value.address.copy(buffer + 2 + sizeof(uint32_t));
add_option(icmpv6_option(MAP, buffer, buffer + sizeof(buffer)));
add_option(option(MAP, buffer, buffer + sizeof(buffer)));
}
void ICMPv6::route_info(const route_info_type &value) {
@@ -398,7 +422,7 @@ void ICMPv6::route_info(const route_info_type &value) {
padding,
0
);
add_option(icmpv6_option(ROUTE_INFO, buffer.begin(), buffer.end()));
add_option(option(ROUTE_INFO, buffer.begin(), buffer.end()));
}
void ICMPv6::recursive_dns_servers(const recursive_dns_type &value) {
@@ -412,7 +436,7 @@ void ICMPv6::recursive_dns_servers(const recursive_dns_type &value) {
typedef recursive_dns_type::servers_type::const_iterator iterator;
for(iterator it = value.servers.begin(); it != value.servers.end(); ++it)
out = it->copy(out);
add_option(icmpv6_option(RECURSIVE_DNS_SERV, buffer.begin(), buffer.end()));
add_option(option(RECURSIVE_DNS_SERV, buffer.begin(), buffer.end()));
}
void ICMPv6::handover_key_request(const handover_key_req_type &value) {
@@ -428,7 +452,7 @@ void ICMPv6::handover_key_request(const handover_key_req_type &value) {
buffer.end(),
0
);
add_option(icmpv6_option(HANDOVER_KEY_REQ, buffer.begin(), buffer.end()));
add_option(option(HANDOVER_KEY_REQ, buffer.begin(), buffer.end()));
}
void ICMPv6::handover_key_reply(const handover_key_reply_type &value) {
@@ -446,7 +470,7 @@ void ICMPv6::handover_key_reply(const handover_key_reply_type &value) {
buffer.end(),
0
);
add_option(icmpv6_option(HANDOVER_KEY_REPLY, buffer.begin(), buffer.end()));
add_option(option(HANDOVER_KEY_REPLY, buffer.begin(), buffer.end()));
}
void ICMPv6::handover_assist_info(const handover_assist_info_type &value) {
@@ -463,7 +487,7 @@ void ICMPv6::handover_assist_info(const handover_assist_info_type &value) {
padding,
0
);
add_option(icmpv6_option(HANDOVER_ASSIST_INFO, buffer.begin(), buffer.end()));
add_option(option(HANDOVER_ASSIST_INFO, buffer.begin(), buffer.end()));
}
void ICMPv6::mobile_node_identifier(const mobile_node_id_type &value) {
@@ -480,7 +504,7 @@ void ICMPv6::mobile_node_identifier(const mobile_node_id_type &value) {
padding,
0
);
add_option(icmpv6_option(MOBILE_NODE_ID, buffer.begin(), buffer.end()));
add_option(option(MOBILE_NODE_ID, buffer.begin(), buffer.end()));
}
void ICMPv6::dns_search_list(const dns_search_list_type &value) {
@@ -504,7 +528,7 @@ void ICMPv6::dns_search_list(const dns_search_list_type &value) {
if(padding == 8)
padding = 0;
buffer.insert(buffer.end(), padding, 0);
add_option(icmpv6_option(DNS_SEARCH_LIST, buffer.begin(), buffer.end()));
add_option(option(DNS_SEARCH_LIST, buffer.begin(), buffer.end()));
}
// ********************************************************************
@@ -512,21 +536,21 @@ void ICMPv6::dns_search_list(const dns_search_list_type &value) {
// ********************************************************************
ICMPv6::hwaddress_type ICMPv6::source_link_layer_addr() const {
const icmpv6_option *opt = search_option(SOURCE_ADDRESS);
const option *opt = search_option(SOURCE_ADDRESS);
if(!opt || opt->data_size() != hwaddress_type::address_size)
throw option_not_found();
return hwaddress_type(opt->data_ptr());
}
ICMPv6::hwaddress_type ICMPv6::target_link_layer_addr() const {
const icmpv6_option *opt = search_option(TARGET_ADDRESS);
const option *opt = search_option(TARGET_ADDRESS);
if(!opt || opt->data_size() != hwaddress_type::address_size)
throw option_not_found();
return hwaddress_type(opt->data_ptr());
}
ICMPv6::prefix_info_type ICMPv6::prefix_info() const {
const icmpv6_option *opt = search_option(PREFIX_INFO);
const option *opt = search_option(PREFIX_INFO);
if(!opt || opt->data_size() != 2 + sizeof(uint32_t) * 3 + ipaddress_type::address_size)
throw option_not_found();
const uint8_t *ptr = opt->data_ptr();
@@ -542,7 +566,7 @@ ICMPv6::prefix_info_type ICMPv6::prefix_info() const {
}
PDU::serialization_type ICMPv6::redirect_header() const {
const icmpv6_option *opt = search_option(REDIRECT_HEADER);
const option *opt = search_option(REDIRECT_HEADER);
if(!opt || opt->data_size() < 6)
throw option_not_found();
const uint8_t *ptr = opt->data_ptr() + 6;
@@ -550,28 +574,28 @@ PDU::serialization_type ICMPv6::redirect_header() const {
}
uint32_t ICMPv6::mtu() const {
const icmpv6_option *opt = search_option(MTU);
const option *opt = search_option(MTU);
if(!opt || opt->data_size() != sizeof(uint16_t) + sizeof(uint32_t))
throw option_not_found();
return Endian::be_to_host(*(const uint32_t*)(opt->data_ptr() + sizeof(uint16_t)));
}
uint8_t ICMPv6::shortcut_limit() const {
const icmpv6_option *opt = search_option(NBMA_SHORT_LIMIT);
const option *opt = search_option(NBMA_SHORT_LIMIT);
if(!opt || opt->data_size() != sizeof(uint16_t) + sizeof(uint32_t))
throw option_not_found();
return *opt->data_ptr();
}
uint32_t ICMPv6::new_advert_interval() const {
const icmpv6_option *opt = search_option(ADVERT_INTERVAL);
const option *opt = search_option(ADVERT_INTERVAL);
if(!opt || opt->data_size() != sizeof(uint16_t) + sizeof(uint32_t))
throw option_not_found();
return Endian::be_to_host(*(const uint32_t*)(opt->data_ptr() + sizeof(uint16_t)));
}
ICMPv6::new_ha_info_type ICMPv6::new_home_agent_info() const {
const icmpv6_option *opt = search_option(HOME_AGENT_INFO);
const option *opt = search_option(HOME_AGENT_INFO);
if(!opt || opt->data_size() != sizeof(uint16_t) + sizeof(uint32_t))
throw option_not_found();
return std::make_pair(
@@ -588,8 +612,8 @@ ICMPv6::addr_list_type ICMPv6::target_addr_list() const {
return search_addr_list(T_ADDRESS_LIST);
}
ICMPv6::addr_list_type ICMPv6::search_addr_list(Options type) const {
const icmpv6_option *opt = search_option(type);
ICMPv6::addr_list_type ICMPv6::search_addr_list(OptionTypes type) const {
const option *opt = search_option(type);
if(!opt || opt->data_size() < 6 + ipaddress_type::address_size)
throw option_not_found();
addr_list_type output;
@@ -604,7 +628,7 @@ ICMPv6::addr_list_type ICMPv6::search_addr_list(Options type) const {
}
ICMPv6::rsa_sign_type ICMPv6::rsa_signature() const {
const icmpv6_option *opt = search_option(RSA_SIGN);
const option *opt = search_option(RSA_SIGN);
// 2 bytes reserved + at least 1 byte signature.
// 16 == sizeof(rsa_sign_type::key_hash), removed the sizeof
// expression since gcc 4.2 doesn't like it
@@ -619,21 +643,21 @@ ICMPv6::rsa_sign_type ICMPv6::rsa_signature() const {
}
uint64_t ICMPv6::timestamp() const {
const icmpv6_option *opt = safe_search_option<std::less>(
const option *opt = safe_search_option<std::less>(
TIMESTAMP, 6 + sizeof(uint64_t)
);
return Endian::be_to_host(*(uint64_t*)(opt->data_ptr() + 6));
}
ICMPv6::nonce_type ICMPv6::nonce() const {
const icmpv6_option *opt = safe_search_option<std::equal_to>(
const option *opt = safe_search_option<std::equal_to>(
NONCE, 0
);
return nonce_type(opt->data_ptr(), opt->data_ptr() + opt->data_size());
}
ICMPv6::ip_prefix_type ICMPv6::ip_prefix() const {
const icmpv6_option *opt = safe_search_option<std::less>(
const option *opt = safe_search_option<std::less>(
IP_PREFIX, 2
);
const uint8_t *ptr = opt->data_ptr();
@@ -648,7 +672,7 @@ ICMPv6::ip_prefix_type ICMPv6::ip_prefix() const {
ICMPv6::lladdr_type ICMPv6::link_layer_addr() const {
// at least the option_code and 1 byte from the link layer address
const icmpv6_option *opt = safe_search_option<std::less>(
const option *opt = safe_search_option<std::less>(
LINK_ADDRESS, 2
);
const uint8_t *ptr = opt->data_ptr();
@@ -658,7 +682,7 @@ ICMPv6::lladdr_type ICMPv6::link_layer_addr() const {
}
ICMPv6::naack_type ICMPv6::naack() const {
const icmpv6_option *opt = safe_search_option<std::not_equal_to>(
const option *opt = safe_search_option<std::not_equal_to>(
NAACK, 6
);
const uint8_t *ptr = opt->data_ptr();
@@ -666,7 +690,7 @@ ICMPv6::naack_type ICMPv6::naack() const {
}
ICMPv6::map_type ICMPv6::map() const {
const icmpv6_option *opt = safe_search_option<std::not_equal_to>(
const option *opt = safe_search_option<std::not_equal_to>(
MAP, 2 + sizeof(uint32_t) + ipaddress_type::address_size
);
const uint8_t *ptr = opt->data_ptr();
@@ -681,7 +705,7 @@ ICMPv6::map_type ICMPv6::map() const {
}
ICMPv6::route_info_type ICMPv6::route_info() const {
const icmpv6_option *opt = safe_search_option<std::less>(
const option *opt = safe_search_option<std::less>(
ROUTE_INFO, 2 + sizeof(uint32_t)
);
const uint8_t *ptr = opt->data_ptr();
@@ -695,7 +719,7 @@ ICMPv6::route_info_type ICMPv6::route_info() const {
}
ICMPv6::recursive_dns_type ICMPv6::recursive_dns_servers() const {
const icmpv6_option *opt = safe_search_option<std::less>(
const option *opt = safe_search_option<std::less>(
RECURSIVE_DNS_SERV, 2 + sizeof(uint32_t) + ipaddress_type::address_size
);
const uint8_t *ptr = opt->data_ptr() + 2, *end = opt->data_ptr() + opt->data_size();
@@ -712,7 +736,7 @@ ICMPv6::recursive_dns_type ICMPv6::recursive_dns_servers() const {
}
ICMPv6::handover_key_req_type ICMPv6::handover_key_request() const {
const icmpv6_option *opt = safe_search_option<std::less>(
const option *opt = safe_search_option<std::less>(
HANDOVER_KEY_REQ, 2 + sizeof(uint32_t)
);
const uint8_t *ptr = opt->data_ptr() + 1, *end = opt->data_ptr() + opt->data_size();
@@ -726,7 +750,7 @@ ICMPv6::handover_key_req_type ICMPv6::handover_key_request() const {
}
ICMPv6::handover_key_reply_type ICMPv6::handover_key_reply() const {
const icmpv6_option *opt = safe_search_option<std::less>(
const option *opt = safe_search_option<std::less>(
HANDOVER_KEY_REPLY, 2 + sizeof(uint32_t)
);
const uint8_t *ptr = opt->data_ptr() + 1, *end = opt->data_ptr() + opt->data_size();
@@ -742,7 +766,7 @@ ICMPv6::handover_key_reply_type ICMPv6::handover_key_reply() const {
}
ICMPv6::handover_assist_info_type ICMPv6::handover_assist_info() const {
const icmpv6_option *opt = safe_search_option<std::less>(
const option *opt = safe_search_option<std::less>(
HANDOVER_ASSIST_INFO, 2
);
const uint8_t *ptr = opt->data_ptr(), *end = ptr + opt->data_size();
@@ -755,7 +779,7 @@ ICMPv6::handover_assist_info_type ICMPv6::handover_assist_info() const {
}
ICMPv6::mobile_node_id_type ICMPv6::mobile_node_identifier() const {
const icmpv6_option *opt = safe_search_option<std::less>(
const option *opt = safe_search_option<std::less>(
MOBILE_NODE_ID, 2
);
const uint8_t *ptr = opt->data_ptr(), *end = ptr + opt->data_size();
@@ -768,7 +792,7 @@ ICMPv6::mobile_node_id_type ICMPv6::mobile_node_identifier() const {
}
ICMPv6::dns_search_list_type ICMPv6::dns_search_list() const {
const icmpv6_option *opt = safe_search_option<std::less>(
const option *opt = safe_search_option<std::less>(
DNS_SEARCH_LIST, 2 + sizeof(uint32_t)
);
const uint8_t *ptr = opt->data_ptr(), *end = ptr + opt->data_size();

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,10 +29,16 @@
#include "internals.h"
#include "ip.h"
#include "ethernetII.h"
#include "ieee802_3.h"
#include "radiotap.h"
#include "dot11.h"
#include "ipv6.h"
#include "arp.h"
#include "eapol.h"
#include "rawpdu.h"
#include "dot1q.h"
#include "pppoe.h"
using std::string;
@@ -71,13 +77,62 @@ Tins::PDU *pdu_from_flag(Constants::Ethernet::e flag, const uint8_t *buffer,
return new Tins::IPv6(buffer, size);
case Tins::Constants::Ethernet::ARP:
return new Tins::ARP(buffer, size);
case Tins::Constants::Ethernet::PPPOED:
return new Tins::PPPoE(buffer, size);
case Tins::Constants::Ethernet::EAPOL:
return Tins::EAPOL::from_bytes(buffer, size);
case Tins::Constants::Ethernet::VLAN:
return new Tins::Dot1Q(buffer, size);
default:
return rawpdu_on_no_match ? new RawPDU(buffer, size) : 0;
};
}
Tins::PDU *pdu_from_flag(PDU::PDUType type, const uint8_t *buffer, uint32_t size)
{
switch(type) {
case Tins::PDU::ETHERNET_II:
return new Tins::EthernetII(buffer, size);
case Tins::PDU::IP:
return new Tins::IP(buffer, size);
case Tins::PDU::IPv6:
return new Tins::IPv6(buffer, size);
case Tins::PDU::ARP:
return new Tins::ARP(buffer, size);
case Tins::PDU::IEEE802_3:
return new Tins::IEEE802_3(buffer, size);
case Tins::PDU::RADIOTAP:
return new Tins::RadioTap(buffer, size);
case Tins::PDU::PPPOE:
return new Tins::PPPoE(buffer, size);
case Tins::PDU::DOT11:
case Tins::PDU::DOT11_ACK:
case Tins::PDU::DOT11_ASSOC_REQ:
case Tins::PDU::DOT11_ASSOC_RESP:
case Tins::PDU::DOT11_AUTH:
case Tins::PDU::DOT11_BEACON:
case Tins::PDU::DOT11_BLOCK_ACK:
case Tins::PDU::DOT11_BLOCK_ACK_REQ:
case Tins::PDU::DOT11_CF_END:
case Tins::PDU::DOT11_DATA:
case Tins::PDU::DOT11_CONTROL:
case Tins::PDU::DOT11_DEAUTH:
case Tins::PDU::DOT11_DIASSOC:
case Tins::PDU::DOT11_END_CF_ACK:
case Tins::PDU::DOT11_MANAGEMENT:
case Tins::PDU::DOT11_PROBE_REQ:
case Tins::PDU::DOT11_PROBE_RESP:
case Tins::PDU::DOT11_PS_POLL:
case Tins::PDU::DOT11_REASSOC_REQ:
case Tins::PDU::DOT11_REASSOC_RESP:
case Tins::PDU::DOT11_RTS:
case Tins::PDU::DOT11_QOS_DATA:
return Tins::Dot11::from_bytes(buffer, size);
default:
return 0;
};
}
Constants::Ethernet::e pdu_flag_to_ether_type(PDU::PDUType flag) {
switch (flag) {
case PDU::IP:
@@ -86,6 +141,10 @@ Constants::Ethernet::e pdu_flag_to_ether_type(PDU::PDUType flag) {
return Constants::Ethernet::IPV6;
case PDU::ARP:
return Constants::Ethernet::ARP;
case PDU::DOT1Q:
return Constants::Ethernet::VLAN;
case PDU::PPPOE:
return Constants::Ethernet::PPPOED;
default:
return Constants::Ethernet::UNKNOWN;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,7 +29,9 @@
#include <stdexcept>
#include <cstring>
#ifdef TINS_DEBUG
#include <cassert>
#endif
#include <algorithm>
#ifndef WIN32
#include <netdb.h>
@@ -48,6 +50,8 @@
#include "utils.h"
#include "packet_sender.h"
#include "constants.h"
#include "network_interface.h"
#include "exceptions.h"
using std::list;
@@ -55,8 +59,7 @@ namespace Tins {
const uint8_t IP::DEFAULT_TTL = 128;
IP::IP(address_type ip_dst, address_type ip_src, PDU *child)
: PDU(child)
IP::IP(address_type ip_dst, address_type ip_src)
{
init_ip_fields();
this->dst_addr(ip_dst);
@@ -65,18 +68,17 @@ IP::IP(address_type ip_dst, address_type ip_src, PDU *child)
IP::IP(const uint8_t *buffer, uint32_t total_sz)
{
const char *msg = "Not enough size for an IP header in the buffer.";
if(total_sz < sizeof(iphdr))
throw std::runtime_error(msg);
throw malformed_packet();
std::memcpy(&_ip, buffer, sizeof(iphdr));
/* Options... */
/* Establish beginning and ending of the options */
const uint8_t* ptr_buffer = buffer + sizeof(iphdr);
if(total_sz < head_len() * sizeof(uint32_t))
throw std::runtime_error(msg);
throw malformed_packet();
if(head_len() * sizeof(uint32_t) < sizeof(iphdr))
throw std::runtime_error("Malformed head len field");
throw malformed_packet();
buffer += head_len() * sizeof(uint32_t);
_options_size = 0;
@@ -87,47 +89,28 @@ IP::IP(const uint8_t *buffer, uint32_t total_sz)
option_identifier opt_type;
memcpy(&opt_type, ptr_buffer, sizeof(uint8_t));
ptr_buffer++;
switch (opt_type.number) {
if(opt_type.number > NOOP) {
/* Multibyte options with length as second byte */
case SEC:
case LSSR:
case TIMESTAMP:
case EXTSEC:
case RR:
case SID:
case SSRR:
case MTUPROBE:
case MTUREPLY:
case EIP:
case TR:
case ADDEXT:
case RTRALT:
case SDB:
case DPS:
case UMP:
case QS:
if(ptr_buffer == buffer || *ptr_buffer == 0)
throw std::runtime_error(msg);
{
const uint8_t data_size = *ptr_buffer - 2;
if(data_size > 0) {
ptr_buffer++;
if(buffer - ptr_buffer < data_size)
throw std::runtime_error(msg);
_ip_options.push_back(ip_option(opt_type, ptr_buffer, ptr_buffer + data_size));
}
else
_ip_options.push_back(ip_option(opt_type));
}
if(ptr_buffer == buffer || *ptr_buffer == 0)
throw malformed_packet();
ptr_buffer += _ip_options.back().data_size() + 1;
break;
default:
_ip_options.push_back(ip_option(opt_type));
break;
const uint8_t data_size = *ptr_buffer - 2;
if(data_size > 0) {
ptr_buffer++;
if(buffer - ptr_buffer < data_size)
throw malformed_packet();
_ip_options.push_back(option(opt_type, ptr_buffer, ptr_buffer + data_size));
}
else
_ip_options.push_back(option(opt_type));
ptr_buffer += _ip_options.back().data_size() + 1;
_options_size += _ip_options.back().data_size() + 2;
}
else {
_ip_options.push_back(option(opt_type));
_options_size++;
}
_options_size += _ip_options.back().data_size() + 2;
}
uint8_t padding = _options_size % 4;
_padded_options_size = padding ? (_options_size - padding + 4) : _options_size;
@@ -189,7 +172,7 @@ void IP::protocol(uint8_t new_protocol) {
_ip.protocol = new_protocol;
}
void IP::check(uint16_t new_check) {
void IP::checksum(uint16_t new_check) {
_ip.check = Endian::host_to_be(new_check);
}
@@ -231,7 +214,7 @@ void IP::security(const security_type &data) {
array[6] = ((value >> 16) & 0xff);
add_option(
ip_option(
option(
130,
sizeof(array),
array
@@ -242,7 +225,7 @@ void IP::security(const security_type &data) {
void IP::stream_identifier(uint16_t stream_id) {
stream_id = Endian::host_to_be(stream_id);
add_option(
ip_option(
option(
136,
sizeof(uint16_t),
(const uint8_t*)&stream_id
@@ -264,7 +247,7 @@ void IP::add_route_option(option_identifier id, const generic_route_option_type
opt_data[1 + i * 4 + 3] = (ip >> 24) & 0xff;
}
add_option(
ip_option(
option(
id,
opt_data.size(),
&opt_data[0]
@@ -273,7 +256,7 @@ void IP::add_route_option(option_identifier id, const generic_route_option_type
}
IP::generic_route_option_type IP::search_route_option(option_identifier id) const {
const ip_option *option = search_option(id);
const option *option = search_option(id);
if(!option || option->data_size() < 1 + sizeof(uint32_t) ||
((option->data_size() - 1) % sizeof(uint32_t)) != 0)
throw option_not_found();
@@ -287,7 +270,7 @@ IP::generic_route_option_type IP::search_route_option(option_identifier id) cons
}
IP::security_type IP::security() const {
const ip_option *option = search_option(130);
const option *option = search_option(130);
if(!option || option->data_size() < 9)
throw option_not_found();
security_type output;
@@ -303,35 +286,42 @@ IP::security_type IP::security() const {
}
uint16_t IP::stream_identifier() const {
const ip_option *option = search_option(136);
const option *option = search_option(136);
if(!option || option->data_size() != sizeof(uint16_t))
throw option_not_found();
return Endian::be_to_host(*(const uint16_t*)option->data_ptr());
}
void IP::add_option(const ip_option &option) {
_ip_options.push_back(option);
_options_size += 1 + option.data_size();
void IP::add_option(const option &opt) {
internal_add_option(opt);
_ip_options.push_back(opt);
}
void IP::internal_add_option(const option &opt) {
_options_size += 1 + opt.data_size();
uint8_t padding = _options_size % 4;
_padded_options_size = padding ? (_options_size - padding + 4) : _options_size;
}
const IP::ip_option *IP::search_option(option_identifier id) const {
for(std::list<ip_option>::const_iterator it = _ip_options.begin(); it != _ip_options.end(); ++it) {
const IP::option *IP::search_option(option_identifier id) const {
for(options_type::const_iterator it = _ip_options.begin(); it != _ip_options.end(); ++it) {
if(it->option() == id)
return &(*it);
}
return 0;
}
uint8_t* IP::write_option(const ip_option &opt, uint8_t* buffer) {
uint8_t* IP::write_option(const option &opt, uint8_t* buffer) {
option_identifier opt_type = opt.option();
memcpy(buffer, &opt_type, 1);
if(*buffer <= 1)
return ++buffer;
buffer++;
*(buffer++) = opt.data_size() + 2;
std::copy(opt.data_ptr(), opt.data_ptr() + opt.data_size(), buffer);
buffer += opt.data_size();
return buffer;
*buffer = opt.length_field();
if(opt.data_size() == opt.length_field())
*buffer += 2;
buffer++;
return std::copy(opt.data_ptr(), opt.data_ptr() + opt.data_size(), buffer);
}
/* Virtual method overriding. */
@@ -340,33 +330,54 @@ uint32_t IP::header_size() const {
return sizeof(iphdr) + _padded_options_size;
}
void IP::send(PacketSender& sender) {
struct sockaddr_in link_addr;
PacketSender::SocketType type = PacketSender::IP_SOCKET;
PacketSender::SocketType pdu_type_to_sender_type(PDU::PDUType type) {
switch(type) {
case PDU::TCP:
return PacketSender::IP_TCP_SOCKET;
case PDU::UDP:
return PacketSender::IP_UDP_SOCKET;
case PDU::ICMP:
return PacketSender::ICMP_SOCKET;
default:
return PacketSender::IP_RAW_SOCKET;
}
}
void IP::send(PacketSender& sender, const NetworkInterface &) {
sockaddr_in link_addr;
PacketSender::SocketType type = PacketSender::IP_RAW_SOCKET;
link_addr.sin_family = AF_INET;
link_addr.sin_port = 0;
link_addr.sin_addr.s_addr = _ip.daddr;
if(inner_pdu() && inner_pdu()->pdu_type() == PDU::ICMP)
type = PacketSender::ICMP_SOCKET;
if(inner_pdu())
type = pdu_type_to_sender_type(inner_pdu()->pdu_type());
sender.send_l3(*this, (struct sockaddr*)&link_addr, sizeof(link_addr), type);
}
PDU *IP::recv_response(PacketSender &sender) {
struct sockaddr_in link_addr;
PacketSender::SocketType type = PacketSender::IP_SOCKET;
link_addr.sin_family = AF_INET;
link_addr.sin_port = 0;
link_addr.sin_addr.s_addr = _ip.daddr;
if(inner_pdu() && inner_pdu()->pdu_type() == PDU::ICMP)
type = PacketSender::ICMP_SOCKET;
PDU *IP::recv_response(PacketSender &sender, const NetworkInterface &) {
sockaddr_in link_addr;
PacketSender::SocketType type = PacketSender::IP_RAW_SOCKET;
std::memset(&link_addr, 0, sizeof(link_addr));
if(inner_pdu())
type = pdu_type_to_sender_type(inner_pdu()->pdu_type());
return sender.recv_l3(*this, (struct sockaddr*)&link_addr, sizeof(link_addr), type);
return sender.recv_l3(*this, 0, sizeof(link_addr), type);
}
void IP::prepare_for_serialize(const PDU *parent) {
if(!parent && _ip.saddr == 0) {
NetworkInterface iface(dst_addr());
src_addr(iface.addresses().ip_addr);
}
}
void IP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU* parent) {
uint32_t my_sz = header_size();
#ifdef TINS_DEBUG
assert(total_sz >= my_sz);
#endif
checksum(0);
if(inner_pdu()) {
uint32_t new_flag;
switch(inner_pdu()->pdu_type()) {
@@ -390,7 +401,7 @@ void IP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU* pare
//flag(new_flag);
}
#ifdef __FreeBSD__
#if __FreeBSD__ || defined(__FreeBSD_kernel__)
if(!parent)
total_sz = Endian::host_to_be<uint16_t>(total_sz);
#endif
@@ -400,44 +411,30 @@ void IP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU* pare
memcpy(buffer, &_ip, sizeof(_ip));
uint8_t* ptr_buffer = buffer + sizeof(_ip);
for(list<ip_option>::iterator it = _ip_options.begin(); it != _ip_options.end(); ++it)
for(options_type::const_iterator it = _ip_options.begin(); it != _ip_options.end(); ++it) {
ptr_buffer = write_option(*it, ptr_buffer);
}
memset(buffer + sizeof(_ip) + _options_size, 0, _padded_options_size - _options_size);
if(parent && !_ip.check) {
uint32_t checksum = Utils::do_checksum(buffer, buffer + sizeof(_ip) + _padded_options_size);
while (checksum >> 16)
checksum = (checksum & 0xffff) + (checksum >> 16);
((iphdr*)buffer)->check = Endian::host_to_be<uint16_t>(~checksum);
this->check(0);
if(parent) {
uint32_t check = Utils::do_checksum(buffer, buffer + sizeof(_ip) + _padded_options_size);
while (check >> 16)
check = (check & 0xffff) + (check >> 16);
checksum(~check);
((iphdr*)buffer)->check = _ip.check;
}
}
bool IP::matches_response(uint8_t *ptr, uint32_t total_sz) {
bool IP::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
if(total_sz < sizeof(iphdr))
return false;
iphdr *ip_ptr = (iphdr*)ptr;
if(_ip.daddr == ip_ptr->saddr && _ip.saddr == ip_ptr->daddr) {
uint32_t sz = _ip.ihl * sizeof(uint32_t);
const iphdr *ip_ptr = (const iphdr*)ptr;
// checks for broadcast addr
if((_ip.saddr == ip_ptr->daddr && (_ip.daddr == ip_ptr->saddr || _ip.daddr == 0xffffffff)) ||
(_ip.daddr == 0xffffffff && _ip.saddr == 0)) {
uint32_t sz = std::min<uint32_t>(_ip.ihl * sizeof(uint32_t), total_sz);
return inner_pdu() ? inner_pdu()->matches_response(ptr + sz, total_sz - sz) : true;
}
return false;
}
PDU *IP::clone_packet(const uint8_t *ptr, uint32_t total_sz) {
if(total_sz < sizeof(iphdr))
return 0;
const iphdr *ip_ptr = (iphdr*)ptr;
uint32_t sz = ip_ptr->ihl * sizeof(uint32_t);
if(total_sz < sz)
return 0;
PDU *child = 0, *cloned;
if(total_sz > sz) {
if((child = PDU::clone_inner_pdu(ptr + sizeof(_ip), total_sz - sizeof(_ip))) == 0)
return 0;
}
cloned = new IP(ptr, std::min(total_sz, (uint32_t)(Endian::be_to_host(ip_ptr->tot_len) * sizeof(uint32_t))));
cloned->inner_pdu(child);
return cloned;
}
}

View File

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

View File

@@ -1,12 +1,43 @@
/*
* 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>
#ifdef TINS_DEBUG
#include <cassert>
#endif
#ifndef WIN32
#include <netinet/in.h>
#include <sys/socket.h>
#else
#include <ws2tcpip.h>
#endif
#include <iostream> //borrame
#include <algorithm>
#include "ipv6.h"
#include "constants.h"
#include "packet_sender.h"
@@ -16,6 +47,7 @@
#include "icmp.h"
#include "icmpv6.h"
#include "rawpdu.h"
#include "exceptions.h"
namespace Tins {
@@ -31,7 +63,7 @@ IPv6::IPv6(address_type ip_dst, address_type ip_src, PDU *child)
IPv6::IPv6(const uint8_t *buffer, uint32_t total_sz)
: headers_size(0) {
if(total_sz < sizeof(_header))
throw std::runtime_error("Not enough size for an IPv6 PDU");
throw malformed_packet();
std::memcpy(&_header, buffer, sizeof(_header));
buffer += sizeof(_header);
total_sz -= sizeof(_header);
@@ -39,16 +71,16 @@ IPv6::IPv6(const uint8_t *buffer, uint32_t total_sz)
while(total_sz) {
if(is_extension_header(current_header)) {
if(total_sz < 8)
throw header_size_error();
throw malformed_packet();
// every ext header is at least 8 bytes long
// minus one, from the next_header field.
uint32_t size = static_cast<uint32_t>(buffer[1]) + 8;
// -1 -> next header identifier
if(total_sz < size)
throw header_size_error();
throw malformed_packet();
// minus one, from the size field
add_ext_header(
ipv6_ext_header(buffer[0], size - sizeof(uint8_t)*2, buffer + 2)
ext_header(buffer[0], size - sizeof(uint8_t)*2, buffer + 2)
);
current_header = buffer[0];
buffer += size;
@@ -132,8 +164,35 @@ uint32_t IPv6::header_size() const {
return sizeof(_header) + headers_size;
}
bool IPv6::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
if(total_sz < sizeof(ipv6_header))
return false;
const ipv6_header *hdr_ptr = (const ipv6_header*)ptr;
// checks for ff02 multicast
if(src_addr() == hdr_ptr->dst_addr &&
(dst_addr() == hdr_ptr->src_addr || (_header.dst_addr[0] == 0xff && _header.dst_addr[1] == 0x02))) {
// is this OK? there's no inner pdu, simple dst/src addr match should suffice
if(!inner_pdu())
return true;
ptr += sizeof(ipv6_header);
total_sz -= sizeof(ipv6_header);
uint8_t current = hdr_ptr->next_header;
// 8 == minimum header size
while(total_sz > 8 && is_extension_header(current)) {
if(static_cast<uint32_t>(ptr[1] + 1) * 8 > total_sz)
return false;
current = ptr[0];
total_sz -= (ptr[1] + 1) * 8;
ptr += (ptr[1] + 1) * 8;
}
if(!is_extension_header(current))
return inner_pdu()->matches_response(ptr, total_sz);
}
return false;
}
void IPv6::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
#ifdef DEBUG
#ifdef TINS_DEBUG
assert(total_sz >= header_size());
#endif
if(inner_pdu()) {
@@ -169,7 +228,7 @@ void IPv6::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *pa
}
#ifndef BSD
void IPv6::send(PacketSender &sender) {
void IPv6::send(PacketSender &sender, const NetworkInterface &) {
struct sockaddr_in6 link_addr;
PacketSender::SocketType type = PacketSender::IPV6_SOCKET;
link_addr.sin6_family = AF_INET6;
@@ -182,12 +241,12 @@ void IPv6::send(PacketSender &sender) {
}
#endif
void IPv6::add_ext_header(const ipv6_ext_header &header) {
void IPv6::add_ext_header(const ext_header &header) {
ext_headers.push_back(header);
headers_size += header.data_size() + sizeof(uint8_t) * 2;
}
const IPv6::ipv6_ext_header *IPv6::search_header(ExtensionHeader id) const {
const IPv6::ext_header *IPv6::search_header(ExtensionHeader id) const {
uint8_t current_header = _header.next_header;
headers_type::const_iterator it = ext_headers.begin();
while(it != ext_headers.end() && current_header != id) {
@@ -206,9 +265,9 @@ void IPv6::set_last_next_header(uint8_t value) {
ext_headers.back().option(value);
}
uint8_t *IPv6::write_header(const ipv6_ext_header &header, uint8_t *buffer) {
uint8_t *IPv6::write_header(const ext_header &header, uint8_t *buffer) {
*buffer++ = header.option();
*buffer++ = (header.data_size() > 8) ? (header.data_size() - 8) : 0;
*buffer++ = (header.length_field() > 8) ? (header.length_field() - 8) : 0;
return std::copy(header.data_ptr(), header.data_ptr() + header.data_size(), buffer);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -39,7 +39,6 @@
#include <mstcpip.h>
#endif
#include <limits>
#include <iostream> // borrame
#include <sstream>
#include "ipv6_address.h"

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,11 +29,13 @@
#include <stdexcept>
#include <cstring>
#ifdef TINS_DEBUG
#include <cassert>
#include "pdu.h"
#endif
#include "llc.h"
#include "stp.h"
#include "rawpdu.h"
#include "exceptions.h"
using std::list;
@@ -41,8 +43,8 @@ namespace Tins {
const uint8_t LLC::GLOBAL_DSAP_ADDR = 0xFF;
const uint8_t LLC::NULL_ADDR = 0x00;
LLC::LLC(PDU *child)
: PDU(child), _type(LLC::INFORMATION)
LLC::LLC()
: _type(LLC::INFORMATION)
{
memset(&_header, 0, sizeof(llchdr));
control_field_length = 2;
@@ -50,8 +52,8 @@ LLC::LLC(PDU *child)
information_field_length = 0;
}
LLC::LLC(uint8_t dsap, uint8_t ssap, PDU *child)
: PDU(child), _type(LLC::INFORMATION)
LLC::LLC(uint8_t dsap, uint8_t ssap)
: _type(LLC::INFORMATION)
{
_header.dsap = dsap;
_header.ssap = ssap;
@@ -63,14 +65,14 @@ LLC::LLC(uint8_t dsap, uint8_t ssap, PDU *child)
LLC::LLC(const uint8_t *buffer, uint32_t total_sz) {
// header + 1 info byte
if(total_sz < sizeof(_header) + 1)
throw std::runtime_error("Not enough size for a LLC header in the buffer.");
throw malformed_packet();
std::memcpy(&_header, buffer, sizeof(_header));
buffer += sizeof(_header);
total_sz -= sizeof(_header);
information_field_length = 0;
if ((buffer[0] & 0x03) == LLC::UNNUMBERED) {
if(total_sz < sizeof(un_control_field))
throw std::runtime_error("Not enough size for a LLC header in the buffer.");
throw malformed_packet();
type(LLC::UNNUMBERED);
std::memcpy(&control_field.unnumbered, buffer, sizeof(un_control_field));
buffer += sizeof(un_control_field);
@@ -79,15 +81,19 @@ LLC::LLC(const uint8_t *buffer, uint32_t total_sz) {
}
else {
if(total_sz < sizeof(info_control_field))
throw std::runtime_error("Not enough size for a LLC header in the buffer.");
throw malformed_packet();
type((Format)(buffer[0] & 0x03));
control_field_length = 2;
std::memcpy(&control_field.info, buffer, sizeof(info_control_field));
buffer += 2;
total_sz -= 2;
}
if(total_sz > 0)
inner_pdu(new Tins::RawPDU(buffer, total_sz));
if(total_sz > 0) {
if(dsap() == 0x42 && ssap() == 0x42)
inner_pdu(new Tins::STP(buffer, total_sz));
else
inner_pdu(new Tins::RawPDU(buffer, total_sz));
}
}
void LLC::group(bool value) {
@@ -200,7 +206,13 @@ void LLC::clear_information_fields() {
}
void LLC::write_serialization(uint8_t *buffer, uint32_t total_sz, const Tins::PDU *parent) {
#ifdef TINS_DEBUG
assert(total_sz >= header_size());
#endif
if(inner_pdu() && inner_pdu()->pdu_type() == PDU::STP) {
dsap(0x42);
ssap(0x42);
}
std::memcpy(buffer, &_header, sizeof(_header));
buffer += sizeof(_header);
switch (type()) {
@@ -219,7 +231,6 @@ void LLC::write_serialization(uint8_t *buffer, uint32_t total_sz, const Tins::PD
}
for (list<field_type>::const_iterator it = information_fields.begin(); it != information_fields.end(); it++) {
//std::memcpy(buffer, it->second, it->first);
std::copy(it->begin(), it->end(), buffer);
buffer += it->size();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,13 +36,16 @@
#endif
#endif
#include <stdexcept>
#ifdef TINS_DEBUG
#include <cassert>
#endif
#include <cstring>
#include "loopback.h"
#include "packet_sender.h"
#include "ip.h"
#include "llc.h"
#include "rawpdu.h"
#include "exceptions.h"
#if !defined(PF_LLC)
// compilation fix, nasty but at least works on BSD
@@ -54,18 +57,12 @@ Loopback::Loopback()
: _family()
{
}
Loopback::Loopback(const NetworkInterface &iface, PDU *inner_pdu)
: PDU(inner_pdu), _family(), _iface(iface)
{
}
Loopback::Loopback(const uint8_t *buffer, uint32_t total_sz)
{
if(total_sz < sizeof(_family))
throw std::runtime_error("Not enough size for a loopback PDU");
throw malformed_packet();
_family = *reinterpret_cast<const uint32_t*>(buffer);
buffer += sizeof(uint32_t);
total_sz -= sizeof(uint32_t);
@@ -90,17 +87,15 @@ void Loopback::family(uint32_t family_id) {
_family = family_id;
}
void Loopback::iface(const NetworkInterface &new_iface) {
_iface = new_iface;
}
uint32_t Loopback::header_size() const {
return sizeof(_family);
}
void Loopback::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *)
{
#ifdef TINS_DEBUG
assert(total_sz >= sizeof(_family));
#endif
if(dynamic_cast<const Tins::IP*>(inner_pdu()))
_family = PF_INET;
else if(dynamic_cast<const Tins::LLC*>(inner_pdu()))
@@ -108,11 +103,11 @@ void Loopback::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU
*reinterpret_cast<uint32_t*>(buffer) = _family;
}
#ifdef BSD
void Loopback::send(PacketSender &sender) {
if(!_iface)
throw std::runtime_error("Interface has not been set");
void Loopback::send(PacketSender &sender, const NetworkInterface &iface) {
if(!iface)
throw invalid_interface();
sender.send_l2(*this, 0, 0, _iface);
sender.send_l2(*this, 0, 0, iface);
}
#endif // WIN32
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,7 +33,7 @@
#include "macros.h"
#ifndef WIN32
#include <netinet/in.h>
#ifdef BSD
#if defined(BSD) || defined(__FreeBSD_kernel__)
#include <ifaddrs.h>
#include <net/if_dl.h>
#include <sys/socket.h>
@@ -64,7 +64,7 @@ struct InterfaceInfoCollector {
bool operator() (const struct ifaddrs *addr) {
using Tins::Endian::host_to_be;
using Tins::IPv4Address;
#ifdef BSD
#if defined(BSD) || defined(__FreeBSD_kernel__)
const struct sockaddr_dl* addr_ptr = ((struct sockaddr_dl*)addr->ifa_addr);
if(addr->ifa_addr->sa_family == AF_LINK && addr_ptr->sdl_index == iface_id)
@@ -138,7 +138,7 @@ NetworkInterface::NetworkInterface(IPv4Address ip) : iface_id(0) {
typedef std::vector<Utils::RouteEntry> entries_type;
if(ip == "127.0.0.1")
#ifdef BSD
#if defined(BSD) || defined(__FreeBSD_kernel__)
iface_id = resolve_index("lo0");
#else
iface_id = resolve_index("lo");

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Nasel
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,7 +34,7 @@
#include <sys/time.h>
#include <arpa/inet.h>
#include <unistd.h>
#ifdef BSD
#if defined(BSD) || defined(__FreeBSD_kernel__)
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -53,12 +53,18 @@
#include <winsock2.h>
#include <ws2tcpip.h>
#endif
#include <cassert>
#include <cstring>
#include <ctime>
#include "pdu.h"
#include "macros.h"
#include "network_interface.h"
// PDUs required by PacketSender::send(PDU&, NetworkInterface)
#include "ethernetII.h"
#include "radiotap.h"
#include "dot11.h"
#include "radiotap.h"
#include "ieee802_3.h"
#include "internals.h"
namespace Tins {
@@ -76,15 +82,17 @@ const uint32_t PacketSender::DEFAULT_TIMEOUT = 2;
}
#endif
PacketSender::PacketSender(uint32_t recv_timeout, uint32_t usec)
PacketSender::PacketSender(const NetworkInterface &iface, uint32_t recv_timeout,
uint32_t usec)
: _sockets(SOCKETS_END, INVALID_RAW_SOCKET),
#if !defined(BSD) && !defined(WIN32)
#if !defined(BSD) && !defined(WIN32) && !defined(__FreeBSD_kernel__)
_ether_socket(INVALID_RAW_SOCKET),
#endif
_timeout(recv_timeout),
_timeout_usec(usec)
_timeout(recv_timeout), _timeout_usec(usec), default_iface(iface)
{
_types[IP_SOCKET] = IPPROTO_RAW;
_types[IP_TCP_SOCKET] = IPPROTO_TCP;
_types[IP_UDP_SOCKET] = IPPROTO_UDP;
_types[IP_RAW_SOCKET] = IPPROTO_RAW;
_types[IPV6_SOCKET] = IPPROTO_RAW;
_types[ICMP_SOCKET] = IPPROTO_ICMP;
}
@@ -98,7 +106,7 @@ PacketSender::~PacketSender() {
::closesocket(_sockets[i]);
#endif
}
#ifdef BSD
#if defined(BSD) || defined(__FreeBSD_kernel__)
for(BSDEtherSockets::iterator it = _ether_socket.begin(); it != _ether_socket.end(); ++it)
::close(it->second);
#elif !defined(WIN32)
@@ -107,9 +115,17 @@ PacketSender::~PacketSender() {
#endif
}
void PacketSender::default_interface(const NetworkInterface &iface) {
default_iface = iface;
}
const NetworkInterface& PacketSender::default_interface() {
return default_iface;
}
#ifndef WIN32
bool PacketSender::ether_socket_initialized(const NetworkInterface& iface) const {
#ifdef BSD
#if defined(BSD) || defined(__FreeBSD_kernel__)
return _ether_socket.count(iface.id());
#else
return _ether_socket != INVALID_RAW_SOCKET;
@@ -119,7 +135,7 @@ bool PacketSender::ether_socket_initialized(const NetworkInterface& iface) const
int PacketSender::get_ether_socket(const NetworkInterface& iface) {
if(!ether_socket_initialized(iface))
open_l2_socket(iface);
#ifdef BSD
#if defined(BSD) || defined(__FreeBSD_kernel__)
return _ether_socket[iface.id()];
#else
return _ether_socket;
@@ -127,7 +143,7 @@ int PacketSender::get_ether_socket(const NetworkInterface& iface) {
}
void PacketSender::open_l2_socket(const NetworkInterface& iface) {
#ifdef BSD
#if defined(BSD) || defined(__FreeBSD_kernel__)
int sock = -1;
// At some point, there should be an available device
for (int i = 0; sock == -1;i++) {
@@ -137,13 +153,13 @@ void PacketSender::open_l2_socket(const NetworkInterface& iface) {
sock = open(oss.str().c_str(), O_RDWR);
}
if(sock == -1)
throw SocketOpenError(make_error_string());
throw socket_open_error(make_error_string());
struct ifreq ifr;
strncpy(ifr.ifr_name, iface.name().c_str(), sizeof(ifr.ifr_name) - 1);
if(ioctl(sock, BIOCSETIF, (caddr_t)&ifr) < 0) {
::close(sock);
throw SocketOpenError(make_error_string());
throw socket_open_error(make_error_string());
}
_ether_socket[iface.id()] = sock;
#else
@@ -151,7 +167,7 @@ void PacketSender::open_l2_socket(const NetworkInterface& iface) {
_ether_socket = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (_ether_socket == -1)
throw SocketOpenError(make_error_string());
throw socket_open_error(make_error_string());
}
#endif
}
@@ -160,12 +176,12 @@ void PacketSender::open_l2_socket(const NetworkInterface& iface) {
void PacketSender::open_l3_socket(SocketType type) {
int socktype = find_type(type);
if(socktype == -1)
throw InvalidSocketTypeError();
throw invalid_socket_type();
if(_sockets[type] == INVALID_RAW_SOCKET) {
int sockfd;
sockfd = socket((type == IPV6_SOCKET) ? AF_INET6 : AF_INET, SOCK_RAW, socktype);
if (sockfd < 0)
throw SocketOpenError(make_error_string());
throw socket_open_error(make_error_string());
const int on = 1;
#ifndef WIN32
@@ -181,27 +197,27 @@ void PacketSender::open_l3_socket(SocketType type) {
void PacketSender::close_socket(SocketType type, const NetworkInterface &iface) {
if(type == ETHER_SOCKET) {
#ifdef BSD
#if defined(BSD) || defined(__FreeBSD_kernel__)
BSDEtherSockets::iterator it = _ether_socket.find(iface.id());
if(it == _ether_socket.end())
throw InvalidSocketTypeError();
throw invalid_socket_type();
if(::close(it->second) == -1)
throw SocketCloseError(make_error_string());
throw socket_close_error(make_error_string());
_ether_socket.erase(it);
#elif !defined(WIN32)
if(_ether_socket == INVALID_RAW_SOCKET)
throw InvalidSocketTypeError();
throw invalid_socket_type();
if(::close(_ether_socket) == -1)
throw SocketCloseError(make_error_string());
throw socket_close_error(make_error_string());
_ether_socket = INVALID_RAW_SOCKET;
#endif
}
else {
if(type >= SOCKETS_END || _sockets[type] == INVALID_RAW_SOCKET)
throw InvalidSocketTypeError();
throw invalid_socket_type();
#ifndef WIN32
if(close(_sockets[type]) == -1)
throw SocketCloseError(make_error_string());
throw socket_close_error(make_error_string());
#else
closesocket(_sockets[type]);
#endif
@@ -210,35 +226,62 @@ void PacketSender::close_socket(SocketType type, const NetworkInterface &iface)
}
void PacketSender::send(PDU &pdu) {
pdu.send(*this);
pdu.send(*this, default_iface);
}
void PacketSender::send(PDU &pdu, const NetworkInterface &iface) {
PDU::PDUType type = pdu.pdu_type();
switch(type) {
case PDU::ETHERNET_II:
send<Tins::EthernetII>(pdu, iface);
break;
case PDU::DOT11:
send<Tins::Dot11>(pdu, iface);
break;
case PDU::RADIOTAP:
send<Tins::RadioTap>(pdu, iface);
break;
case PDU::IEEE802_3:
send<Tins::IEEE802_3>(pdu, iface);
break;
default:
send(pdu);
};
}
PDU *PacketSender::send_recv(PDU &pdu) {
return send_recv(pdu, NetworkInterface());
}
PDU *PacketSender::send_recv(PDU &pdu, const NetworkInterface &iface) {
try {
pdu.send(*this);
pdu.send(*this, iface);
}
catch(std::runtime_error&) {
return 0;
}
return pdu.recv_response(*this);
return pdu.recv_response(*this, iface);
}
#ifndef WIN32
void PacketSender::send_l2(PDU &pdu, struct sockaddr* link_addr,
uint32_t len_addr, const NetworkInterface &iface) {
uint32_t len_addr, const NetworkInterface &iface)
{
int sock = get_ether_socket(iface);
PDU::serialization_type buffer = pdu.serialize();
if(!buffer.empty()) {
#ifdef BSD
#if defined(BSD) || defined(__FreeBSD_kernel__)
if(::write(sock, &buffer[0], buffer.size()) == -1)
#else
if(::sendto(sock, &buffer[0], buffer.size(), 0, link_addr, len_addr) == -1)
#endif
throw SocketWriteError(make_error_string());
throw socket_write_error(make_error_string());
}
}
PDU *PacketSender::recv_l2(PDU &pdu, struct sockaddr *link_addr,
uint32_t len_addr, const NetworkInterface &iface) {
uint32_t len_addr, const NetworkInterface &iface)
{
int sock = get_ether_socket(iface);
return recv_match_loop(sock, pdu, link_addr, len_addr);
}
@@ -254,7 +297,7 @@ void PacketSender::send_l3(PDU &pdu, struct sockaddr* link_addr, uint32_t len_ad
int sock = _sockets[type];
PDU::serialization_type buffer = pdu.serialize();
if(sendto(sock, (const char*)&buffer[0], buffer.size(), 0, link_addr, len_addr) == -1)
throw SocketWriteError(make_error_string());
throw socket_write_error(make_error_string());
}
PDU *PacketSender::recv_match_loop(int sock, PDU &pdu, struct sockaddr* link_addr, uint32_t addrlen) {
@@ -281,7 +324,7 @@ PDU *PacketSender::recv_match_loop(int sock, PDU &pdu, struct sockaddr* link_add
#endif
size = recvfrom(sock, (char*)buffer, 2048, 0, link_addr, &length);
if(pdu.matches_response(buffer, size)) {
return pdu.clone_packet(buffer, size);
return Internals::pdu_from_flag(pdu.pdu_type(), buffer, size);
}
}
struct timeval this_time, diff;

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