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

59 Commits
v0.2 ... v0.3

Author SHA1 Message Date
Matias Fontanini
a24e0d5a4b Done some changes on the build system. 2013-01-31 16:48:32 -03:00
Bruno Nery
c6dc18d215 Added get_fd() to BaseSniffer.
Signed-off-by: Matias Fontanini <matias.fontanini@gmail.com>
2013-01-29 20:25:48 -03:00
Matias Fontanini
931a86eff9 Done minor modification, mostly on documentation. 2013-01-29 16:18:08 -03:00
Matias Fontanini
2a1a28c3fb Added README, THANKS and CHANGES files. 2013-01-28 17:57:43 -03:00
Matias Fontanini
3f060de381 PacketWriter is now movable. 2013-01-28 17:56:59 -03:00
Matias Fontanini
0945e0b29e Added DHCPv6 client/server id options' getters/setters. 2013-01-28 16:23:47 -03:00
Matias Fontanini
5ee0ebb264 Added some fixes to the build system. Fixed bugs in DNS and ICMPv6 triggered in big-endian architectures. 2013-01-24 23:55:01 -03:00
Matias Fontanini
0dc762f15d Added missing build system files. 2013-01-24 13:52:45 -03:00
Matias Fontanini
c7c56a610c Done some -pedantic modifications. 2013-01-24 13:44:30 -03:00
Matias Fontanini
a826d92666 The build system now uses libtool. 2013-01-24 13:44:15 -03:00
Matias Fontanini
5b2e117347 Implemented every DHCPv6 option getter/setter, except for those involving DUIDs. 2013-01-22 23:24:10 -03:00
Matias Fontanini
e712550cb8 Move constructors are now noexcept. 2013-01-20 00:22:21 -03:00
Matias Fontanini
044d0a5a31 Added DHCPv6 initial support. 2013-01-16 20:15:04 -03:00
Matias Fontanini
9d0e84f1fa Added SLL tests. 2013-01-16 16:24:44 -03:00
Matias Fontanini
02265061cc Added SLL pseudo protocol header. 2013-01-16 00:05:28 -03:00
Bruno Nery
a13d7d0cb1 Fixed Timestamp::operator std::chrono::microseconds issue.
Signed-off-by: Matias Fontanini <matias.fontanini@gmail.com>
2013-01-15 18:38:35 -03:00
Matias Fontanini
7a86012292 IPv6::send now works on linux. BSD does not support sending IPv6 as the lowest layer. 2012-12-10 20:31:32 -03:00
Matias Fontanini
c933faaf5e Null/Loopback PDUs can now be sent on *BSD. 2012-12-09 13:05:39 -03:00
Matias Fontanini
a7e0c094fb Implemented several ICMPv6 option getters/setters. 2012-12-08 11:15:41 -03:00
Matias Fontanini
592a15ebe4 Added some ICMPv6 option getters/setters. 2012-12-05 23:33:09 -03:00
Matias Fontanini
75b32c75bc Added concat operator to Packet and an overload that takes a PDU*. 2012-12-05 17:04:39 -03:00
Matias Fontanini
765285c6ee Added several ICMPv6 option getters/setters. 2012-12-04 23:15:38 -03:00
Matias Fontanini
356fe00aad Fixed compilation error in OSX. Fixed bug when sending IP PDUs in BSD. 2012-12-04 16:15:08 -03:00
Matias Fontanini
647ba1f46e Fixed ternary operator associativity issue in dot11.h. 2012-12-03 20:56:47 -03:00
Matias Fontanini
53fe80d8a7 Added fix for IP::tot_len's endianess in OSX. 2012-12-03 20:34:15 -03:00
Matias Fontanini
742276c251 libtins compiles and runs under windows. Packets apparently can't be sent yet. 2012-12-02 20:25:05 -03:00
Matias Fontanini
6d1e96866e libtins now compiles on windows. A couple of features were disabled and need to be fixed though. 2012-12-02 00:45:10 -03:00
Matias Fontanini
dbe67c8cae DNSRecords are now movable.! 2012-12-01 20:18:23 -03:00
Matias Fontanini
dd9c0b3fd5 Fixed bugs in IPv6 and ICMPv6 when constructing an object from a buffer. 2012-12-01 13:43:19 -03:00
Matias Fontanini
9bdee61e5b Fixed some issues with Endian::change_endian triggered in OSX. 2012-11-29 21:30:13 -03:00
Matias Fontanini
e2426b493e configure script now works on BSD. 2012-11-29 18:00:41 -03:00
Matias Fontanini
acff776d56 Utils::route_entries now works on BSD. 2012-11-29 17:11:10 -03:00
Matias Fontanini
4036e7daa2 Merge branch 'master' of ssh://git.code.sf.net/p/libtins/code 2012-11-29 14:01:55 -03:00
Matias Fontanini
93b5b86c5d Added some ICMPv6 option getters/setters. 2012-11-29 14:01:22 -03:00
Matias Fontanini
de82dc2322 Link layer protocols can now be sent on BSD. 2012-11-28 16:50:47 -03:00
Matias Fontanini
6696c1b284 Ported almost everything to BSD. Utils::route_entries and sending link layer PDUs still don't work. 2012-11-28 00:11:42 -03:00
Matias Fontanini
e6e3e8453b Fixed some bugs in ICMPv6. 2012-11-26 19:47:15 -03:00
Matias Fontanini
4576d8746c Added another constructor to Packet. 2012-11-26 16:01:26 -03:00
Matias Fontanini
b42c868a66 Added .so file symlinks. 2012-11-26 15:50:06 -03:00
Matias Fontanini
a18cd3e0de PDU::find_pdu now has a const overload. 2012-11-26 15:38:53 -03:00
Matias Fontanini
88faee9b26 Added Packet conversion to bool. 2012-11-26 15:22:29 -03:00
Matias Fontanini
16a29fab3e Fixed memory leak in Packet's copy assignment operator. 2012-11-26 15:03:09 -03:00
Matias Fontanini
cd6bc16d48 Packets are now copyable and movable. 2012-11-26 14:02:50 -03:00
Matias Fontanini
443803caf0 Added ICMPv6 class. It's working. Option getters/setters are missing. 2012-11-24 18:50:21 -03:00
Matias Fontanini
75a4bbfed6 Added Timestamp conversion to std::chrono::microseconds. BaseSniffer is now movable. 2012-11-23 20:30:16 -03:00
Matias Fontanini
b74a353c17 Added packet.h and timestamp.h to tins.h 2012-11-23 18:56:39 -03:00
Matias Fontanini
492fd611f9 Added Packet and some wrapper packet classes. Modified the return value of BaseSniffer::next_packet. 2012-11-23 18:10:51 -03:00
Matias Fontanini
a938d2ecfd Added support for IPv6 extension headers. Specific headers getters and setters are not yet implemented. 2012-11-22 17:18:59 -03:00
Matias Fontanini
8276e7d086 Added IPv6 class. It's working, but there's no support for extension headers yet. 2012-11-21 22:09:58 -03:00
Matias Fontanini
ffdfb160c4 Added ipv6_address.h include to tins.h. 2012-11-21 15:52:31 -03:00
Matias Fontanini
bf6c086b3d Added BaseSniffer::timestamp method. 2012-11-21 13:33:28 -03:00
Matias Fontanini
08b4c92dac Added support for IPv6 addresses in DNS. 2012-11-20 23:57:02 -03:00
Matias Fontanini
2a0b248518 Added IPv6Address. 2012-11-20 23:46:22 -03:00
Matias Fontanini
60323ded9b AAAA records are now parsed correctly. 2012-11-20 21:19:05 -03:00
Matias Fontanini
f3ea99e0b0 Used a better strategy in DNSResourceRecord's constructor from buffer which will parse the data even if contains_dname returns false. 2012-11-20 18:31:33 -03:00
Matias Fontanini
7e080cf1ab Added some missing DNS record types which contain domain names to the 'contains_dname' helper function. 2012-11-20 18:27:59 -03:00
Matias Fontanini
688be1e1da Fixed the try/catch block in BaseSniffer::sniff_loop. It now only catches std::runtime_errors. 2012-11-20 16:33:26 -03:00
Bruno Nery
28e5df3abc Fixed BaseSniffer::next_packet() to return when error occurred. Updated its documentation.
Signed-off-by: Matias Fontanini <matias.fontanini@gmail.com>
2012-11-20 16:30:34 -03:00
Matias Fontanini
d0048e3aef Fixed bug in DNS triggered when adding two records for the same domain name. 2012-11-20 16:10:24 -03:00
104 changed files with 49050 additions and 2742 deletions

View File

@@ -1,2 +1,2 @@
Matias Fontanini - mfontanini@nasel.com.ar
Matias Fontanini - matias.fontanini@gmail.com
Santiago Alessandri - salessandri@nasel.com.ar

39
CHANGES Normal file
View File

@@ -0,0 +1,39 @@
v0.3 - Thu Jan 31 16:47:27 ART 2013
- Added IPv6, ICMPv6 and DHCPv6 classes.
- Added support for Loopback interfaces and the Linux Crooked Capture
pseudo protocol.
- Added support for IPv6 records in DNS.
- Added Packet/RefPacket class.
- Added support for FreeBSD, OSX and Windows.
- Added C++11 move semantics to several classes.
- Done a complete rewrite of the build system; it now uses libtool.
- Fixed several bugs in DNS.
v0.2 - Sat Oct 20 11:26:40 2012
- Added support for big endian architectures.
- Simplified several interfaces.
- Added IPv4Address and HWAddress class to simplify handling IP and hardware addresses.
- Added NetworkInterface class to abstract network interfaces.
- Added TCPStreamFollower class to follow TCP streams on the fly.
- Added WEPDecrypter class to decrypt WEP-encrypted 802.11 data frames on the fly.
- Added several new PDUs: Loopback, IEEE802_3, LLC, DNS.
- Added support for reading and writing pcap files.
- Moved to BSD-2 license.

View File

@@ -31,7 +31,7 @@ PROJECT_NAME = libtins
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER = 0.1
PROJECT_NUMBER = 0.3
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.

93
Makefile.am Normal file
View File

@@ -0,0 +1,93 @@
AUTOMAKE_OPTIONS=subdir-objects
ACLOCAL_AMFLAGS=${ACLOCAL_FLAGS} -I m4
# pkg-config stuff
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libtins.pc
lib_LTLIBRARIES=libtins.la
libtins_la_LDFLAGS = -version-info @LIBTINS_VERSION@
AM_CXXFLAGS = -Wall -pedantic -I@LIBTINS_INCLUDE_DIR@
libtins_la_SOURCES=src/arp.cpp \
src/bootp.cpp \
src/crypto.cpp \
src/dhcp.cpp \
src/dhcpv6.cpp \
src/dns.cpp \
src/dns_record.cpp \
src/dot11.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 \
src/ipv6_address.cpp \
src/llc.cpp \
src/loopback.cpp \
src/network_interface.cpp \
src/packet_sender.cpp \
src/packet_writer.cpp \
src/pdu.cpp \
src/radiotap.cpp \
src/rawpdu.cpp \
src/rsn_information.cpp \
src/sll.cpp \
src/snap.cpp \
src/sniffer.cpp \
src/tcp.cpp \
src/tcp_stream.cpp \
src/udp.cpp \
src/utils.cpp
libtins_includedir = $(includedir)/tins
libtins_include_HEADERS = include/internals.h \
include/dhcpv6.h \
include/dot11.h \
include/small_uint.h \
include/ip.h \
include/dns_record.h \
include/eapol.h \
include/tcp_stream.h \
include/ipv6.h \
include/icmpv6.h \
include/endianness.h \
include/rsn_information.h \
include/loopback.h \
include/ieee802_3.h \
include/ethernetII.h \
include/crypto.h \
include/packet.h \
include/llc.h \
include/icmp.h \
include/hw_address.h \
include/packet_writer.h \
include/macros.h \
include/arp.h \
include/ip_address.h \
include/pdu.h \
include/packet_sender.h \
include/bootp.h \
include/network_interface.h \
include/sll.h \
include/radiotap.h \
include/dns.h \
include/rawpdu.h \
include/sniffer.h \
include/snap.h \
include/pdu_cacher.h \
include/dhcp.h \
include/timestamp.h \
include/tcp.h \
include/pdu_option.h \
include/tins.h \
include/udp.h \
include/ipv6_address.h \
include/constants.h \
include/utils.h \
include/cxxstd.h

File diff suppressed because it is too large Load Diff

58
README Normal file
View File

@@ -0,0 +1,58 @@
------------------------------------------------------------------------
libtins v0.3
------------------------------------------------------------------------
-------------------------------- About ---------------------------------
libtins is a C++ library for crafting, sending, sniffing and
interpreting raw network packets.
Its main purpose is to provide the C++ developer an easy, efficient,
platform and endianess-independent way to create tools which need to
send, receive and manipulate specially crafted packets.
In order to read tutorials, examples and checkout some benchmarks which
show libtins' actual performance, please visit:
http://libtins.sourceforge.net
------------------------------- Compiling ------------------------------
In order to compile, execute:
./configure
make
Note that by default, only the shared object is compiled. If you would
like to generate a static library file as well, run:
./configure --enable-static
The generated static/shared library files will be located in the .libs
directory.
If you want to enable C++11 features, such as move semantics, use the
--enable-c++11 switch:
./configure --enable-c++11
------------------------------ Installing-------------------------------
Once you're done, if you want to install the header files and the
shared object, execute as root:
make install
This will install the shared object typically in /usr/local/lib. Note
that you might have to update ldconfig's cache before using it, so
in order to invalidate it, you should run(as root):
ldconfig
------------------------------ Examples --------------------------------
You might want to have a look at the examples located in the "examples"
directory. The same samples can be found online at:
http://libtins.sourceforge.net/index.php?page=examples

7
THANKS Normal file
View File

@@ -0,0 +1,7 @@
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.

9617
aclocal.m4 vendored Normal file

File diff suppressed because it is too large Load Diff

1530
config.guess vendored Executable file

File diff suppressed because it is too large Load Diff

1773
config.sub vendored Executable file

File diff suppressed because it is too large Load Diff

14768
configure vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,16 +1,59 @@
AC_INIT(myconfig, 0.2)
AC_INIT([libtins], [0.3], [matias.fontanini@gmail.com], [libtins], [http://libtins.sourceforge.net])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
LT_INIT([disable-static])
AC_CONFIG_MACRO_DIR([m4])
AM_MAINTAINER_MODE([enable])
AC_PROG_CXX()
AC_PROG_CXX
AC_LANG(C++)
AC_PROG_LIBTOOL
if test -n "$debug"
then
CFLAGS="-DDEBUG -g"
CXXFLAGS="$CXXFLAGS -DTINS_DEBUG -g"
else
CFLAGS="-O3"
CXXFLAGS="$CXXFLAGS -O3"
fi
AC_CHECK_HEADERS([pcap.h])
AC_CHECK_LIB(pcap, pcap_loop, [], [AC_MSG_ERROR([pcap library is needed!])])
AC_SUBST(CFLAGS)
AC_OUTPUT(Makefile)
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])],
[CXXFLAGS="$CXXFLAGS -I$withval"; CPPFLAGS="-I$withval"])
AC_ARG_WITH([pcap-lib-path],
[AS_HELP_STRING([--with-pcap-lib-path], [location of the libpcap libraries])],
[LIBS="$LIBS -L$withval"])
AC_CHECK_LIB(pcap, pcap_loop, [], [AC_MSG_ERROR([pcap library is missing!])])
old_cppflags=$CPPFLAGS
CPPFLAGS=""
# Headers
LIBTINS_INCLUDE_DIR="include"
AC_CHECK_HEADERS([pcap.h], [], [AC_MSG_ERROR([libpcap headers are missing!])])
CPPFLAGS=$old_cppflags
# Substitute options
AC_SUBST(CXXFLAGS)
AC_SUBST(LIBS)
AC_SUBST(LIBTINS_INCLUDE_DIR)
AC_SUBST([LIBTINS_VERSION], [0:3:0])
AC_CONFIG_FILES([Makefile libtins.pc])
AC_OUTPUT

688
depcomp Executable file
View File

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

558
depends.d
View File

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

View File

@@ -31,6 +31,7 @@
#ifndef TINS_ARP_H
#define TINS_ARP_H
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
#include "hw_address.h"
@@ -285,6 +286,7 @@ namespace Tins {
return new ARP(*this);
}
private:
TINS_BEGIN_PACK
struct arphdr {
uint16_t ar_hrd; /* format of hardware address */
uint16_t ar_pro; /* format of protocol address */
@@ -300,11 +302,11 @@ namespace Tins {
uint8_t ar_tha[hwaddress_type::address_size];
/* target IP address */
uint32_t ar_tip;
} __attribute__((__packed__));
} TINS_END_PACK;
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
arphdr _arp;
};
};
}
#endif //TINS_ARP_H

View File

@@ -34,6 +34,7 @@
#include <algorithm>
#include <vector>
#include "pdu.h"
#include "macros.h"
#include "endianness.h"
#include "ip_address.h"
#include "hw_address.h"
@@ -320,6 +321,7 @@ namespace Tins {
/**
* Struct that represents the Bootp datagram.
*/
TINS_BEGIN_PACK
struct bootphdr {
uint8_t opcode;
uint8_t htype;
@@ -335,11 +337,11 @@ namespace Tins {
uint8_t chaddr[16];
uint8_t sname[64];
uint8_t file[128];
} __attribute__((__packed__));
} TINS_END_PACK;
bootphdr _bootp;
vend_type _vend;
};
};
}
#endif // TINS_BOOTP_H

View File

@@ -73,7 +73,8 @@ namespace Tins {
struct Ethernet {
enum e {
PUP = 0x0200, /* Xerox PUP */
UNKNOWN = 0,
//~ PUP = 0x0200, /* Xerox PUP */
SPRITE = 0x0500, /* Sprite */
IP = 0x0800, /* IP */
ARP = 0x0806, /* Address resolution */
@@ -147,11 +148,11 @@ namespace Tins {
IEEE802154 = 804, /* IEEE 802.15.4 header. */
IEEE802154_PHY = 805, /* IEEE 802.15.4 PHY header. */
VOID_TYPE = 0xFFFF, /* Void type, nothing is known. */
NONE = 0xFFFE, /* Zero header length. */
NONE = 0xFFFE /* Zero header length. */
};
};
};
};
}
}
#endif // TINS_CONSTANTS_H

41
include/cxxstd.h Normal file
View File

@@ -0,0 +1,41 @@
/*
* Copyright (c) 2012, Nasel
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_CXXSTD_H
#define TINS_CXXSTD_H
#ifdef __GXX_EXPERIMENTAL_CXX0X__
#define TINS_CXXSTD_GCC_FIX 1
#else
#define TINS_CXXSTD_GCC_FIX 0
#endif // __GXX_EXPERIMENTAL_CXX0X__
#define TINS_IS_CXX11 (__cplusplus > 199711L || TINS_CXXSTD_GCC_FIX == 1)
#endif // TINS_CXXSTD_H

View File

@@ -418,6 +418,6 @@ namespace Tins {
options_type _options;
uint32_t _size;
};
};
}
#endif // TINS_DHCP_H

949
include/dhcpv6.h Normal file
View File

@@ -0,0 +1,949 @@
/*
* Copyright (c) 2012, Nasel
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_DHCPV6_H
#define TINS_DHCPV6_H
#include <list>
#include "pdu.h"
#include "endianness.h"
#include "small_uint.h"
#include "ipv6_address.h"
#include "pdu_option.h"
namespace Tins {
/**
* Represents a DHCPv6 PDU.
*/
class DHCPv6 : public PDU {
public:
/**
* Represents a DHCPv6 option.
*/
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_;
};
/**
* The message types.
*/
enum MessageType {
SOLICIT = 1,
ADVERTISE,
REQUEST,
CONFIRM,
RENEW,
REBIND,
REPLY,
RELEASE,
DECLINE,
RECONFIGURE,
INFO_REQUEST,
RELAY_FORWARD,
RELAY_REPLY,
LEASE_QUERY,
LEASE_QUERY_REPLY,
LEASE_QUERY_DONE,
LEASE_QUERY_DATA
};
/**
* The DHCPv6 options.
*/
enum Option {
CLIENTID = 1,
SERVERID,
IA_NA,
IA_TA,
IA_ADDR,
OPTION_REQUEST,
PREFERENCE,
ELAPSED_TIME,
RELAY_MSG,
AUTH = 11,
UNICAST,
STATUS_CODE,
RAPID_COMMIT,
USER_CLASS,
VENDOR_CLASS,
VENDOR_OPTS,
INTERFACE_ID,
RECONF_MSG,
RECONF_ACCEPT,
SIP_SERVER_D,
SIP_SERVER_A,
DNS_SERVERS,
DOMAIN_LIST,
IA_PD,
IAPREFIX,
NIS_SERVERS,
NISP_SERVERS,
NIS_DOMAIN_NAME,
NISP_DOMAIN_NAME,
SNTP_SERVERS,
INFORMATION_REFRESH_TIME,
BCMCS_SERVER_D,
BCMCS_SERVER_A,
GEOCONF_CIVIC = 36,
REMOTE_ID,
SUBSCRIBER_ID,
CLIENT_FQDN,
PANA_AGENT,
NEW_POSIX_TIMEZONE,
NEW_TZDB_TIMEZONE,
ERO,
LQ_QUERY,
CLIENT_DATA,
CLT_TIME,
LQ_RELAY_DATA,
LQ_CLIENT_LINK,
MIP6_HNIDF,
MIP6_VDINF,
V6_LOST,
CAPWAP_AC_V6,
RELAY_ID,
NTP_SERVER,
V6_ACCESS_DOMAIN,
SIP_UA_CS_LIST,
BOOTFILE_URL,
BOOTFILE_PARAM,
CLIENT_ARCH_TYPE,
NII,
GEOLOCATION,
AFTR_NAME,
ERP_LOCAL_DOMAIN_NAME,
RSOO,
PD_EXCLUDE,
VSS,
MIP6_IDINF,
MIP6_UDINF,
MIP6_HNP,
MIP6_HAA,
MIP6_HAF,
RDNSS_SELECTION,
KRB_PRINCIPAL_NAME,
KRB_REALM_NAME,
KRB_DEFAULT_REALM_NAME,
KRB_KDC
};
/**
* The type used to store the DHCPv6 options.
*/
typedef std::list<dhcpv6_option> options_type;
/**
* The type used to store IP addresses.
*/
typedef IPv6Address ipaddress_type;
/**
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::DHCPv6;
/**
* The type used to store the Identity Association for Non-Temporary
* Addresses option.
*/
struct ia_na_type {
typedef std::vector<uint8_t> options_type;
uint32_t id, t1, t2;
options_type options;
ia_na_type(uint32_t id = 0, uint32_t t1 = 0, uint32_t t2 = 0,
const options_type& options = options_type())
: id(id), t1(t1), t2(t2), options(options) {}
};
/**
* The type used to store the Identity Association for Temporary
* Addresses option.
*/
struct ia_ta_type {
typedef std::vector<uint8_t> options_type;
uint32_t id;
options_type options;
ia_ta_type(uint32_t id = 0,
const options_type& options = options_type())
: id(id), options(options) {}
};
/**
* The type used to store the Identity Association Address option.
*/
struct ia_address_type {
typedef std::vector<uint8_t> options_type;
ipaddress_type address;
uint32_t preferred_lifetime, valid_lifetime;
options_type options;
ia_address_type(ipaddress_type address = ipaddress_type(),
uint32_t preferred_lifetime = 0, uint32_t valid_lifetime = 0,
const options_type& options = options_type())
: address(address), preferred_lifetime(preferred_lifetime),
valid_lifetime(valid_lifetime), options(options) {}
};
/**
* The type used to store the Authentication option.
*/
struct authentication_type {
typedef std::vector<uint8_t> auth_info_type;
uint8_t protocol, algorithm, rdm;
uint64_t replay_detection;
auth_info_type auth_info;
authentication_type(uint8_t protocol = 0, uint8_t algorithm = 0,
uint8_t rdm = 0, uint64_t replay_detection = 0,
const auth_info_type &auth_info = auth_info_type())
: protocol(protocol), algorithm(algorithm), rdm(rdm),
replay_detection(replay_detection), auth_info(auth_info) {}
};
/**
* The type used to store the Status Code option.
*/
struct status_code_type {
uint16_t code;
std::string message;
status_code_type(uint16_t code = 0, const std::string &message = "")
: code(code), message(message) { }
};
/**
* The type used to store the Vendor-specific Information option.
*/
struct vendor_info_type {
typedef std::vector<uint8_t> data_type;
uint32_t enterprise_number;
data_type data;
vendor_info_type(uint32_t enterprise_number = 0,
const data_type &data = data_type())
: enterprise_number(enterprise_number), data(data) { }
};
/**
* The type used to store the User Class option's user class data.
*/
typedef std::vector<uint8_t> class_option_data_type;
/**
* The type used to store the User Class option.
*/
typedef std::vector<class_option_data_type> user_class_type;
/**
* The type used to store the Vendor Class option.
*/
struct vendor_class_type {
typedef std::vector<class_option_data_type> class_data_type;
uint32_t enterprise_number;
class_data_type vendor_class_data;
vendor_class_type(uint32_t enterprise_number = 0,
const class_data_type &vendor_class_data = class_data_type())
: enterprise_number(enterprise_number),
vendor_class_data(vendor_class_data) { }
};
/**
* The type used to represent DUIDs Based on Link-layer Address Plus
* Time.
*/
struct duid_llt {
static const uint16_t duid_id = 1;
typedef std::vector<uint8_t> lladdress_type;
uint16_t hw_type;
uint32_t time;
lladdress_type lladdress;
duid_llt(uint16_t hw_type = 0, uint32_t time = 0,
const lladdress_type &lladdress = lladdress_type())
: hw_type(hw_type), time(time), lladdress(lladdress) {}
PDU::serialization_type serialize() const;
static duid_llt from_bytes(const uint8_t *buffer, uint32_t total_sz);
};
/**
* The type used to represent DUIDs Based on Enterprise Number
*/
struct duid_en {
static const uint16_t duid_id = 2;
typedef std::vector<uint8_t> identifier_type;
uint32_t enterprise_number;
identifier_type identifier;
duid_en(uint32_t enterprise_number = 0,
const identifier_type &identifier = identifier_type())
: enterprise_number(enterprise_number), identifier(identifier) {}
PDU::serialization_type serialize() const;
static duid_en from_bytes(const uint8_t *buffer, uint32_t total_sz);
};
/**
* The type used to represent DUIDs Based on Link-layer Address.
*/
struct duid_ll {
static const uint16_t duid_id = 3;
typedef std::vector<uint8_t> lladdress_type;
uint16_t hw_type;
lladdress_type lladdress;
duid_ll(uint16_t hw_type = 0,
const lladdress_type &lladdress = lladdress_type())
: hw_type(hw_type), lladdress(lladdress) {}
PDU::serialization_type serialize() const;
static duid_ll from_bytes(const uint8_t *buffer, uint32_t total_sz);
};
/**
* Type type used to represent DUIDs. This will be stored as the
* value for the Client/Server Identifier options.
*/
struct duid_type {
typedef PDU::serialization_type data_type;
uint16_t id;
data_type data;
duid_type(uint16_t id = 0, const data_type &data = data_type())
: id(id), data(data) {}
duid_type(const duid_llt &identifier)
: id(duid_llt::duid_id), data(identifier.serialize()) {}
duid_type(const duid_en &identifier)
: id(duid_en::duid_id), data(identifier.serialize()) {}
duid_type(const duid_ll &identifier)
: id(duid_en::duid_id), data(identifier.serialize()) {}
};
/**
* The type used to store the Option Request option.
*/
typedef std::vector<Option> option_request_type;
/**
* The type used to store the Relay Message option.
*/
typedef std::vector<uint8_t> relay_msg_type;
/**
* The type used to store the Interface-ID option.
*/
typedef std::vector<uint8_t> interface_id_type;
/**
* Default constructor.
*/
DHCPv6();
/**
* \brief Constructor which constructs a DHCPv6 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.
*/
DHCPv6(const uint8_t *buffer, uint32_t total_sz);
// Getters
/**
* \brief Getter for the message type field.
*
* \return The stored message type field.
*/
MessageType msg_type() const {
return static_cast<MessageType>(header_data[0]);
}
/**
* \brief Getter for the hop count field.
*
* \return The stored hop count field.
*/
uint8_t hop_count() const { return header_data[1]; }
/**
* \brief Getter for the transaction id field.
*
* \return The stored transaction id field.
*/
small_uint<24> transaction_id() const {
return (header_data[1] << 16) | (header_data[2] << 8) | header_data[3];
}
/**
* \brief Getter for the peer address field.
*
* \return The stored peer address field.
*/
const ipaddress_type &peer_address() const { return peer_addr; }
/**
* \brief Getter for the link address field.
*
* \return The stored link address field.
*/
const ipaddress_type &link_address() const { return link_addr; }
/**
* \brief Getter for the DHCPv6 options.
*
* \return The stored options.
*/
const options_type &options() const { return options_; }
;
// Setters
/**
* \brief Setter for the message type field.
*
* \param type The new message type.
*/
void msg_type(MessageType type);
/**
* \brief Setter for the hop count field.
*
* \param count The new hop count.
*/
void hop_count(uint8_t count);
/**
* \brief Setter for the transaction id field.
*
* \param id The new transaction id.
*/
void transaction_id(small_uint<24> id);
/**
* \brief Setter for the peer address field.
*
* \param count The new peer address.
*/
void peer_address(const ipaddress_type &addr);
/**
* \brief Setter for the link address field.
*
* \param count The new link address.
*/
void link_address(const ipaddress_type &addr);
// Option getters
/**
* \brief Getter for the Identity Association for Non-Temporary
* Addresses option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
ia_na_type ia_na() const;
/**
* \brief Getter for the Identity Association for Temporary
* Addresses option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
ia_ta_type ia_ta() const;
/**
* \brief Getter for the Identity Association Address option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
ia_address_type ia_address() const;
/**
* \brief Getter for the Option Request option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
option_request_type option_request() const;
/**
* \brief Getter for the Preference option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
uint8_t preference() const;
/**
* \brief Getter for the Elapsed Time option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
uint16_t elapsed_time() const;
/**
* \brief Getter for the Relay Message option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
relay_msg_type relay_message() const;
/**
* \brief Getter for the Authentication option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
authentication_type authentication() const;
/**
* \brief Getter for the Server Unicast option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
ipaddress_type server_unicast() const;
/**
* \brief Getter for the Server Unicast option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
status_code_type status_code() const;
/**
* \brief Getter for the Rapid Commit option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
bool has_rapid_commit() const;
/**
* \brief Getter for the User Class option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
user_class_type user_class() const;
/**
* \brief Getter for the Vendor Class option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
vendor_class_type vendor_class() const;
/**
* \brief Getter for the Vendor-specific Information option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
vendor_info_type vendor_info() const;
/**
* \brief Getter for the Interface ID option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
interface_id_type interface_id() const;
/**
* \brief Getter for the Reconfigure Message option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
uint8_t reconfigure_msg() const;
/**
* \brief Getter for the Reconfigure Accept option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
bool has_reconfigure_accept() const;
/**
* \brief Getter for the Client Identifier option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
duid_type client_id() const;
/**
* \brief Getter for the Server Identifier option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
duid_type server_id() const;
// Option setters
/**
* \brief Setter for the Identity Association for Non-Temporary
* Addresses option.
*
* \param value The new IA_NA option data.
*/
void ia_na(const ia_na_type &value);
/**
* \brief Setter for the Identity Association for Temporary
* Addresses option.
*
* \param value The new IA_TA option data.
*/
void ia_ta(const ia_ta_type &value);
/**
* \brief Setter for the Identity Association Address option.
*
* \param value The new IA Address option data.
*/
void ia_address(const ia_address_type &value);
/**
* \brief Setter for the Identity Association Address option.
*
* \param value The new Option Request option data.
*/
void option_request(const option_request_type &value);
/**
* \brief Setter for the Preference option.
*
* \param value The new Preference option data.
*/
void preference(uint8_t value);
/**
* \brief Setter for the Elapsed Time option.
*
* \param value The new Elapsed Time option data.
*/
void elapsed_time(uint16_t value);
/**
* \brief Setter for the Relay Message option.
*
* \param value The new Relay Message option data.
*/
void relay_message(const relay_msg_type &value);
/**
* \brief Setter for the Authentication option.
*
* \param value The new Authentication option data.
*/
void authentication(const authentication_type &value);
/**
* \brief Setter for the Server Unicast option.
*
* \param value The new Server Unicast option data.
*/
void server_unicast(const ipaddress_type &value);
/**
* \brief Setter for the Status Code option.
*
* \param value The new Status Code option data.
*/
void status_code(const status_code_type &value);
/**
* \brief Adds a Rapid Commit option.
*/
void rapid_commit();
/**
* \brief Setter for the User Class option.
*
* \param value The new User Class option data.
*/
void user_class(const user_class_type &value);
/**
* \brief Setter for the Vendor Class option.
*
* \param value The new Vendor Class option data.
*/
void vendor_class(const vendor_class_type &value);
/**
* \brief Setter for the Vendor-specific Information option.
*
* \param value The new Vendor-specific Information option data.
*/
void vendor_info(const vendor_info_type &value);
/**
* \brief Setter for the Interface ID option.
*
* \param value The new Interface ID option data.
*/
void interface_id(const interface_id_type &value);
/**
* \brief Setter for the Reconfigure Message option.
*
* \param value The new Reconfigure Message option data.
*/
void reconfigure_msg(uint8_t value);
/**
* \brief Adds a Reconfigure Accept option.
*/
void reconfigure_accept();
/**
* \brief Setter for the Client Identifier option.
*
* \param value The new Client Identifier option data.
*/
void client_id(const duid_type &value);
/**
* \brief Setter for the Server Identifier option.
*
* \param value The new Server Identifier option data.
*/
void server_id(const duid_type &value);
// Other stuff
/**
* Indicates whether this is a relay agent/server message
*/
bool is_relay_message() const;
/**
* \brief Adds a DHCPv6 option.
*
* The option is added after the last option in the option
* fields.
*
* \param option The option to be added
*/
void add_option(const dhcpv6_option &option);
/**
* \brief Searchs for an option that matchs the given flag.
*
* If the option is not found, a null pointer is returned.
* Deleting the returned pointer will result in <b>undefined
* behaviour</b>.
*
* \param id The option identifier to be searched.
*/
const dhcpv6_option *search_option(Option id) const;
// PDU stuff
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \sa PDU::clone
*/
DHCPv6 *clone() const {
return new DHCPv6(*this);
}
private:
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
uint8_t* write_option(const dhcpv6_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);
if(!option || Functor<uint32_t>()(option->data_size(), size))
throw option_not_found();
return option;
}
template<typename InputIterator>
void class_option_data2option(InputIterator start, InputIterator end,
std::vector<uint8_t>& buffer, size_t start_index = 0)
{
size_t index = start_index;
while(start != end) {
buffer.resize(buffer.size() + sizeof(uint16_t) + start->size());
*(uint16_t*)&buffer[index] = Endian::host_to_be<uint16_t>(start->size());
index += sizeof(uint16_t);
std::copy(start->begin(), start->end(), buffer.begin() + index);
index += start->size();
start++;
}
}
template<typename OutputType>
OutputType option2class_option_data(const uint8_t *ptr, uint32_t total_sz) const
{
typedef typename OutputType::value_type value_type;
OutputType output;
size_t index = 0;
while(index + 2 < total_sz) {
uint16_t size = Endian::be_to_host(
*(const uint16_t*)(ptr + index)
);
index += sizeof(uint16_t);
if(index + size > total_sz)
throw option_not_found();
output.push_back(
value_type(ptr + index, ptr + index + size)
);
index += size;
}
if(index != total_sz)
throw option_not_found();
return output;
}
uint8_t header_data[4];
uint32_t options_size;
ipaddress_type link_addr, peer_addr;
options_type options_;
};
}
#endif // TINS_DHCPV6_H

