mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 18:55:58 +01:00
Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a24e0d5a4b | ||
|
|
c6dc18d215 | ||
|
|
931a86eff9 | ||
|
|
2a1a28c3fb | ||
|
|
3f060de381 | ||
|
|
0945e0b29e | ||
|
|
5ee0ebb264 | ||
|
|
0dc762f15d | ||
|
|
c7c56a610c | ||
|
|
a826d92666 | ||
|
|
5b2e117347 | ||
|
|
e712550cb8 | ||
|
|
044d0a5a31 | ||
|
|
9d0e84f1fa | ||
|
|
02265061cc | ||
|
|
a13d7d0cb1 | ||
|
|
7a86012292 | ||
|
|
c933faaf5e | ||
|
|
a7e0c094fb | ||
|
|
592a15ebe4 | ||
|
|
75b32c75bc | ||
|
|
765285c6ee | ||
|
|
356fe00aad | ||
|
|
647ba1f46e | ||
|
|
53fe80d8a7 | ||
|
|
742276c251 | ||
|
|
6d1e96866e | ||
|
|
dbe67c8cae | ||
|
|
dd9c0b3fd5 | ||
|
|
9bdee61e5b | ||
|
|
e2426b493e | ||
|
|
acff776d56 | ||
|
|
4036e7daa2 | ||
|
|
93b5b86c5d | ||
|
|
de82dc2322 | ||
|
|
6696c1b284 | ||
|
|
e6e3e8453b | ||
|
|
4576d8746c | ||
|
|
b42c868a66 | ||
|
|
a18cd3e0de | ||
|
|
88faee9b26 | ||
|
|
16a29fab3e | ||
|
|
cd6bc16d48 | ||
|
|
443803caf0 | ||
|
|
75a4bbfed6 | ||
|
|
b74a353c17 | ||
|
|
492fd611f9 | ||
|
|
a938d2ecfd | ||
|
|
8276e7d086 | ||
|
|
ffdfb160c4 | ||
|
|
bf6c086b3d | ||
|
|
08b4c92dac | ||
|
|
2a0b248518 | ||
|
|
60323ded9b | ||
|
|
f3ea99e0b0 | ||
|
|
7e080cf1ab | ||
|
|
688be1e1da | ||
|
|
28e5df3abc | ||
|
|
d0048e3aef |
2
AUTHORS
2
AUTHORS
@@ -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
39
CHANGES
Normal 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.
|
||||
2
Doxyfile
2
Doxyfile
@@ -31,7 +31,7 @@ PROJECT_NAME = libtins
|
||||
# This could be handy for archiving the generated documentation or
|
||||
# if some version control system is used.
|
||||
|
||||
PROJECT_NUMBER = 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
93
Makefile.am
Normal 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
|
||||
1009
Makefile.in
1009
Makefile.in
File diff suppressed because it is too large
Load Diff
58
README
Normal file
58
README
Normal 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
7
THANKS
Normal 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
9617
aclocal.m4
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1530
config.guess
vendored
Executable file
1530
config.guess
vendored
Executable file
File diff suppressed because it is too large
Load Diff
1773
config.sub
vendored
Executable file
1773
config.sub
vendored
Executable file
File diff suppressed because it is too large
Load Diff
59
configure.ac
59
configure.ac
@@ -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
688
depcomp
Executable 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
558
depends.d
@@ -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:
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
41
include/cxxstd.h
Normal 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
|
||||
@@ -418,6 +418,6 @@ namespace Tins {
|
||||
options_type _options;
|
||||
uint32_t _size;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_DHCP_H
|
||||
|
||||
949
include/dhcpv6.h
Normal file
949
include/dhcpv6.h
Normal 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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
136
include/dot11.h
136
include/dot11.h
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
1208
include/icmpv6.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
67
include/internals.h
Normal 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
|
||||
48
include/ip.h
48
include/ip.h
@@ -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
|
||||
|
||||
@@ -136,7 +136,7 @@ namespace Tins {
|
||||
|
||||
uint32_t ip_addr;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif // TINS_IPADDRESS_H
|
||||
|
||||
330
include/ipv6.h
Normal file
330
include/ipv6.h
Normal 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
197
include/ipv6_address.h
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
48
include/macros.h
Normal 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
292
include/packet.h
Normal 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 ×tamp() 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 ×tamp() 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
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -133,7 +133,7 @@ namespace Tins {
|
||||
|
||||
payload_type _payload;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif // TINS_RAWPDU_H
|
||||
|
||||
172
include/sll.h
Normal file
172
include/sll.h
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
111
include/timestamp.h
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
139
include/utils.h
139
include/utils.h
@@ -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
527
install-sh
Executable 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
11
libtins.pc.in
Normal 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
|
||||
1
m4/libtool.m4
vendored
Symbolic link
1
m4/libtool.m4
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
/usr/share/aclocal/libtool.m4
|
||||
1
m4/ltoptions.m4
vendored
Symbolic link
1
m4/ltoptions.m4
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
/usr/share/aclocal/ltoptions.m4
|
||||
1
m4/ltsugar.m4
vendored
Symbolic link
1
m4/ltsugar.m4
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
/usr/share/aclocal/ltsugar.m4
|
||||
1
m4/ltversion.m4
vendored
Symbolic link
1
m4/ltversion.m4
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
/usr/share/aclocal/ltversion.m4
|
||||
1
m4/lt~obsolete.m4
vendored
Symbolic link
1
m4/lt~obsolete.m4
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
/usr/share/aclocal/lt~obsolete.m4
|
||||
331
missing
Executable file
331
missing
Executable 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
646
src/dhcpv6.cpp
Normal 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
|
||||
23
src/dns.cpp
23
src/dns.cpp
@@ -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),
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
33
src/icmp.cpp
33
src/icmp.cpp
@@ -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
795
src/icmpv6.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
94
src/internals.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
src/ip.cpp
11
src/ip.cpp
@@ -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
215
src/ipv6.cpp
Normal 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
102
src/ipv6_address.cpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ void PDU::send(PacketSender &) {
|
||||
}
|
||||
|
||||
PDU *PDU::recv_response(PacketSender &) {
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PDU::inner_pdu(PDU *next_pdu) {
|
||||
|
||||
@@ -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
91
src/sll.cpp
Normal 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));
|
||||
}
|
||||
}
|
||||
14
src/snap.cpp
14
src/snap.cpp
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
42
src/tcp.cpp
42
src/tcp.cpp
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
157
tests/configure
vendored
@@ -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
|
||||
;;
|
||||
|
||||
@@ -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)
|
||||
|
||||
2554
tests/depends.d
2554
tests/depends.d
File diff suppressed because it is too large
Load Diff
339
tests/src/dhcpv6.cpp
Normal file
339
tests/src/dhcpv6.cpp
Normal 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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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
422
tests/src/icmpv6.cpp
Normal 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
183
tests/src/ipv6.cpp
Normal 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
87
tests/src/ipv6address.cpp
Normal 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);
|
||||
}
|
||||
@@ -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'};
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user