View File

@@ -36,12 +36,14 @@
#include <cstring>
#include <string>
#include <map>
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
#include "dns_record.h"
namespace Tins {
class IPv4Address;
class IPv6Address;
/**
* \class DNS
@@ -240,6 +242,7 @@ namespace Tins {
typedef std::list<Query> queries_type;
typedef std::list<Resource> resources_type;
typedef IPv4Address address_type;
typedef IPv6Address address_v6_type;
/**
* \brief Default constructor.
@@ -485,6 +488,18 @@ namespace Tins {
*/
void add_answer(const std::string &name,
const DNSResourceRecord::info &info, address_type ip);
/**
* \brief Add a query response.
*
* \param name The resolved name.
* \param type The type of this answer.
* \param qclass The class of this answer.
* \param ttl The time-to-live of this answer.
* \param ip The ip address of the resolved name.
*/
void add_answer(const std::string &name,
const DNSResourceRecord::info &info, address_v6_type ip);
/**
* \brief Add a query response.
@@ -569,6 +584,7 @@ namespace Tins {
return DNSResourceRecord::info((uint16_t)type, (uint16_t)qclass, ttl);
}
private:
TINS_BEGIN_PACK
struct dnshdr {
uint16_t id;
#if TINS_IS_LITTLE_ENDIAN
@@ -598,7 +614,7 @@ namespace Tins {
#endif
uint16_t questions, answers,
authority, additional;
} __attribute__((packed));
} TINS_END_PACK;
typedef std::map<uint16_t, std::string> SuffixMap;
typedef std::map<uint16_t, uint16_t> SuffixIndices;
@@ -630,7 +646,7 @@ namespace Tins {
mutable SuffixMap suffixes;
mutable SuffixIndices suffix_indices;
};
};
}
#endif // TINS_DNS_H

View File

@@ -33,6 +33,8 @@
#include <string>
#include <vector>
#include <stdint.h>
#include "cxxstd.h"
#include "macros.h"
namespace Tins {
class DNSRRImpl;
@@ -45,6 +47,7 @@ public:
/**
* \brief The type used to store resource records' information.
*/
TINS_BEGIN_PACK
struct info {
uint16_t type, qclass;
uint32_t ttl;
@@ -53,7 +56,7 @@ public:
: type(tp), qclass(qc), ttl(tm) { }
info() : type(), qclass(), ttl() {}
} __attribute__((packed));
} TINS_END_PACK;
/**
* \brief Constructs a record.
@@ -97,6 +100,18 @@ public:
*/
DNSResourceRecord& operator=(const DNSResourceRecord &rhs);
#if TINS_IS_CXX11
/**
* Move constructor.
*/
DNSResourceRecord(DNSResourceRecord &&rhs) noexcept;
/**
* Move assignment operator.
*/
DNSResourceRecord& operator=(DNSResourceRecord &&rhs) noexcept;
#endif // TINS_IS_CXX11
/**
* \brief Destructor.
*

View File

@@ -35,6 +35,7 @@
#include <stdint.h>
#include <utility>
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
#include "hw_address.h"
@@ -423,7 +424,7 @@ namespace Tins {
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return flag == pdu_flag;
}
@@ -449,38 +450,40 @@ namespace Tins {
/**
* Struct that represents the 802.11 header
*/
TINS_BEGIN_PACK
struct ieee80211_header {
TINS_BEGIN_PACK
struct {
#if TINS_IS_LITTLE_ENDIAN
unsigned int protocol:2;
unsigned int type:2;
unsigned int subtype:4;
unsigned int to_ds:1;
unsigned int from_ds:1;
unsigned int more_frag:1;
unsigned int retry:1;
unsigned int power_mgmt:1;
unsigned int more_data:1;
unsigned int wep:1;
unsigned int order:1;
uint16_t protocol:2,
type:2,
subtype:4,
to_ds:1,
from_ds:1,
more_frag:1,
retry:1,
power_mgmt:1,
more_data:1,
wep:1,
order:1;
#elif TINS_IS_BIG_ENDIAN
unsigned int subtype:4;
unsigned int type:2;
unsigned int protocol:2;
unsigned int order:1;
unsigned int wep:1;
unsigned int more_data:1;
unsigned int power_mgmt:1;
unsigned int retry:1;
unsigned int more_frag:1;
unsigned int from_ds:1;
unsigned int to_ds:1;
uint16_t subtype:4,
type:2,
protocol:2,
order:1,
wep:1,
more_data:1,
power_mgmt:1,
retry:1,
more_frag:1,
from_ds:1,
to_ds:1;
#endif
} __attribute__((__packed__)) control;
} TINS_END_PACK control;
uint16_t duration_id;
uint8_t addr1[address_type::address_size];
} __attribute__((__packed__));
} TINS_END_PACK;
private:
Dot11(const ieee80211_header *header_ptr);
@@ -557,6 +560,7 @@ namespace Tins {
/**
* Represents the IEEE 802.11 frames' capability information.
*/
TINS_BEGIN_PACK
class capability_information {
private:
#if TINS_IS_LITTLE_ENDIAN
@@ -819,8 +823,9 @@ namespace Tins {
*/
void immediate_block_ack(bool new_value) { _immediate_block_ack = new_value; }
} __attribute__((__packed__));
} TINS_END_PACK;
TINS_BEGIN_PACK
struct fh_params_set {
uint16_t dwell_time;
uint8_t hop_set, hop_pattern, hop_index;
@@ -831,8 +836,9 @@ namespace Tins {
uint8_t hop_pattern, uint8_t hop_index)
: dwell_time(dwell_time), hop_set(hop_set),
hop_pattern(hop_pattern), hop_index(hop_index) {}
} __attribute__((__packed__));
} TINS_END_PACK;
TINS_BEGIN_PACK
struct cf_params_set {
uint8_t cfp_count, cfp_period;
uint16_t cfp_max_duration, cfp_dur_remaining;
@@ -844,7 +850,7 @@ namespace Tins {
: cfp_count(cfp_count), cfp_period(cfp_period),
cfp_max_duration(cfp_max_duration),
cfp_dur_remaining(cfp_dur_remaining) {}
} __attribute__((__packed__));
} TINS_END_PACK;
struct ibss_dfs_params {
static const size_t minimum_size = address_type::address_size + sizeof(uint8_t) + 2 * sizeof(uint8_t);
@@ -1437,15 +1443,16 @@ namespace Tins {
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11::matches_flag(flag);
}
protected:
TINS_BEGIN_PACK
struct ExtendedHeader {
uint8_t addr2[address_type::address_size];
uint8_t addr3[address_type::address_size];
uint16_t frag_seq;
} __attribute__((__packed__));
} TINS_END_PACK;
Dot11ManagementFrame(const address_type &dst_hw_addr = address_type(),
@@ -1563,7 +1570,7 @@ namespace Tins {
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
}
@@ -1582,11 +1589,12 @@ namespace Tins {
*/
PDUType pdu_type() const { return pdu_flag; }
private:
TINS_BEGIN_PACK
struct BeaconBody {
uint64_t timestamp;
uint16_t interval;
capability_information capability;
} __attribute__((__packed__));
} TINS_END_PACK;
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
@@ -1658,7 +1666,7 @@ namespace Tins {
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
}
@@ -1761,7 +1769,7 @@ namespace Tins {
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
}
@@ -1879,7 +1887,7 @@ namespace Tins {
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
}
@@ -1998,7 +2006,7 @@ namespace Tins {
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
}
@@ -2117,7 +2125,7 @@ namespace Tins {
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
}
@@ -2236,7 +2244,7 @@ namespace Tins {
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
}
@@ -2326,7 +2334,7 @@ namespace Tins {
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
}
@@ -2391,7 +2399,7 @@ namespace Tins {
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
}
@@ -2510,17 +2518,18 @@ namespace Tins {
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
}
protected:
private:
TINS_BEGIN_PACK
struct ProbeResp {
uint64_t timestamp;
uint16_t interval;
capability_information capability;
} __attribute__((__packed__));
} TINS_END_PACK;
ProbeResp _body;
@@ -2658,7 +2667,7 @@ namespace Tins {
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11::matches_flag(flag);
}
@@ -2671,15 +2680,18 @@ namespace Tins {
return new Dot11Data(*this);
}
protected:
TINS_BEGIN_PACK
struct ExtendedHeader {
uint8_t addr2[address_type::address_size];
uint8_t addr3[address_type::address_size];
uint16_t frag_seq;
} __attribute__((__packed__));
} TINS_END_PACK;
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
uint32_t data_frame_size() { return sizeof(_ext_header) + (from_ds() && to_ds()) ? sizeof(_addr4) : 0; }
uint32_t data_frame_size() {
return sizeof(_ext_header) + ((from_ds() && to_ds()) ? sizeof(_addr4) : 0);
}
private:
ExtendedHeader _ext_header;
address_type _addr4;
@@ -2756,7 +2768,7 @@ namespace Tins {
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return flag == PDU::DOT11_QOS_DATA || Dot11Data::matches_flag(flag);
}
private:
@@ -2807,7 +2819,7 @@ namespace Tins {
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return flag == PDU::DOT11_CONTROL || Dot11::matches_flag(flag);
}
};
@@ -2919,7 +2931,7 @@ namespace Tins {
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11Control::matches_flag(flag);
}
};
@@ -2973,7 +2985,7 @@ namespace Tins {
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11Control::matches_flag(flag);
}
};
@@ -3027,7 +3039,7 @@ namespace Tins {
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11Control::matches_flag(flag);
}
};
@@ -3081,7 +3093,7 @@ namespace Tins {
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11Control::matches_flag(flag);
}
};
@@ -3133,7 +3145,7 @@ namespace Tins {
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11Control::matches_flag(flag);
}
};
@@ -3238,21 +3250,23 @@ namespace Tins {
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11Control::matches_flag(flag);
}
protected:
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
private:
TINS_BEGIN_PACK
struct BarControl {
uint16_t reserved:12,
tid:4;
} __attribute__((__packed__));
} TINS_END_PACK;
TINS_BEGIN_PACK
struct StartSequence {
uint16_t frag:4,
seq:12;
} __attribute__((__packed__));
} TINS_END_PACK;
void init_block_ack();
@@ -3358,7 +3372,7 @@ namespace Tins {
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return flag == pdu_flag || Dot11Control::matches_flag(flag);
}
@@ -3371,15 +3385,17 @@ namespace Tins {
return new Dot11BlockAck(*this);
}
private:
TINS_BEGIN_PACK
struct BarControl {
uint16_t reserved:12,
tid:4;
} __attribute__((__packed__));
} TINS_END_PACK;
TINS_BEGIN_PACK
struct StartSequence {
uint16_t frag:4,
seq:12;
} __attribute__((__packed__));
} TINS_END_PACK;
void init_block_ack();
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
@@ -3389,8 +3405,6 @@ namespace Tins {
StartSequence _start_sequence;
uint8_t _bitmap[bitmap_size];
};
};
}
#endif // TINS_DOT_11

View File

@@ -32,6 +32,7 @@
#include <stdint.h>
#include "pdu.h"
#include "macros.h"
#include "small_uint.h"
#include "endianness.h"
@@ -134,11 +135,6 @@ namespace Tins {
*/
EAPOL(uint8_t packet_type, EAPOLTYPE type);
/**
* \brief Copy constructor.
*/
EAPOL(const EAPOL &other);
/**
* \brief Constructor which creates an EAPOL object from a buffer.
* \param buffer The buffer from which this PDU will be constructed.
@@ -146,13 +142,12 @@ namespace Tins {
*/
EAPOL(const uint8_t *buffer, uint32_t total_sz);
void copy_eapol_fields(const EAPOL *other);
TINS_BEGIN_PACK
struct eapolhdr {
uint8_t version, packet_type;
uint16_t length;
uint8_t type;
} __attribute__((__packed__));
} TINS_END_PACK;
/**
* \brief Virtual method which should serialize the subclass specific
@@ -324,7 +319,7 @@ namespace Tins {
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return flag == PDU::RC4EAPOL || EAPOL::matches_flag(flag);
}
@@ -337,6 +332,7 @@ namespace Tins {
return new RC4EAPOL(*this);
}
private:
TINS_BEGIN_PACK
struct rc4hdr {
uint16_t key_length;
uint64_t replay_counter;
@@ -344,7 +340,7 @@ namespace Tins {
uint8_t key_index:7,
key_flag:1;
uint8_t key_sign[16];
} __attribute__((__packed__));
} TINS_END_PACK;
void write_body(uint8_t *buffer, uint32_t total_sz);
@@ -665,7 +661,7 @@ namespace Tins {
* \param flag The flag to match
* \sa PDU::matches_flag
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return flag == PDU::RSNEAPOL || EAPOL::matches_flag(flag);
}
@@ -678,6 +674,7 @@ namespace Tins {
return new RSNEAPOL(*this);
}
private:
TINS_BEGIN_PACK
struct rsnhdr {
#if TINS_IS_LITTLE_ENDIAN
uint16_t key_mic:1,
@@ -716,7 +713,7 @@ namespace Tins {
uint8_t mic[mic_size];
uint16_t wpa_length;
#endif
} __attribute__((__packed__));
} TINS_END_PACK;
void write_body(uint8_t *buffer, uint32_t total_sz);
@@ -724,6 +721,6 @@ namespace Tins {
rsnhdr _header;
key_type _key;
};
};
}
#endif // TINS_EAPOL_H

View File

@@ -31,12 +31,27 @@
#define TINS_ENDIANNESS_H
#include <stdint.h>
#ifndef WIN32
#include "macros.h"
#if defined(__APPLE__)
#include <sys/types.h>
#define TINS_IS_LITTLE_ENDIAN (BYTE_ORDER == LITTLE_ENDIAN)
#define TINS_IS_BIG_ENDIAN (BYTE_ORDER == BIG_ENDIAN)
#elif defined(BSD)
#include <sys/endian.h>
#define TINS_IS_LITTLE_ENDIAN (_BYTE_ORDER == _LITTLE_ENDIAN)
#define TINS_IS_BIG_ENDIAN (_BYTE_ORDER == _BIG_ENDIAN)
#elif defined(WIN32)
// Assume windows == little endian. fixme later
#define TINS_IS_LITTLE_ENDIAN 1
#define TINS_IS_BIG_ENDIAN 0
#else
#include <endian.h>
#define TINS_IS_LITTLE_ENDIAN (__BYTE_ORDER == __LITTLE_ENDIAN)
#define TINS_IS_BIG_ENDIAN (__BYTE_ORDER == __BIG_ENDIAN)
#endif
#define TINS_IS_LITTLE_ENDIAN (__BYTE_ORDER == __LITTLE_ENDIAN)
#define TINS_IS_BIG_ENDIAN (__BYTE_ORDER == __BIG_ENDIAN)
namespace Tins {
namespace Endian {
@@ -45,7 +60,7 @@ namespace Endian {
*
* \param data The data to convert.
*/
inline uint16_t change_endian(uint16_t data) {
inline uint16_t do_change_endian(uint16_t data) {
return ((data & 0xff00) >> 8) | ((data & 0x00ff) << 8);
}
@@ -54,7 +69,7 @@ namespace Endian {
*
* \param data The data to convert.
*/
inline uint32_t change_endian(uint32_t data) {
inline uint32_t do_change_endian(uint32_t data) {
return (((data & 0xff000000) >> 24) | ((data & 0x00ff0000) >> 8) |
((data & 0x0000ff00) << 8) | ((data & 0x000000ff) << 24));
}
@@ -64,9 +79,56 @@ namespace Endian {
*
* \param data The data to convert.
*/
inline uint64_t change_endian(uint64_t data) {
return (((uint64_t)(change_endian((uint32_t)((data << 32) >> 32))) << 32) |
(change_endian(((uint32_t)(data >> 32)))));
inline uint64_t do_change_endian(uint64_t data) {
return (((uint64_t)(do_change_endian((uint32_t)((data << 32) >> 32))) << 32) |
(do_change_endian(((uint32_t)(data >> 32)))));
}
/**
* \cond
*/
// Helpers to convert
template<typename T>
struct conversion_dispatch_helper {
static T dispatch(T data) {
return do_change_endian(data);
}
};
template<size_t>
struct conversion_dispatcher;
template<>
struct conversion_dispatcher<sizeof(uint16_t)>
: public conversion_dispatch_helper<uint16_t>
{ };
template<>
struct conversion_dispatcher<sizeof(uint32_t)>
: public conversion_dispatch_helper<uint32_t>
{ };
template<>
struct conversion_dispatcher<sizeof(uint64_t)>
: public conversion_dispatch_helper<uint64_t>
{ };
/**
* \endcond
*/
/**
* \brief Changes an integral value's endianess.
*
* This dispatchs to the corresponding function.
*
* \param data The data to convert.
*/
template<typename T>
inline T change_endian(T data) {
return conversion_dispatcher<sizeof(T)>::dispatch(data);
}
#if TINS_IS_LITTLE_ENDIAN

View File

@@ -31,7 +31,7 @@
#define TINS_ETHERNET_II_H
#include <stdint.h>
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
#include "hw_address.h"
@@ -203,11 +203,12 @@ namespace Tins {
/**
* Struct that represents the Ethernet II header
*/
TINS_BEGIN_PACK
struct ethhdr {
uint8_t dst_mac[address_type::address_size];
uint8_t src_mac[address_type::address_size];
uint16_t payload_type;
} __attribute__((__packed__));
} TINS_END_PACK;
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
@@ -215,7 +216,7 @@ namespace Tins {
NetworkInterface _iface;
};
};
}
#endif // TINS_ETHERNET_II_H

View File

@@ -30,7 +30,7 @@
#ifndef TINS_ICMP_H
#define TINS_ICMP_H
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
@@ -141,14 +141,6 @@ namespace Tins {
*/
void set_echo_request(uint16_t id, uint16_t seq);
/**
* \brief Sets echo request flag for this PDU.
*
* This uses a global id and sequence number to fill the request's
* fields.
*/
void set_echo_request();
/**
* \brief Sets echo reply flag for this PDU.
*
@@ -157,14 +149,6 @@ namespace Tins {
*/
void set_echo_reply(uint16_t id, uint16_t seq);
/**
* \brief Sets echo reply flag for this PDU.
*
* This uses a global id and sequence number to fill the request's
* fields.
*/
void set_echo_reply();
/**
* \brief Sets information request flag for this PDU.
*
@@ -317,8 +301,7 @@ namespace Tins {
return new ICMP(*this);
}
private:
static uint16_t global_id, global_seq;
TINS_BEGIN_PACK
struct icmphdr {
uint8_t type;
uint8_t code;
@@ -330,12 +313,12 @@ namespace Tins {
} echo;
uint32_t gateway;
struct {
uint16_t __unused;
uint16_t unused;
uint16_t mtu;
} frag;
uint8_t pointer;
} un;
} __attribute__((__packed__));
} TINS_END_PACK;
/** \brief Serialices this ICMP PDU.
* \param buffer The buffer in which the PDU will be serialized.
@@ -346,6 +329,6 @@ namespace Tins {
icmphdr _icmp;
};
};
}
#endif // TINS_ICMP_H

1208
include/icmpv6.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -31,7 +31,7 @@
#define TINS_IEEE802_3_H
#include <stdint.h>
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
#include "hw_address.h"
@@ -201,11 +201,12 @@ namespace Tins {
/**
* Struct that represents the Ethernet II header
*/
TINS_BEGIN_PACK
struct ethhdr {
uint8_t dst_mac[address_type::address_size];
uint8_t src_mac[address_type::address_size];
uint16_t length;
} __attribute__((__packed__));
} TINS_END_PACK;
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
@@ -213,8 +214,7 @@ namespace Tins {
ethhdr _eth;
NetworkInterface _iface;
};
};
}
#endif // TINS_IEEE802_3_H

67
include/internals.h Normal file
View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 2012, Nasel
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_INTERNALS_H
#define TINS_INTERNALS_H
#include <sstream>
#include <string>
#include <stdint.h>
#include "constants.h"
#include "pdu.h"
/**
* \cond
*/
namespace Tins {
namespace Internals {
void skip_line(std::istream &input);
bool from_hex(const std::string &str, uint32_t &result);
template<bool, typename>
struct enable_if {
};
template<typename T>
struct enable_if<true, T> {
typedef T type;
};
PDU *pdu_from_flag(Constants::Ethernet::e flag, const uint8_t *buffer,
uint32_t size, bool rawpdu_on_no_match = true);
Constants::Ethernet::e pdu_flag_to_ether_type(PDU::PDUType flag);
}
}
/**
* \endcond
*/
#endif

View File

@@ -36,6 +36,7 @@
#include "endianness.h"
#include "ip_address.h"
#include "pdu_option.h"
#include "macros.h"
namespace Tins {
@@ -49,7 +50,7 @@ namespace Tins {
class IP : public PDU {
public:
/**
* his PDU's flag.
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::IP;
@@ -99,6 +100,7 @@ namespace Tins {
/**
* \brief The type used to represent an option's type.
*/
TINS_BEGIN_PACK
struct option_identifier {
#if TINS_IS_LITTLE_ENDIAN
uint8_t number:5,
@@ -161,7 +163,7 @@ namespace Tins {
bool operator==(const option_identifier &rhs) const {
return number == rhs.number && op_class == rhs.op_class && copied == rhs.copied;
}
} __attribute__((__packed__));
} TINS_END_PACK;
/**
* The IP options type.
@@ -212,6 +214,11 @@ namespace Tins {
*/
typedef generic_route_option_type record_route_type;
/**
* The type used to store IP options.
*/
typedef std::list<ip_option> options_type;
/**
* \brief Constructor for building the IP PDU.
*
@@ -229,8 +236,9 @@ namespace Tins {
PDU *child = 0);
/**
* \brief Constructor which creates an IP object from a buffer and adds all identifiable
* PDUs found in the buffer as children of this one.
* \brief Constructor which constructs an IP 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.
*/
@@ -257,7 +265,9 @@ namespace Tins {
*
* \return The total length of this IP PDU.
*/
uint16_t tot_len() const { return Endian::be_to_host(_ip.tot_len); }
uint16_t tot_len() const {
return Endian::be_to_host(_ip.tot_len);
}
/**
* \brief Getter for the id field.
@@ -313,6 +323,12 @@ namespace Tins {
*/
small_uint<4> version() const { return _ip.version; }
/**
* \brief Getter for the IP options.
* \return The stored options.
*/
const options_type &options() const { return _ip_options; }
/* Setters */
/**
@@ -404,6 +420,11 @@ namespace Tins {
/**
* \brief Searchs for an option that matchs the given flag.
*
* If the option is not found, a null pointer is returned.
* Deleting the returned pointer will result in <b>undefined
* behaviour</b>.
*
* \param id The option identifier to be searched.
*/
const ip_option *search_option(option_identifier id) const;
@@ -578,15 +599,14 @@ namespace Tins {
private:
static const uint8_t DEFAULT_TTL;
TINS_BEGIN_PACK
struct iphdr {
#if TINS_IS_LITTLE_ENDIAN
unsigned int ihl:4;
unsigned int version:4;
#elif TINS_IS_BIG_ENDIAN
unsigned int version:4;
unsigned int ihl:4;
uint8_t ihl:4,
version:4;
#else
# error "Endian is not LE nor BE..."
uint8_t version:4,
ihl:4;
#endif
uint8_t tos;
uint16_t tot_len;
@@ -598,7 +618,7 @@ namespace Tins {
uint32_t saddr;
uint32_t daddr;
/*The options start here. */
} __attribute__((__packed__));
} TINS_END_PACK;
void init_ip_fields();
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
@@ -607,9 +627,9 @@ namespace Tins {
generic_route_option_type search_route_option(option_identifier id) const;
iphdr _ip;
std::list<ip_option> _ip_options;
options_type _ip_options;
uint32_t _options_size, _padded_options_size;
};
};
}
#endif // TINS_IP_H

View File

@@ -136,7 +136,7 @@ namespace Tins {
uint32_t ip_addr;
};
};
}
#endif // TINS_IPADDRESS_H

330
include/ipv6.h Normal file
View File

@@ -0,0 +1,330 @@
/*
* Copyright (c) 2012, Nasel
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_IPV6_h
#define TINS_IPV6_h
#include <list>
#include <stdexcept>
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
#include "small_uint.h"
#include "pdu_option.h"
#include "ipv6_address.h"
namespace Tins {
class PacketSender;
/**
* Represents an IPv6 PDU.
*/
class IPv6 : public PDU {
public:
/**
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::IPv6;
/**
* The type used to store addresses.
*/
typedef IPv6Address address_type;
/**
* The type used to represent IPv6 extension headers.
*/
typedef PDUOption<uint8_t> ipv6_ext_header;
/**
* The type used to store the extension headers.
*/
typedef std::list<ipv6_ext_header> headers_type;
/**
* The values used to identify extension headers.
*/
enum ExtensionHeader {
HOP_BY_HOP = 0,
DESTINATION_ROUTING_OPTIONS = 60,
ROUTING = 43,
FRAGMENT = 44,
AUTHENTICATION = 51,
SECURITY_ENCAPSULATION = 50,
DESTINATION_OPTIONS = 60,
MOBILITY = 135,
NO_NEXT_HEADER = 59
};
/**
* 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.
*
* \param ip_dst The destination ip address(optional).
* \param ip_src The source ip address(optional).
* \param child pointer to a PDU which will be set as the inner_pdu
* for the packet being constructed(optional).
*/
IPv6(address_type ip_dst = address_type(),
address_type ip_src = address_type(),
PDU *child = 0);
/**
* \brief Constructor which creates an IPv6 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.
*/
IPv6(const uint8_t *buffer, uint32_t total_sz);
// Getters
/**
* \brief Getter for the version field.
* \return The stored version field value.
*/
small_uint<4> version() const {
return _header.version;
}
/**
* \brief Getter for the traffic_class field.
* \return The stored traffic_class field value.
*/
uint8_t traffic_class() const {
#if TINS_IS_LITTLE_ENDIAN
return ((_header.traffic_class << 4) & 0xf0) |
((_header.flow_label[0] >> 4) & 0x0f);
#else
return _header.traffic_class;
#endif
}
/**
* \brief Getter for the flow_label field.
* \return The stored flow_label field value.
*/
small_uint<20> flow_label() const {
#if TINS_IS_LITTLE_ENDIAN
return ((_header.flow_label[0] & 0x0f) << 16)
| (_header.flow_label[1] << 8)
| (_header.flow_label[2]);
#else
return _header.flow_label;
#endif
}
/**
* \brief Getter for the payload_length field.
* \return The stored payload_length field value.
*/
uint16_t payload_length() const {
return Endian::be_to_host(_header.payload_length);
}
/**
* \brief Getter for the next_header field.
* \return The stored next_header field value.
*/
uint8_t next_header() const {
return _header.next_header;
}
/**
* \brief Getter for the hop_limit field.
* \return The stored hop_limit field value.
*/
uint8_t hop_limit() const {
return _header.hop_limit;
}
/**
* \brief Getter for the src_addr field.
* \return The stored src_addr field value.
*/
address_type src_addr() const {
return _header.src_addr;
}
/**
* \brief Getter for the dst_addr field.
* \return The stored dst_addr field value.
*/
address_type dst_addr() const {
return _header.dst_addr;
}
/**
* \brief Getter for the IPv6 extension headers.
* \return The stored headers.
*/
const headers_type& headers() const {
return ext_headers;
}
// Setters
/**
* \brief Setter for the version field.
* \param new_version The new version field value.
*/
void version(small_uint<4> new_version);
/**
* \brief Setter for the traffic_class field.
* \param new_traffic_class The new traffic_class field value.
*/
void traffic_class(uint8_t new_traffic_class);
/**
* \brief Setter for the flow_label field.
* \param new_flow_label The new flow_label field value.
*/
void flow_label(small_uint<20> new_flow_label);
/**
* \brief Setter for the payload_length field.
* \param new_payload_length The new payload_length field value.
*/
void payload_length(uint16_t new_payload_length);
/**
* \brief Setter for the next_header field.
* \param new_next_header The new next_header field value.
*/
void next_header(uint8_t new_next_header);
/**
* \brief Setter for the hop_limit field.
* \param new_hop_limit The new hop_limit field value.
*/
void hop_limit(uint8_t new_hop_limit);
/**
* \brief Setter for the src_addr field.
* \param new_src_addr The new src_addr field value.
*/
void src_addr(const address_type &new_src_addr);
/**
* \brief Setter for the dst_addr field.
* \param new_dst_addr The new dst_addr field value.
*/
void dst_addr(const address_type &new_dst_addr);
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \sa PDU::clone
*/
IPv6 *clone() const {
return new IPv6(*this);
}
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
#ifndef BSD
/**
* \sa PDU::send()
*/
void send(PacketSender &sender);
#endif
/**
* Adds an extension header.
*
* \param header The extension header to be added.
*/
void add_ext_header(const ipv6_ext_header &header);
/**
* \brief Searchs for an extension header that matchs the given
* flag.
*
* If the header is not found, a null pointer is returned.
* Deleting the returned pointer will result in <b>undefined
* behaviour</b>.
*
* \param id The header identifier to be searched.
*/
const ipv6_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 bool is_extension_header(uint8_t header_id);
TINS_BEGIN_PACK
struct ipv6_header {
#if TINS_IS_BIG_ENDIAN
uint32_t version:4,
traffic_class:8,
flow_label:20;
uint32_t payload_length:16,
next_header:8,
hop_limit:8;
#else
uint8_t traffic_class:4,
version:4;
uint8_t flow_label[3];
uint16_t payload_length;
uint8_t next_header;
uint8_t hop_limit;
#endif
uint8_t src_addr[16], dst_addr[16];
} TINS_END_PACK;
ipv6_header _header;
headers_type ext_headers;
uint32_t headers_size;
};
}
#endif // TINS_IPV6_h

197
include/ipv6_address.h Normal file
View File

@@ -0,0 +1,197 @@
/*
* Copyright (c) 2012, Nasel
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_IPV6_ADDRESS
#define TINS_IPV6_ADDRESS
#include <string>
#include <stdexcept>
#include <stdint.h>
namespace Tins {
class IPv6Address {
public:
/**
* The exception thrown when a malformed address is parsed.
*/
class malformed_address : public std::exception {
public:
const char *what() const throw() {
return "Malformed address";
}
};
static const size_t address_size = 16;
/**
* The iterator type.
*/
typedef uint8_t* iterator;
/**
* The const iterator type.
*/
typedef const uint8_t* const_iterator;
/**
* \brief Default constructor.
* Initializes this IPv6 address to "::"
*/
IPv6Address();
/**
* \brief Constructor from a text representation char*.
* \param addr The text representation from which to construct this
* object.
*/
IPv6Address(const char *addr);
/**
* \brief Constructor from a text representation std::string.
* \param addr The text representation from which to construct this
* object.
*/
IPv6Address(const std::string &addr);
/**
* \brief Constructor from a buffer.
*
* The ptr parameter must be at least address_size bytes long.
*
* \param ptr The buffer from which to construct this object.
*/
IPv6Address(const_iterator ptr);
/**
* \brief Retrieve the string representation of this address.
*
* \return std::string containing the representation of this address.
*/
std::string to_string() const;
/**
* Returns an iterator to the beginning of this address.
*/
iterator begin() {
return address;
}
/**
* Returns a const iterator to the beginning of this address.
*/
const_iterator begin() const {
return address;
}
/**
* Returns an iterator to the one-past-the-end element of this address.
*/
iterator end() {
return address + address_size;
}
/**
* Returns a const iterator to the one-past-the-end element of this
* address.
*/
const_iterator end() const {
return address + address_size;
}
/**
* \brief Compares this address for equality.
*
* \param rhs The address to be compared to.
*
* \return bool indicating whether addresses are equal.
*/
bool operator==(const IPv6Address &rhs) const {
return std::equal(begin(), end(), rhs.begin());
}
/**
* \brief Compares this address for inequality.
*
* \param rhs The address to be compared to.
*
* \return bool indicating whether addresses are distinct.
*/
bool operator!=(const IPv6Address &rhs) const {
return !(*this == rhs);
}
/**
* \brief Compares this address for less-than inequality.
*
* \param rhs The address to be compared to.
*
* \return bool indicating whether this address is less-than rhs.
*/
bool operator<(const IPv6Address &rhs) const {
return std::lexicographical_compare(begin(), end(), rhs.begin(), rhs.end());
}
/**
* \brief Helper function which copies the address into an output
* iterator.
*
* This is the same as:
*
* std::copy(begin(), end(), iter);
*
* But since some PDUs return a IPv6Address by value, this function
* can be used to avoid temporaries.
*
* \param iter The output iterator in which to store this address.
* \return OutputIterator pointing to one-past the last position
* written.
*/
template<typename OutputIterator>
OutputIterator copy(OutputIterator iter) const {
return std::copy(begin(), end(), iter);
}
/**
* \brief Writes this address in hex-notation to a std::ostream.
*
* \param os The stream in which to write the address.
* \param addr The parameter to be written.
* \return std::ostream& pointing to the os parameter.
*/
friend std::ostream &operator<<(std::ostream &os, const IPv6Address &addr) {
return os << addr.to_string();
}
private:
void init(const char *addr);
uint8_t address[address_size];
};
}
#endif // TINS_IPV6_ADDRESS

View File

@@ -33,6 +33,7 @@
#include <list>
#include <vector>
#include <stdint.h>
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
@@ -314,57 +315,63 @@ namespace Tins {
return new LLC(*this);
}
private:
TINS_BEGIN_PACK
struct llchdr {
uint8_t dsap;
uint8_t ssap;
} __attribute__((__packed__));
} TINS_END_PACK;
#if TINS_IS_LITTLE_ENDIAN
TINS_BEGIN_PACK
struct info_control_field {
uint16_t
type_bit:1,
send_seq_num:7,
poll_final_bit:1,
recv_seq_num:7;
} __attribute__((__packed__));
} TINS_END_PACK;
TINS_BEGIN_PACK
struct super_control_field {
uint16_t type_bit:2,
supervisory_func:2,
unused:4,
poll_final_bit:1,
recv_seq_num:7;
} __attribute__((__packed__));
} TINS_END_PACK;
TINS_BEGIN_PACK
struct un_control_field {
uint8_t type_bits:2,
mod_func1:2,
poll_final_bit:1,
mod_func2:3;
} __attribute__((__packed__));
} TINS_END_PACK;
#elif TINS_IS_BIG_ENDIAN
TINS_BEGIN_PACK
struct info_control_field {
uint16_t send_seq_num:7,
type_bit:1,
recv_seq_num:7,
poll_final_bit:1;
} __attribute__((__packed__));
} TINS_END_PACK;
TINS_BEGIN_PACK
struct super_control_field {
uint16_t unused:4,
supervisory_func:2,
type_bit:2,
recv_seq_num:7,
poll_final_bit:1;
} __attribute__((__packed__));
} TINS_END_PACK;
TINS_BEGIN_PACK
struct un_control_field {
uint8_t mod_func2:3,
poll_final_bit:1,
mod_func1:2,
type_bits:2;
} __attribute__((__packed__));
} TINS_END_PACK;
#endif
typedef std::vector<uint8_t> field_type;
@@ -384,6 +391,6 @@ namespace Tins {
std::list<field_type> information_fields;
};
};
}
#endif // TINS_IEEE8022_H

View File

@@ -31,6 +31,8 @@
#define TINS_LOOPBACK_H
#include "pdu.h"
#include "macros.h"
#include "network_interface.h"
namespace Tins {
class Loopback : public PDU {
@@ -50,10 +52,13 @@ public:
/**
* \brief Construct a Loopback object.
*
* \param family_id The family id to be used.
* 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(uint32_t family_id, PDU *inner_pdu = 0);
Loopback(const NetworkInterface &iface, PDU *inner_pdu = 0);
/**
* \brief Construct a Loopback object from a buffer.
@@ -86,16 +91,36 @@ 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
*/
Loopback *clone() const {
return new Loopback(*this);
}
// Null/Loopback can only be sent in *BSD
#ifdef BSD
/**
* \sa PDU::send()
*/
void send(PacketSender &sender);
#endif // BSD
private:
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
uint32_t _family;
NetworkInterface _iface;
};
}

48
include/macros.h Normal file
View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 2012, Nasel
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_MACROS_H
#define TINS_MACROS_H
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <sys/param.h>
#endif
// Packing directives....
#ifdef _MSC_VER
#define TINS_BEGIN_PACK __pragma( pack(push, 1) )
#define TINS_END_PACK __pragma( pack(pop) )
#define TINS_PACKED(DECLARATION) __pragma( pack(push, 1) ) DECLARATION __pragma( pack(pop) )
#else
#define TINS_BEGIN_PACK
#define TINS_END_PACK __attribute__((packed))
#define TINS_PACKED(DECLARATION) DECLARATION __attribute__((packed))
#endif
#endif

292
include/packet.h Normal file
View File

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

View File

@@ -36,12 +36,15 @@
#include <vector>
#include <stdint.h>
#include <map>
#include "network_interface.h"
#include "macros.h"
struct timeval;
struct sockaddr;
namespace Tins {
class PDU;
/**
* \brief Class that enables sending the created PDUs
*
@@ -63,6 +66,7 @@ namespace Tins {
IP_SOCKET,
ARP_SOCKET,
ICMP_SOCKET,
IPV6_SOCKET,
SOCKETS_END
};
@@ -86,7 +90,7 @@ namespace Tins {
*
* If this operation fails, then a SocketOpenError will be thrown.
*/
void open_l2_socket();
void open_l2_socket(const NetworkInterface& iface = NetworkInterface());
#endif // WIN32
/**
@@ -113,7 +117,7 @@ namespace Tins {
*
* \param type The type of the socket to be closed.
*/
void close_socket(SocketType type);
void close_socket(SocketType type, const NetworkInterface &iface = NetworkInterface());
/**
* \brief Sends a PDU.
@@ -152,7 +156,8 @@ namespace Tins {
* \param len_addr The sockaddr struct length.
* \return Returns the response PDU. If no response is received, then 0 is returned.
*/
PDU *recv_l2(PDU &pdu, struct sockaddr *link_addr, uint32_t len_addr);
PDU *recv_l2(PDU &pdu, struct sockaddr *link_addr, uint32_t len_addr,
const NetworkInterface &iface = NetworkInterface());
/**
* \brief Sends a level 2 PDU.
@@ -167,7 +172,8 @@ namespace Tins {
* \param link_addr The sockaddr struct which will be used to send the PDU.
* \param len_addr The sockaddr struct length.
*/
void send_l2(PDU &pdu, struct sockaddr* link_addr, uint32_t len_addr);
void send_l2(PDU &pdu, struct sockaddr* link_addr, uint32_t len_addr,
const NetworkInterface &iface = NetworkInterface());
#endif // WIN32
/**
@@ -205,10 +211,22 @@ namespace Tins {
int find_type(SocketType type);
int timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y);
#ifndef WIN32
bool ether_socket_initialized(const NetworkInterface& iface = NetworkInterface()) const;
int get_ether_socket(const NetworkInterface& iface = NetworkInterface());
#endif
PDU *recv_match_loop(int sock, PDU &pdu, struct sockaddr* link_addr, uint32_t addrlen);
std::vector<int> _sockets;
#ifndef WIN32
#ifdef BSD
typedef std::map<uint32_t, int> BSDEtherSockets;
BSDEtherSockets _ether_socket;
#else
int _ether_socket;
#endif
#endif
SocketTypeMap _types;
uint32_t _timeout, _timeout_usec;
};
@@ -238,6 +256,6 @@ namespace Tins {
return "The provided socket type is invalid";
}
};
};
}
#endif // TINS_PACKET_SENDER_H

View File

@@ -34,6 +34,7 @@
#include <iterator>
#include <pcap.h>
#include "utils.h"
#include "cxxstd.h"
namespace Tins {
class PDU;
@@ -53,7 +54,8 @@ public:
enum LinkType {
RADIOTAP = DLT_IEEE802_11_RADIO,
DOT11 = DLT_IEEE802_11,
ETH2 = DLT_EN10MB
ETH2 = DLT_EN10MB,
SLL = DLT_LINUX_SLL
};
/**
@@ -64,6 +66,28 @@ public:
*/
PacketWriter(const std::string &file_name, LinkType lt);
#if TINS_IS_CXX11
/**
* \brief Move constructor.
*
* Note that calling PacketWriter::write on an previously moved
* object will lead to undefined behaviour.
*
* \param rhs The PacketWriter to be moved.
*/
PacketWriter(PacketWriter &&rhs) noexcept;
/**
* \brief Move assignment operator.
*
* Note that calling PacketWriter::write on an previously moved
* object will lead to undefined behaviour.
*
* \param rhs The PacketWriter to be moved.
*/
PacketWriter& operator=(PacketWriter &&rhs) noexcept;
#endif
/**
* Destructor.
*/

View File

@@ -101,7 +101,11 @@ namespace Tins {
RC4EAPOL,
RSNEAPOL,
DNS,
LOOPBACK
LOOPBACK,
IPv6,
ICMPv6,
SLL,
DHCPv6
};
/** \brief PDU constructor
@@ -195,6 +199,16 @@ namespace Tins {
}
return 0;
}
/**
* \brief Find and returns the first PDU that matches the given flag.
*
* \param flag The flag which being searched.
*/
template<class T>
const T *find_pdu(PDUType type = T::pdu_flag) const {
return const_cast<PDU*>(this)->find_pdu<T>();
}
/**
* \brief Clones this packet.
@@ -243,7 +257,7 @@ namespace Tins {
* classes' flag.
* \param flag The flag to match.
*/
virtual bool matches_flag(PDUType flag) {
virtual bool matches_flag(PDUType flag) const {
return flag == pdu_type();
}
@@ -350,6 +364,17 @@ namespace Tins {
lop /= rop;
return lop;
}
};
/**
* \brief Concatenation operator on PDU pointers.
*
* \sa operator/=
*/
template<typename T>
T *operator/= (T* lop, const PDU &rop) {
*lop /= rop;
return lop;
}
}
#endif // TINS_PDU_H

View File

@@ -115,7 +115,7 @@ public:
/**
* Forwards the call to the cached PDU. \sa PDU::matches_flag.
*/
bool matches_flag(PDUType flag) {
bool matches_flag(PDUType flag) const {
return cached.matches_flag(flag);
}

View File

@@ -104,6 +104,14 @@ public:
return option_;
}
/**
* Sets this option's type
* \param opt The option type to be set.
*/
void option(option_type opt) {
option_ = opt;
}
/**
* Retrieves this option's data.
*
@@ -111,7 +119,7 @@ public:
* dereferencing the returned pointer will result in undefined
* behaviour.
*
* \return const value_type& containing this option's value.
* \return const data_type& containing this option's value.
*/
const data_type *data_ptr() const {
return &*(++value_.begin());

View File

@@ -30,6 +30,7 @@
#ifndef TINS_RADIOTAP_H
#define TINS_RADIOTAP_H
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
#include "network_interface.h"
@@ -124,10 +125,12 @@ namespace Tins {
/* Setters */
#ifndef WIN32
/**
* \sa PDU::send()
*/
void send(PacketSender &sender);
#endif
/**
* \brief Setter for the version field.
@@ -316,6 +319,7 @@ namespace Tins {
*/
PDUType pdu_type() const { return PDU::RADIOTAP; }
private:
TINS_BEGIN_PACK
struct radiotap_hdr {
#if TINS_IS_LITTLE_ENDIAN
uint8_t it_version;
@@ -366,7 +370,7 @@ namespace Tins {
reserved4:7,
ext:1;
#endif
} __attribute__((__packed__));
} TINS_END_PACK;
void init();
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
@@ -380,6 +384,6 @@ namespace Tins {
uint16_t _channel_freq, _rx_flags;
uint8_t _antenna, _flags, _rate, _dbm_signal, _dbm_noise, _channel, _max_power;
};
};
}
#endif // TINS_RADIOTAP_H

View File

@@ -133,7 +133,7 @@ namespace Tins {
payload_type _payload;
};
};
}
#endif // TINS_RAWPDU_H

172
include/sll.h Normal file
View File

@@ -0,0 +1,172 @@
/*
* Copyright (c) 2012, Nasel
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_SLL_H
#define TINS_SLL_H
#include <vector>
#include "pdu.h"
#include "endianness.h"
#include "hw_address.h"
namespace Tins {
class SLL : public PDU {
public:
/**
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::SLL;
/**
* The type of the address type
*/
typedef HWAddress<8> address_type;
/**
* Default constructor
*/
SLL();
/**
* \brief Constructor which constructs an SLL 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.
*/
SLL(const uint8_t *buffer, uint32_t total_sz);
// Getters
/**
* \brief Getter for the packet_type field.
* \return The stored packet_type field value.
*/
uint16_t packet_type() const {
return Endian::be_to_host(_header.packet_type);
}
/**
* \brief Getter for the lladdr_type field.
* \return The stored lladdr_type field value.
*/
uint16_t lladdr_type() const {
return Endian::be_to_host(_header.lladdr_type);
}
/**
* \brief Getter for the lladdr_len field.
* \return The stored lladdr_len field value.
*/
uint16_t lladdr_len() const {
return Endian::be_to_host(_header.lladdr_len);
}
/**
* \brief Getter for the address field.
* \return The stored address field value.
*/
address_type address() const {
return _header.address;
}
/**
* \brief Getter for the protocol field.
* \return The stored protocol field value.
*/
uint16_t protocol() const {
return Endian::be_to_host(_header.protocol);
}
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
// Setters
/**
* \brief Setter for the packet_type field.
* \param new_packet_type The new packet_type field value.
*/
void packet_type(uint16_t new_packet_type);
/**
* \brief Setter for the lladdr_type field.
* \param new_lladdr_type The new lladdr_type field value.
*/
void lladdr_type(uint16_t new_lladdr_type);
/**
* \brief Setter for the lladdr_len field.
* \param new_lladdr_len The new lladdr_len field value.
*/
void lladdr_len(uint16_t new_lladdr_len);
/**
* \brief Setter for the address field.
* \param new_address The new address field value.
*/
void address(const address_type &new_address);
/**
* \brief Setter for the protocol field.
* \param new_protocol The new protocol field value.
*/
void protocol(uint16_t new_protocol);
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \sa PDU::clone
*/
SLL *clone() const {
return new SLL(*this);
}
private:
TINS_BEGIN_PACK
struct sllhdr {
uint16_t packet_type, lladdr_type, lladdr_len;
uint8_t address[8];
uint16_t protocol;
} TINS_END_PACK;
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
sllhdr _header;
};
}
#endif // TINS_SLL_H

View File

@@ -33,6 +33,7 @@
#include <stdint.h>
#include "pdu.h"
#include "macros.h"
#include "endianness.h"
#include "small_uint.h"
@@ -154,25 +155,18 @@ namespace Tins {
return new SNAP(*this);
}
private:
TINS_BEGIN_PACK
struct snaphdr {
uint8_t dsap;
uint8_t ssap;
/*#if TINS_IS_LITTLE_ENDIAN
uint32_t control:8,
org_code:24;
#elif TINS_IS_BIG_ENDIAN
uint32_t org_code:24,
control:8;
#endif*/
uint32_t control_org;
uint16_t eth_type;
} __attribute__((__packed__));
} TINS_END_PACK;
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
snaphdr _snap;
};
};
}
#endif // TINS_SNAP_H

View File

@@ -39,8 +39,11 @@
#include "pdu.h"
#include "ethernetII.h"
#include "radiotap.h"
#include "packet.h"
#include "loopback.h"
#include "dot11.h"
#include "sll.h"
#include "cxxstd.h"
namespace Tins {
/**
@@ -55,6 +58,20 @@ namespace Tins {
*/
class BaseSniffer {
public:
#if TINS_IS_CXX11
/**
* \brief Move constructor.
* This constructor is available only in C++11.
*/
BaseSniffer(BaseSniffer &&rhs) noexcept;
/**
* \brief Move assignment operator.
* This opeartor is available only in C++11.
*/
BaseSniffer& operator=(BaseSniffer &&rhs) noexcept;
#endif
/**
* \brief Sniffer destructor.
* This frees all memory used by the pcap handle.
@@ -67,29 +84,64 @@ namespace Tins {
* This method returns the first sniffed packet that matches the
* sniffer's filter, or the first sniffed packet if no filter has
* been set.
* \return The captured packet, matching the given filter, 0 if an
* error occured(probably compiling the filter).
*
* The return type is a thin wrapper over a PDU* and a Timestamp
* object. This wrapper can be both implicitly converted to a
* PDU* and a Packet object. So doing this:
*
* \code
* Sniffer s(...);
* std::unique_ptr<PDU> pdu(s.next_packet());
* // Packet takes care of the PDU*.
* Packet packet(s.next_packet());
* \endcode
*
* Is fine, but this:
*
* \code
* // bad!!
* PtrPacket p = s.next_packet();
*
* \endcode
*
* Is not, since PtrPacket can't be copy constructed.
*
* \sa Packet::release_pdu
*
* \return The captured packet, matching the given filter.
* If an error occured(probably compiling the filter), PtrPacket::pdu
* will return 0. Caller takes ownership of the PDU * stored in
* the PtrPacket.
*/
PDU *next_packet();
PtrPacket next_packet();
/**
* \brief Starts a sniffing loop, using a callback object for every
* sniffed packet.
*
* The callback object must implement an operator with the
* following(or compatible) signature:
* The callback object must implement an operator with some of
* the following(or compatible) signatures:
*
* \code
* bool operator()(PDU&);
* bool operator()(RefPacket&);
* \endcode
*
* This operator will be called using the sniffed packets
* as arguments. You can modify the PDU argument as you wish.
* as arguments. You can modify the parameter argument as you wish.
* Calling PDU methods like PDU::release_inner_pdu is perfectly
* valid.
*
* The callback taking a RefPacket will contain a timestamp
* indicating the moment in which the packet was taken out of
* the wire/pcap file.
*
* Note that the Functor object will be copied using its copy
* constructor, so that object should be some kind of proxy to
* another object which will process the packets(e.g. std::bind).
*
* \sa RefPacket
*
* \param cback_handler The callback handler object which should process packets.
* \param max_packets The maximum amount of packets to sniff. 0 == infinite.
*/
@@ -107,6 +159,11 @@ namespace Tins {
* \brief Stops sniffing loops.
*/
void stop_sniff();
/**
* \brief Gets the file descriptor associated with the sniffer.
*/
int get_fd();
protected:
/**
* Default constructor.
@@ -132,14 +189,15 @@ namespace Tins {
LoopData(pcap_t *_handle, const Functor _handler,
int if_type)
: handle(_handle), c_handler(_handler), iface_type(if_type) { }
: handle(_handle), c_handler(_handler), iface_type(if_type)
{ }
};
BaseSniffer(const BaseSniffer&);
BaseSniffer &operator=(const BaseSniffer&);
template<class ConcretePDU, class Functor>
static bool call_functor(LoopData<Functor> *data, const u_char *packet, size_t len);
static bool call_functor(LoopData<Functor> *data, const u_char *packet, const struct pcap_pkthdr *header);
bool compile_set_filter(const std::string &filter, bpf_program &prog);
@@ -199,9 +257,13 @@ namespace Tins {
}
template<class ConcretePDU, class Functor>
bool Tins::BaseSniffer::call_functor(LoopData<Functor> *data, const u_char *packet, size_t len) {
ConcretePDU some_pdu((const uint8_t*)packet, len);
return data->c_handler(some_pdu);
bool Tins::BaseSniffer::call_functor(LoopData<Functor> *data, const u_char *packet,
const struct pcap_pkthdr *header)
{
ConcretePDU some_pdu((const uint8_t*)packet, header->caplen);
Timestamp ts(header->ts);
RefPacket pck(some_pdu, ts);
return data->c_handler(pck);
}
template<class Functor>
@@ -211,21 +273,25 @@ namespace Tins {
LoopData<Functor> *data = reinterpret_cast<LoopData<Functor>*>(args);
bool ret_val(false);
if(data->iface_type == DLT_EN10MB)
ret_val = call_functor<Tins::EthernetII>(data, packet, header->caplen);
ret_val = 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->caplen);
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));
if(pdu.get())
ret_val = data->c_handler(*pdu);
if(pdu.get()) {
RefPacket pck(*pdu, header->ts);
ret_val = data->c_handler(pck);
}
}
else if(data->iface_type == DLT_NULL)
ret_val = call_functor<Tins::Loopback>(data, packet, header->caplen);
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(...) {
catch(std::runtime_error&) {
}
}
@@ -252,6 +318,6 @@ namespace Tins {
{
return HandlerProxy<T>(ptr, function);
}
};
}
#endif // TINS_SNIFFER_H

View File

@@ -37,6 +37,7 @@
#include <stdexcept>
#include <utility>
#include "pdu.h"
#include "macros.h"
#include "endianness.h"
#include "small_uint.h"
#include "pdu_option.h"
@@ -391,6 +392,7 @@ namespace Tins {
return new TCP(*this);
}
private:
TINS_BEGIN_PACK
struct tcphdr {
uint16_t sport;
uint16_t dport;
@@ -424,7 +426,7 @@ namespace Tins {
uint16_t window;
uint16_t check;
uint16_t urg_ptr;
} __attribute__((packed));
} TINS_END_PACK;
static const uint16_t DEFAULT_WINDOW;
@@ -444,6 +446,6 @@ namespace Tins {
options_type _options;
uint32_t _options_size, _total_options_size;
};
};
}
#endif // TINS_TCP_H

111
include/timestamp.h Normal file
View File

@@ -0,0 +1,111 @@
/*
* Copyright (c) 2012, Nasel
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_TIMESTAMP_H
#define TINS_TIMESTAMP_H
#ifdef WIN32
#define NOMINMAX
#include <winsock2.h>
#else
#include <sys/time.h>
#endif
#include "cxxstd.h"
#if TINS_IS_CXX11
#include <chrono>
#endif
namespace Tins {
/**
* \brief Represents a packet timestamp.
*/
class Timestamp {
public:
#ifdef WIN32
typedef long seconds_type;
typedef long microseconds_type;
#else
typedef time_t seconds_type;
typedef suseconds_t microseconds_type;
#endif
/**
* \brief Constructs a Timestamp which will hold the current time.
*/
static Timestamp current_time() {
#ifdef WIN32
//fixme
return Timestamp();
#else
timeval tv;
gettimeofday(&tv, 0);
return tv;
#endif
}
/**
* Default constructs the timestamp.
*/
Timestamp() : tv() {}
/**
* Constructs a timestamp from a timeval object.
* \param time_val The timeval object.
*/
Timestamp(const timeval &time_val) : tv(time_val) {}
/**
* Returns the amount of seconds in this timestamp.
*/
seconds_type seconds() const {
return tv.tv_sec;
}
/**
* Returns the amount of microseconds in this timestamp.
*/
microseconds_type microseconds() const {
return tv.tv_usec;
}
#if TINS_IS_CXX11
/**
* Converts this Timestamp to a std::chrono::microseconds
*/
operator std::chrono::microseconds() const {
return std::chrono::seconds(seconds()) +
std::chrono::microseconds(microseconds());
}
#endif
private:
timeval tv;
};
}
#endif // TINS_TIMESTAMP_H

View File

@@ -30,6 +30,7 @@
#ifndef TINS_TINS_H
#define TINS_TINS_H
#include "dns.h"
#include "arp.h"
#include "bootp.h"
#include "dhcp.h"
@@ -38,8 +39,10 @@
#include "ieee802_3.h"
#include "llc.h"
#include "icmp.h"
#include "icmpv6.h"
#include "dot11.h"
#include "ip.h"
#include "ipv6.h"
#include "packet_sender.h"
#include "packet_writer.h"
#include "pdu.h"
@@ -50,10 +53,15 @@
#include "tcp.h"
#include "udp.h"
#include "utils.h"
#include "dns.h"
#include "tcp_stream.h"
#include "crypto.h"
#include "pdu_cacher.h"
#include "rsn_information.h"
#include "ipv6_address.h"
#include "ip_address.h"
#include "packet.h"
#include "timestamp.h"
#include "sll.h"
#include "dhcpv6.h"
#endif // TINS_TINS_H

View File

@@ -30,7 +30,7 @@
#ifndef TINS_UDP_H
#define TINS_UDP_H
#include "macros.h"
#include "pdu.h"
#include "endianness.h"
@@ -123,18 +123,19 @@ namespace Tins {
return new UDP(*this);
}
private:
TINS_BEGIN_PACK
struct udphdr {
uint16_t sport;
uint16_t dport;
uint16_t len;
uint16_t check;
} __attribute__((packed));
} TINS_END_PACK;
void copy_fields(const UDP *other);
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
udphdr _udp;
};
};
}
#endif // TINS_UDP_H

View File

@@ -33,16 +33,30 @@
#ifndef WIN32
#include <ifaddrs.h>
#else
#define NOMINMAX
#include <winsock2.h>
#include <iphlpapi.h>
#undef interface
#endif
#include "macros.h"
#ifdef BSD
#include <sys/file.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/route.h>
#include <netinet/in.h>
#endif
#include <string>
#include <set>
#include <fstream>
#include <vector>
#include <stdint.h>
#include "ip_address.h"
#include "ipv6_address.h"
#include "hw_address.h"
#include "internals.h"
namespace Tins {
class NetworkInterface;
@@ -190,6 +204,16 @@ namespace Tins {
* \return The pseudo header checksum.
*/
uint32_t pseudoheader_checksum(IPv4Address source_ip, IPv4Address dest_ip, uint32_t len, uint32_t flag);
/** \brief Performs the pseudo header checksum used in TCP and UDP PDUs.
*
* \param source_ip The source ip address.
* \param dest_ip The destination ip address.
* \param len The length to be included in the pseudo header.
* \param flag The flag to use in the protocol field of the pseudo header.
* \return The pseudo header checksum.
*/
uint32_t pseudoheader_checksum(IPv6Address source_ip, IPv6Address dest_ip, uint32_t len, uint32_t flag);
/** \brief Generic function to iterate through interface and collect
* data.
@@ -228,27 +252,6 @@ namespace Tins {
}
#endif // WIN32
/**
* \cond
*/
namespace Internals {
void skip_line(std::istream &input);
bool from_hex(const std::string &str, uint32_t &result);
template<bool, typename>
struct enable_if {
};
template<typename T>
struct enable_if<true, T> {
typedef T type;
};
}
/**
* \endcond
*/
template <typename T>
struct is_pdu {
template <typename U>
@@ -280,12 +283,101 @@ namespace Tins {
dereference_until_pdu(T &value) {
return dereference_until_pdu(*value);
}
#ifdef BSD
inline std::vector<char> query_route_table() {
int mib[6];
std::vector<char> buf;
size_t len;
mib[0] = CTL_NET;
mib[1] = AF_ROUTE;
mib[2] = 0;
mib[3] = AF_INET;
mib[4] = NET_RT_DUMP;
mib[5] = 0;
if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
throw std::runtime_error("sysctl failed");
buf.resize(len);
if (sysctl(mib, 6, &buf[0], &len, NULL, 0) < 0) {
throw std::runtime_error("sysctl failed");
}
return buf;
}
template<typename ForwardIterator>
void parse_header(struct rt_msghdr *rtm, ForwardIterator iter)
{
char *ptr = (char *)(rtm + 1);
sockaddr *sa = 0;
for (int i = 0; i < RTAX_MAX; i++) {
if (rtm->rtm_addrs & (1 << i)) {
sa = (struct sockaddr *)ptr;
ptr += sa->sa_len;
if (sa->sa_family == 0)
sa = 0;
}
*iter++ = sa;
}
}
#endif
}
}
#ifdef BSD
template<class ForwardIterator>
void Tins::Utils::route_entries(ForwardIterator output) {
using namespace Utils::Internals;
std::vector<char> buffer = query_route_table();
char *next = &buffer[0], *end = &buffer[buffer.size()];
rt_msghdr *rtm;
std::vector<sockaddr*> sa(RTAX_MAX);
char iface_name[IF_NAMESIZE];
while(next < end) {
rtm = (rt_msghdr*)next;
parse_header(rtm, sa.begin());
if (sa[RTAX_DST] && sa[RTAX_GATEWAY] && if_indextoname(rtm->rtm_index, iface_name)) {
RouteEntry entry;
entry.destination = IPv4Address(((struct sockaddr_in *)sa[RTAX_DST])->sin_addr.s_addr);
entry.gateway = IPv4Address(((struct sockaddr_in *)sa[RTAX_GATEWAY])->sin_addr.s_addr);
if(sa[RTAX_GENMASK])
entry.mask = IPv4Address(((struct sockaddr_in *)sa[RTAX_GENMASK])->sin_addr.s_addr);
else
entry.mask = IPv4Address(uint32_t());
entry.interface = iface_name;
*output++ = entry;
}
next += rtm->rtm_msglen;
}
}
#elif defined(WIN32)
template<class ForwardIterator>
void Tins::Utils::route_entries(ForwardIterator output) {
MIB_IPFORWARDTABLE *table;
ULONG size = 0;
char iface_name[256];
GetIpForwardTable(0, &size, 0);
std::vector<uint8_t> buffer(size);
table = (MIB_IPFORWARDTABLE*)&buffer[0];
GetIpForwardTable(table, &size, 0);
for (DWORD i = 0; i < table->dwNumEntries; i++) {
MIB_IPFORWARDROW *row = &table->table[i];
if(row->dwForwardType == MIB_IPROUTE_TYPE_INDIRECT) {
if_indextoname(row->dwForwardIfIndex, iface_name);
RouteEntry entry;
entry.interface = iface_name;
entry.destination = IPv4Address(row->dwForwardDest);
entry.mask = IPv4Address(row->dwForwardMask);
entry.gateway = IPv4Address(row->dwForwardNextHop);
*output++ = entry;
}
}
}
#else
template<class ForwardIterator>
void Tins::Utils::route_entries(ForwardIterator output) {
using namespace Tins::Internals;
std::ifstream input("/proc/net/route");
std::string destination, mask, gw;
uint32_t dummy;
@@ -305,5 +397,6 @@ void Tins::Utils::route_entries(ForwardIterator output) {
++output;
}
}
#endif
#endif // TINS_UTILS_H

527
install-sh Executable file
View File

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

11
libtins.pc.in Normal file
View File

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

9661
ltmain.sh Normal file

File diff suppressed because it is too large Load Diff

1
m4/libtool.m4 vendored Symbolic link
View File

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

1
m4/ltoptions.m4 vendored Symbolic link
View File

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

1
m4/ltsugar.m4 vendored Symbolic link
View File

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

1
m4/ltversion.m4 vendored Symbolic link
View File

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

1
m4/lt~obsolete.m4 vendored Symbolic link
View File

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

331
missing Executable file
View File

@@ -0,0 +1,331 @@
#! /bin/sh
# Common stub for a few missing GNU programs while installing.
scriptversion=2012-01-06.13; # UTC
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
# 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
if test $# -eq 0; then
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
fi
run=:
sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
# In the cases where this matters, `missing' is being run in the
# srcdir already.
if test -f configure.ac; then
configure_ac=configure.ac
else
configure_ac=configure.in
fi
msg="missing on your system"
case $1 in
--run)
# Try to run requested program, and just exit if it succeeds.
run=
shift
"$@" && exit 0
# Exit code 63 means version mismatch. This often happens
# when the user try to use an ancient version of a tool on
# a file that requires a minimum version. In this case we
# we should proceed has if the program had been absent, or
# if --run hadn't been passed.
if test $? = 63; then
run=:
msg="probably too old"
fi
;;
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
error status if there is no known handling for PROGRAM.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
--run try to run the given command, and emulate it if it fails
Supported PROGRAM values:
aclocal touch file \`aclocal.m4'
autoconf touch file \`configure'
autoheader touch file \`config.h.in'
autom4te touch the output file, or create a stub one
automake touch all \`Makefile.in' files
bison create \`y.tab.[ch]', if possible, from existing .[ch]
flex create \`lex.yy.c', if possible, from existing .c
help2man touch the output file
lex create \`lex.yy.c', if possible, from existing .c
makeinfo touch the output file
yacc create \`y.tab.[ch]', if possible, from existing .[ch]
Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and
\`g' are ignored when checking the name.
Send bug reports to <bug-automake@gnu.org>."
exit $?
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing $scriptversion (GNU Automake)"
exit $?
;;
-*)
echo 1>&2 "$0: Unknown \`$1' option"
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
;;
esac
# normalize program name to check for.
program=`echo "$1" | sed '
s/^gnu-//; t
s/^gnu//; t
s/^g//; t'`
# Now exit if we have it, but it failed. Also exit now if we
# don't have it and --version was passed (most likely to detect
# the program). This is about non-GNU programs, so use $1 not
# $program.
case $1 in
lex*|yacc*)
# Not GNU programs, they don't have --version.
;;
*)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
# Could not run --version or --help. This is probably someone
# running `$TOOL --version' or `$TOOL --help' to check whether
# $TOOL exists and not knowing $TOOL uses missing.
exit 1
fi
;;
esac
# If it does not exist, or fails to run (possibly an outdated version),
# try to emulate it.
case $program in
aclocal*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`acinclude.m4' or \`${configure_ac}'. You might want
to install the \`Automake' and \`Perl' packages. Grab them from
any GNU archive site."
touch aclocal.m4
;;
autoconf*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`${configure_ac}'. You might want to install the
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
archive site."
touch configure
;;
autoheader*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`acconfig.h' or \`${configure_ac}'. You might want
to install the \`Autoconf' and \`GNU m4' packages. Grab them
from any GNU archive site."
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
test -z "$files" && files="config.h"
touch_files=
for f in $files; do
case $f in
*:*) touch_files="$touch_files "`echo "$f" |
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
*) touch_files="$touch_files $f.in";;
esac
done
touch $touch_files
;;
automake*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
You might want to install the \`Automake' and \`Perl' packages.
Grab them from any GNU archive site."
find . -type f -name Makefile.am -print |
sed 's/\.am$/.in/' |
while read f; do touch "$f"; done
;;
autom4te*)
echo 1>&2 "\
WARNING: \`$1' is needed, but is $msg.
You might have modified some files without having the
proper tools for further handling them.
You can get \`$1' as part of \`Autoconf' from any GNU
archive site."
file=`echo "$*" | sed -n "$sed_output"`
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
if test -f "$file"; then
touch $file
else
test -z "$file" || exec >$file
echo "#! /bin/sh"
echo "# Created by GNU Automake missing as a replacement of"
echo "# $ $@"
echo "exit 0"
chmod +x $file
exit 1
fi
;;
bison*|yacc*)
echo 1>&2 "\
WARNING: \`$1' $msg. You should only need it if
you modified a \`.y' file. You may need the \`Bison' package
in order for those modifications to take effect. You can get
\`Bison' from any GNU archive site."
rm -f y.tab.c y.tab.h
if test $# -ne 1; then
eval LASTARG=\${$#}
case $LASTARG in
*.y)
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
if test -f "$SRCFILE"; then
cp "$SRCFILE" y.tab.c
fi
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
if test -f "$SRCFILE"; then
cp "$SRCFILE" y.tab.h
fi
;;
esac
fi
if test ! -f y.tab.h; then
echo >y.tab.h
fi
if test ! -f y.tab.c; then
echo 'main() { return 0; }' >y.tab.c
fi
;;
lex*|flex*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified a \`.l' file. You may need the \`Flex' package
in order for those modifications to take effect. You can get
\`Flex' from any GNU archive site."
rm -f lex.yy.c
if test $# -ne 1; then
eval LASTARG=\${$#}
case $LASTARG in
*.l)
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
if test -f "$SRCFILE"; then
cp "$SRCFILE" lex.yy.c
fi
;;
esac
fi
if test ! -f lex.yy.c; then
echo 'main() { return 0; }' >lex.yy.c
fi
;;
help2man*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified a dependency of a manual page. You may need the
\`Help2man' package in order for those modifications to take
effect. You can get \`Help2man' from any GNU archive site."
file=`echo "$*" | sed -n "$sed_output"`
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
if test -f "$file"; then
touch $file
else
test -z "$file" || exec >$file
echo ".ab help2man is required to generate this page"
exit $?
fi
;;
makeinfo*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified a \`.texi' or \`.texinfo' file, or any other file
indirectly affecting the aspect of the manual. The spurious
call might also be the consequence of using a buggy \`make' (AIX,
DU, IRIX). You might want to install the \`Texinfo' package or
the \`GNU make' package. Grab either from any GNU archive site."
# The file to touch is that specified with -o ...
file=`echo "$*" | sed -n "$sed_output"`
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
if test -z "$file"; then
# ... or it is the one specified with @setfilename ...
infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
file=`sed -n '
/^@setfilename/{
s/.* \([^ ]*\) *$/\1/
p
q
}' $infile`
# ... or it is derived from the source name (dir/f.texi becomes f.info)
test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
fi
# If the file does not exist, the user really needs makeinfo;
# let's fail without touching anything.
test -f $file || exit 1
touch $file
;;
*)
echo 1>&2 "\
WARNING: \`$1' is needed, and is $msg.
You might have modified some files without having the
proper tools for further handling them. Check the \`README' file,
it often tells you about the needed prerequisites for installing
this package. You may also peek at any GNU archive site, in case
some other package would contain this missing \`$1' program."
exit 1
;;
esac
exit 0
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

646
src/dhcpv6.cpp Normal file
View File

@@ -0,0 +1,646 @@
/*
* Copyright (c) 2012, Nasel
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <iostream> //borrame
#include <vector>
#include <algorithm>
#include "dhcpv6.h"
namespace Tins {
DHCPv6::DHCPv6() : options_size() {
std::fill(header_data, header_data + sizeof(header_data), 0);
}
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);
// 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);
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);
link_addr = buffer;
peer_addr = buffer + ipaddress_type::address_size;
buffer += ipaddress_type::address_size * 2;
total_sz -= ipaddress_type::address_size * 2;
}
options_size = total_sz;
while(total_sz) {
if(total_sz < sizeof(uint16_t) * 2)
throw std::runtime_error(opt_err_msg);
const uint16_t option = 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);
buffer += sizeof(uint16_t) * 2;
add_option(
dhcpv6_option(option, 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);
}
const DHCPv6::dhcpv6_option *DHCPv6::search_option(Option id) const {
for(options_type::const_iterator it = options_.begin(); it != options_.end(); ++it) {
if(it->option() == static_cast<uint16_t>(id))
return &*it;
}
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());
return std::copy(
option.data_ptr(),
option.data_ptr() + option.data_size(),
buffer + sizeof(uint16_t) * 2
);
}
void DHCPv6::msg_type(MessageType type) {
header_data[0] = static_cast<uint8_t>(type);
}
void DHCPv6::hop_count(uint8_t count) {
header_data[1] = count;
}
void DHCPv6::transaction_id(small_uint<24> id) {
uint32_t id_32 = id;
header_data[1] = id_32 >> 16;
header_data[2] = id_32 >> 8;
header_data[3] = id_32 & 0xff;
}
void DHCPv6::peer_address(const ipaddress_type &addr) {
peer_addr = addr;
}
void DHCPv6::link_address(const ipaddress_type &addr) {
link_addr = addr;
}
bool DHCPv6::is_relay_message() const {
return msg_type() == 12 || msg_type() == 13;
}
uint32_t DHCPv6::header_size() const {
return (is_relay_message() ? (2 + ipaddress_type::address_size * 2) : 4) + options_size;
}
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);
if(is_relay_message()) {
buffer = link_addr.copy(buffer);
buffer = peer_addr.copy(buffer);
}
for(options_type::const_iterator it = options_.begin(); it != options_.end(); ++it)
buffer = write_option(*it, buffer);
}
// ********************************************************************
// Option getters
// ********************************************************************
DHCPv6::ia_na_type DHCPv6::ia_na() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
IA_NA, sizeof(uint32_t) * 3
);
const uint8_t *ptr = opt->data_ptr() + sizeof(uint32_t) * 3;
const uint32_t *ptr_32 = (const uint32_t*)opt->data_ptr();
DHCPv6::ia_na_type output;
output.id = Endian::be_to_host(*ptr_32++);
output.t1 = Endian::be_to_host(*ptr_32++);
output.t2 = Endian::be_to_host(*ptr_32++);
output.options.assign(ptr, opt->data_ptr() + opt->data_size());
return output;
}
DHCPv6::ia_ta_type DHCPv6::ia_ta() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
IA_TA, sizeof(uint32_t)
);
const uint8_t *ptr = opt->data_ptr() + sizeof(uint32_t);
const uint32_t *ptr_32 = (const uint32_t*)opt->data_ptr();
DHCPv6::ia_ta_type output;
output.id = Endian::be_to_host(*ptr_32++);
output.options.assign(ptr, opt->data_ptr() + opt->data_size());
return output;
}
DHCPv6::ia_address_type DHCPv6::ia_address() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
IA_ADDR, sizeof(uint32_t) * 2 + ipaddress_type::address_size
);
const uint8_t *ptr = opt->data_ptr() + sizeof(uint32_t) * 2 + ipaddress_type::address_size;
const uint32_t *ptr_32 = (const uint32_t*)(opt->data_ptr() + ipaddress_type::address_size);
DHCPv6::ia_address_type output;
output.address = opt->data_ptr();
output.preferred_lifetime = Endian::be_to_host(*ptr_32++);
output.valid_lifetime = Endian::be_to_host(*ptr_32++);
output.options.assign(ptr, opt->data_ptr() + opt->data_size());
return output;
}
DHCPv6::option_request_type DHCPv6::option_request() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
OPTION_REQUEST, 2
);
const uint16_t *ptr = (const uint16_t*)opt->data_ptr(),
*end = (const uint16_t*)(opt->data_ptr() + opt->data_size());
option_request_type output;
while(ptr < end) {
output.push_back(
static_cast<Option>(Endian::be_to_host(*ptr++))
);
}
return output;
}
uint8_t DHCPv6::preference() const {
const dhcpv6_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>(
ELAPSED_TIME, 2
);
return Endian::be_to_host(
*(const uint16_t*)opt->data_ptr()
);
}
DHCPv6::relay_msg_type DHCPv6::relay_message() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
RELAY_MSG, 1
);
return relay_msg_type(
opt->data_ptr(),
opt->data_ptr() + opt->data_size()
);
}
DHCPv6::authentication_type DHCPv6::authentication() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
AUTH, sizeof(uint8_t) * 3 + sizeof(uint64_t)
);
const uint8_t *ptr = opt->data_ptr();
authentication_type output;
output.protocol = *ptr++;
output.algorithm = *ptr++;
output.rdm = *ptr++;
output.replay_detection = Endian::be_to_host(
*(const uint64_t*)ptr
);
ptr += sizeof(uint64_t);
output.auth_info.assign(ptr, opt->data_ptr() + opt->data_size());
return output;
}
DHCPv6::ipaddress_type DHCPv6::server_unicast() const {
const dhcpv6_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>(
STATUS_CODE, sizeof(uint16_t)
);
status_code_type output;
output.code = Endian::be_to_host(*(const uint16_t*)opt->data_ptr());
output.message.assign(
opt->data_ptr() + sizeof(uint16_t),
opt->data_ptr() + opt->data_size()
);
return output;
}
bool DHCPv6::has_rapid_commit() const {
return search_option(RAPID_COMMIT);
}
DHCPv6::user_class_type DHCPv6::user_class() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
USER_CLASS, sizeof(uint16_t)
);
return option2class_option_data<user_class_type>(
opt->data_ptr(), opt->data_size()
);
}
DHCPv6::vendor_class_type DHCPv6::vendor_class() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
VENDOR_CLASS, sizeof(uint32_t)
);
typedef vendor_class_type::class_data_type data_type;
vendor_class_type output;
output.enterprise_number = Endian::be_to_host(
*(const uint32_t*)opt->data_ptr()
);
output.vendor_class_data = option2class_option_data<data_type>(
opt->data_ptr() + sizeof(uint32_t),
opt->data_size() - sizeof(uint32_t)
);
return output;
}
DHCPv6::vendor_info_type DHCPv6::vendor_info() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
VENDOR_OPTS, sizeof(uint32_t)
);
vendor_info_type output;
output.enterprise_number = Endian::be_to_host(
*(const uint32_t*)opt->data_ptr()
);
output.data.assign(
opt->data_ptr() + sizeof(uint32_t),
opt->data_ptr() + opt->data_size()
);
return output;
}
DHCPv6::interface_id_type DHCPv6::interface_id() const {
const dhcpv6_option *opt = safe_search_option<std::equal_to>(
INTERFACE_ID, 0
);
return interface_id_type(
opt->data_ptr(),
opt->data_ptr() + opt->data_size()
);
}
uint8_t DHCPv6::reconfigure_msg() const {
return *safe_search_option<std::not_equal_to>(
RECONF_MSG, 1
)->data_ptr();
}
bool DHCPv6::has_reconfigure_accept() const {
return search_option(RECONF_ACCEPT);
}
DHCPv6::duid_type DHCPv6::client_id() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
CLIENTID, sizeof(uint16_t) + 1
);
return duid_type(
Endian::be_to_host(*(const uint16_t*)opt->data_ptr()),
serialization_type(
opt->data_ptr() + sizeof(uint16_t),
opt->data_ptr() + opt->data_size()
)
);
}
DHCPv6::duid_type DHCPv6::server_id() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
SERVERID, sizeof(uint16_t) + 1
);
return duid_type(
Endian::be_to_host(*(const uint16_t*)opt->data_ptr()),
serialization_type(
opt->data_ptr() + sizeof(uint16_t),
opt->data_ptr() + opt->data_size()
)
);
}
// ********************************************************************
// Option setters
// ********************************************************************
void DHCPv6::ia_na(const ia_na_type &value) {
std::vector<uint8_t> buffer(sizeof(uint32_t) * 3 + value.options.size());
uint32_t *ptr = (uint32_t*)&buffer[0];
*ptr++ = Endian::host_to_be(value.id);
*ptr++ = Endian::host_to_be(value.t1);
*ptr++ = Endian::host_to_be(value.t2);
std::copy(
value.options.begin(),
value.options.end(),
buffer.begin() + sizeof(uint32_t) * 3
);
add_option(
dhcpv6_option(IA_NA, buffer.begin(), buffer.end())
);
}
void DHCPv6::ia_ta(const ia_ta_type &value) {
std::vector<uint8_t> buffer(sizeof(uint32_t) + value.options.size());
uint32_t *ptr = (uint32_t*)&buffer[0];
*ptr++ = Endian::host_to_be(value.id);
std::copy(
value.options.begin(),
value.options.end(),
buffer.begin() + sizeof(uint32_t)
);
add_option(
dhcpv6_option(IA_TA, buffer.begin(), buffer.end())
);
}
void DHCPv6::ia_address(const ia_address_type &value) {
std::vector<uint8_t> buffer(
sizeof(uint32_t) * 2 + ipaddress_type::address_size + value.options.size()
);
uint32_t *ptr = (uint32_t*)&buffer[ipaddress_type::address_size];
value.address.copy(&buffer[0]);
*ptr++ = Endian::host_to_be(value.preferred_lifetime);
*ptr++ = Endian::host_to_be(value.valid_lifetime);
std::copy(
value.options.begin(),
value.options.end(),
buffer.begin() + sizeof(uint32_t) * 2 + ipaddress_type::address_size
);
add_option(
dhcpv6_option(IA_ADDR, buffer.begin(), buffer.end())
);
}
void DHCPv6::option_request(const option_request_type &value) {
typedef option_request_type::const_iterator iterator;
std::vector<uint8_t> buffer(value.size() * sizeof(uint16_t));
size_t index = 0;
for(iterator it = value.begin(); it != value.end(); ++it, index += 2)
*(uint16_t*)&buffer[index] = Endian::host_to_be<uint16_t>(*it);
add_option(
dhcpv6_option(OPTION_REQUEST, buffer.begin(), buffer.end())
);
}
void DHCPv6::preference(uint8_t value) {
add_option(
dhcpv6_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)
);
}
void DHCPv6::relay_message(const relay_msg_type &value) {
add_option(
dhcpv6_option(RELAY_MSG, value.begin(), value.end())
);
}
void DHCPv6::authentication(const authentication_type &value) {
std::vector<uint8_t> buffer(
sizeof(uint8_t) * 3 + sizeof(uint64_t) + value.auth_info.size()
);
buffer[0] = value.protocol;
buffer[1] = value.algorithm;
buffer[2] = value.rdm;
*(uint64_t*)&buffer[3] = Endian::host_to_be(value.replay_detection);
std::copy(
value.auth_info.begin(),
value.auth_info.end(),
buffer.begin() + sizeof(uint8_t) * 3 + sizeof(uint64_t)
);
add_option(
dhcpv6_option(AUTH, buffer.begin(), buffer.end())
);
}
void DHCPv6::server_unicast(const ipaddress_type &value) {
add_option(
dhcpv6_option(UNICAST, value.begin(), value.end())
);
}
void DHCPv6::status_code(const status_code_type &value) {
std::vector<uint8_t> buffer(sizeof(uint16_t) + value.message.size());
*(uint16_t*)&buffer[0] = Endian::host_to_be(value.code);
std::copy(
value.message.begin(),
value.message.end(),
buffer.begin() + sizeof(uint16_t)
);
add_option(
dhcpv6_option(STATUS_CODE, buffer.begin(), buffer.end())
);
}
void DHCPv6::rapid_commit() {
add_option(
RAPID_COMMIT
);
}
void DHCPv6::user_class(const user_class_type &value) {
typedef user_class_type::const_iterator iterator;
std::vector<uint8_t> buffer;
class_option_data2option(value.begin(), value.end(), buffer);
add_option(
dhcpv6_option(USER_CLASS, buffer.begin(), buffer.end())
);
}
void DHCPv6::vendor_class(const vendor_class_type &value) {
std::vector<uint8_t> buffer(
sizeof(uint32_t)
);
*(uint32_t*)&buffer[0] = Endian::host_to_be(value.enterprise_number);
class_option_data2option(
value.vendor_class_data.begin(),
value.vendor_class_data.end(),
buffer,
sizeof(uint32_t)
);
add_option(
dhcpv6_option(VENDOR_CLASS, buffer.begin(), buffer.end())
);
}
void DHCPv6::vendor_info(const vendor_info_type &value) {
std::vector<uint8_t> buffer(sizeof(uint32_t) + value.data.size());
*(uint32_t*)&buffer[0] = Endian::host_to_be(value.enterprise_number);
std::copy(
value.data.begin(),
value.data.end(),
buffer.begin() + sizeof(uint32_t)
);
add_option(
dhcpv6_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())
);
}
void DHCPv6::reconfigure_msg(uint8_t value) {
add_option(
dhcpv6_option(RECONF_MSG, 1, &value)
);
}
void DHCPv6::reconfigure_accept() {
add_option(RECONF_ACCEPT);
}
// DUIDs
DHCPv6::duid_llt DHCPv6::duid_llt::from_bytes(const uint8_t *buffer, uint32_t total_sz)
{
// at least one byte for lladdress
if(total_sz < sizeof(uint16_t) + sizeof(uint32_t) + 1)
throw std::runtime_error("Not enough size for a DUID_LLT identifier");
duid_llt output;
output.hw_type = Endian::be_to_host(*(const uint16_t*)buffer);
buffer += sizeof(uint16_t);
output.time = Endian::be_to_host(*(const uint32_t*)buffer);
buffer += sizeof(uint32_t);
total_sz -= sizeof(uint16_t) + sizeof(uint32_t);
output.lladdress.assign(buffer, buffer + total_sz);
return output;
}
PDU::serialization_type DHCPv6::duid_llt::serialize() const {
serialization_type output(sizeof(uint16_t) + sizeof(uint32_t) + lladdress.size());
*(uint16_t*)&output[0] = Endian::host_to_be(hw_type);
*(uint32_t*)&output[sizeof(uint16_t)] = Endian::host_to_be(time);
std::copy(
lladdress.begin(),
lladdress.end(),
output.begin() + sizeof(uint16_t) + sizeof(uint32_t)
);
return output;
}
DHCPv6::duid_en DHCPv6::duid_en::from_bytes(const uint8_t *buffer, uint32_t total_sz)
{
// at least one byte for identifier
if(total_sz < sizeof(uint32_t) + 1)
throw std::runtime_error("Not enough size for a DUID_en identifier");
duid_en output;
output.enterprise_number = Endian::be_to_host(*(const uint32_t*)buffer);
buffer += sizeof(uint32_t);
total_sz -= sizeof(uint32_t);
output.identifier.assign(buffer, buffer + total_sz);
return output;
}
PDU::serialization_type DHCPv6::duid_en::serialize() const {
serialization_type output(sizeof(uint32_t) + identifier.size());
*(uint32_t*)&output[0] = Endian::host_to_be(enterprise_number);
std::copy(
identifier.begin(),
identifier.end(),
output.begin() + sizeof(uint32_t)
);
return output;
}
DHCPv6::duid_ll DHCPv6::duid_ll::from_bytes(const uint8_t *buffer, uint32_t total_sz)
{
// at least one byte for lladdress
if(total_sz < sizeof(uint16_t) + 1)
throw std::runtime_error("Not enough size for a DUID_en identifier");
duid_ll output;
output.hw_type = Endian::be_to_host(*(const uint16_t*)buffer);
buffer += sizeof(uint16_t);
total_sz -= sizeof(uint16_t);
output.lladdress.assign(buffer, buffer + total_sz);
return output;
}
PDU::serialization_type DHCPv6::duid_ll::serialize() const {
serialization_type output(sizeof(uint16_t) + lladdress.size());
*(uint16_t*)&output[0] = Endian::host_to_be(hw_type);
std::copy(
lladdress.begin(),
lladdress.end(),
output.begin() + sizeof(uint16_t)
);
return output;
}
void DHCPv6::client_id(const duid_type &value) {
serialization_type buffer(sizeof(uint16_t) + value.data.size());
*(uint16_t*)&buffer[0] = Endian::host_to_be(value.id);
std::copy(
value.data.begin(),
value.data.end(),
buffer.begin() + sizeof(uint16_t)
);
add_option(
dhcpv6_option(CLIENTID, buffer.begin(), buffer.end())
);
}
void DHCPv6::server_id(const duid_type &value) {
serialization_type buffer(sizeof(uint16_t) + value.data.size());
*(uint16_t*)&buffer[0] = Endian::host_to_be(value.id);
std::copy(
value.data.begin(),
value.data.end(),
buffer.begin() + sizeof(uint16_t)
);
add_option(
dhcpv6_option(SERVERID, buffer.begin(), buffer.end())
);
}
} // namespace Tins

View File

@@ -30,9 +30,11 @@
#include <utility>
#include <stdexcept>
#include <cassert>
#include <sstream>
#include <memory>
#include "dns.h"
#include "ip_address.h"
#include "ipv6_address.h"
using std::string;
using std::list;
@@ -165,6 +167,13 @@ void DNS::add_answer(const string &name, const DNSResourceRecord::info &info,
dns.answers = Endian::host_to_be<uint16_t>(ans.size());
}
void DNS::add_answer(const string &name, const DNSResourceRecord::info &info,
address_v6_type ip)
{
ans.push_back(make_record(name, info, ip.begin(), address_v6_type::address_size));
dns.answers = Endian::host_to_be<uint16_t>(ans.size());
}
void DNS::add_answer(const std::string &name, const DNSResourceRecord::info &info,
const std::string &dname)
{
@@ -326,7 +335,7 @@ void DNS::add_suffix(uint32_t index, const uint8_t *data, uint32_t sz) const {
uint32_t DNS::build_suffix_map(uint32_t index, const ResourcesType &lst) const {
const string *str;
for(ResourcesType::const_iterator it(lst.begin()); it != lst.end(); ++it) {
str = it->dname();
str = it->has_domain_name() ? it->dname() : 0;
if(str) {
add_suffix(index, (uint8_t*)str->c_str(), str->size());
index += str->size() + 1;
@@ -374,7 +383,9 @@ void DNS::compose_name(const uint8_t *ptr, uint32_t sz, std::string &out) const
index &= 0x3fff;
SuffixMap::iterator it(suffixes.find(index));
SuffixIndices::iterator suff_it(suffix_indices.find(index));
if(it == suffixes.end() || suff_it == suffix_indices.end())
// 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");
bool first(true);
do {
@@ -427,7 +438,13 @@ void DNS::convert_resources(const ResourcesType &lst, std::list<Resource> &res)
ptr += 2;
sz -= 2;
}
compose_name(ptr, sz, addr);
if(Endian::be_to_host(it->information().type) == DNS::AAAA) {
if(sz != 16)
throw std::runtime_error("Malformed IPv6 address");
addr = IPv6Address(ptr).to_string();
}
else
compose_name(ptr, sz, addr);
}
res.push_back(
Resource(dname, addr, Endian::be_to_host(it->information().type),

View File

@@ -37,8 +37,10 @@
namespace Tins {
bool contains_dname(uint16_t type) {
type = Endian::be_to_host(type);
return type == 15 || type == 5 ||
type == 12 || type == 2;
return type == 1 || type == 2 ||
type == 5 || type == 6 ||
type == 12 || type == 15 ||
type == 28 || type == 41;
}
DNSResourceRecord::DNSResourceRecord(DNSRRImpl *impl,
@@ -82,12 +84,10 @@ 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");
if(contains_dname(info_.type))
if(contains_dname(info_.type) || data.size() != sizeof(uint32_t))
std::copy(buffer, buffer + data.size(), data.begin());
else if(data.size() == sizeof(uint32_t))
*(uint32_t*)&data[0] = *(uint32_t*)buffer;
else
throw std::runtime_error("Not enough size for resource data");
impl = tmp_impl.release();
}
@@ -106,6 +106,24 @@ 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;
}
@@ -156,7 +174,7 @@ bool DNSResourceRecord::matches(const std::string &dname) const {
// OffsetedRecord
OffsetedDNSRRImpl::OffsetedDNSRRImpl(uint16_t off)
: offset_(off | 0xc0)
: offset_(off | Endian::host_to_be<uint16_t>(0xc000))
{
}
@@ -191,7 +209,8 @@ uint32_t NamedDNSRRImpl::size() const {
}
uint32_t NamedDNSRRImpl::do_write(uint8_t *buffer) const {
std::copy(name.begin(), name.end() + 1, buffer);
buffer = std::copy(name.begin(), name.end(), buffer);
*buffer = 0;
return name.size() + 1;
}

View File

@@ -32,9 +32,16 @@
#include <stdexcept>
#include <algorithm>
#include <utility>
#include "macros.h"
#ifndef WIN32
#if defined(BSD) || defined(__APPLE__)
#include <sys/types.h>
#include <net/if_dl.h>
#else
#include <netpacket/packet.h>
#endif
#include <net/ethernet.h>
#include <netpacket/packet.h>
#include <netinet/in.h>
#endif
#include "dot11.h"
@@ -170,17 +177,20 @@ void Dot11::send(PacketSender &sender) {
if(!_iface)
throw std::runtime_error("Interface has not been set");
struct sockaddr_ll addr;
#ifndef BSD
sockaddr_ll addr;
memset(&addr, 0, sizeof(struct sockaddr_ll));
memset(&addr, 0, sizeof(struct sockaddr_ll));
addr.sll_family = Endian::host_to_be<uint16_t>(PF_PACKET);
addr.sll_protocol = Endian::host_to_be<uint16_t>(ETH_P_ALL);
addr.sll_halen = 6;
addr.sll_ifindex = _iface.id();
memcpy(&(addr.sll_addr), _header.addr1, 6);
sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
addr.sll_family = Endian::host_to_be<uint16_t>(PF_PACKET);
addr.sll_protocol = Endian::host_to_be<uint16_t>(ETH_P_ALL);
addr.sll_halen = 6;
addr.sll_ifindex = _iface.id();
memcpy(&(addr.sll_addr), _header.addr1, 6);
sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
#else
sender.send_l2(*this, 0, 0, _iface);
#endif
}
#endif // WIN32
@@ -208,7 +218,9 @@ void Dot11::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *p
Dot11 *Dot11::from_bytes(const uint8_t *buffer, uint32_t total_sz) {
// We only need the control field, the length of the PDU will depend on the flags set.
if(total_sz < sizeof(ieee80211_header::control))
// 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.");
const ieee80211_header *hdr = (const ieee80211_header*)buffer;
Dot11 *ret = 0;

View File

@@ -51,10 +51,6 @@ EAPOL::EAPOL(const uint8_t *buffer, uint32_t total_sz)
std::memcpy(&_header, buffer, sizeof(_header));
}
EAPOL::EAPOL(const EAPOL &other) : PDU(other) {
copy_eapol_fields(&other);
}
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.");
@@ -96,11 +92,6 @@ void EAPOL::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *)
write_body(buffer + sizeof(_header), total_sz - sizeof(_header));
}
void EAPOL::copy_eapol_fields(const EAPOL *other) {
std::memcpy(&_header, &other->_header, sizeof(_header));
}
/* RC4EAPOL */
RC4EAPOL::RC4EAPOL()
@@ -188,7 +179,7 @@ RSNEAPOL::RSNEAPOL(const uint8_t *buffer, uint32_t total_sz)
_key.assign(buffer, buffer + total_sz);
}
void RSNEAPOL::RSNEAPOL::nonce(const uint8_t *new_nonce) {
void RSNEAPOL::nonce(const uint8_t *new_nonce) {
std::copy(new_nonce, new_nonce + nonce_size, _header.nonce);
}

View File

@@ -31,17 +31,24 @@
#include <cstring>
#include <stdexcept>
#include <algorithm>
#include "macros.h"
#ifndef WIN32
#include <net/ethernet.h>
#ifdef BSD
#include <net/if_dl.h>
#else
#include <netpacket/packet.h>
#endif
#include <netinet/in.h>
#include <netpacket/packet.h>
#include <net/ethernet.h>
#endif
#include "ethernetII.h"
#include "packet_sender.h"
#include "rawpdu.h"
#include "ip.h"
#include "ipv6.h"
#include "arp.h"
#include "constants.h"
#include "internals.h"
namespace Tins {
const EthernetII::address_type EthernetII::BROADCAST("ff:ff:ff:ff:ff:ff");
@@ -64,22 +71,16 @@ 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.");
memcpy(&_eth, buffer, sizeof(ethhdr));
PDU *next = 0;
buffer += sizeof(ethhdr);
total_sz -= sizeof(ethhdr);
if(total_sz) {
switch(payload_type()) {
case Constants::Ethernet::IP:
next = new Tins::IP(buffer, total_sz);
break;
case Constants::Ethernet::ARP:
next = new Tins::ARP(buffer, total_sz);
break;
default:
next = new Tins::RawPDU(buffer, total_sz);
// Other protos plz
}
inner_pdu(next);
inner_pdu(
Internals::pdu_from_flag(
(Constants::Ethernet::e)payload_type(),
buffer,
total_sz
)
);
}
}
@@ -107,17 +108,22 @@ uint32_t EthernetII::header_size() const {
void EthernetII::send(PacketSender &sender) {
if(!_iface)
throw std::runtime_error("Interface has not been set");
struct sockaddr_ll addr;
#ifndef BSD
struct sockaddr_ll addr;
memset(&addr, 0, sizeof(struct sockaddr_ll));
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();
memcpy(&(addr.sll_addr), _eth.dst_mac, address_type::address_size);
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();
memcpy(&(addr.sll_addr), _eth.dst_mac, address_type::address_size);
sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
#else
sender.send_l2(*this, 0, 0, _iface);
#endif
}
#endif // WIN32
@@ -138,34 +144,30 @@ void EthernetII::write_serialization(uint8_t *buffer, uint32_t total_sz, const P
/* Inner type defaults to IP */
if ((_eth.payload_type == 0) && inner_pdu()) {
uint16_t type = Constants::Ethernet::IP;
switch (inner_pdu()->pdu_type()) {
case PDU::IP:
type = Constants::Ethernet::IP;
break;
case PDU::ARP:
type = Constants::Ethernet::ARP;
break;
default:
type = 0;
}
_eth.payload_type = Endian::host_to_be(type);
Constants::Ethernet::e flag = Internals::pdu_flag_to_ether_type(
inner_pdu()->pdu_type()
);
payload_type(static_cast<uint16_t>(flag));
}
memcpy(buffer, &_eth, sizeof(ethhdr));
}
#ifndef WIN32
PDU *EthernetII::recv_response(PacketSender &sender) {
struct sockaddr_ll addr;
memset(&addr, 0, sizeof(struct sockaddr_ll));
#ifndef BSD
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();
memcpy(&(addr.sll_addr), _eth.dst_mac, address_type::address_size);
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();
memcpy(&(addr.sll_addr), _eth.dst_mac, address_type::address_size);
return sender.recv_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
return sender.recv_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
#else
return sender.recv_l2(*this, 0, 0, _iface);
#endif
}
#endif // WIN32

View File

@@ -31,30 +31,17 @@
#include <cstring>
#include <cassert>
#ifndef WIN32
#define NOMINMAX
#include <netinet/in.h>
#endif
#include "icmp.h"
#include "rawpdu.h"
#include "utils.h"
uint16_t Tins::ICMP::global_id = 0, Tins::ICMP::global_seq = 0;
Tins::ICMP::ICMP(Flags flag)
{
std::memset(&_icmp, 0, sizeof(icmphdr));
switch(flag) {
case ECHO_REPLY:
break;
case ECHO_REQUEST:
set_echo_request();
break;
case DEST_UNREACHABLE:
set_dest_unreachable();
break;
default:
break;
};
type(flag);
}
Tins::ICMP::ICMP(const uint8_t *buffer, uint32_t total_sz)
@@ -109,28 +96,12 @@ void Tins::ICMP::set_echo_request(uint16_t id, uint16_t seq) {
sequence(seq);
}
void Tins::ICMP::set_echo_request() {
set_echo_request(global_id++, global_seq++);
if(global_id == 0xffff)
global_id = 0;
if(global_seq == 0xffff)
global_seq = 0;
}
void Tins::ICMP::set_echo_reply(uint16_t id, uint16_t seq) {
type(ECHO_REPLY);
this->id(id);
sequence(seq);
}
void Tins::ICMP::set_echo_reply() {
set_echo_reply(global_id++, global_seq++);
if(global_id == 0xffff)
global_id = 0;
if(global_seq == 0xffff)
global_seq = 0;
}
void Tins::ICMP::set_info_request(uint16_t id, uint16_t seq) {
type(INFO_REQUEST);
code(0);

795
src/icmpv6.cpp Normal file
View File

@@ -0,0 +1,795 @@
/*
* Copyright (c) 2012, Nasel
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <cassert>
#include <cstring>
#include "icmpv6.h"
#include "ipv6.h"
#include "rawpdu.h"
#include "utils.h"
#include "constants.h"
namespace Tins {
ICMPv6::ICMPv6(Types tp)
: _options_size(), reach_time(0), retrans_timer(0)
{
std::memset(&_header, 0, sizeof(_header));
type(tp);
}
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");
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");
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");
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");
const uint32_t *ptr_32 = (const uint32_t*)buffer;
reach_time = *ptr_32++;
retrans_timer = *ptr_32++;
buffer += sizeof(uint32_t) * 2;
total_sz -= sizeof(uint32_t) * 2;
}
if(has_options())
parse_options(buffer, total_sz);
if(total_sz > 0)
inner_pdu(new RawPDU(buffer, 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");
// 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));
total_sz -= buffer[1] * 8;
buffer += buffer[1] * 8;
}
}
void ICMPv6::type(Types new_type) {
_header.type = new_type;
}
void ICMPv6::code(uint8_t new_code) {
_header.code = new_code;
}
void ICMPv6::checksum(uint16_t new_cksum) {
_header.cksum = Endian::host_to_be(new_cksum);
}
void ICMPv6::identifier(uint16_t new_identifier) {
_header.u_echo.identifier = Endian::host_to_be(new_identifier);
}
void ICMPv6::sequence(uint16_t new_sequence) {
_header.u_echo.sequence = Endian::host_to_be(new_sequence);
}
void ICMPv6::override(small_uint<1> new_override) {
_header.u_nd_advt.override = new_override;
}
void ICMPv6::solicited(small_uint<1> new_solicited) {
_header.u_nd_advt.solicited = new_solicited;
}
void ICMPv6::router(small_uint<1> new_router) {
_header.u_nd_advt.router = new_router;
}
void ICMPv6::hop_limit(uint8_t new_hop_limit) {
_header.u_nd_ra.hop_limit = new_hop_limit;
}
void ICMPv6::router_pref(small_uint<2> new_router_pref) {
_header.u_nd_ra.router_pref = new_router_pref;
}
void ICMPv6::home_agent(small_uint<1> new_home_agent) {
_header.u_nd_ra.home_agent = new_home_agent;
}
void ICMPv6::other(small_uint<1> new_other) {
_header.u_nd_ra.other = new_other;
}
void ICMPv6::managed(small_uint<1> new_managed) {
_header.u_nd_ra.managed = new_managed;
}
void ICMPv6::router_lifetime(uint16_t new_router_lifetime) {
_header.u_nd_ra.router_lifetime = Endian::host_to_be(new_router_lifetime);
}
void ICMPv6::reachable_time(uint32_t new_reachable_time) {
reach_time = Endian::host_to_be(new_reachable_time);
}
void ICMPv6::retransmit_timer(uint32_t new_retrans_timer) {
retrans_timer = Endian::host_to_be(new_retrans_timer);
}
void ICMPv6::target_addr(const ipaddress_type &new_target_addr) {
_target_address = new_target_addr;
}
void ICMPv6::dest_addr(const ipaddress_type &new_dest_addr) {
_dest_address = new_dest_addr;
}
uint32_t ICMPv6::header_size() const {
uint32_t extra = 0;
if(type() == ROUTER_ADVERT)
extra = sizeof(uint32_t) * 2;
return sizeof(_header) + _options_size + extra +
(has_target_addr() ? ipaddress_type::address_size : 0) +
(has_dest_addr() ? ipaddress_type::address_size : 0);
}
void ICMPv6::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
#ifdef TINS_DEBUG
assert(total_sz >= header_size());
#endif
icmp6hdr* ptr_header = (icmp6hdr*)buffer;
std::memcpy(buffer, &_header, sizeof(_header));
buffer += sizeof(_header);
total_sz -= sizeof(_header);
if(has_target_addr()) {
buffer = _target_address.copy(buffer);
total_sz -= sizeof(ipaddress_type::address_size);
}
if(has_dest_addr()) {
buffer = _dest_address.copy(buffer);
total_sz -= sizeof(ipaddress_type::address_size);
}
if(type() == ROUTER_ADVERT) {
*(uint32_t*)buffer = reach_time;
buffer += sizeof(uint32_t);
*(uint32_t*)buffer = retrans_timer;
buffer += sizeof(uint32_t);
total_sz -= sizeof(uint32_t) * 2;
}
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 -= it->data_size() + sizeof(uint8_t) * 2;
#endif
buffer = write_option(*it, buffer);
}
if(!_header.cksum) {
const Tins::IPv6 *ipv6 = dynamic_cast<const Tins::IPv6*>(parent);
if(ipv6) {
uint32_t checksum = Utils::pseudoheader_checksum(
ipv6->src_addr(),
ipv6->dst_addr(),
size(),
Constants::IP::PROTO_ICMPV6
) + Utils::do_checksum((uint8_t*)ptr_header, buffer);
while (checksum >> 16)
checksum = (checksum & 0xffff) + (checksum >> 16);
ptr_header->cksum = Endian::host_to_be<uint16_t>(~checksum);
}
}
}
// can i haz more?
bool ICMPv6::has_options() const {
return type() == NEIGHBOUR_SOLICIT ||
type() == ROUTER_ADVERT;
}
void ICMPv6::add_option(const icmpv6_option &option) {
_options.push_back(option);
_options_size += option.data_size() + sizeof(uint8_t) * 2;
}
uint8_t *ICMPv6::write_option(const icmpv6_option &opt, uint8_t *buffer) {
*buffer++ = opt.option();
*buffer++ = (opt.data_size() + 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 {
for(options_type::const_iterator it = _options.begin(); it != _options.end(); ++it) {
if(it->option() == id)
return &*it;
}
return 0;
}
// ********************************************************************
// Option setters
// ********************************************************************
void ICMPv6::source_link_layer_addr(const hwaddress_type &addr) {
add_option(icmpv6_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()));
}
void ICMPv6::prefix_info(prefix_info_type info) {
uint8_t buffer[2 + sizeof(uint32_t) * 3 + ipaddress_type::address_size];
buffer[0] = info.prefix_len;
buffer[1] = (info.L << 7) | (info.A << 6);
*(uint32_t*)(buffer + 2) = Endian::host_to_be(info.valid_lifetime);
*(uint32_t*)(buffer + 2 + sizeof(uint32_t)) = Endian::host_to_be(info.preferred_lifetime);
*(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))
);
}
void ICMPv6::redirect_header(PDU::serialization_type data) {
// Reserved fields
data.insert(data.begin(), 6, 0);
// Padding(if necessary)
uint8_t padding = 8 - (data.size() + sizeof(uint8_t) * 2) % 8;
if(padding == 8)
padding = 0;
data.insert(data.end(), padding, 0);
add_option(icmpv6_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));
}
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));
}
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));
}
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));
}
void ICMPv6::source_addr_list(const addr_list_type &value) {
add_addr_list(S_ADDRESS_LIST, value);
}
void ICMPv6::target_addr_list(const addr_list_type &value) {
add_addr_list(T_ADDRESS_LIST, value);
}
void ICMPv6::add_addr_list(uint8_t type, const addr_list_type &value) {
std::vector<uint8_t> buffer;
buffer.reserve(value.size() + 6);
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()));
}
void ICMPv6::rsa_signature(const rsa_sign_type &value) {
uint32_t total_sz = 4 + sizeof(value.key_hash) + value.signature.size();
uint8_t padding = 8 - total_sz % 8;
if(padding == 8)
padding = 0;
std::vector<uint8_t> buffer;
buffer.reserve(total_sz + padding);
buffer.insert(buffer.end(), 2, 0);
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()));
}
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()));
}
void ICMPv6::nonce(const nonce_type &value) {
add_option(icmpv6_option(NONCE, value.begin(), value.end()));
}
void ICMPv6::ip_prefix(const ip_prefix_type &value) {
std::vector<uint8_t> buffer;
buffer.reserve(6 + ipaddress_type::address_size);
buffer.push_back(value.option_code);
buffer.push_back(value.prefix_len);
// 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()));
}
void ICMPv6::link_layer_addr(lladdr_type value) {
value.address.insert(value.address.begin(), value.option_code);
uint8_t padding = 8 - (2 + value.address.size()) % 8;
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()));
}
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)));
}
void ICMPv6::map(const map_type &value) {
uint8_t buffer[sizeof(uint8_t) * 2 + sizeof(uint32_t) + ipaddress_type::address_size];
buffer[0] = value.dist << 4 | value.pref;
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)));
}
void ICMPv6::route_info(const route_info_type &value) {
uint8_t padding = 8 - value.prefix.size() % 8;
if(padding == 8)
padding = 0;
std::vector<uint8_t> buffer(2 + sizeof(uint32_t) + value.prefix.size() + padding);
buffer[0] = value.prefix_len;
buffer[1] = value.pref << 3;
*(uint32_t*)&buffer[2] = Endian::host_to_be(value.route_lifetime);
// copy the prefix and then fill with padding
buffer.insert(
std::copy(value.prefix.begin(), value.prefix.end(), buffer.begin() + 2 + sizeof(uint32_t)),
padding,
0
);
add_option(icmpv6_option(ROUTE_INFO, buffer.begin(), buffer.end()));
}
void ICMPv6::recursive_dns_servers(const recursive_dns_type &value) {
std::vector<uint8_t> buffer(
2 + sizeof(uint32_t) + value.servers.size() * ipaddress_type::address_size
);
buffer[0] = buffer[1] = 0;
*(uint32_t*)&buffer[2] = Endian::host_to_be(value.lifetime);
std::vector<uint8_t>::iterator out = buffer.begin() + 2 + sizeof(uint32_t);
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()));
}
void ICMPv6::handover_key_request(const handover_key_req_type &value) {
uint8_t padding = 8 - (value.key.size() + 4) % 8;
if(padding == 8)
padding = 0;
std::vector<uint8_t> buffer(2 + value.key.size() + padding);
buffer[0] = padding;
buffer[1] = value.AT << 4;
// copy the key, and fill with padding
std::fill(
std::copy(value.key.begin(), value.key.end(), buffer.begin() + 2),
buffer.end(),
0
);
add_option(icmpv6_option(HANDOVER_KEY_REQ, buffer.begin(), buffer.end()));
}
void ICMPv6::handover_key_reply(const handover_key_reply_type &value) {
const uint32_t data_size = value.key.size() + 2 + sizeof(uint16_t);
uint8_t padding = 8 - (data_size+2) % 8;
if(padding == 8)
padding = 0;
std::vector<uint8_t> buffer(data_size + padding);
buffer[0] = padding;
buffer[1] = value.AT << 4;
*(uint16_t*)&buffer[2] = Endian::host_to_be(value.lifetime);
// copy the key, and fill with padding
std::fill(
std::copy(value.key.begin(), value.key.end(), buffer.begin() + 2 + sizeof(uint16_t)),
buffer.end(),
0
);
add_option(icmpv6_option(HANDOVER_KEY_REPLY, buffer.begin(), buffer.end()));
}
void ICMPv6::handover_assist_info(const handover_assist_info_type &value) {
const uint32_t data_size = value.hai.size() + 2;
uint8_t padding = 8 - (data_size+2) % 8;
if(padding == 8)
padding = 0;
std::vector<uint8_t> buffer(data_size + padding);
buffer[0] = value.option_code;
buffer[1] = static_cast<uint8_t>(value.hai.size());
// copy hai + padding
buffer.insert(
std::copy(value.hai.begin(), value.hai.end(), buffer.begin() + 2),
padding,
0
);
add_option(icmpv6_option(HANDOVER_ASSIST_INFO, buffer.begin(), buffer.end()));
}
void ICMPv6::mobile_node_identifier(const mobile_node_id_type &value) {
const uint32_t data_size = value.mn.size() + 2;
uint8_t padding = 8 - (data_size+2) % 8;
if(padding == 8)
padding = 0;
std::vector<uint8_t> buffer(data_size + padding);
buffer[0] = value.option_code;
buffer[1] = static_cast<uint8_t>(value.mn.size());
// copy mn + padding
buffer.insert(
std::copy(value.mn.begin(), value.mn.end(), buffer.begin() + 2),
padding,
0
);
add_option(icmpv6_option(MOBILE_NODE_ID, buffer.begin(), buffer.end()));
}
void ICMPv6::dns_search_list(const dns_search_list_type &value) {
// at least it's got this size
std::vector<uint8_t> buffer(2 + sizeof(uint32_t));
*(uint32_t*)&buffer[2] = Endian::host_to_be(value.lifetime);
typedef dns_search_list_type::domains_type::const_iterator iterator;
for(iterator it = value.domains.begin(); it != value.domains.end(); ++it) {
size_t prev = 0, index;
do {
index = it->find('.', prev);
std::string::const_iterator end = (index == std::string::npos) ? it->end() : (it->begin() + index);
buffer.push_back(end - (it->begin() + prev));
buffer.insert(buffer.end(), it->begin() + prev, end);
prev = index + 1;
} while(index != std::string::npos);
// delimiter
buffer.push_back(0);
}
uint8_t padding = 8 - (buffer.size() + 2) % 8;
if(padding == 8)
padding = 0;
buffer.insert(buffer.end(), padding, 0);
add_option(icmpv6_option(DNS_SEARCH_LIST, buffer.begin(), buffer.end()));
}
// ********************************************************************
// Option getters
// ********************************************************************
ICMPv6::hwaddress_type ICMPv6::source_link_layer_addr() const {
const icmpv6_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);
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);
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();
prefix_info_type output;
output.prefix_len = *ptr++;
output.L = (*ptr >> 7) & 0x1;
output.A = (*ptr++ >> 6) & 0x1;
output.valid_lifetime = Endian::be_to_host(*(uint32_t*)ptr);
ptr += sizeof(uint32_t);
output.preferred_lifetime = Endian::be_to_host(*(uint32_t*)ptr);
output.prefix = ptr + sizeof(uint32_t) * 2;
return output;
}
PDU::serialization_type ICMPv6::redirect_header() const {
const icmpv6_option *opt = search_option(REDIRECT_HEADER);
if(!opt || opt->data_size() < 6)
throw option_not_found();
const uint8_t *ptr = opt->data_ptr() + 6;
return serialization_type(ptr, ptr + opt->data_size() - 6);
}
uint32_t ICMPv6::mtu() const {
const icmpv6_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);
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);
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);
if(!opt || opt->data_size() != sizeof(uint16_t) + sizeof(uint32_t))
throw option_not_found();
return std::make_pair(
Endian::be_to_host(*(const uint16_t*)(opt->data_ptr() + sizeof(uint16_t))),
Endian::be_to_host(*(const uint16_t*)(opt->data_ptr() + sizeof(uint16_t) * 2))
);
}
ICMPv6::addr_list_type ICMPv6::source_addr_list() const {
return search_addr_list(S_ADDRESS_LIST);
}
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);
if(!opt || opt->data_size() < 6 + ipaddress_type::address_size)
throw option_not_found();
addr_list_type output;
const uint8_t *ptr = opt->data_ptr() + 6, *end = opt->data_ptr() + opt->data_size();
while(ptr < end) {
if(ptr + ipaddress_type::address_size > end)
throw option_not_found();
output.push_back(ipaddress_type(ptr));
ptr += ipaddress_type::address_size;
}
return output;
}
ICMPv6::rsa_sign_type ICMPv6::rsa_signature() const {
const icmpv6_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
if(!opt || opt->data_size() < 2 + 16 + 1)
throw option_not_found();
const uint8_t *ptr = opt->data_ptr() + 2;
rsa_sign_type output;
std::copy(ptr, ptr + sizeof(output.key_hash), output.key_hash);
ptr += sizeof(output.key_hash);
output.signature.assign(ptr, opt->data_ptr() + opt->data_size());
return output;
}
uint64_t ICMPv6::timestamp() const {
const icmpv6_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>(
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>(
IP_PREFIX, 2
);
const uint8_t *ptr = opt->data_ptr();
ip_prefix_type output;
output.option_code = *ptr++;
output.prefix_len = *ptr++;
// skip padding
ptr += sizeof(uint32_t);
output.address = ipaddress_type(ptr);
return output;
}
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>(
LINK_ADDRESS, 2
);
const uint8_t *ptr = opt->data_ptr();
lladdr_type output(*ptr++);
output.address.assign(ptr, opt->data_ptr() + opt->data_size());
return output;
}
ICMPv6::naack_type ICMPv6::naack() const {
const icmpv6_option *opt = safe_search_option<std::not_equal_to>(
NAACK, 6
);
const uint8_t *ptr = opt->data_ptr();
return naack_type(ptr[0], ptr[1]);
}
ICMPv6::map_type ICMPv6::map() const {
const icmpv6_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();
map_type output;
output.dist = (*ptr >> 4) & 0x0f;
output.pref = *ptr++ & 0x0f;
output.r = (*ptr++ >> 7) & 0x01;
output.valid_lifetime = *(uint32_t*)ptr;
ptr += sizeof(uint32_t);
output.address = ptr;
return output;
}
ICMPv6::route_info_type ICMPv6::route_info() const {
const icmpv6_option *opt = safe_search_option<std::less>(
ROUTE_INFO, 2 + sizeof(uint32_t)
);
const uint8_t *ptr = opt->data_ptr();
route_info_type output;
output.prefix_len = *ptr++;
output.pref = (*ptr++ >> 3) & 0x3;
output.route_lifetime = Endian::be_to_host(*(uint32_t*)ptr);
ptr += sizeof(uint32_t);
output.prefix.assign(ptr, opt->data_ptr() + opt->data_size());
return output;
}
ICMPv6::recursive_dns_type ICMPv6::recursive_dns_servers() const {
const icmpv6_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();
recursive_dns_type output;
output.lifetime = Endian::be_to_host(*(uint32_t*)ptr);
ptr += sizeof(uint32_t);
while(ptr < end) {
if(ptr + ipaddress_type::address_size > end)
throw option_not_found();
output.servers.push_back(ptr);
ptr += ipaddress_type::address_size;
}
return output;
}
ICMPv6::handover_key_req_type ICMPv6::handover_key_request() const {
const icmpv6_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();
handover_key_req_type output;
output.AT = (*ptr++ >> 4) & 0x3;
// is there enough size for the indicated padding?
if(end - ptr < *opt->data_ptr())
throw option_not_found();
output.key.assign(ptr, ptr + ((end - ptr) - *opt->data_ptr()));
return output;
}
ICMPv6::handover_key_reply_type ICMPv6::handover_key_reply() const {
const icmpv6_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();
handover_key_reply_type output;
output.AT = (*ptr++ >> 4) & 0x3;
output.lifetime = Endian::be_to_host(*(uint16_t*)ptr);
ptr += sizeof(uint16_t);
// is there enough size for the indicated padding?
if(end - ptr < *opt->data_ptr())
throw option_not_found();
output.key.assign(ptr, ptr + ((end - ptr) - *opt->data_ptr()));
return output;
}
ICMPv6::handover_assist_info_type ICMPv6::handover_assist_info() const {
const icmpv6_option *opt = safe_search_option<std::less>(
HANDOVER_ASSIST_INFO, 2
);
const uint8_t *ptr = opt->data_ptr(), *end = ptr + opt->data_size();
handover_assist_info_type output;
output.option_code = *ptr++;
if((end - ptr - 1) < *ptr)
throw option_not_found();
output.hai.assign(ptr + 1, ptr + 1 + *ptr);
return output;
}
ICMPv6::mobile_node_id_type ICMPv6::mobile_node_identifier() const {
const icmpv6_option *opt = safe_search_option<std::less>(
MOBILE_NODE_ID, 2
);
const uint8_t *ptr = opt->data_ptr(), *end = ptr + opt->data_size();
mobile_node_id_type output;
output.option_code = *ptr++;
if((end - ptr - 1) < *ptr)
throw option_not_found();
output.mn.assign(ptr + 1, ptr + 1 + *ptr);
return output;
}
ICMPv6::dns_search_list_type ICMPv6::dns_search_list() const {
const icmpv6_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();
dns_search_list_type output;
output.lifetime = Endian::be_to_host(*(uint32_t*)(ptr + 2));
ptr += 2 + sizeof(uint32_t);
while(ptr < end && *ptr) {
std::string domain;
while(ptr < end && *ptr && *ptr < (end - ptr)) {
if(!domain.empty())
domain.push_back('.');
domain.insert(domain.end(), ptr + 1, ptr + *ptr + 1);
ptr += *ptr + 1;
}
// not enough size
if(ptr < end && *ptr != 0)
throw option_not_found();
output.domains.push_back(domain);
ptr++;
}
return output;
}
}

View File

@@ -31,10 +31,15 @@
#include <cstring>
#include <stdexcept>
#include <algorithm>
#include "macros.h"
#ifndef WIN32
#ifdef BSD
#include <net/if_dl.h>
#else
#include <netpacket/packet.h>
#endif
#include <net/ethernet.h>
#include <netinet/in.h>
#include <netpacket/packet.h>
#endif
#include "ieee802_3.h"
#include "packet_sender.h"
@@ -91,18 +96,22 @@ uint32_t IEEE802_3::header_size() const {
void IEEE802_3::send(PacketSender &sender) {
if(!_iface)
throw std::runtime_error("Interface has not been set");
struct sockaddr_ll addr;
#ifndef BSD
struct sockaddr_ll addr;
memset(&addr, 0, sizeof(struct sockaddr_ll));
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();
memcpy(&(addr.sll_addr), _eth.dst_mac, sizeof(_eth.dst_mac));
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();
memcpy(&(addr.sll_addr), _eth.dst_mac, sizeof(_eth.dst_mac));
sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
#else
sender.send_l2(*this, 0, 0, _iface);
#endif
}
#endif // WIN32
@@ -132,16 +141,22 @@ void IEEE802_3::write_serialization(uint8_t *buffer, uint32_t total_sz, const PD
#ifndef WIN32
PDU *IEEE802_3::recv_response(PacketSender &sender) {
struct sockaddr_ll addr;
memset(&addr, 0, sizeof(struct sockaddr_ll));
if(!_iface)
throw std::runtime_error("Interface has not been set");
#ifndef BSD
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();
memcpy(&(addr.sll_addr), _eth.dst_mac, sizeof(_eth.dst_mac));
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();
memcpy(&(addr.sll_addr), _eth.dst_mac, sizeof(_eth.dst_mac));
return sender.recv_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
return sender.recv_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
#else
return sender.recv_l2(*this, 0, 0, _iface);
#endif
}
#endif // WIN32

94
src/internals.cpp Normal file
View File

@@ -0,0 +1,94 @@
/*
* Copyright (c) 2012, Nasel
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "internals.h"
#include "ip.h"
#include "ipv6.h"
#include "arp.h"
#include "eapol.h"
#include "rawpdu.h"
using std::string;
namespace Tins {
namespace Internals {
bool from_hex(const string &str, uint32_t &result) {
unsigned i(0);
result = 0;
while(i < str.size()) {
uint8_t tmp;
if(str[i] >= 'A' && str[i] <= 'F')
tmp = (str[i] - 'A' + 10);
else if(str[i] >= '0' && str[i] <= '9')
tmp = (str[i] - '0');
else
return false;
result = (result << 4) | tmp;
i++;
}
return true;
}
void skip_line(std::istream &input) {
int c = 0;
while(c != '\n' && input)
c = input.get();
}
Tins::PDU *pdu_from_flag(Constants::Ethernet::e flag, const uint8_t *buffer,
uint32_t size, bool rawpdu_on_no_match)
{
switch(flag) {
case Tins::Constants::Ethernet::IP:
return new Tins::IP(buffer, size);
case Constants::Ethernet::IPV6:
return new Tins::IPv6(buffer, size);
case Tins::Constants::Ethernet::ARP:
return new Tins::ARP(buffer, size);
case Tins::Constants::Ethernet::EAPOL:
return Tins::EAPOL::from_bytes(buffer, size);
default:
return rawpdu_on_no_match ? new RawPDU(buffer, size) : 0;
};
}
Constants::Ethernet::e pdu_flag_to_ether_type(PDU::PDUType flag) {
switch (flag) {
case PDU::IP:
return Constants::Ethernet::IP;
case PDU::IPv6:
return Constants::Ethernet::IPV6;
case PDU::ARP:
return Constants::Ethernet::ARP;
default:
return Constants::Ethernet::UNKNOWN;
}
}
}
}

View File

@@ -34,10 +34,13 @@
#ifndef WIN32
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#else
#define NOMINMAX
#include <winsock2.h>
#endif
#include "ip.h"
#include "ipv6.h"
#include "tcp.h"
#include "udp.h"
#include "icmp.h"
@@ -141,6 +144,9 @@ IP::IP(const uint8_t *buffer, uint32_t total_sz)
case Constants::IP::PROTO_ICMP:
inner_pdu(new Tins::ICMP(buffer, total_sz));
break;
case Constants::IP::PROTO_IPV6:
inner_pdu(new Tins::IPv6(buffer, total_sz));
break;
default:
inner_pdu(new Tins::RawPDU(buffer, total_sz));
break;
@@ -383,6 +389,11 @@ void IP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU* pare
protocol(new_flag);
//flag(new_flag);
}
#ifdef __FreeBSD__
if(!parent)
total_sz = Endian::host_to_be<uint16_t>(total_sz);
#endif
tot_len(total_sz);
head_len(my_sz / sizeof(uint32_t));

215
src/ipv6.cpp Normal file
View File

@@ -0,0 +1,215 @@
#include <cstring>
#include <cassert>
#ifndef WIN32
#include <netinet/in.h>
#include <sys/socket.h>
#else
#include <ws2tcpip.h>
#endif
#include <iostream> //borrame
#include "ipv6.h"
#include "constants.h"
#include "packet_sender.h"
#include "ip.h"
#include "tcp.h"
#include "udp.h"
#include "icmp.h"
#include "icmpv6.h"
#include "rawpdu.h"
namespace Tins {
IPv6::IPv6(address_type ip_dst, address_type ip_src, PDU *child)
: headers_size(0)
{
std::memset(&_header, 0, sizeof(_header));
version(6);
dst_addr(ip_dst);
src_addr(ip_src);
}
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");
std::memcpy(&_header, buffer, sizeof(_header));
buffer += sizeof(_header);
total_sz -= sizeof(_header);
uint8_t current_header = _header.next_header;
while(total_sz) {
if(is_extension_header(current_header)) {
if(total_sz < 8)
throw header_size_error();
// 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();
// minus one, from the size field
add_ext_header(
ipv6_ext_header(buffer[0], size - sizeof(uint8_t)*2, buffer + 2)
);
current_header = buffer[0];
buffer += size;
total_sz -= size;
}
else {
switch(current_header) {
case Constants::IP::PROTO_TCP:
inner_pdu(new Tins::TCP(buffer, total_sz));
break;
case Constants::IP::PROTO_UDP:
inner_pdu(new Tins::UDP(buffer, total_sz));
break;
case Constants::IP::PROTO_ICMP:
inner_pdu(new Tins::ICMP(buffer, total_sz));
break;
case Constants::IP::PROTO_ICMPV6:
inner_pdu(new Tins::ICMPv6(buffer, total_sz));
break;
default:
inner_pdu(new Tins::RawPDU(buffer, total_sz));
break;
}
total_sz = 0;
}
}
}
bool IPv6::is_extension_header(uint8_t header_id) {
return header_id == HOP_BY_HOP || header_id == DESTINATION_ROUTING_OPTIONS
|| header_id == ROUTING || header_id == FRAGMENT || header_id == AUTHENTICATION
|| header_id == SECURITY_ENCAPSULATION || header_id == DESTINATION_OPTIONS
|| header_id == MOBILITY || header_id == NO_NEXT_HEADER;
}
void IPv6::version(small_uint<4> new_version) {
_header.version = new_version;
}
void IPv6::traffic_class(uint8_t new_traffic_class) {
#if TINS_IS_LITTLE_ENDIAN
_header.traffic_class = (new_traffic_class >> 4) & 0xf;
_header.flow_label[0] = (_header.flow_label[0] & 0x0f) | ((new_traffic_class << 4) & 0xf0);
#else
_header.traffic_class = new_traffic_class;
#endif
}
void IPv6::flow_label(small_uint<20> new_flow_label) {
#if TINS_IS_LITTLE_ENDIAN
uint32_t value = Endian::host_to_be<uint32_t>(new_flow_label);
_header.flow_label[2] = (value >> 24) & 0xff;
_header.flow_label[1] = (value >> 16) & 0xff;
_header.flow_label[0] = ((value >> 8) & 0x0f) | (_header.flow_label[0] & 0xf0);
#else
_header.flow_label = new_flow_label;
#endif
}
void IPv6::payload_length(uint16_t new_payload_length) {
_header.payload_length = Endian::host_to_be(new_payload_length);
}
void IPv6::next_header(uint8_t new_next_header) {
_header.next_header = new_next_header;
}
void IPv6::hop_limit(uint8_t new_hop_limit) {
_header.hop_limit = new_hop_limit;
}
void IPv6::src_addr(const address_type &new_src_addr) {
new_src_addr.copy(_header.src_addr);
}
void IPv6::dst_addr(const address_type &new_dst_addr) {
new_dst_addr.copy(_header.dst_addr);
}
uint32_t IPv6::header_size() const {
return sizeof(_header) + headers_size;
}
void IPv6::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
#ifdef DEBUG
assert(total_sz >= header_size());
#endif
if(inner_pdu()) {
uint8_t new_flag = 0xff;
switch(inner_pdu()->pdu_type()) {
case PDU::IP:
new_flag = Constants::IP::PROTO_IPIP;
break;
case PDU::TCP:
new_flag = Constants::IP::PROTO_TCP;
break;
case PDU::UDP:
new_flag = Constants::IP::PROTO_UDP;
break;
case PDU::ICMP:
new_flag = Constants::IP::PROTO_ICMP;
break;
case PDU::ICMPv6:
new_flag = Constants::IP::PROTO_ICMPV6;
break;
default:
break;
};
if(new_flag != 0xff)
set_last_next_header(new_flag);
}
payload_length(total_sz - sizeof(_header));
std::memcpy(buffer, &_header, sizeof(_header));
buffer += sizeof(_header);
for(headers_type::const_iterator it = ext_headers.begin(); it != ext_headers.end(); ++it) {
buffer = write_header(*it, buffer);
}
}
#ifndef BSD
void IPv6::send(PacketSender &sender) {
struct sockaddr_in6 link_addr;
PacketSender::SocketType type = PacketSender::IPV6_SOCKET;
link_addr.sin6_family = AF_INET6;
link_addr.sin6_port = 0;
std::copy(_header.dst_addr, _header.dst_addr + address_type::address_size, (uint8_t*)&link_addr.sin6_addr);
if(inner_pdu() && inner_pdu()->pdu_type() == PDU::ICMP)
type = PacketSender::ICMP_SOCKET;
sender.send_l3(*this, (struct sockaddr*)&link_addr, sizeof(link_addr), type);
}
#endif
void IPv6::add_ext_header(const ipv6_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 {
uint8_t current_header = _header.next_header;
headers_type::const_iterator it = ext_headers.begin();
while(it != ext_headers.end() && current_header != id) {
current_header = it->option();
++it;
}
if(it == ext_headers.end())
return 0;
return &*it;
}
void IPv6::set_last_next_header(uint8_t value) {
if(ext_headers.empty())
_header.next_header = value;
else
ext_headers.back().option(value);
}
uint8_t *IPv6::write_header(const ipv6_ext_header &header, uint8_t *buffer) {
*buffer++ = header.option();
*buffer++ = (header.data_size() > 8) ? (header.data_size() - 8) : 0;
return std::copy(header.data_ptr(), header.data_ptr() + header.data_size(), buffer);
}
}

102
src/ipv6_address.cpp Normal file
View File

@@ -0,0 +1,102 @@
/*
* Copyright (c) 2012, Nasel
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <algorithm>
#include "macros.h"
#ifndef WIN32
#include <arpa/inet.h>
#ifdef BSD
#include <sys/socket.h>
#endif
#else
#include <ws2tcpip.h>
#include <mstcpip.h>
#endif
#include <limits>
#include <iostream> // borrame
#include <sstream>
#include "ipv6_address.h"
namespace Tins {
IPv6Address::IPv6Address() {
std::fill(address, address + address_size, 0);
}
IPv6Address::IPv6Address(const char *addr) {
init(addr);
}
IPv6Address::IPv6Address(const_iterator ptr) {
std::copy(ptr, ptr + address_size, address);
}
IPv6Address::IPv6Address(const std::string &addr) {
init(addr.c_str());
}
void IPv6Address::init(const char *addr) {
#ifdef WIN32
// mingw on linux somehow doesn't have InetPton
#ifdef _MSC_VER
if(InetPtonA(AF_INET6, addr, address) != 1)
throw malformed_address();
#else
ULONG dummy1;
USHORT dummy2;
// Maybe change this, mingw doesn't have any other conversion function
if(RtlIpv6StringToAddressExA(addr, (IN6_ADDR*)address, &dummy1, &dummy2) != NO_ERROR)
throw malformed_address();
#endif
#else
if(inet_pton(AF_INET6, addr, address) == 0)
throw malformed_address();
#endif
}
std::string IPv6Address::to_string() const {
char buffer[INET6_ADDRSTRLEN];
#ifdef WIN32
// mingw on linux somehow doesn't have InetNtop
#ifdef _MSC_VER
if(InetNtopA(AF_INET6, (PVOID)address, buffer, sizeof(buffer)) != 0)
throw malformed_address();
#else
ULONG sz = sizeof(buffer);
if(RtlIpv6AddressToStringExA((const IN6_ADDR*)address, 0, 0, buffer, &sz) != NO_ERROR)
throw malformed_address();
#endif
#else
if(inet_ntop(AF_INET6, address, buffer, sizeof(buffer)) == 0)
throw malformed_address();
#endif
return buffer;
}
}

View File

@@ -29,15 +29,26 @@
#ifndef WIN32
#include <sys/socket.h>
#ifdef BSD
#include <net/if_dl.h>
#include <netinet/in.h>
#include <net/ethernet.h>
#endif
#endif
#include <stdexcept>
#include <cassert>
#include <cstring>
#include "loopback.h"
#include "packet_sender.h"
#include "ip.h"
#include "llc.h"
#include "rawpdu.h"
#if !defined(PF_LLC)
// compilation fix, nasty but at least works on BSD
#define PF_LLC 26
#endif
namespace Tins {
Loopback::Loopback()
: _family()
@@ -45,8 +56,8 @@ Loopback::Loopback()
}
Loopback::Loopback(uint32_t family_id, PDU *inner_pdu)
: PDU(inner_pdu), _family(family_id)
Loopback::Loopback(const NetworkInterface &iface, PDU *inner_pdu)
: PDU(inner_pdu), _family(), _iface(iface)
{
}
@@ -79,6 +90,10 @@ 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);
}
@@ -86,6 +101,18 @@ uint32_t Loopback::header_size() const {
void Loopback::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *)
{
assert(total_sz >= sizeof(_family));
if(dynamic_cast<const Tins::IP*>(inner_pdu()))
_family = PF_INET;
else if(dynamic_cast<const Tins::LLC*>(inner_pdu()))
_family = PF_LLC;
*reinterpret_cast<uint32_t*>(buffer) = _family;
}
#ifdef BSD
void Loopback::send(PacketSender &sender) {
if(!_iface)
throw std::runtime_error("Interface has not been set");
sender.send_l2(*this, 0, 0, _iface);
}
#endif // WIN32
}

View File

@@ -30,11 +30,19 @@
#include <stdexcept>
#include <vector>
#include <cstring>
#include "macros.h"
#ifndef WIN32
#include <linux/if_packet.h>
#include <net/if.h>
#include <netinet/in.h>
#ifdef BSD
#include <ifaddrs.h>
#include <net/if_dl.h>
#include <sys/socket.h>
#else
#include <linux/if_packet.h>
#endif
#include <net/if.h>
#else
#define NOMINMAX
#include <winsock2.h>
#endif
#include "network_interface.h"
@@ -55,38 +63,52 @@ struct InterfaceInfoCollector {
#ifndef WIN32
bool operator() (const struct ifaddrs *addr) {
using Tins::Endian::host_to_be;
using Tins::IPv4Address;
const struct sockaddr_ll* addr_ptr = ((struct sockaddr_ll*)addr->ifa_addr);
if(addr->ifa_addr->sa_family == AF_PACKET && addr_ptr->sll_ifindex == iface_id)
info->hw_addr = addr_ptr->sll_addr;
else if(addr->ifa_addr->sa_family == AF_INET && !std::strcmp(addr->ifa_name, iface_name)) {
info->ip_addr = IPv4Address(((struct sockaddr_in *)addr->ifa_addr)->sin_addr.s_addr);
info->netmask = IPv4Address(((struct sockaddr_in *)addr->ifa_netmask)->sin_addr.s_addr);
if((addr->ifa_flags & (IFF_BROADCAST | IFF_POINTOPOINT)))
info->bcast_addr = IPv4Address(((struct sockaddr_in *)addr->ifa_ifu.ifu_broadaddr)->sin_addr.s_addr);
else
info->bcast_addr = 0;
found = true;
}
return found;
using Tins::IPv4Address;
#ifdef BSD
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)
info->hw_addr = (const uint8_t*)LLADDR(addr_ptr); // mmmm
else if(addr->ifa_addr->sa_family == AF_INET && !std::strcmp(addr->ifa_name, iface_name)) {
info->ip_addr = IPv4Address(((struct sockaddr_in *)addr->ifa_addr)->sin_addr.s_addr);
info->netmask = IPv4Address(((struct sockaddr_in *)addr->ifa_netmask)->sin_addr.s_addr);
if((addr->ifa_flags & (IFF_BROADCAST | IFF_POINTOPOINT)))
info->bcast_addr = IPv4Address(((struct sockaddr_in *)addr->ifa_dstaddr)->sin_addr.s_addr);
else
info->bcast_addr = 0;
found = true;
}
return found;
#else
const struct sockaddr_ll* addr_ptr = ((struct sockaddr_ll*)addr->ifa_addr);
if(addr->ifa_addr->sa_family == AF_PACKET && addr_ptr->sll_ifindex == iface_id)
info->hw_addr = addr_ptr->sll_addr;
else if(addr->ifa_addr->sa_family == AF_INET && !std::strcmp(addr->ifa_name, iface_name)) {
info->ip_addr = IPv4Address(((struct sockaddr_in *)addr->ifa_addr)->sin_addr.s_addr);
info->netmask = IPv4Address(((struct sockaddr_in *)addr->ifa_netmask)->sin_addr.s_addr);
if((addr->ifa_flags & (IFF_BROADCAST | IFF_POINTOPOINT)))
info->bcast_addr = IPv4Address(((struct sockaddr_in *)addr->ifa_ifu.ifu_broadaddr)->sin_addr.s_addr);
else
info->bcast_addr = 0;
found = true;
}
return found;
#endif
}
#else // WIN32
bool operator() (const IP_ADAPTER_ADDRESSES *iface) {
using Tins::IPv4Address;
// This surely doesn't work
if(iface_id == iface->IfIndex) {
using Tins::Endian::host_to_be;
if(iface_id == uint32_t(iface->IfIndex)) {
std::copy(iface->PhysicalAddress, iface->PhysicalAddress + 6, info->hw_addr.begin());
const IP_ADAPTER_PREFIX *prefix_ptr = iface->FirstPrefix;
for(size_t i = 0; prefix_ptr; prefix_ptr = prefix_ptr->Next, i++) {
if(i == 0)
info->ip_addr = IPv4Address(((const struct sockaddr_in *)prefix_ptr->Address.lpSockaddr)->sin_addr.s_addr);
else if(i == 2)
info->bcast_addr = IPv4Address(((const struct sockaddr_in *)prefix_ptr->Address.lpSockaddr)->sin_addr.s_addr);
const IP_ADAPTER_UNICAST_ADDRESS *unicast = iface->FirstUnicastAddress;
if(unicast) {
info->ip_addr = IPv4Address(((const struct sockaddr_in *)unicast->Address.lpSockaddr)->sin_addr.s_addr);
info->netmask = IPv4Address(host_to_be<uint32_t>(0xffffffff << (32 - unicast->OnLinkPrefixLength)));
info->bcast_addr = IPv4Address((info->ip_addr & info->netmask) | ~info->netmask);
found = true;
}
// (?????)
info->netmask = IPv4Address(info->ip_addr - info->bcast_addr);
found = true;
}
return found;
}
@@ -116,20 +138,26 @@ NetworkInterface::NetworkInterface(IPv4Address ip) : iface_id(0) {
typedef std::vector<Utils::RouteEntry> entries_type;
if(ip == "127.0.0.1")
#ifdef BSD
iface_id = resolve_index("lo0");
#else
iface_id = resolve_index("lo");
#endif
else {
Utils::RouteEntry *best_match = 0;
const Utils::RouteEntry *best_match = 0;
entries_type entries;
uint32_t ip_int = ip;
Utils::route_entries(std::back_inserter(entries));
for(entries_type::const_iterator it(entries.begin()); it != entries.end(); ++it) {
if((ip_int & it->mask) == it->destination) {
if(!best_match || it->mask > best_match->mask)
iface_id = resolve_index(it->interface.c_str());
if(!best_match || it->mask > best_match->mask) {
best_match = &*it;
}
}
}
if(best_match)
if(!best_match)
throw std::runtime_error("Error looking up interface");
iface_id = resolve_index(best_match->interface.c_str());
}
}
@@ -155,26 +183,9 @@ NetworkInterface::Info NetworkInterface::addresses() const {
}
NetworkInterface::id_type NetworkInterface::resolve_index(const char *name) {
#ifndef WIN32
id_type id = if_nametoindex(name);
if(!id)
throw std::runtime_error("Invalid interface error");
#else // WIN32
id_type id;
ULONG size;
GetAdaptersInfo(0, &size);
std::vector<uint8_t> buffer(size);
if ( GetAdaptersInfo((IP_ADAPTER_INFO *)&buffer[0], &size) == ERROR_SUCCESS) {
PIP_ADAPTER_INFO iface = (IP_ADAPTER_INFO *)&buffer[0];
while(iface) {
if(!strcmp(iface->AdapterName, name)) {
id = iface->Index;
break;
}
iface = iface->Next;
}
}
#endif // WIN32
throw std::runtime_error("Invalid interface");
return id;
}
}

View File

@@ -27,18 +27,29 @@
*
*/
#include "packet_sender.h"
#ifndef WIN32
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#ifdef BSD
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <net/if.h>
#include <net/bpf.h>
#else
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#endif
#include <netdb.h>
#include <netinet/in.h>
#include <errno.h>
#else
#define NOMINMAX
#include <winsock2.h>
#include <ws2tcpip.h>
#endif
@@ -46,7 +57,8 @@
#include <cstring>
#include <ctime>
#include "pdu.h"
#include "packet_sender.h"
#include "macros.h"
#include "network_interface.h"
namespace Tins {
@@ -58,14 +70,22 @@ const uint32_t PacketSender::DEFAULT_TIMEOUT = 2;
return strerror(errno);
}
#else
// fixme
const char *make_error_string() {
return "error";
}
#endif
PacketSender::PacketSender(uint32_t recv_timeout, uint32_t usec) :
_sockets(SOCKETS_END, INVALID_RAW_SOCKET), _timeout(recv_timeout),
PacketSender::PacketSender(uint32_t recv_timeout, uint32_t usec)
: _sockets(SOCKETS_END, INVALID_RAW_SOCKET),
#if !defined(BSD) && !defined(WIN32)
_ether_socket(INVALID_RAW_SOCKET),
#endif
_timeout(recv_timeout),
_timeout_usec(usec)
{
_types[IP_SOCKET] = IPPROTO_RAW;
_types[IPV6_SOCKET] = IPPROTO_RAW;
_types[ICMP_SOCKET] = IPPROTO_ICMP;
}
@@ -78,16 +98,62 @@ PacketSender::~PacketSender() {
::closesocket(_sockets[i]);
#endif
}
#ifdef BSD
for(BSDEtherSockets::iterator it = _ether_socket.begin(); it != _ether_socket.end(); ++it)
::close(it->second);
#elif !defined(WIN32)
if(_ether_socket != INVALID_RAW_SOCKET)
::close(_ether_socket);
#endif
}
#ifndef WIN32
void PacketSender::open_l2_socket() {
if (_sockets[ETHER_SOCKET] == INVALID_RAW_SOCKET) {
int sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sock == -1)
bool PacketSender::ether_socket_initialized(const NetworkInterface& iface) const {
#ifdef BSD
return _ether_socket.count(iface.id());
#else
return _ether_socket != INVALID_RAW_SOCKET;
#endif
}
int PacketSender::get_ether_socket(const NetworkInterface& iface) {
if(!ether_socket_initialized(iface))
open_l2_socket(iface);
#ifdef BSD
return _ether_socket[iface.id()];
#else
return _ether_socket;
#endif
}
void PacketSender::open_l2_socket(const NetworkInterface& iface) {
#ifdef BSD
int sock = -1;
// At some point, there should be an available device
for (int i = 0; sock == -1;i++) {
std::ostringstream oss;
oss << "/dev/bpf" << i;
sock = open(oss.str().c_str(), O_RDWR);
}
if(sock == -1)
throw SocketOpenError(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());
}
_ether_socket[iface.id()] = sock;
#else
if (_ether_socket == INVALID_RAW_SOCKET) {
_ether_socket = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (_ether_socket == -1)
throw SocketOpenError(make_error_string());
_sockets[ETHER_SOCKET] = sock;
}
#endif
}
#endif // WIN32
@@ -97,7 +163,7 @@ void PacketSender::open_l3_socket(SocketType type) {
throw InvalidSocketTypeError();
if(_sockets[type] == INVALID_RAW_SOCKET) {
int sockfd;
sockfd = socket(AF_INET, SOCK_RAW, socktype);
sockfd = socket((type == IPV6_SOCKET) ? AF_INET6 : AF_INET, SOCK_RAW, socktype);
if (sockfd < 0)
throw SocketOpenError(make_error_string());
@@ -113,16 +179,34 @@ void PacketSender::open_l3_socket(SocketType type) {
}
}
void PacketSender::close_socket(SocketType type) {
if(type >= SOCKETS_END || _sockets[type] == INVALID_RAW_SOCKET)
throw InvalidSocketTypeError();
#ifndef WIN32
if(close(_sockets[type]) == -1)
throw SocketCloseError(make_error_string());
#else
closesocket(_sockets[type]);
#endif
_sockets[type] = INVALID_RAW_SOCKET;
void PacketSender::close_socket(SocketType type, const NetworkInterface &iface) {
if(type == ETHER_SOCKET) {
#ifdef BSD
BSDEtherSockets::iterator it = _ether_socket.find(iface.id());
if(it == _ether_socket.end())
throw InvalidSocketTypeError();
if(::close(it->second) == -1)
throw SocketCloseError(make_error_string());
_ether_socket.erase(it);
#elif !defined(WIN32)
if(_ether_socket == INVALID_RAW_SOCKET)
throw InvalidSocketTypeError();
if(::close(_ether_socket) == -1)
throw SocketCloseError(make_error_string());
_ether_socket = INVALID_RAW_SOCKET;
#endif
}
else {
if(type >= SOCKETS_END || _sockets[type] == INVALID_RAW_SOCKET)
throw InvalidSocketTypeError();
#ifndef WIN32
if(close(_sockets[type]) == -1)
throw SocketCloseError(make_error_string());
#else
closesocket(_sockets[type]);
#endif
_sockets[type] = INVALID_RAW_SOCKET;
}
}
void PacketSender::send(PDU &pdu) {
@@ -139,20 +223,24 @@ PDU *PacketSender::send_recv(PDU &pdu) {
return pdu.recv_response(*this);
}
#ifndef WIN32
void PacketSender::send_l2(PDU &pdu, struct sockaddr* link_addr, uint32_t len_addr) {
open_l2_socket();
int sock = _sockets[ETHER_SOCKET];
void PacketSender::send_l2(PDU &pdu, struct sockaddr* link_addr,
uint32_t len_addr, const NetworkInterface &iface) {
int sock = get_ether_socket(iface);
PDU::serialization_type buffer = pdu.serialize();
if(!buffer.empty()) {
if(sendto(sock, &buffer[0], buffer.size(), 0, link_addr, len_addr) == -1)
#ifdef BSD
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());
}
}
PDU *PacketSender::recv_l2(PDU &pdu, struct sockaddr *link_addr, uint32_t len_addr) {
open_l2_socket();
return recv_match_loop(_sockets[ETHER_SOCKET], pdu, link_addr, len_addr);
PDU *PacketSender::recv_l2(PDU &pdu, struct sockaddr *link_addr,
uint32_t len_addr, const NetworkInterface &iface) {
int sock = get_ether_socket(iface);
return recv_match_loop(sock, pdu, link_addr, len_addr);
}
#endif // WIN32
@@ -184,16 +272,26 @@ PDU *PacketSender::recv_match_loop(int sock, PDU &pdu, struct sockaddr* link_add
return 0;
}
if(FD_ISSET(sock, &readfds)) {
ssize_t size = recvfrom(sock, (char*)buffer, 2048, 0, link_addr, &addrlen);
#ifdef WIN32
int length = addrlen;
int size;
#else
socklen_t length = addrlen;
ssize_t size;
#endif
size = recvfrom(sock, (char*)buffer, 2048, 0, link_addr, &length);
if(pdu.matches_response(buffer, size)) {
return pdu.clone_packet(buffer, size);
}
}
struct timeval this_time, diff;
gettimeofday(&this_time, 0);
if(timeval_subtract(&diff, &end_time, &this_time)) {
#ifdef WIN32
// fixme
#else
gettimeofday(&this_time, 0);
#endif // WIN32
if(timeval_subtract(&diff, &end_time, &this_time))
return 0;
}
timeout.tv_sec = diff.tv_sec;
timeout.tv_usec = diff.tv_usec;
}

View File

@@ -47,19 +47,40 @@ PacketWriter::PacketWriter(const std::string &file_name, LinkType lt) {
}
}
#if TINS_IS_CXX11
PacketWriter::PacketWriter(PacketWriter &&rhs) noexcept {
*this = std::move(rhs);
}
PacketWriter& PacketWriter::operator=(PacketWriter &&rhs) noexcept {
handle = 0;
dumper = 0;
std::swap(handle, rhs.handle);
std::swap(dumper, rhs.dumper);
return *this;
}
#endif
PacketWriter::~PacketWriter() {
pcap_dump_close(dumper);
pcap_close(handle);
if(dumper && handle) {
pcap_dump_close(dumper);
pcap_close(handle);
}
}
void PacketWriter::write(PDU &pdu) {
PDU::serialization_type buffer = pdu.serialize();
struct timeval tm;
gettimeofday(&tm, 0);
timeval tm;
#ifndef WIN32
gettimeofday(&tm, 0);
#else
// fixme
tm = timeval();
#endif
struct pcap_pkthdr header = {
tm,
buffer.size(),
buffer.size()
static_cast<bpf_u_int32>(buffer.size()),
static_cast<bpf_u_int32>(buffer.size())
};
pcap_dump((u_char*)dumper, &header, &buffer[0]);
}

View File

@@ -71,7 +71,7 @@ void PDU::send(PacketSender &) {
}
PDU *PDU::recv_response(PacketSender &) {
return false;
return 0;
}
void PDU::inner_pdu(PDU *next_pdu) {

View File

@@ -30,9 +30,14 @@
#include <cstring>
#include <cassert>
#include <stdexcept>
#include "macros.h"
#ifndef WIN32
#ifdef BSD
#include <net/if_dl.h>
#else
#include <netpacket/packet.h>
#endif
#include <net/ethernet.h>
#include <netpacket/packet.h>
#endif
#include "radiotap.h"
#include "dot11.h"
@@ -222,27 +227,33 @@ uint32_t RadioTap::trailer_size() const {
return ((_flags & 0x10) != 0) ? sizeof(uint32_t) : 0;
}
#ifndef WIN32
void RadioTap::send(PacketSender &sender) {
if(!_iface)
throw std::runtime_error("Interface has not been set");
struct sockaddr_ll addr;
#ifndef BSD
struct sockaddr_ll addr;
memset(&addr, 0, sizeof(struct sockaddr_ll));
memset(&addr, 0, sizeof(struct sockaddr_ll));
addr.sll_family = Endian::host_to_be<uint16_t>(PF_PACKET);
addr.sll_protocol = Endian::host_to_be<uint16_t>(ETH_P_ALL);
addr.sll_halen = 6;
addr.sll_ifindex = _iface.id();
Tins::Dot11 *wlan = dynamic_cast<Tins::Dot11*>(inner_pdu());
if(wlan) {
Tins::Dot11::address_type dot11_addr(wlan->addr1());
std::copy(dot11_addr.begin(), dot11_addr.end(), addr.sll_addr);
}
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();
Tins::Dot11 *wlan = dynamic_cast<Tins::Dot11*>(inner_pdu());
if(wlan) {
Tins::Dot11::address_type dot11_addr(wlan->addr1());
std::copy(dot11_addr.begin(), dot11_addr.end(), addr.sll_addr);
}
sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
#else
sender.send_l2(*this, 0, 0, _iface);
#endif
}
#endif
void RadioTap::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
uint32_t sz = header_size();

91
src/sll.cpp Normal file
View File

@@ -0,0 +1,91 @@
/*
* Copyright (c) 2012, Nasel
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdexcept>
#include <cstring>
#include "sll.h"
#include "internals.h"
namespace Tins {
SLL::SLL() : _header() {
}
SLL::SLL(const uint8_t *buffer, uint32_t total_sz) {
const char *err_msg = "Not enough size for a SLL header";
if(total_sz < sizeof(_header))
throw std::runtime_error(err_msg);
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)protocol(),
buffer,
total_sz
)
);
}
}
void SLL::packet_type(uint16_t new_packet_type) {
_header.packet_type = Endian::host_to_be(new_packet_type);
}
void SLL::lladdr_type(uint16_t new_lladdr_type) {
_header.lladdr_type = Endian::host_to_be(new_lladdr_type);
}
void SLL::lladdr_len(uint16_t new_lladdr_len) {
_header.lladdr_len = Endian::host_to_be(new_lladdr_len);
}
void SLL::address(const address_type &new_address) {
new_address.copy(_header.address);
}
void SLL::protocol(uint16_t new_protocol) {
_header.protocol = Endian::host_to_be(new_protocol);
}
uint32_t SLL::header_size() const {
return sizeof(_header);
}
void SLL::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) {
if(inner_pdu()) {
Constants::Ethernet::e flag = Internals::pdu_flag_to_ether_type(
inner_pdu()->pdu_type()
);
protocol(static_cast<uint16_t>(flag));
}
std::memcpy(buffer, &_header, sizeof(_header));
}
}

View File

@@ -38,6 +38,7 @@
#include "arp.h"
#include "ip.h"
#include "eapol.h"
#include "internals.h"
Tins::SNAP::SNAP(PDU *child) : PDU(child)
@@ -55,7 +56,7 @@ Tins::SNAP::SNAP(const uint8_t *buffer, uint32_t total_sz)
buffer += sizeof(_snap);
total_sz -= sizeof(_snap);
if(total_sz) {
switch(eth_type()) {
/*switch(eth_type()) {
case Tins::Constants::Ethernet::IP:
inner_pdu(new Tins::IP(buffer, total_sz));
break;
@@ -65,7 +66,14 @@ Tins::SNAP::SNAP(const uint8_t *buffer, uint32_t total_sz)
case Tins::Constants::Ethernet::EAPOL:
inner_pdu(Tins::EAPOL::from_bytes(buffer, total_sz));
break;
};
};*/
inner_pdu(
Internals::pdu_from_flag(
(Constants::Ethernet::e)eth_type(),
buffer,
total_sz
)
);
}
}
@@ -96,7 +104,7 @@ uint32_t Tins::SNAP::header_size() const {
void Tins::SNAP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
assert(total_sz >= sizeof(_snap));
if (!_snap.eth_type && inner_pdu()) {
uint16_t type = ETHERTYPE_IP;
uint16_t type = Tins::Constants::Ethernet::IP;
switch (inner_pdu()->pdu_type()) {
case PDU::IP:
type = Tins::Constants::Ethernet::IP;

View File

@@ -27,6 +27,7 @@
*
*/
#include <algorithm>
#include "sniffer.h"
@@ -38,6 +39,24 @@ BaseSniffer::BaseSniffer() : handle(0), mask(0)
{
actual_filter.bf_insns = 0;
}
#if TINS_IS_CXX11
BaseSniffer::BaseSniffer(BaseSniffer &&rhs) noexcept
{
*this = std::move(rhs);
}
BaseSniffer& 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
BaseSniffer::~BaseSniffer() {
if(actual_filter.bf_insns)
@@ -62,34 +81,34 @@ bool BaseSniffer::compile_set_filter(const string &filter, bpf_program &prog) {
return (pcap_compile(handle, &prog, filter.c_str(), 0, mask) != -1 && pcap_setfilter(handle, &prog) != -1);
}
PDU *BaseSniffer::next_packet() {
PtrPacket BaseSniffer::next_packet() {
pcap_pkthdr header;
PDU *ret = 0;
while(!ret) {
const u_char *content = pcap_next(handle, &header);
if(content) {
try {
if(iface_type == DLT_EN10MB)
ret = new EthernetII((const uint8_t*)content, header.caplen);
else if(iface_type == DLT_IEEE802_11_RADIO)
ret = new RadioTap((const uint8_t*)content, header.caplen);
else if(iface_type == DLT_IEEE802_11)
ret = Dot11::from_bytes((const uint8_t*)content, header.caplen);
else if(iface_type == DLT_LOOP)
ret = new Tins::Loopback((const uint8_t*)content, header.caplen);
}
catch(...) {
ret = 0;
}
}
const u_char *content = pcap_next(handle, &header);
// timestamp_ = header.ts;
if(content) {
if(iface_type == DLT_EN10MB)
ret = new EthernetII((const uint8_t*)content, header.caplen);
else if(iface_type == DLT_IEEE802_11_RADIO)
ret = new RadioTap((const uint8_t*)content, header.caplen);
else if(iface_type == DLT_IEEE802_11)
ret = Dot11::from_bytes((const uint8_t*)content, header.caplen);
else if(iface_type == DLT_LOOP)
ret = new Tins::Loopback((const uint8_t*)content, header.caplen);
else if(iface_type == DLT_LINUX_SLL)
ret = new Tins::SLL((const uint8_t*)content, header.caplen);
}
return ret;
return PtrPacket(ret, header.ts);
}
void BaseSniffer::stop_sniff() {
pcap_breakloop(handle);
}
int BaseSniffer::get_fd() {
return pcap_get_selectable_fd(handle);
}
bool BaseSniffer::set_filter(const std::string &filter) {
if(actual_filter.bf_insns)
pcap_freecode(&actual_filter);

View File

@@ -31,6 +31,7 @@
#include <cassert>
#include "tcp.h"
#include "ip.h"
#include "ipv6.h"
#include "constants.h"
#include "rawpdu.h"
#include "utils.h"
@@ -148,7 +149,7 @@ void TCP::sack_permitted() {
}
bool TCP::has_sack_permitted() const {
return search_option(SACK_OK);
return bool(search_option(SACK_OK));
}
void TCP::sack(const sack_type &edges) {
@@ -188,7 +189,7 @@ std::pair<uint32_t, uint32_t> TCP::timestamp() const {
throw option_not_found();
uint64_t buffer = *(const uint64_t*)option->data_ptr();
buffer = Endian::be_to_host(buffer);
return std::make_pair((buffer >> 32) & 0xffffffff, buffer & 0xffffffff);
return std::make_pair(static_cast<uint32_t>(buffer >> 32), buffer & 0xffffffff);
}
void TCP::altchecksum(AltChecksums value) {
@@ -297,18 +298,35 @@ void TCP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *par
}
}
const Tins::IP *ip_packet = dynamic_cast<const Tins::IP*>(parent);
memcpy(tcp_start, &_tcp, sizeof(tcphdr));
if(!_tcp.check && ip_packet) {
uint32_t checksum = Utils::pseudoheader_checksum(ip_packet->src_addr(),
ip_packet->dst_addr(),
size(), Constants::IP::PROTO_TCP) +
Utils::do_checksum(tcp_start, tcp_start + total_sz);
while (checksum >> 16)
checksum = (checksum & 0xffff) + (checksum >> 16);
((tcphdr*)tcp_start)->check = Endian::host_to_be<uint16_t>(~checksum);
if(!_tcp.check) {
const Tins::IP *ip_packet = dynamic_cast<const Tins::IP*>(parent);
if(ip_packet) {
uint32_t checksum = Utils::pseudoheader_checksum(ip_packet->src_addr(),
ip_packet->dst_addr(),
size(), Constants::IP::PROTO_TCP) +
Utils::do_checksum(tcp_start, tcp_start + total_sz);
while (checksum >> 16)
checksum = (checksum & 0xffff) + (checksum >> 16);
((tcphdr*)tcp_start)->check = Endian::host_to_be<uint16_t>(~checksum);
}
else {
const Tins::IPv6 *ipv6_packet = dynamic_cast<const Tins::IPv6*>(parent);
if(ipv6_packet) {
uint32_t checksum = Utils::pseudoheader_checksum(ipv6_packet->src_addr(),
ipv6_packet->dst_addr(),
size(), Constants::IP::PROTO_TCP) +
Utils::do_checksum(tcp_start, tcp_start + total_sz);
while (checksum >> 16)
checksum = (checksum & 0xffff) + (checksum >> 16);
((tcphdr*)tcp_start)->check = Endian::host_to_be<uint16_t>(~checksum);
}
}
}
_tcp.check = 0;
}

View File

@@ -32,19 +32,25 @@
#include <memory>
#include <cassert>
#include <cstring>
#include "utils.h"
#ifndef WIN32
#ifdef BSD
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if_dl.h>
#else
#include <netpacket/packet.h>
#endif
#include <netdb.h>
#include <linux/if_packet.h>
#include <net/if.h>
#endif
#include "utils.h"
#include "pdu.h"
#include "arp.h"
#include "ethernetII.h"
#include "endianness.h"
#include "network_interface.h"
#include "packet_sender.h"
#include "cxxstd.h"
using namespace std;
@@ -52,14 +58,21 @@ using namespace std;
/** \cond */
struct InterfaceCollector {
set<string> ifaces;
#ifdef WIN32
bool operator() (PIP_ADAPTER_ADDRESSES addr) {
ifaces.insert(addr->AdapterName);
return true;
}
#else
bool operator() (struct ifaddrs *addr) {
ifaces.insert(addr->ifa_name);
return true;
}
#endif
};
struct IPv4Collector {
/*struct IPv4Collector {
uint32_t ip;
bool found;
const char *iface;
@@ -73,33 +86,10 @@ struct IPv4Collector {
}
return found;
}
};
};*/
namespace Tins {
bool Utils::Internals::from_hex(const string &str, uint32_t &result) {
unsigned i(0);
result = 0;
while(i < str.size()) {
uint8_t tmp;
if(str[i] >= 'A' && str[i] <= 'F')
tmp = (str[i] - 'A' + 10);
else if(str[i] >= '0' && str[i] <= '9')
tmp = (str[i] - '0');
else
return false;
result = (result << 4) | tmp;
i++;
}
return true;
}
void Utils::Internals::skip_line(istream &input) {
int c = 0;
while(c != '\n' && input)
c = input.get();
}
/** \endcond */
IPv4Address Utils::resolve_ip(const string &to_resolve) {
@@ -115,12 +105,16 @@ bool Utils::resolve_hwaddr(const NetworkInterface &iface, IPv4Address ip,
IPv4Address my_ip;
NetworkInterface::Info info(iface.addresses());
EthernetII packet = ARP::make_arp_request(iface, ip, info.ip_addr, info.hw_addr);
std::auto_ptr<PDU> response(sender.send_recv(packet));
#if TINS_IS_CXX11
std::unique_ptr<PDU> response(sender.send_recv(packet));
#else
std::auto_ptr<PDU> response(sender.send_recv(packet));
#endif
if(response.get()) {
ARP *arp_resp = response->find_pdu<ARP>();
if(arp_resp)
*address = arp_resp->sender_hw_addr();
return arp_resp;
return arp_resp != 0;
}
else
return false;
@@ -184,11 +178,23 @@ uint32_t Utils::pseudoheader_checksum(IPv4Address source_ip, IPv4Address dest_ip
uint32_t checksum(0);
uint32_t source_ip_int = Endian::host_to_be<uint32_t>(source_ip),
dest_ip_int = Endian::host_to_be<uint32_t>(dest_ip);
uint16_t *ptr = (uint16_t*)&source_ip_int;
char buffer[sizeof(uint32_t) * 2];
uint16_t *ptr = (uint16_t*)buffer, *end = (uint16_t*)(buffer + sizeof(buffer));
std::memcpy(buffer, &source_ip_int, sizeof(source_ip_int));
std::memcpy(buffer + sizeof(uint32_t), &dest_ip_int, sizeof(dest_ip_int));
while(ptr < end)
checksum += (uint32_t)*ptr++;
checksum += flag + len;
return checksum;
}
checksum += (uint32_t)(*ptr) + (uint32_t)(*(ptr+1));
ptr = (uint16_t*)&dest_ip_int;
checksum += (uint32_t)(*ptr) + (uint32_t)(*(ptr+1));
uint32_t Utils::pseudoheader_checksum(IPv6Address source_ip, IPv6Address dest_ip, uint32_t len, uint32_t flag) {
uint32_t checksum = 0;
IPv6Address::const_iterator it;
for(it = source_ip.begin(); it != source_ip.end(); ++it)
checksum += *it;
for(it = dest_ip.begin(); it != dest_ip.end(); ++it)
checksum += *it;
checksum += flag + len;
return checksum;
}

View File

@@ -1,7 +1,7 @@
CXX=@CXX@
CFLAGS=-c -Wall @CFLAGS@ -DTINS_VERSION=@PACKAGE_VERSION@
LDFLAGS=-lpcap -lgtest -lpthread
SOURCES=$(wildcard src/*.cpp src/dot11/*.cpp ../src/*.cpp)
SOURCES=@SOURCE_FILES@
OBJECTS=$(SOURCES:.cpp=.o)
INCLUDE=-Iinclude/ -I../include
@@ -32,4 +32,4 @@ $(EXECUTABLE): $(OBJECTS)
clean:
rm $(OBJECTS) $(EXECUTABLE)
-include depends.d
include depends.d

157
tests/configure vendored
View File

@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.67 for myconfig 0.1.
# Generated by GNU Autoconf 2.68 for myconfig 0.1.
#
#
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -89,6 +89,7 @@ fi
IFS=" "" $as_nl"
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
*[\\/]* ) as_myself=$0 ;;
*) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -214,11 +215,18 @@ IFS=$as_save_IFS
# We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
# works around shells that cannot unset nonexistent variables.
# Preserve -v and -x to the replacement shell.
BASH_ENV=/dev/null
ENV=/dev/null
(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
export CONFIG_SHELL
exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
case $- in # ((((
*v*x* | *x*v* ) as_opts=-vx ;;
*v* ) as_opts=-v ;;
*x* ) as_opts=-x ;;
* ) as_opts= ;;
esac
exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
fi
if test x$as_have_required = xno; then :
@@ -592,6 +600,7 @@ ac_includes_default="\
ac_subst_vars='LTLIBOBJS
LIBOBJS
SOURCE_FILES
CFLAGS
EGREP
GREP
@@ -644,6 +653,7 @@ SHELL'
ac_subst_files=''
ac_user_opts='
enable_option_checking
enable_c__11
'
ac_precious_vars='build_alias
host_alias
@@ -1059,7 +1069,7 @@ Try \`$0 --help' for more information"
$as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
$as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
: ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
: "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
;;
esac
@@ -1262,6 +1272,12 @@ if test -n "$ac_init_help"; then
esac
cat <<\_ACEOF
Optional Features:
--disable-option-checking ignore unrecognized --enable/--with options
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--enable-c++11 enable C++11 features
Some influential environment variables:
CXX C++ compiler command
CXXFLAGS C++ compiler flags
@@ -1339,7 +1355,7 @@ test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
myconfig configure 0.1
generated by GNU Autoconf 2.67
generated by GNU Autoconf 2.68
Copyright (C) 2010 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
@@ -1385,7 +1401,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
fi
eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_cxx_try_compile
@@ -1422,7 +1438,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
fi
eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_cxx_try_cpp
@@ -1435,10 +1451,10 @@ fi
ac_fn_cxx_check_header_mongrel ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
if eval "test \"\${$3+set}\"" = set; then :
if eval \${$3+:} false; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
if eval "test \"\${$3+set}\"" = set; then :
if eval \${$3+:} false; then :
$as_echo_n "(cached) " >&6
fi
eval ac_res=\$$3
@@ -1501,7 +1517,7 @@ $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
if eval "test \"\${$3+set}\"" = set; then :
if eval \${$3+:} false; then :
$as_echo_n "(cached) " >&6
else
eval "$3=\$ac_header_compiler"
@@ -1510,7 +1526,7 @@ eval ac_res=\$$3
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
fi
eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_cxx_check_header_mongrel
@@ -1551,7 +1567,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=$ac_status
fi
rm -rf conftest.dSYM conftest_ipa8_conftest.oo
eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_cxx_try_run
@@ -1565,7 +1581,7 @@ ac_fn_cxx_check_header_compile ()
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
if eval "test \"\${$3+set}\"" = set; then :
if eval \${$3+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -1583,7 +1599,7 @@ fi
eval ac_res=\$$3
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_cxx_check_header_compile
@@ -1628,7 +1644,7 @@ fi
# interfere with the next link command; also delete a directory that is
# left behind by Apple's compiler. We do this before executing the actions.
rm -rf conftest.dSYM conftest_ipa8_conftest.oo
eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_cxx_try_link
@@ -1637,7 +1653,7 @@ This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by myconfig $as_me 0.1, which was
generated by GNU Autoconf 2.67. Invocation command line was
generated by GNU Autoconf 2.68. Invocation command line was
$ $0 $@
@@ -1895,7 +1911,7 @@ $as_echo "$as_me: loading site script $ac_site_file" >&6;}
|| { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "failed to load site script $ac_site_file
See \`config.log' for more details" "$LINENO" 5 ; }
See \`config.log' for more details" "$LINENO" 5; }
fi
done
@@ -2001,7 +2017,7 @@ if test -z "$CXX"; then
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if test "${ac_cv_prog_CXX+set}" = set; then :
if ${ac_cv_prog_CXX+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$CXX"; then
@@ -2045,7 +2061,7 @@ do
set dummy $ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then :
if ${ac_cv_prog_ac_ct_CXX+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$ac_ct_CXX"; then
@@ -2209,7 +2225,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "C++ compiler cannot create executables
See \`config.log' for more details" "$LINENO" 5 ; }
See \`config.log' for more details" "$LINENO" 5; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
@@ -2252,7 +2268,7 @@ else
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of executables: cannot compile and link
See \`config.log' for more details" "$LINENO" 5 ; }
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest conftest$ac_cv_exeext
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
@@ -2311,7 +2327,7 @@ $as_echo "$ac_try_echo"; } >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot run C++ compiled programs.
If you meant to cross compile, use \`--host'.
See \`config.log' for more details" "$LINENO" 5 ; }
See \`config.log' for more details" "$LINENO" 5; }
fi
fi
fi
@@ -2322,7 +2338,7 @@ rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
ac_clean_files=$ac_clean_files_save
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
$as_echo_n "checking for suffix of object files... " >&6; }
if test "${ac_cv_objext+set}" = set; then :
if ${ac_cv_objext+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -2363,7 +2379,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of object files: cannot compile
See \`config.log' for more details" "$LINENO" 5 ; }
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest.$ac_cv_objext conftest.$ac_ext
fi
@@ -2373,7 +2389,7 @@ OBJEXT=$ac_cv_objext
ac_objext=$OBJEXT
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
if test "${ac_cv_cxx_compiler_gnu+set}" = set; then :
if ${ac_cv_cxx_compiler_gnu+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -2410,7 +2426,7 @@ ac_test_CXXFLAGS=${CXXFLAGS+set}
ac_save_CXXFLAGS=$CXXFLAGS
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
$as_echo_n "checking whether $CXX accepts -g... " >&6; }
if test "${ac_cv_prog_cxx_g+set}" = set; then :
if ${ac_cv_prog_cxx_g+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_save_cxx_werror_flag=$ac_cxx_werror_flag
@@ -2499,7 +2515,16 @@ ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ex
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
CFLAGS="-DDEBUG -g"
CFLAGS="-DTINS_DEBUG -g"
# Check whether --enable-c++11 was given.
if test "${enable_c__11+set}" = set; then :
enableval=$enable_c__11; CFLAGS="$CFLAGS -std=c++0x"
fi
SOURCE_FILES=$(ls ../src/*cpp src/*cpp src/dot11/*cpp | tr '\n' ' ')
ac_ext=cpp
@@ -2510,7 +2535,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5
$as_echo_n "checking how to run the C++ preprocessor... " >&6; }
if test -z "$CXXCPP"; then
if test "${ac_cv_prog_CXXCPP+set}" = set; then :
if ${ac_cv_prog_CXXCPP+:} false; then :
$as_echo_n "(cached) " >&6
else
# Double quotes because CXXCPP needs to be expanded
@@ -2626,7 +2651,7 @@ else
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check
See \`config.log' for more details" "$LINENO" 5 ; }
See \`config.log' for more details" "$LINENO" 5; }
fi
ac_ext=cpp
@@ -2638,7 +2663,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
if test "${ac_cv_path_GREP+set}" = set; then :
if ${ac_cv_path_GREP+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -z "$GREP"; then
@@ -2701,7 +2726,7 @@ $as_echo "$ac_cv_path_GREP" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
$as_echo_n "checking for egrep... " >&6; }
if test "${ac_cv_path_EGREP+set}" = set; then :
if ${ac_cv_path_EGREP+:} false; then :
$as_echo_n "(cached) " >&6
else
if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
@@ -2768,7 +2793,7 @@ $as_echo "$ac_cv_path_EGREP" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
$as_echo_n "checking for ANSI C header files... " >&6; }
if test "${ac_cv_header_stdc+set}" = set; then :
if ${ac_cv_header_stdc+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -2910,7 +2935,7 @@ done
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcap_loop in -lpcap" >&5
$as_echo_n "checking for pcap_loop in -lpcap... " >&6; }
if test "${ac_cv_lib_pcap_pcap_loop+set}" = set; then :
if ${ac_cv_lib_pcap_pcap_loop+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
@@ -2944,7 +2969,7 @@ LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcap_pcap_loop" >&5
$as_echo "$ac_cv_lib_pcap_pcap_loop" >&6; }
if test "x$ac_cv_lib_pcap_pcap_loop" = x""yes; then :
if test "x$ac_cv_lib_pcap_pcap_loop" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBPCAP 1
_ACEOF
@@ -2957,6 +2982,7 @@ fi
#AC_CHECK_LIB([gtest_main], [main], [], [AC_MSG_ERROR([gtest library is needed!])])
ac_config_files="$ac_config_files Makefile"
cat >confcache <<\_ACEOF
@@ -3023,10 +3049,21 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
:end' >>confcache
if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
if test -w "$cache_file"; then
test "x$cache_file" != "x/dev/null" &&
if test "x$cache_file" != "x/dev/null"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
$as_echo "$as_me: updating cache $cache_file" >&6;}
cat confcache >$cache_file
if test ! -f "$cache_file" || test -h "$cache_file"; then
cat confcache >"$cache_file"
else
case $cache_file in #(
*/* | ?:*)
mv -f confcache "$cache_file"$$ &&
mv -f "$cache_file"$$ "$cache_file" ;; #(
*)
mv -f confcache "$cache_file" ;;
esac
fi
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
@@ -3094,7 +3131,7 @@ LTLIBOBJS=$ac_ltlibobjs
: ${CONFIG_STATUS=./config.status}
: "${CONFIG_STATUS=./config.status}"
ac_write_fail=0
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files $CONFIG_STATUS"
@@ -3195,6 +3232,7 @@ fi
IFS=" "" $as_nl"
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
*[\\/]* ) as_myself=$0 ;;
*) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -3502,7 +3540,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# values after options handling.
ac_log="
This file was extended by myconfig $as_me 0.1, which was
generated by GNU Autoconf 2.67. Invocation command line was
generated by GNU Autoconf 2.68. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
@@ -3555,7 +3593,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
myconfig config.status 0.1
configured by $0, generated by GNU Autoconf 2.67,
configured by $0, generated by GNU Autoconf 2.68,
with options \\"\$ac_cs_config\\"
Copyright (C) 2010 Free Software Foundation, Inc.
@@ -3666,7 +3704,7 @@ do
case $ac_config_target in
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;;
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
esac
done
@@ -3687,9 +3725,10 @@ fi
# after its creation but before its name has been assigned to `$tmp'.
$debug ||
{
tmp=
tmp= ac_tmp=
trap 'exit_status=$?
{ test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
: "${ac_tmp:=$tmp}"
{ test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
' 0
trap 'as_fn_exit 1' 1 2 13 15
}
@@ -3697,12 +3736,13 @@ $debug ||
{
tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
test -n "$tmp" && test -d "$tmp"
test -d "$tmp"
} ||
{
tmp=./conf$$-$RANDOM
(umask 077 && mkdir "$tmp")
} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
ac_tmp=$tmp
# Set up the scripts for CONFIG_FILES section.
# No need to generate them if there are no CONFIG_FILES.
@@ -3724,7 +3764,7 @@ else
ac_cs_awk_cr=$ac_cr
fi
echo 'BEGIN {' >"$tmp/subs1.awk" &&
echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
_ACEOF
@@ -3752,7 +3792,7 @@ done
rm -f conf$$subs.sh
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
cat >>"\$tmp/subs1.awk" <<\\_ACAWK &&
cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
_ACEOF
sed -n '
h
@@ -3800,7 +3840,7 @@ t delim
rm -f conf$$subs.awk
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
_ACAWK
cat >>"\$tmp/subs1.awk" <<_ACAWK &&
cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
for (key in S) S_is_set[key] = 1
FS = ""
@@ -3832,7 +3872,7 @@ if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
else
cat
fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \
fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
|| as_fn_error $? "could not setup config files machinery" "$LINENO" 5
_ACEOF
@@ -3872,7 +3912,7 @@ do
esac
case $ac_mode$ac_tag in
:[FHL]*:*);;
:L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5 ;;
:L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
:[FH]-) ac_tag=-:-;;
:[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
esac
@@ -3891,7 +3931,7 @@ do
for ac_f
do
case $ac_f in
-) ac_f="$tmp/stdin";;
-) ac_f="$ac_tmp/stdin";;
*) # Look for the file first in the build tree, then in the source tree
# (if the path is not absolute). The absolute path cannot be DOS-style,
# because $ac_f cannot contain `:'.
@@ -3900,7 +3940,7 @@ do
[\\/$]*) false;;
*) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
esac ||
as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5 ;;
as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
esac
case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
as_fn_append ac_file_inputs " '$ac_f'"
@@ -3926,8 +3966,8 @@ $as_echo "$as_me: creating $ac_file" >&6;}
esac
case $ac_tag in
*:-:* | *:-) cat >"$tmp/stdin" \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
*:-:* | *:-) cat >"$ac_tmp/stdin" \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
esac
;;
esac
@@ -4052,21 +4092,22 @@ s&@abs_builddir@&$ac_abs_builddir&;t t
s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
$ac_datarootdir_hack
"
eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
>$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
{ ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
{ ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
{ ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
{ ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
"$ac_tmp/out"`; test -z "$ac_out"; } &&
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&5
$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&2;}
rm -f "$tmp/stdin"
rm -f "$ac_tmp/stdin"
case $ac_file in
-) cat "$tmp/out" && rm -f "$tmp/out";;
*) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";;
-) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
*) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
esac \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
;;

View File

@@ -3,10 +3,19 @@ AC_INIT(myconfig, 0.1)
AC_PROG_CXX()
AC_LANG(C++)
CFLAGS="-DDEBUG -g"
CFLAGS="-DTINS_DEBUG -g"
AC_ARG_ENABLE(
c++11,
[ --enable-c++11 enable C++11 features],
[CFLAGS="$CFLAGS -std=c++0x"]
)
SOURCE_FILES=$(ls ../src/*cpp src/*cpp src/dot11/*cpp | tr '\n' ' ')
AC_CHECK_HEADERS([pcap.h gtest/gtest.h])
AC_CHECK_LIB(pcap, pcap_loop, [], [AC_MSG_ERROR([pcap library is needed!])])
#AC_CHECK_LIB([gtest_main], [main], [], [AC_MSG_ERROR([gtest library is needed!])])
AC_SUBST(CFLAGS)
AC_SUBST(SOURCE_FILES)
AC_OUTPUT(Makefile)

File diff suppressed because it is too large Load Diff

339
tests/src/dhcpv6.cpp Normal file
View File

@@ -0,0 +1,339 @@
#include <gtest/gtest.h>
#include <cstring>
#include <string>
#include <stdint.h>
#include "dhcpv6.h"
using namespace Tins;
class DHCPv6Test : public testing::Test {
public:
static const uint8_t expected_packet[];
void test_equals(const DHCPv6 &dhcp1, const DHCPv6 &dhcp2);
};
const uint8_t DHCPv6Test::expected_packet[] = {
'\x01', '\xe8', '(', '\xb9', '\x00', '\x01', '\x00', '\n', '\x00',
'\x03', '\x00', '\x01', '\x00', '\x01', '\x02', '\x03', '\x04',
'\x05', '\x00', '\x03', '\x00', '\x0c', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x08', '\x00', '\x02', '\x00', '\x00', '\x00',
'\x06', '\x00', '\x02', '\x00', '\x03'
};
TEST_F(DHCPv6Test, DefaultConstructor) {
DHCPv6 dhcp;
EXPECT_EQ(0, (int)dhcp.msg_type());
EXPECT_EQ(0, dhcp.hop_count());
EXPECT_EQ(0, dhcp.transaction_id());
}
TEST_F(DHCPv6Test, ConstructorFromBuffer) {
DHCPv6 dhcp(expected_packet, sizeof(expected_packet));
EXPECT_EQ(DHCPv6::SOLICIT, dhcp.msg_type());
EXPECT_EQ(0xe828b9, dhcp.transaction_id());
EXPECT_TRUE(dhcp.search_option(DHCPv6::CLIENTID));
EXPECT_TRUE(dhcp.search_option(DHCPv6::IA_NA));
EXPECT_TRUE(dhcp.search_option(DHCPv6::ELAPSED_TIME));
EXPECT_TRUE(dhcp.search_option(DHCPv6::OPTION_REQUEST));
EXPECT_FALSE(dhcp.search_option(DHCPv6::SERVERID));
}
TEST_F(DHCPv6Test, Serialize) {
DHCPv6 dhcp(expected_packet, sizeof(expected_packet));
DHCPv6::serialization_type buffer = dhcp.serialize();
ASSERT_EQ(sizeof(expected_packet), buffer.size());
EXPECT_EQ(
DHCPv6::serialization_type(expected_packet, expected_packet + sizeof(expected_packet)),
buffer
);
}
TEST_F(DHCPv6Test, MessageType) {
DHCPv6 dhcp;
dhcp.msg_type(DHCPv6::SOLICIT);
EXPECT_EQ(DHCPv6::SOLICIT, dhcp.msg_type());
}
TEST_F(DHCPv6Test, HopCount) {
DHCPv6 dhcp;
dhcp.hop_count(0x8a);
EXPECT_EQ(0x8a, dhcp.hop_count());
}
TEST_F(DHCPv6Test, TransactionId) {
DHCPv6 dhcp;
dhcp.transaction_id(0x8af2ad);
EXPECT_EQ(0x8af2ad, dhcp.transaction_id());
}
// Options
TEST_F(DHCPv6Test, IA_NA) {
DHCPv6 dhcp;
DHCPv6::ia_na_type data, output;
data.id = 0x9283f78a;
data.t1 = 0xaf235212;
data.t2 = 0x9a8293fa;
data.options.push_back(0);
data.options.push_back(1);
data.options.push_back(2);
dhcp.ia_na(data);
output = dhcp.ia_na();
EXPECT_EQ(data.id, output.id);
EXPECT_EQ(data.t1, output.t1);
EXPECT_EQ(data.t2, output.t2);
EXPECT_EQ(data.options, output.options);
}
TEST_F(DHCPv6Test, IA_TA) {
DHCPv6 dhcp;
DHCPv6::ia_ta_type data, output;
data.id = 0x9283f78a;
data.options.push_back(0);
data.options.push_back(1);
data.options.push_back(2);
dhcp.ia_ta(data);
output = dhcp.ia_ta();
EXPECT_EQ(data.id, output.id);
EXPECT_EQ(data.options, output.options);
}
TEST_F(DHCPv6Test, IA_Address) {
DHCPv6 dhcp;
DHCPv6::ia_address_type data, output;
data.address = "fe00:feaa::1";
data.preferred_lifetime = 0x9283f78a;
data.valid_lifetime = 0x938fda32;
data.options.push_back(0);
data.options.push_back(1);
data.options.push_back(2);
dhcp.ia_address(data);
output = dhcp.ia_address();
EXPECT_EQ(data.address, output.address);
EXPECT_EQ(data.preferred_lifetime, output.preferred_lifetime);
EXPECT_EQ(data.valid_lifetime, output.valid_lifetime);
EXPECT_EQ(data.options, output.options);
}
TEST_F(DHCPv6Test, OptionRequest) {
DHCPv6 dhcp;
DHCPv6::option_request_type data, output;
data.push_back(DHCPv6::IA_ADDR);
data.push_back(DHCPv6::IA_NA);
dhcp.option_request(data);
output = dhcp.option_request();
EXPECT_EQ(data, output);
}
TEST_F(DHCPv6Test, Preference) {
DHCPv6 dhcp;
dhcp.preference(0x8a);
EXPECT_EQ(0x8a, dhcp.preference());
}
TEST_F(DHCPv6Test, ElapsedTime) {
DHCPv6 dhcp;
dhcp.elapsed_time(0x8a2f);
EXPECT_EQ(0x8a2f, dhcp.elapsed_time());
}
TEST_F(DHCPv6Test, RelayMessage) {
DHCPv6 dhcp;
DHCPv6::relay_msg_type data, output;
data.push_back(1);
data.push_back(156);
data.push_back(12);
dhcp.relay_message(data);
output = dhcp.relay_message();
EXPECT_EQ(data, output);
}
TEST_F(DHCPv6Test, Authentication) {
DHCPv6 dhcp;
DHCPv6::authentication_type data, output;
data.protocol = 0x92;
data.algorithm = 0x8f;
data.rdm = 0xa1;
data.replay_detection = 0x78ad6d5290398df7;
data.auth_info.push_back(0);
data.auth_info.push_back(1);
data.auth_info.push_back(2);
dhcp.authentication(data);
output = dhcp.authentication();
EXPECT_EQ(data.protocol, output.protocol);
EXPECT_EQ(data.algorithm, output.algorithm);
EXPECT_EQ(data.rdm, output.rdm);
EXPECT_EQ(data.replay_detection, output.replay_detection);
EXPECT_EQ(data.auth_info, output.auth_info);
}
TEST_F(DHCPv6Test, ServerUnicast) {
const IPv6Address addr("fe00:0a9d:dd23::1");
DHCPv6 dhcp;
dhcp.server_unicast(addr);
EXPECT_EQ(addr, dhcp.server_unicast());
}
TEST_F(DHCPv6Test, StatusCode) {
DHCPv6 dhcp;
DHCPv6::status_code_type data(0x72, "libtins, mah frend"), output;
dhcp.status_code(data);
output = dhcp.status_code();
EXPECT_EQ(data.code, output.code);
EXPECT_EQ(data.message, output.message);
}
TEST_F(DHCPv6Test, RapidCommit) {
DHCPv6 dhcp;
dhcp.rapid_commit();
EXPECT_EQ(true, dhcp.has_rapid_commit());
}
TEST_F(DHCPv6Test, UserClass) {
DHCPv6 dhcp;
DHCPv6::user_class_type data, output;
DHCPv6::class_option_data_type user_data;
user_data.push_back(22);
user_data.push_back(176);
data.push_back(user_data);
user_data.push_back(99);
user_data.push_back(231);
data.push_back(user_data);
dhcp.user_class(data);
output = dhcp.user_class();
EXPECT_EQ(data, output);
}
TEST_F(DHCPv6Test, VendorClass) {
DHCPv6 dhcp;
DHCPv6::vendor_class_type data(15), output;
DHCPv6::class_option_data_type user_data;
user_data.push_back(22);
user_data.push_back(176);
data.vendor_class_data.push_back(user_data);
user_data.push_back(99);
user_data.push_back(231);
data.vendor_class_data.push_back(user_data);
dhcp.vendor_class(data);
output = dhcp.vendor_class();
EXPECT_EQ(data.enterprise_number, output.enterprise_number);
EXPECT_EQ(data.vendor_class_data, output.vendor_class_data);
}
TEST_F(DHCPv6Test, VendorInfo) {
DHCPv6 dhcp;
DHCPv6::vendor_info_type data(0x72988fad), output;
data.data.push_back(22);
data.data.push_back(176);
data.data.push_back(99);
data.data.push_back(231);
dhcp.vendor_info(data);
output = dhcp.vendor_info();
EXPECT_EQ(data.enterprise_number, output.enterprise_number);
EXPECT_EQ(data.data, output.data);
}
TEST_F(DHCPv6Test, InterfaceID) {
DHCPv6 dhcp;
DHCPv6::interface_id_type data, output;
data.push_back(1);
data.push_back(156);
data.push_back(12);
dhcp.interface_id(data);
output = dhcp.interface_id();
EXPECT_EQ(data, output);
}
TEST_F(DHCPv6Test, ReconfigureMsg) {
DHCPv6 dhcp;
dhcp.reconfigure_msg(0x8a);
EXPECT_EQ(0x8a, dhcp.reconfigure_msg());
}
TEST_F(DHCPv6Test, ReconfigureAccept) {
DHCPv6 dhcp;
dhcp.reconfigure_accept();
EXPECT_EQ(true, dhcp.has_reconfigure_accept());
}
TEST_F(DHCPv6Test, Client_Server_ID_DUIDLL) {
DHCPv6 dhcp;
DHCPv6::duid_ll data, output;
DHCPv6::duid_type tmp, tmp2;
data.hw_type = 0x5f;
data.lladdress.push_back(78);
data.lladdress.push_back(66);
data.lladdress.push_back(209);
dhcp.client_id(data);
tmp = dhcp.client_id();
output = DHCPv6::duid_ll::from_bytes(&tmp.data[0], tmp.data.size());
EXPECT_EQ(data.hw_type, output.hw_type);
EXPECT_EQ(data.lladdress, output.lladdress);
dhcp.server_id(data);
tmp2 = dhcp.server_id();
EXPECT_EQ(tmp.id, tmp2.id);
EXPECT_EQ(tmp.data, tmp2.data);
}
TEST_F(DHCPv6Test, Client_Server_ID_DUIDLLT) {
DHCPv6 dhcp;
DHCPv6::duid_llt data, output;
DHCPv6::duid_type tmp, tmp2;
data.hw_type = 0x5f;
data.time = 0x92837af;
data.lladdress.push_back(78);
data.lladdress.push_back(66);
data.lladdress.push_back(209);
dhcp.client_id(data);
tmp = dhcp.client_id();
output = DHCPv6::duid_llt::from_bytes(&tmp.data[0], tmp.data.size());
EXPECT_EQ(data.hw_type, output.hw_type);
EXPECT_EQ(data.time, output.time);
EXPECT_EQ(data.lladdress, output.lladdress);
dhcp.server_id(data);
tmp2 = dhcp.server_id();
EXPECT_EQ(tmp.id, tmp2.id);
EXPECT_EQ(tmp.data, tmp2.data);
}
TEST_F(DHCPv6Test, Client_Server_ID_DUIDEN) {
DHCPv6 dhcp;
DHCPv6::duid_en data, output;
DHCPv6::duid_type tmp, tmp2;
data.enterprise_number = 0x5faa23da;
data.identifier.push_back(78);
data.identifier.push_back(66);
data.identifier.push_back(209);
dhcp.client_id(data);
tmp = dhcp.client_id();
output = DHCPv6::duid_en::from_bytes(&tmp.data[0], tmp.data.size());
EXPECT_EQ(data.enterprise_number, output.enterprise_number);
EXPECT_EQ(data.identifier, output.identifier);
dhcp.server_id(data);
tmp2 = dhcp.server_id();
EXPECT_EQ(tmp.id, tmp2.id);
EXPECT_EQ(tmp.data, tmp2.data);
}

View File

@@ -1,6 +1,7 @@
#include <gtest/gtest.h>
#include <iostream>
#include "dns.h"
#include "ipv6_address.h"
#include "utils.h"
using namespace Tins;
@@ -221,4 +222,33 @@ TEST_F(DNSTest, Answers) {
}
}
TEST_F(DNSTest, AnswersWithSameName) {
DNS dns;
dns.add_answer("www.example.com", DNS::make_info(DNS::A, DNS::IN, 0x762), IPv4Address("127.0.0.1"));
dns.add_answer("www.example.com", DNS::make_info(DNS::A, DNS::IN, 0x762), IPv4Address("127.0.0.2"));
ASSERT_EQ(dns.answers_count(), 2);
DNS::resources_type resources = dns.answers();
for(DNS::resources_type::const_iterator it = resources.begin(); it != resources.end(); ++it) {
EXPECT_TRUE(it->data() == "127.0.0.1" || it->data() == "127.0.0.2");
EXPECT_EQ(it->dname(), "www.example.com");
EXPECT_EQ(it->type(), DNS::A);
EXPECT_EQ(it->ttl(), 0x762);
EXPECT_EQ(it->query_class(), DNS::IN);
}
}
TEST_F(DNSTest, AnswersV6) {
DNS dns;
dns.add_answer("www.example.com", DNS::make_info(DNS::AAAA, DNS::IN, 0x762), IPv6Address("f9a8:239::1:1"));
dns.add_answer("www.example.com", DNS::make_info(DNS::AAAA, DNS::IN, 0x762), IPv6Address("f9a8:239::1:1"));
ASSERT_EQ(dns.answers_count(), 2);
DNS::resources_type resources = dns.answers();
for(DNS::resources_type::const_iterator it = resources.begin(); it != resources.end(); ++it) {
EXPECT_EQ(it->dname(), "www.example.com");
EXPECT_EQ(it->type(), DNS::AAAA);
EXPECT_EQ(it->ttl(), 0x762);
EXPECT_EQ(it->data(), "f9a8:239::1:1");
EXPECT_EQ(it->query_class(), DNS::IN);
}
}

View File

@@ -36,7 +36,7 @@ void test_equals(const Dot11ProbeResponse &dot1, const Dot11ProbeResponse &dot2)
void test_equals_expected(const Dot11ProbeResponse &dot11) {
test_equals_expected(static_cast<const Dot11ManagementFrame&>(dot11));
EXPECT_EQ(dot11.timestamp(), 0x17a698df27838a91);
EXPECT_EQ(dot11.timestamp(), 0x17a698df27838a91LL);
EXPECT_EQ(dot11.interval(), 0x928d);
EXPECT_EQ(dot11.subtype(), Dot11::PROBE_RESP);
}
@@ -75,8 +75,8 @@ TEST_F(Dot11ProbeResponseTest, Interval) {
TEST_F(Dot11ProbeResponseTest, Timestamp) {
Dot11ProbeResponse dot11;
dot11.timestamp(0x92af8a72df928a7c);
EXPECT_EQ(dot11.timestamp(), 0x92af8a72df928a7c);
dot11.timestamp(0x92af8a72df928a7cLL);
EXPECT_EQ(dot11.timestamp(), 0x92af8a72df928a7cLL);
}
TEST_F(Dot11ProbeResponseTest, ClonePDU) {

View File

@@ -2,6 +2,9 @@
#include <gtest/gtest.h>
#include "ethernetII.h"
#include "utils.h"
#include "macros.h"
#include "ipv6.h"
#include "ip.h"
#include "network_interface.h"
using namespace Tins;
@@ -10,9 +13,9 @@ typedef EthernetII::address_type address_type;
class EthernetIITest : public ::testing::Test {
public:
static const uint8_t expected_packet[];
static address_type s_addr;
static address_type d_addr;
static const uint8_t expected_packet[], ip_packet[], ipv6_packet[];
static address_type src_addr;
static address_type dst_addr;
static address_type empty_addr;
static const NetworkInterface iface;
static const uint16_t p_type;
@@ -21,19 +24,37 @@ public:
};
const uint8_t EthernetIITest::expected_packet[] = {
'\xaa', '\xbb', '\xcc', '\xdd',
'\xee', '\xff', '\x8a', '\x8b',
'\x8c', '\x8d', '\x8e', '\x8f',
'\xd0', '\xab'
'\xaa', '\xbb', '\xcc', '\xdd',
'\xee', '\xff', '\x8a', '\x8b',
'\x8c', '\x8d', '\x8e', '\x8f',
'\xd0', '\xab'
},
EthernetIITest::ip_packet[] = {
'\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x08', '\x00', 'E', '\x00', '\x00', '\x14',
'\x00', '\x01', '\x00', '\x00', '@', '\x00', '|', '\xe7', '\x7f', '\x00',
'\x00', '\x01', '\x7f', '\x00', '\x00', '\x01'
},
EthernetIITest::ipv6_packet[] = {
'\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x86', '\xdd', '`', '\x00', '\x00', '\x00',
'\x00', '\x00', ';', '@', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x01', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x01'
};
address_type EthernetIITest::s_addr("8a:8b:8c:8d:8e:8f");
address_type EthernetIITest::src_addr("8a:8b:8c:8d:8e:8f");
address_type EthernetIITest::d_addr("aa:bb:cc:dd:ee:ff");
address_type EthernetIITest::dst_addr("aa:bb:cc:dd:ee:ff");
address_type EthernetIITest::empty_addr;
#ifdef BSD
const NetworkInterface EthernetIITest::iface("lo0");
#else
const NetworkInterface EthernetIITest::iface("lo");
#endif
const uint16_t EthernetIITest::p_type = 0xd0ab;
@@ -78,14 +99,14 @@ TEST_F(EthernetIITest, NestedCopy) {
TEST_F(EthernetIITest, SourceAddress) {
EthernetII eth;
eth.src_addr(s_addr);
ASSERT_EQ(eth.src_addr(), s_addr);
eth.src_addr(src_addr);
ASSERT_EQ(eth.src_addr(), src_addr);
}
TEST_F(EthernetIITest, DestinationAddress) {
EthernetII eth;
eth.dst_addr(d_addr);
ASSERT_EQ(eth.dst_addr(), d_addr);
eth.dst_addr(dst_addr);
ASSERT_EQ(eth.dst_addr(), dst_addr);
}
TEST_F(EthernetIITest, PayloadType) {
@@ -102,16 +123,16 @@ TEST_F(EthernetIITest, Interface) {
TEST_F(EthernetIITest, CompleteConstructor) {
EthernetII* eth2 = new EthernetII();
EthernetII eth(iface, d_addr, s_addr, eth2);
EXPECT_EQ(eth.dst_addr(), d_addr);
EXPECT_EQ(eth.src_addr(), s_addr);
EthernetII eth(iface, dst_addr, src_addr, eth2);
EXPECT_EQ(eth.dst_addr(), dst_addr);
EXPECT_EQ(eth.src_addr(), src_addr);
EXPECT_TRUE(eth.inner_pdu() == eth2);
EXPECT_EQ(eth.payload_type(), 0);
EXPECT_EQ(eth.iface(), iface);
}
TEST_F(EthernetIITest, Serialize) {
EthernetII eth(iface, d_addr, s_addr);
EthernetII eth(iface, dst_addr, src_addr);
eth.payload_type(p_type);
PDU::serialization_type serialized = eth.serialize();
ASSERT_EQ(serialized.size(), sizeof(expected_packet));
@@ -120,9 +141,20 @@ TEST_F(EthernetIITest, Serialize) {
TEST_F(EthernetIITest, ConstructorFromBuffer) {
EthernetII eth(expected_packet, sizeof(expected_packet));
EXPECT_EQ(eth.src_addr(), s_addr);
EXPECT_EQ(eth.dst_addr(), d_addr);
EXPECT_EQ(eth.src_addr(), src_addr);
EXPECT_EQ(eth.dst_addr(), dst_addr);
EXPECT_EQ(eth.payload_type(), p_type);
}
TEST_F(EthernetIITest, ConstructorFromIPBuffer) {
EthernetII eth(ip_packet, sizeof(ip_packet));
ASSERT_TRUE(eth.inner_pdu());
EXPECT_EQ(eth.find_pdu<IP>(), eth.inner_pdu());
}
TEST_F(EthernetIITest, ConstructorFromIPv6Buffer) {
EthernetII eth(ipv6_packet, sizeof(ipv6_packet));
ASSERT_TRUE(eth.inner_pdu());
EXPECT_EQ(eth.find_pdu<IPv6>(), eth.inner_pdu());
}

View File

@@ -29,8 +29,6 @@ TEST_F(ICMPTest, DefaultConstructor) {
EXPECT_EQ(icmp.type(), ICMP::ECHO_REQUEST);
EXPECT_EQ(icmp.id(), 0);
EXPECT_EQ(icmp.check(), 0);
EXPECT_EQ(icmp.gateway(), 0);
EXPECT_EQ(icmp.mtu(), 0);
}
TEST_F(ICMPTest, CopyConstructor) {

422
tests/src/icmpv6.cpp Normal file
View File

@@ -0,0 +1,422 @@
#include <gtest/gtest.h>
#include <cstring>
#include <string>
#include <stdint.h>
#include "icmpv6.h"
#include "ip.h"
#include "tcp.h"
#include "utils.h"
#include "hw_address.h"
using namespace Tins;
class ICMPv6Test : public testing::Test {
public:
static const uint8_t expected_packet[];
static const uint8_t expected_packet1[];
void test_equals(const ICMPv6 &icmp1, const ICMPv6 &icmp2);
};
const uint8_t ICMPv6Test::expected_packet[] = {
'\x88', '\x00', '\xdc', '\x15', '\xc0', '\x00', '\x00', '\x00', '?',
'\xfe', '\x05', '\x07', '\x00', '\x00', '\x00', '\x01', '\x02', '`',
'\x97', '\xff', '\xfe', '\x07', 'i', '\xea'
};
const uint8_t ICMPv6Test::expected_packet1[] = {
'\x86', '\x00', 'F', '%', '@', '\x00', '\x07', '\x08', '\x00', '\x00',
'u', '0', '\x00', '\x00', '\x03', '\xe8', '\x01', '\x01', '\x00', '`',
'\x97', '\x07', 'i', '\xea', '\x05', '\x01', '\x00', '\x00', '\x00',
'\x00', '\x05', '\xdc', '\x03', '\x04', '@', '\xc0', '\x00', '6',
'\xee', '\x80', '\x00', '6', '\xee', '\x80', '\x00', '\x00', '\x00',
'\x00', '?', '\xfe', '\x05', '\x07', '\x00', '\x00', '\x00', '\x01',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'
};
TEST_F(ICMPv6Test, Constructor) {
ICMPv6 icmp;
EXPECT_EQ(icmp.type(), ICMPv6::ECHO_REQUEST);
EXPECT_EQ(icmp.code(), 0);
EXPECT_EQ(icmp.checksum(), 0);
EXPECT_EQ(icmp.identifier(), 0);
EXPECT_EQ(icmp.sequence(), 0);
EXPECT_EQ(icmp.override(), 0);
EXPECT_EQ(icmp.solicited(), 0);
EXPECT_EQ(icmp.router(), 0);
EXPECT_EQ(icmp.hop_limit(), 0);
EXPECT_EQ(icmp.router_pref(), 0);
EXPECT_EQ(icmp.home_agent(), 0);
EXPECT_EQ(icmp.other(), 0);
EXPECT_EQ(icmp.managed(), 0);
EXPECT_EQ(icmp.router_lifetime(), 0);
}
TEST_F(ICMPv6Test, ConstructorFromBuffer) {
ICMPv6 icmp(expected_packet, sizeof(expected_packet));
EXPECT_EQ(icmp.type(), ICMPv6::NEIGHBOUR_ADVERT);
EXPECT_EQ(icmp.code(), 0);
EXPECT_EQ(icmp.checksum(), 0xdc15);
EXPECT_EQ(icmp.solicited(), 1);
EXPECT_EQ(icmp.router(), 1);
EXPECT_EQ(icmp.override(), 0);
EXPECT_EQ(icmp.target_addr(), "3ffe:507:0:1:260:97ff:fe07:69ea");
}
TEST_F(ICMPv6Test, ConstructorFromBuffer2) {
ICMPv6 icmp(expected_packet1, sizeof(expected_packet1));
EXPECT_EQ(icmp.type(), ICMPv6::ROUTER_ADVERT);
EXPECT_EQ(icmp.code(), 0);
EXPECT_EQ(icmp.checksum(), 0x4625);
EXPECT_EQ(icmp.managed(), 0);
EXPECT_EQ(icmp.home_agent(), 0);
EXPECT_EQ(icmp.other(), 0);
EXPECT_EQ(icmp.router_pref(), 0);
EXPECT_EQ(icmp.router_lifetime(), 1800);
EXPECT_EQ(icmp.reachable_time(), 30000);
EXPECT_EQ(icmp.retransmit_timer(), 1000);
const ICMPv6::icmpv6_option *opt = icmp.search_option(ICMPv6::SOURCE_ADDRESS);
ASSERT_TRUE(opt);
EXPECT_EQ(opt->data_size(), 6);
EXPECT_EQ(HWAddress<6>(opt->data_ptr()), "00:60:97:07:69:ea");
opt = icmp.search_option(ICMPv6::MTU);
ASSERT_TRUE(opt);
EXPECT_EQ(opt->data_size(), 6);
opt = icmp.search_option(ICMPv6::PREFIX_INFO);
ASSERT_TRUE(opt);
EXPECT_EQ(opt->data_size(), 30);
}
TEST_F(ICMPv6Test, Type) {
ICMPv6 icmp;
icmp.type(ICMPv6::MLD2_REPORT);
EXPECT_EQ(icmp.type(), ICMPv6::MLD2_REPORT);
}
TEST_F(ICMPv6Test, Code) {
ICMPv6 icmp;
icmp.code(0x7a);
EXPECT_EQ(icmp.code(), 0x7a);
}
TEST_F(ICMPv6Test, Checksum) {
ICMPv6 icmp;
icmp.checksum(0x827f);
EXPECT_EQ(icmp.checksum(), 0x827f);
}
TEST_F(ICMPv6Test, Identifier) {
ICMPv6 icmp;
icmp.identifier(0x827f);
EXPECT_EQ(icmp.identifier(), 0x827f);
}
TEST_F(ICMPv6Test, Sequence) {
ICMPv6 icmp;
icmp.sequence(0x827f);
EXPECT_EQ(icmp.sequence(), 0x827f);
}
TEST_F(ICMPv6Test, Override) {
ICMPv6 icmp;
icmp.override(1);
EXPECT_EQ(icmp.override(), 1);
icmp.override(0);
EXPECT_EQ(icmp.override(), 0);
}
TEST_F(ICMPv6Test, Solicited) {
ICMPv6 icmp;
icmp.solicited(1);
EXPECT_EQ(icmp.solicited(), 1);
icmp.solicited(0);
EXPECT_EQ(icmp.solicited(), 0);
}
TEST_F(ICMPv6Test, Router) {
ICMPv6 icmp;
icmp.router(1);
EXPECT_EQ(icmp.router(), 1);
icmp.router(0);
EXPECT_EQ(icmp.router(), 0);
}
TEST_F(ICMPv6Test, RouterPref) {
ICMPv6 icmp;
icmp.router_pref(1);
EXPECT_EQ(icmp.router_pref(), 1);
icmp.router_pref(0);
EXPECT_EQ(icmp.router_pref(), 0);
}
TEST_F(ICMPv6Test, HomeAgent) {
ICMPv6 icmp;
icmp.home_agent(1);
EXPECT_EQ(icmp.home_agent(), 1);
icmp.home_agent(0);
EXPECT_EQ(icmp.home_agent(), 0);
}
TEST_F(ICMPv6Test, Other) {
ICMPv6 icmp;
icmp.other(1);
EXPECT_EQ(icmp.other(), 1);
icmp.other(0);
EXPECT_EQ(icmp.other(), 0);
}
TEST_F(ICMPv6Test, Managed) {
ICMPv6 icmp;
icmp.managed(1);
EXPECT_EQ(icmp.managed(), 1);
icmp.managed(0);
EXPECT_EQ(icmp.managed(), 0);
}
TEST_F(ICMPv6Test, RTLifetime) {
ICMPv6 icmp;
icmp.router_lifetime(0x827f);
EXPECT_EQ(icmp.router_lifetime(), 0x827f);
}
TEST_F(ICMPv6Test, SourceLinkLayerAddress) {
ICMPv6 icmp;
icmp.source_link_layer_addr("09:fe:da:fe:22:33");
EXPECT_EQ(icmp.source_link_layer_addr(), "09:fe:da:fe:22:33");
}
TEST_F(ICMPv6Test, TargetLinkLayerAddress) {
ICMPv6 icmp;
icmp.target_link_layer_addr("09:fe:da:fe:22:33");
EXPECT_EQ(icmp.target_link_layer_addr(), "09:fe:da:fe:22:33");
}
TEST_F(ICMPv6Test, PrefixInformation) {
ICMPv6 icmp;
ICMPv6::prefix_info_type result, info(0x8, 1, 0, 0x92038fad,
0x918273fa, "827d:adae::1");
icmp.prefix_info(info);
result = icmp.prefix_info();
EXPECT_EQ(result.prefix_len, info.prefix_len);
EXPECT_EQ(result.A, info.A);
EXPECT_EQ(result.L, info.L);
EXPECT_EQ(result.valid_lifetime, info.valid_lifetime);
EXPECT_EQ(result.preferred_lifetime, info.preferred_lifetime);
EXPECT_EQ(IPv6Address(result.prefix), IPv6Address(result.prefix));
EXPECT_EQ(IPv6Address(result.prefix), "827d:adae::1");
}
TEST_F(ICMPv6Test, RedirectHeader) {
ICMPv6 icmp;
IP ip = IP("127.0.0.1") / TCP(22);
PDU::serialization_type buffer = ip.serialize();
icmp.redirect_header(buffer);
EXPECT_EQ(buffer, icmp.redirect_header());
}
TEST_F(ICMPv6Test, MTU) {
ICMPv6 icmp;
icmp.mtu(0x9a8df7);
EXPECT_EQ(icmp.mtu(), 0x9a8df7);
}
TEST_F(ICMPv6Test, ShortcutLimit) {
ICMPv6 icmp;
icmp.shortcut_limit(123);
EXPECT_EQ(icmp.shortcut_limit(), 123);
}
TEST_F(ICMPv6Test, NewAdvertisementInterval) {
ICMPv6 icmp;
icmp.new_advert_interval(0x9a8df7);
EXPECT_EQ(icmp.new_advert_interval(), 0x9a8df7);
}
TEST_F(ICMPv6Test, NewHomeAgentInformation) {
ICMPv6 icmp;
ICMPv6::new_ha_info_type data(0x92fa, 0xaab3);
icmp.new_home_agent_info(data);
EXPECT_EQ(icmp.new_home_agent_info(), data);
}
TEST_F(ICMPv6Test, SourceAddressList) {
ICMPv6 icmp;
ICMPv6::addr_list_type data;
data.push_back("827d:adae::1");
data.push_back("2929:1234:fefe::2");
icmp.source_addr_list(data);
EXPECT_EQ(icmp.source_addr_list(), data);
}
TEST_F(ICMPv6Test, TargetAddressList) {
ICMPv6 icmp;
ICMPv6::addr_list_type data;
data.push_back("827d:adae::1");
data.push_back("2929:1234:fefe::2");
icmp.target_addr_list(data);
EXPECT_EQ(icmp.target_addr_list(), data);
}
TEST_F(ICMPv6Test, RSASignature) {
ICMPv6 icmp;
ICMPv6::rsa_sign_type data, result;
// can i haz std::iota?
const uint8_t arr[16] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
};
std::copy(arr, arr + sizeof(arr), data.key_hash);
data.signature.push_back(12);
data.signature.push_back(15);
data.signature.push_back(221);
icmp.rsa_signature(data);
result = icmp.rsa_signature();
EXPECT_TRUE(std::equal(data.key_hash, data.key_hash + sizeof(data.key_hash), result.key_hash));
// There might be some padding(in this case, there is).
ASSERT_LE(data.signature.size(), result.signature.size());
EXPECT_TRUE(std::equal(data.signature.begin(), data.signature.end(), result.signature.begin()));
}
TEST_F(ICMPv6Test, Timestamp) {
ICMPv6 icmp;
icmp.timestamp(0x2837d6aaa231L);
EXPECT_EQ(icmp.timestamp(), 0x2837d6aaa231L);
}
TEST_F(ICMPv6Test, Nonce) {
ICMPv6 icmp;
ICMPv6::nonce_type data;
data.push_back(22);
data.push_back(211);
data.push_back(67);
icmp.nonce(data);
EXPECT_EQ(icmp.nonce(), data);
}
TEST_F(ICMPv6Test, IPPrefix) {
ICMPv6 icmp;
ICMPv6::ip_prefix_type data(67, 198, "ff00:0928:ddfa::"), output;
icmp.ip_prefix(data);
output = icmp.ip_prefix();
EXPECT_EQ(output.option_code, data.option_code);
EXPECT_EQ(output.prefix_len, data.prefix_len);
EXPECT_EQ(output.address, data.address);
}
TEST_F(ICMPv6Test, LinkLayerAddress) {
ICMPv6 icmp;
ICMPv6::lladdr_type data(67), output;
data.address.push_back(87);
data.address.push_back(22);
data.address.push_back(185);
icmp.link_layer_addr(data);
output = icmp.link_layer_addr();
EXPECT_EQ(output.option_code, data.option_code);
ASSERT_LE(data.address.size(), output.address.size());
EXPECT_TRUE(std::equal(data.address.begin(), data.address.end(), output.address.begin()));
}
TEST_F(ICMPv6Test, NAACK) {
ICMPv6 icmp;
ICMPv6::naack_type data(0x92, 0xb3);
icmp.naack(data);
EXPECT_EQ(icmp.naack(), data);
}
TEST_F(ICMPv6Test, MAP) {
ICMPv6 icmp;
ICMPv6::map_type data(0x9, 0xb, 1, 0x9283719, "f029:adde::1"), output;
icmp.map(data);
output = icmp.map();
EXPECT_EQ(output.dist, data.dist);
EXPECT_EQ(output.pref, data.pref);
EXPECT_EQ(output.r, data.r);
EXPECT_EQ(output.address, data.address);
}
TEST_F(ICMPv6Test, RouteInfo) {
ICMPv6 icmp;
ICMPv6::route_info_type data(0x92, 2, 0xf23a8823), output;
data.prefix.push_back(98);
data.prefix.push_back(52);
data.prefix.push_back(44);
icmp.route_info(data);
output = icmp.route_info();
EXPECT_EQ(output.prefix_len, data.prefix_len);
EXPECT_EQ(output.pref, data.pref);
EXPECT_EQ(output.route_lifetime, data.route_lifetime);
ASSERT_LE(data.prefix.size(), output.prefix.size());
EXPECT_TRUE(std::equal(data.prefix.begin(), data.prefix.end(), output.prefix.begin()));
}
TEST_F(ICMPv6Test, RecursiveDNSServer) {
ICMPv6 icmp;
ICMPv6::recursive_dns_type data(0x9283712), output;
data.servers.push_back("827d:adae::1");
data.servers.push_back("2929:1234:fefe::2");
icmp.recursive_dns_servers(data);
output = icmp.recursive_dns_servers();
EXPECT_EQ(output.lifetime, data.lifetime);
EXPECT_EQ(output.servers, data.servers);
}
TEST_F(ICMPv6Test, HandoverKeyRequest) {
ICMPv6 icmp;
ICMPv6::handover_key_req_type data(2), output;
data.key.push_back(98);
data.key.push_back(52);
data.key.push_back(44);
icmp.handover_key_request(data);
output = icmp.handover_key_request();
EXPECT_EQ(output.AT, data.AT);
EXPECT_EQ(data.key, output.key);
}
TEST_F(ICMPv6Test, HandoverKeyReply) {
ICMPv6 icmp;
ICMPv6::handover_key_reply_type data(0x9283, 2), output;
data.key.push_back(98);
data.key.push_back(52);
data.key.push_back(44);
icmp.handover_key_reply(data);
output = icmp.handover_key_reply();
EXPECT_EQ(output.AT, data.AT);
EXPECT_EQ(output.lifetime, data.lifetime);
EXPECT_EQ(data.key, output.key);
}
TEST_F(ICMPv6Test, HandoverAssistInfo) {
ICMPv6 icmp;
ICMPv6::handover_assist_info_type data(0x92), output;
data.hai.push_back(98);
data.hai.push_back(52);
data.hai.push_back(44);
icmp.handover_assist_info(data);
output = icmp.handover_assist_info();
EXPECT_EQ(output.option_code, data.option_code);
EXPECT_EQ(data.hai, output.hai);
}
TEST_F(ICMPv6Test, MobileNodeIdentifier) {
ICMPv6 icmp;
ICMPv6::mobile_node_id_type data(0x92), output;
data.mn.push_back(98);
data.mn.push_back(52);
data.mn.push_back(44);
icmp.mobile_node_identifier(data);
output = icmp.mobile_node_identifier();
EXPECT_EQ(output.option_code, data.option_code);
EXPECT_EQ(data.mn, output.mn);
}
TEST_F(ICMPv6Test, DNSSearchList) {
ICMPv6 icmp;
ICMPv6::dns_search_list_type data(0x9283fd1), output;
data.domains.push_back("libtins.sourceforge.net");
data.domains.push_back("www.example.com");
icmp.dns_search_list(data);
output = icmp.dns_search_list();
EXPECT_EQ(output.lifetime, data.lifetime);
EXPECT_EQ(data.domains, output.domains);
}

183
tests/src/ipv6.cpp Normal file
View File

@@ -0,0 +1,183 @@
#include <gtest/gtest.h>
#include <cstring>
#include <string>
#include <stdint.h>
#include "ipv6.h"
#include "tcp.h"
#include "udp.h"
#include "icmp.h"
#include "icmpv6.h"
#include "ipv6_address.h"
#include "utils.h"
using namespace std;
using namespace Tins;
class IPv6Test : public testing::Test {
public:
static const uint8_t expected_packet1[], expected_packet2[];
void test_equals(IPv6 &ip1, IPv6 &ip2);
};
const uint8_t IPv6Test::expected_packet1[] = {
'i', '\xa8', '\'', '4', '\x00', '(', '\x06', '@', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x01', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x01', '\xc6', '\x8c', '\x00', 'P', 'h', 'H', '\x03',
'\x0c', '\x00', '\x00', '\x00', '\x00', '\xa0', '\x02', '\x7f', '\xf0',
'\x00', '0', '\x00', '\x00', '\x02', '\x04', '?', '\xf8', '\x04',
'\x02', '\x08', '\n', '\x00', '\x84', '\xa3', '\x9c', '\x00', '\x00',
'\x00', '\x00', '\x01', '\x03', '\x03', '\x07'
};
const uint8_t IPv6Test::expected_packet2[] = {
'`', '\x00', '\x00', '\x00', '\x00', '$', '\x00', '\x01', '\xfe',
'\x80', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x02',
'\xd0', '\t', '\xff', '\xfe', '\xe3', '\xe8', '\xde', '\xff', '\x02',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x16', ':', '\x00', '\x05', '\x02',
'\x00', '\x00', '\x01', '\x00', '\x8f', '\x00', 't', '\xfe', '\x00',
'\x00', '\x00', '\x01', '\x04', '\x00', '\x00', '\x00', '\xff', '\x02',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x01', '\xff', '\x98', '\x06', '\xe1'
};
void IPv6Test::test_equals(IPv6 &ip1, IPv6 &ip2) {
EXPECT_EQ(ip1.version(), ip2.version());
EXPECT_EQ(ip1.traffic_class(), ip2.traffic_class());
EXPECT_EQ(ip1.flow_label(), ip2.flow_label());
EXPECT_EQ(ip1.payload_length(), ip2.payload_length());
EXPECT_EQ(ip1.next_header(), ip2.next_header());
EXPECT_EQ(ip1.hop_limit(), ip2.hop_limit());
EXPECT_EQ(ip1.dst_addr(), ip2.dst_addr());
EXPECT_EQ(ip1.src_addr(), ip2.src_addr());
EXPECT_EQ(bool(ip1.search_header(IPv6::HOP_BY_HOP)), bool(ip2.search_header(IPv6::HOP_BY_HOP)));
const IPv6::ipv6_ext_header *header1 = ip1.search_header(IPv6::HOP_BY_HOP),
*header2 = ip2.search_header(IPv6::HOP_BY_HOP);
if(header1 && header2) {
EXPECT_EQ(header1->data_size(), header2->data_size());
}
EXPECT_EQ(bool(ip1.inner_pdu()), bool(ip2.inner_pdu()));
const ICMPv6 *icmp1 = ip1.find_pdu<ICMPv6>(), *icmp2 = ip2.find_pdu<ICMPv6>();
ASSERT_EQ(bool(icmp1), bool(icmp2));
if(icmp1 && icmp2) {
EXPECT_EQ(icmp1->checksum(), icmp2->checksum());
}
}
TEST_F(IPv6Test, Constructor) {
IPv6 ipv6("::1:2:3", "f0aa:beef::1");
EXPECT_EQ(ipv6.version(), 6);
EXPECT_EQ(ipv6.traffic_class(), 0);
EXPECT_EQ(ipv6.flow_label(), 0);
EXPECT_EQ(ipv6.payload_length(), 0);
EXPECT_EQ(ipv6.next_header(), 0);
EXPECT_EQ(ipv6.hop_limit(), 0);
EXPECT_EQ(ipv6.dst_addr(), "::1:2:3");
EXPECT_EQ(ipv6.src_addr(), "f0aa:beef::1");
}
TEST_F(IPv6Test, ConstructorFromBuffer) {
IPv6 ipv6(expected_packet1, sizeof(expected_packet1));
EXPECT_EQ(ipv6.version(), 6);
EXPECT_EQ(ipv6.traffic_class(), 0x9a);
EXPECT_EQ(ipv6.flow_label(), 0x82734);
EXPECT_EQ(ipv6.payload_length(), 40);
EXPECT_EQ(ipv6.next_header(), 6);
EXPECT_EQ(ipv6.hop_limit(), 64);
EXPECT_EQ(ipv6.dst_addr(), "::1");
EXPECT_EQ(ipv6.src_addr(), "::1");
ASSERT_TRUE(ipv6.inner_pdu());
TCP *tcp = ipv6.find_pdu<TCP>();
ASSERT_TRUE(tcp);
EXPECT_EQ(tcp->sport(), 50828);
EXPECT_EQ(tcp->dport(), 80);
}
// This one has a hop-by-hop ext header
TEST_F(IPv6Test, ConstructorFromBuffer2) {
IPv6 ipv6(expected_packet2, sizeof(expected_packet2));
EXPECT_EQ(ipv6.version(), 6);
EXPECT_EQ(ipv6.traffic_class(), 0);
EXPECT_EQ(ipv6.flow_label(), 0);
EXPECT_EQ(ipv6.payload_length(), 36);
EXPECT_EQ(ipv6.next_header(), IPv6::HOP_BY_HOP);
EXPECT_EQ(ipv6.hop_limit(), 1);
EXPECT_EQ(ipv6.dst_addr(), "ff02::16");
EXPECT_EQ(ipv6.src_addr(), "fe80::2d0:9ff:fee3:e8de");
ICMPv6 *pdu = ipv6.find_pdu<ICMPv6>();
ASSERT_TRUE(pdu);
EXPECT_EQ(pdu->type(), 143);
EXPECT_EQ(pdu->code(), 0);
EXPECT_EQ(pdu->checksum(), 0x74fe);
EXPECT_EQ(pdu->checksum(), 0x74fe);
const IPv6::ipv6_ext_header *header = ipv6.search_header(IPv6::HOP_BY_HOP);
ASSERT_TRUE(header);
EXPECT_EQ(header->data_size(), 6);
}
TEST_F(IPv6Test, Serialize) {
IPv6 ip1(expected_packet2, sizeof(expected_packet2));
IPv6::serialization_type buffer = ip1.serialize();
ASSERT_EQ(buffer.size(), sizeof(expected_packet2));
EXPECT_TRUE(std::equal(buffer.begin(), buffer.end(), expected_packet2));
IPv6 ip2(&buffer[0], buffer.size());
test_equals(ip1, ip2);
}
TEST_F(IPv6Test, Version) {
IPv6 ipv6;
ipv6.version(3);
EXPECT_EQ(ipv6.version(), 3);
}
TEST_F(IPv6Test, TrafficClass) {
IPv6 ipv6;
ipv6.traffic_class(0x7a);
EXPECT_EQ(ipv6.traffic_class(), 0x7a);
}
TEST_F(IPv6Test, FlowLabel) {
IPv6 ipv6;
ipv6.flow_label(0x918d7);
EXPECT_EQ(ipv6.flow_label(), 0x918d7);
}
TEST_F(IPv6Test, PayloadLength) {
IPv6 ipv6;
ipv6.payload_length(0xaf71);
EXPECT_EQ(ipv6.payload_length(), 0xaf71);
}
TEST_F(IPv6Test, NextHeader) {
IPv6 ipv6;
ipv6.next_header(0x7a);
EXPECT_EQ(ipv6.next_header(), 0x7a);
}
TEST_F(IPv6Test, HopLimit) {
IPv6 ipv6;
ipv6.hop_limit(0x7a);
EXPECT_EQ(ipv6.hop_limit(), 0x7a);
}
TEST_F(IPv6Test, SourceAddress) {
IPv6 ipv6;
ipv6.src_addr("99af:1293::1");
EXPECT_EQ(ipv6.src_addr(), "99af:1293::1");
}
TEST_F(IPv6Test, DestinationAddress) {
IPv6 ipv6;
ipv6.dst_addr("99af:1293::1");
EXPECT_EQ(ipv6.dst_addr(), "99af:1293::1");
}

87
tests/src/ipv6address.cpp Normal file
View File

@@ -0,0 +1,87 @@
#include <gtest/gtest.h>
#include <cstring>
#include <string>
#include <algorithm>
#include <sstream>
#include <stdint.h>
#include "ipv6_address.h"
#include "utils.h"
using namespace Tins;
const uint8_t empty_addr[IPv6Address::address_size] = { 0 };
void test_to_string(const std::string &str) {
EXPECT_EQ(str, IPv6Address(str).to_string());
}
TEST(IPv6AddressTest, DefaultConstructor) {
IPv6Address addr;
EXPECT_TRUE(std::equal(addr.begin(), addr.end(), empty_addr));
}
TEST(IPv6AddressTest, ConstructorFromString1) {
IPv6Address addr("2001:db8:85a3:8d3:1319:8a2e:370:7348");
const uint8_t some_addr[IPv6Address::address_size] = {
0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x08, 0xd3, 0x13, 0x19,
0x8a, 0x2e, 0x03, 0x70, 0x73, 0x48
};
EXPECT_TRUE(std::equal(addr.begin(), addr.end(), some_addr));
}
TEST(IPv6AddressTest, ConstructorFromString2) {
IPv6Address addr("2001:db8:85a3::1319:8a2e:370:7348");
const uint16_t some_addr[IPv6Address::address_size] = {
0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00, 0x13, 0x19,
0x8a, 0x2e, 0x03, 0x70, 0x73, 0x48
};
EXPECT_TRUE(std::equal(addr.begin(), addr.end(), some_addr));
}
TEST(IPv6AddressTest, ConstructorFromString3) {
IPv6Address addr("::1");
const uint16_t some_addr[IPv6Address::address_size] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
};
EXPECT_TRUE(std::equal(addr.begin(), addr.end(), some_addr));
}
TEST(IPv6AddressTest, ToString) {
test_to_string("2001:db8:85a3:8d3:1319:8a2e:370:7348");
test_to_string("2001:db8:85a3:8d3:1319:8a2e::");
test_to_string("1:db8:85a3:8d3:1319:8a2e:370:7348");
test_to_string("::85a3:8d3:1319:8a2e:370:7348");
test_to_string("::1:2:3");
}
TEST(IPv6AddressTest, EqualOperator) {
EXPECT_EQ(IPv6Address("17f8::1"), IPv6Address("17f8:0::0:1"));
EXPECT_EQ(IPv6Address("::1"), IPv6Address("::1"));
EXPECT_EQ(IPv6Address("1::"), IPv6Address("1::"));
}
TEST(IPv6AddressTest, DistinctOperator) {
EXPECT_NE(IPv6Address("17f8::12"), IPv6Address("17f8:0::1:12"));
EXPECT_NE(IPv6Address("::1"), IPv6Address("::2"));
EXPECT_NE(IPv6Address("4::"), IPv6Address("5::"));
}
TEST(IPv6AddressTest, LessThanOperator) {
EXPECT_LT(IPv6Address("17f8::1"), IPv6Address("17f8:0::0:5"));
EXPECT_LT(IPv6Address("::1"), IPv6Address("::5"));
EXPECT_LT(IPv6Address("1::"), IPv6Address("2::"));
}
TEST(IPv6AddressTest, OutputOperator) {
std::ostringstream oss;
oss << IPv6Address("17f8::1");
EXPECT_EQ("17f8::1", oss.str());
}
TEST(IPv6AddressTest, Copy) {
IPv6Address addr1("17f8::1");
IPv6Address addr2;
addr1.copy(addr2.begin());
EXPECT_EQ(addr1, addr2);
}

View File

@@ -10,7 +10,6 @@ using namespace std;
class LLCTest : public testing::Test {
public:
static const uint8_t expected_packet[];
static const uint8_t from_buffer_unnumbered[];
static const uint8_t from_buffer_info[];
static const uint8_t from_buffer_super[];
@@ -18,7 +17,6 @@ public:
//void test_equals(const IP &ip1, const IP &ip2);
};
const uint8_t LLCTest::expected_packet[] = {};
const uint8_t LLCTest::from_buffer_info[] = {'\xfe', '\x48', '\x3c', '\x3b'};
const uint8_t LLCTest::from_buffer_super[] = {'\x4b', '\x19', '\x05', '\x3a'};
const uint8_t LLCTest::from_buffer_unnumbered[] = {'\xaa', '\x17', '\xcf'};

View File

@@ -2,6 +2,7 @@
#include <string>
#include "network_interface.h"
#include "utils.h"
#include "macros.h"
using namespace Tins;
@@ -10,9 +11,17 @@ public:
static const std::string iface_name, iface_addr;
};
#ifdef BSD
const std::string NetworkInterfaceTest::iface_name("lo0"),
NetworkInterfaceTest::iface_addr("");
#elif defined(WIN32)
// modify me on every windows environment :D
const std::string NetworkInterfaceTest::iface_name("{INSERT-SOME-INTERFACE-NAME}"),
NetworkInterfaceTest::iface_addr("");
#else
const std::string NetworkInterfaceTest::iface_name("lo"),
NetworkInterfaceTest::iface_addr("");
#endif
TEST_F(NetworkInterfaceTest, ConstructorFromString) {
// just test this doesn't throw
@@ -29,7 +38,7 @@ TEST_F(NetworkInterfaceTest, ConstructorFromString) {
TEST_F(NetworkInterfaceTest, ConstructorFromIp) {
NetworkInterface iface(IPv4Address("127.0.0.1"));
EXPECT_EQ(iface.name(), "lo");
EXPECT_EQ(iface.name(), iface_name);
}
TEST_F(NetworkInterfaceTest, Id) {
@@ -51,7 +60,7 @@ TEST_F(NetworkInterfaceTest, EqualsOperator) {
}
TEST_F(NetworkInterfaceTest, DistinctOperator) {
NetworkInterface iface1(iface_name), iface2("eth0");
NetworkInterface iface1(iface_name), iface2;
EXPECT_NE(iface1, iface2);
}

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