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

81 Commits
v3.1 ... v3.2

Author SHA1 Message Date
Matias Fontanini
38ee449921 Update CHANGES file. 2015-03-20 22:12:23 -07:00
Matias Fontanini
9efd00956f Fix BaseSniffer::sniff_loop documentation. 2015-03-20 21:21:38 -07:00
Matias Fontanini
b56be87315 Remove include/tins/config.h. 2015-03-07 09:30:44 -08:00
Matias Fontanini
c67f7ba2e8 Merge pull request #57 from rioderelfte/include-guard
add an include guard to config.h
2015-03-07 09:24:34 -08:00
Matias Fontanini
aad0c511a8 Merge pull request #51 from EricMCornelius/master
Use type_traits to enable Packet& sniff_loop callback variant in C++11
2015-03-06 09:42:25 -08:00
Matias Fontanini
8bdce8e7b8 Merge pull request #60 from mfontanini/radiotap_fixes
Radiotap fixes
2015-03-06 09:04:17 -08:00
Matias Fontanini
64deb4fb39 Merge pull request #59 from haralduna/radiotap_fixes
Rearranged and updated RadioTap fields for big endian
2015-03-06 09:03:49 -08:00
Harald Unander
8c74bada85 Rearranged and updated RadioTap fields for big endian 2015-03-06 14:19:30 +01:00
Florian Sowade
8a51050f0b add an include guard to config.h 2015-03-05 12:41:34 +01:00
Eric Cornelius
4be9719195 Make sure we can still compile old loop signatures without c++11 enabled 2015-03-05 03:25:41 -05:00
Matias Fontanini
fa4a074e2f Add missing RadioTap fields. 2015-03-04 21:27:47 -08:00
Matias Fontanini
be51d67575 Remove Utils::resolve_domain6 test. 2015-03-04 18:19:00 -08:00
Matias Fontanini
695f191bb8 Fix invalid DNS record retrieval. 2015-03-04 18:11:33 -08:00
Eric Cornelius
c304dc08c4 Eliminate unnecessary explicit template parameter specification 2015-02-25 11:04:42 -05:00
Eric Cornelius
87207a8091 Support both move and reference overloads for the loop handler 2015-02-25 10:56:11 -05:00
Matias Fontanini
88c122ffcb Merge pull request #52 from UlfWetzker/master
Add Exception for fields that are not present in RadioTap frames.
2015-02-10 07:49:41 -08:00
Ulf Wetzker
c05f93a16f Fixed RadioTap test case 2015-02-10 15:28:36 +01:00
Ulf Wetzker
93a46366a0 Fixed type for _dbm_signal and _dbm_noise 2015-02-09 14:30:34 +01:00
Ulf Wetzker
179e0722f5 Fixed name in RadioTap present bitmap for field dbm_TX_power 2015-02-09 14:13:07 +01:00
Ulf Wetzker
d640eebb99 Add Exception for fields that are not present in RadioTap frames. 2015-02-09 13:23:03 +01:00
Eric Cornelius
184328ea95 Move packet into callback to avoid unnecessary clone, fix forward_iterator value type, and update comments 2015-02-06 10:24:43 -05:00
Eric Cornelius
eb0b7c9091 Generalize the accepts_type trait a bit, and move to internals.h, rename the _invoke_functor function, and templatize it to avoid need to depend on Packet defintion 2015-02-05 00:45:13 -05:00
Eric Cornelius
2587dd6cb0 Use type_traits to enable Packet& sniff_loop callback variant in C++11 builds 2015-02-04 21:44:50 -05:00
Matias Fontanini
fb97b2b8f0 Merge pull request #49 from joerango/master
Fixed TKIP decryption. Now packets from AP to STA are also decrypted.
2015-01-22 21:27:31 -08:00
Joseph Beshay
7382cc65de Fixed TKIP decryption. Now packets from AP to STA are also decrypted. 2015-01-22 19:51:05 -06:00
Matias Fontanini
1ca4f8166b Fix bug on EAPOL over snap serialization. 2015-01-17 09:49:47 -08:00
Matias Fontanini
65607b0eb5 Fixed PKTAP next layer interpretation. 2014-12-21 10:51:18 -08:00
Matias Fontanini
a4c67e5acd Added PKTAP header. 2014-12-21 10:18:59 -08:00
Matias Fontanini
ccbeca269a Merge pull request #47 from zhiweicai/ipaddress-win-fix
Ipaddress win fix
2014-12-17 10:26:08 -08:00
zhiweicai
ab972565d6 recover config.h 2014-12-16 21:42:20 -05:00
zhiweicai
c3a81f76d5 recover config.h 2014-12-16 21:40:35 -05:00
zhiweicai
8bf3b1af45 fix ip_to_int function on windows 2014-12-16 21:32:59 -05:00
Matias Fontanini
ae135bb035 Fixed IP total length zero bug. 2014-11-25 22:49:05 -08:00
Matias Fontanini
bcd8cc58f7 Merge pull request #45 from carlos-jenkins/master
Re-added support for pkg-config.
2014-11-19 21:20:41 -08:00
Carlos Miguel Jenkins Perez
8415f41722 Re-added support for pkg-config. 2014-11-19 20:35:30 -06:00
Matias Fontanini
3d832cc48e Replaced calls to PDU::rfind_pdu to find_pdu on TCPStreamFollower. 2014-11-13 22:07:31 -08:00
Matias Fontanini
3b126ca02b Removed access to potentially invalid positions on vector. 2014-11-12 21:11:01 -08:00
Matias Fontanini
0ba05f9d1a Fixed assertion throw on DNS on Visual Studio. 2014-11-11 22:01:23 -08:00
Matias Fontanini
3a38d36a60 Fixed invalid parsing of RadioTap ext flag field. 2014-11-06 21:44:59 -08:00
Matias Fontanini
d55a03ca0c Added L3 packet receive exception on BSD. 2014-10-25 17:42:46 -05:00
Matias Fontanini
c4609fedd6 Added Loopback::matches_response. 2014-10-25 00:23:52 -05:00
Matias Fontanini
23a5cfb0c4 Removed obsolete autotools files. 2014-10-23 22:37:15 -05:00
Matias Fontanini
69440fbc75 Fixed exception thrown when an interface didn't have IP address. 2014-10-23 00:04:20 -05:00
Matias Fontanini
64fac4f255 Added NetworkInterface::is_loopback. 2014-10-19 09:13:28 -03:00
Matias Fontanini
9ee90755d1 Moved headers to include/tins. 2014-10-17 12:14:00 -03:00
Matias Fontanini
a1636896aa Fixed compilation warning on unsigned integral constant. 2014-10-17 12:03:37 -03:00
Matias Fontanini
e7435d3974 BaseSniffer::get_pcap_handle is now public. 2014-10-17 12:03:18 -03:00
Matias Fontanini
3ad96422b9 Added correct parsing of PPPoE session packets. 2014-09-24 09:15:20 -03:00
Matias Fontanini
1bc9bd1504 Fixed compiler warning on SnifferIterator. 2014-09-21 10:58:38 -03:00
Matias Fontanini
8fcfd57125 Fixed portscan example. 2014-09-20 15:11:39 -03:00
Matias Fontanini
ff74f3103c Fixed invalid Loopback protocol detection on FreeBSD/OSX. 2014-09-20 09:52:42 -03:00
Matias Fontanini
addf0b3d98 Fixed OSX IP packet sending. 2014-09-19 10:07:31 -03:00
Matias Fontanini
ad5e0614d4 Added constructors to RawPDU. 2014-09-19 08:55:23 -03:00
Matias Fontanini
1ba203d742 Fixed compilation errors on FreeBSD. 2014-09-19 08:50:35 -03:00
Matias Fontanini
74cca6a483 Improved documentation on several classes. 2014-09-14 14:13:25 -03:00
Matias Fontanini
977231cf46 Fixed bug when allocating IP over IP packets. 2014-09-09 08:37:17 -03:00
Matias Fontanini
b532753a16 Fixed network naming on Windows. 2014-09-07 23:48:37 -03:00
Matias Fontanini
e0b9e38587 Utils::network_interface returns pcap compatible names on Windows. 2014-09-07 17:54:11 -03:00
Matias Fontanini
9d4bdce7a9 NetworkInterface::name now works on Windows. 2014-09-07 16:40:50 -03:00
Matias Fontanini
e00d6aaa7e Removed obsolete README file. 2014-09-07 11:22:44 -03:00
Matias Fontanini
9bda470f9d Completely removed autotools build system.
Also cleaned up the project's root, moving some files
into subdirectories.
2014-09-07 00:47:27 -03:00
Matias Fontanini
8b2f6a7fb2 Updated version to 3.2. 2014-09-04 23:04:36 -03:00
Matias Fontanini
57be666de1 Added documentation generation through the build system. 2014-09-04 22:44:10 -03:00
Matias Fontanini
050214a5dc Updated documentation on several classes. 2014-09-02 23:46:27 -03:00
Matias Fontanini
8bd3313010 Removed print statement. 2014-08-31 18:46:13 -03:00
Matias Fontanini
4d8658ca54 Merge pull request #33 from mfontanini/sniffer-config-object
Sniffer config object
2014-08-31 18:44:02 -03:00
Matias Fontanini
b6fdba0077 The timeout Sniffer option is set to 1000 by default. 2014-08-31 18:34:52 -03:00
Matias Fontanini
83ced826d0 Fixed using pcap_compile on a not-yet activated pcap handle. 2014-08-30 23:54:18 -03:00
Matias Fontanini
d820b0d19d Added documentation for SnifferConfiguration. 2014-08-30 23:35:05 -03:00
Matias Fontanini
7135473d19 Fixed bug triggered on Dot3 serialization.
In addition, Dot3 now always sets the packet length on
serialization.
2014-08-30 23:02:41 -03:00
Matias Fontanini
a7a4105cf8 Added OfflinePacketFilter class. 2014-08-30 23:01:46 -03:00
Santiago Alessandri
2b6a079980 Added back the original constructors of the Sniffer and FileSniffer to keep compatibility. Tagged them as deprecated, though.
Changed the default if_mask to 0 as PCAP_NETMASK_UNKNOWN is still not present in all versions of pcap.

Snap length is always set and it's default value is of 65535 not 0.
2014-08-30 17:29:30 -07:00
Matias Fontanini
07be8e244c Renamed NOEXCEPT macro to TINS_NOEXCEPT. 2014-08-30 14:30:47 -03:00
Matias Fontanini
9d2a60ef43 Added DataLinkType class. 2014-08-30 14:28:29 -03:00
Matias Fontanini
88fc1e7a87 Merge pull request #32 from mfontanini/BUG-31
BUG #31 (Closed): Fixed CMake files.
2014-08-29 23:56:30 -03:00
Santiago Alessandri
b063687621 BUG #31 (Closed): Fixed CMake files. 2014-08-29 18:43:40 -07:00
Santiago Alessandri
039b41cb76 Updated the examples to work with the new Sniffer constructor using the SnifferConfiguration object. 2014-08-29 18:20:15 -07:00
Santiago Alessandri
49f451ecd1 Changed the name to SnifferConfiguration, it sounds better. 2014-08-29 16:35:13 -07:00
Santiago Alessandri
10c5013305 Created gitignore file to exclude build directory and config.h automatically generated file. 2014-08-29 16:31:01 -07:00
Santiago Alessandri
5b2934e102 Refactored sniffer class to take a SnifferConfigurator to do the setup.
This way it is easier to extend the different configuration capabilities.
2014-08-29 16:30:13 -07:00
Matias Fontanini
74c85085fb IPv4Address now uses inet_pton when constructing from string. 2014-08-28 22:53:47 -03:00
142 changed files with 3376 additions and 58355 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
build/**
include/tins/config.h

81
CHANGES
View File

@@ -1,3 +1,84 @@
v3.2
- Added include guard for config.h.
- The functor used on BaseSniffer::sniff_loop can now take a Packet.
- Added mcs, tx_flags, ext and data_retries options to RadioTap.
- Fixed big endian representation of RadioTap header.
- RadioTap's dbm_signal and dbm_noise are now signed.
- RadioTap now throws if an option is not present when getting
its value.
- TKIP decryption now works correctly on packets from AP to STA.
- Added support for PKTAP header.
- Fixed endian issue on IPv4Address::ip_to_int on Windows.
- Fixed IP parsing when total length is 0 due to TCP segmentation offload.
- Re-added support for pkg-config.
- TCPStreamFollower now calls PDU::find_pdu instead of PDU::rfind_pdu.
- Fixed assertion throw caused by DNS parsing on Windows on debug mode.
- Added throw on BSD when trying to send_recv L3 packets.
- Added Loopback::matches_response.
- Removed obsolete autotools files.
- Fixed exception thrown when an interface didn't have an IP address
on NetworkInterface.
- Added NetworkInterface::is_loopback.
- Moved all headers to the directory include/tins.
- Fixed compilation warning on TCPStramFollower due to signed to unsigned
conversion on integral constant.
- BaseSniffer::get_pcap_handle is now public.
- PPPoE session packets are now parsed correctly.
- Fixed invalid Loopback protocol detection on FreeBSD/OSX.
- Fixed OSX IP packet sending issue.
- Added useful constructors to RawPDU.
- Fixed compilation errors on FreeBSD.
- Improved documentation on several classes.
- Fixed parsing bug when allocating IP over IP packets.
- Fixed Windows network interface naming.
- Utils::network_interface returns pcap compatible names on Windows.
- NetworkInterface::name now works on Windows.
- Added documentation generation through the build system.
- Added SnifferConfiguration class.
- Fixed bug on Dot3 serialization.
- Added OfflinePacketFilter class.
- Renamed NOEXCEPT macro to TINS_NOEXCEPT.
- Added DataLinkType class.
- IPv4Address now uses inet_pton when constructing from string.
v3.1 - Sun Aug 24 21:39:43 ART 2014
- Fixed ICMPv6 checksum error on serialization.

View File

@@ -28,8 +28,8 @@ ENDIF(LIBTINS_BUILD_SHARED)
# The version number.
SET(LIBTINS_VERSION_MAJOR 3)
SET(LIBTINS_VERSION_MINOR 1)
SET(LIBTINS_CPP_VERSION "${LIBTINS_VERSION_MAJOR}.${LIBTINS_VERSION_MINOR}")
SET(LIBTINS_VERSION_MINOR 2)
SET(LIBTINS_VERSION "${LIBTINS_VERSION_MAJOR}.${LIBTINS_VERSION_MINOR}")
# Required Packages
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
@@ -81,13 +81,44 @@ IF(LIBTINS_ENABLE_DOT11)
ENDIF(LIBTINS_ENABLE_WPA2)
ENDIF(LIBTINS_ENABLE_DOT11)
# Add a target to generate API documentation using Doxygen
FIND_PACKAGE(Doxygen QUIET)
IF(DOXYGEN_FOUND)
CONFIGURE_FILE(
${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile.in
${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
@ONLY
)
ADD_CUSTOM_TARGET(
docs
${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen" VERBATIM
)
ENDIF(DOXYGEN_FOUND)
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
# Congiguration file
# Configuration file
CONFIGURE_FILE(
"${PROJECT_SOURCE_DIR}/include/config.h.in"
"${PROJECT_SOURCE_DIR}/include/config.h"
"${PROJECT_SOURCE_DIR}/include/tins/config.h.in"
"${PROJECT_SOURCE_DIR}/include/tins/config.h"
)
# Support for pkg-config
set(CMAKE_INSTALL_LIBDIR lib)
set(pkgconfig_prefix ${CMAKE_INSTALL_PREFIX})
set(pkgconfig_exec_prefix ${CMAKE_INSTALL_PREFIX})
set(pkgconfig_libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
set(pkgconfig_version ${LIBTINS_VERSION})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libtins.pc.in
${CMAKE_CURRENT_BINARY_DIR}/libtins.pc @ONLY)
install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/libtins.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
)
ENABLE_TESTING()
@@ -110,20 +141,20 @@ EXPORT(PACKAGE libtins)
# for the build tree
SET(CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/include")
CONFIGURE_FILE(
libtinsConfig.cmake.in
cmake/libtinsConfig.cmake.in
"${PROJECT_BINARY_DIR}/libtinsConfig.cmake" @ONLY
)
CONFIGURE_FILE(
libtinsConfigVersion.cmake.in
cmake/libtinsConfigVersion.cmake.in
"${PROJECT_BINARY_DIR}/libtinsConfigVersion.cmake" @ONLY
)
# Install the libtinsConfig.cmake and libtinsConfigVersion.cmake
INSTALL(
FILES
"${PROJECT_BINARY_DIR}/libtinsConfig.cmake"
"${PROJECT_BINARY_DIR}/libtinsConfigVersion.cmake"
DESTINATION CMake
COMPONENT dev
"${PROJECT_BINARY_DIR}/libtinsConfigVersion.cmake"
DESTINATION CMake
COMPONENT dev
)
# Install the export set for use with the install-tree

View File

@@ -1,131 +0,0 @@
AUTOMAKE_OPTIONS=subdir-objects 1.11
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/handshake_capturer.cpp \
src/stp.cpp \
src/pppoe.cpp \
src/crypto.cpp \
src/dhcp.cpp \
src/dhcpv6.cpp \
src/dns.cpp \
src/dot3.cpp \
src/dot1q.cpp \
src/eapol.cpp \
src/ethernetII.cpp \
src/icmp.cpp \
src/icmpv6.cpp \
src/internals.cpp \
src/ip_reassembler.cpp \
src/ip.cpp \
src/ip_address.cpp \
src/ipv6.cpp \
src/ipv6_address.cpp \
src/ipsec.cpp \
src/llc.cpp \
src/loopback.cpp \
src/network_interface.cpp \
src/packet_sender.cpp \
src/packet_writer.cpp \
src/ppi.cpp \
src/pdu.cpp \
src/radiotap.cpp \
src/address_range.cpp \
src/rawpdu.cpp \
src/rsn_information.cpp \
src/sll.cpp \
src/snap.cpp \
src/sniffer.cpp \
src/tcp.cpp \
src/tcp_stream.cpp \
src/udp.cpp \
src/utils.cpp \
src/dot11/dot11_base.cpp \
src/dot11/dot11_data.cpp \
src/dot11/dot11_mgmt.cpp \
src/dot11/dot11_beacon.cpp \
src/dot11/dot11_assoc.cpp \
src/dot11/dot11_auth.cpp \
src/dot11/dot11_probe.cpp \
src/dot11/dot11_control.cpp
libtinsdir = $(includedir)/tins
libtins_HEADERS = include/internals.h \
include/dhcpv6.h \
include/dot11.h \
include/dot1q.h \
include/dot3.h \
include/small_uint.h \
include/ip.h \
include/ipsec.h \
include/eapol.h \
include/tcp_stream.h \
include/pppoe.h \
include/handshake_capturer.h \
include/ipv6.h \
include/icmpv6.h \
include/ieee802_3.h \
include/endianness.h \
include/rsn_information.h \
include/loopback.h \
include/ethernetII.h \
include/crypto.h \
include/packet.h \
include/llc.h \
include/ip_reassembler.h \
include/icmp.h \
include/hw_address.h \
include/packet_writer.h \
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/ppi.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 \
include/stp.h \
include/exceptions.h \
include/config.h \
include/address_range.h \
include/pdu_allocator.h
libtins_dot11_HEADERS = include/dot11/dot11_base.h \
include/dot11/dot11_beacon.h \
include/dot11/dot11_data.h \
include/dot11/dot11_mgmt.h \
include/dot11/dot11_assoc.h \
include/dot11/dot11_auth.h \
include/dot11/dot11_probe.h \
include/dot11/dot11_control.h
libtins_dot11dir = $(includedir)/tins/dot11/

File diff suppressed because it is too large Load Diff

73
README
View File

@@ -1,73 +0,0 @@
------------------------------------------------------------------------
libtins v3.0
------------------------------------------------------------------------
-------------------------------- About ---------------------------------
libtins is a high-level, multiplatform C++ network packet sniffing and
crafting library.
Its main purpose is to provide the C++ developer an easy, efficient,
platform and endianess-independent way to create tools which need to
send, receive and manipulate specially crafted packets.
In order to read tutorials, examples and checkout some benchmarks of the
library, please visit:
http://libtins.github.io/
------------------------------- Compiling ------------------------------
libtins depends on libpcap and openssl, although the latter is not
necessary if some features of the library are disabled.
In order to compile, execute:
./configure
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.
libtins is noticeable faster if you enable C++11 support. Therefore, if
your compiler supports this standard, then you should enable it. In
order to do so, use the --enable-c++11 switch:
./configure --enable-c++11
If you want to disable WPA2 decryption support, which will remove
openssl as a dependency for compilation, use the --disable-wpa2 switch:
./configure --disable-wpa2
If you want to disable IEEE 802.11 support(this will also disable
RadioTap and WPA2 decryption), which will reduce the size of the
resulting library in around 20%, use the --disable-dot11 switch:
./configure --disable-dot11
------------------------------ Installing-------------------------------
Once you're done, if you want to install the header files and the
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.github.io/examples/

1191
aclocal.m4 vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1 +0,0 @@
/usr/share/automake-1.14/compile

1530
config.guess vendored

File diff suppressed because it is too large Load Diff

1782
config.sub vendored

File diff suppressed because it is too large Load Diff

18244
configure vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,85 +0,0 @@
AC_INIT([libtins], [3.0], [matias.fontanini@gmail.com], [libtins], [http://libtins.sourceforge.net])
AC_CANONICAL_SYSTEM
AC_CONFIG_HEADER(include/config.h)
AM_INIT_AUTOMAKE([-Wall -Werror -Wno-extra-portability foreign])
LT_INIT([disable-static])
AC_CONFIG_MACRO_DIR([m4])
AM_MAINTAINER_MODE([disable])
AC_PROG_CXX
AC_LANG(C++)
AC_PROG_LIBTOOL
# Check that libpcap exists
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
# Options
wpa2_msg="WPA2 decryption(which requires openssl) can be disabled using the --disable-wpa2 flag."
AC_ARG_ENABLE(
c++11,
[ --enable-c++11 enable C++11 features],
[AX_CXX_COMPILE_STDCXX_11(noext)]
)
AC_ARG_ENABLE(
dot11,
[ --disable-dot11 disable IEEE 802.11 support],
[],
[
AC_DEFINE([HAVE_DOT11], 1, Have IEEE 802.11 support)
# Only allow enabling WPA2 if Dot11 is enabled.
AC_ARG_ENABLE(
wpa2,
[ --disable-wpa2 disable WPA2 decryption features],
[],
[
AC_CHECK_HEADERS(
[openssl/evp.h openssl/hmac.h openssl/aes.h],
[],
[AC_MSG_ERROR([openssl headers are missing! $wpa2_msg ])]
AC_DEFINE([HAVE_WPA2_DECRYPTION], 0, Have WPA2 decryption library)
)
AC_CHECK_LIB(
crypto,
PKCS5_PBKDF2_HMAC_SHA1,
[],
[AC_MSG_ERROR([openssl library is missing! $wpa2_msg ])]
)
AC_DEFINE([HAVE_WPA2_DECRYPTION], 1, Have WPA2 decryption library)
]
)
]
)
# Substitute options
AC_SUBST(CXXFLAGS)
AC_SUBST(LIBS)
AC_SUBST(LIBTINS_INCLUDE_DIR)
AC_SUBST([LIBTINS_VERSION], [3:0:0])
AC_CONFIG_FILES([Makefile libtins.pc])
AC_OUTPUT

708
depcomp
View File

@@ -1,708 +0,0 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2012-03-27.16; # UTC
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010,
# 2011, 2012 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# 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
# A tabulation character.
tab=' '
# A newline character.
nl='
'
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
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
if test "$depmode" = xlc; then
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency informations.
gccflag=-qmakedep=gcc,-MF
depmode=gcc
fi
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
## 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 ' ' "$nl" < "$tmpdepfile" |
## Some versions of gcc put a space before the ':'. On the theory
## that the space means something, we add a space to the output as
## well. hp depmode also adds that space, but also prefixes the VPATH
## to the object. Take care to not repeat it in the output.
## 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 ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
tr "$nl" ' ' >> "$depfile"
echo >> "$depfile"
# The second pass generates a dummy entry for each header file.
tr ' ' "$nl" < "$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"
;;
xlc)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
# current directory. Also, the AIX compiler puts '$object:' at the
# 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"
sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
# "include basename.Plo" scheme.
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
icc)
# Intel's C compiler anf tcc (Tiny C Compiler) understand '-MD -MF file'.
# However on
# $CC -MD -MF foo.d -c -o sub/foo.o sub/foo.c
# ICC 7.0 will fill foo.d with something like
# foo.o: sub/foo.c
# foo.o: sub/foo.h
# which is wrong. We want
# 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 ... \
# ...
# tcc 0.9.26 (FIXME still under development at the moment of writing)
# will emit a similar output, but also prepend the continuation lines
# with horizontal tabulation characters.
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
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 -e "s/^[ $tab][ $tab]*/ /" -e "s,^[^:]*:,$object :," \
< "$tmpdepfile" > "$depfile"
sed '
s/[ '"$tab"'][ '"$tab"']*/ /g
s/^ *//
s/ *\\*$//
s/^[^:]*: *//
/^$/d
/:$/d
s/$/ :/
' < "$tmpdepfile" >> "$depfile"
rm -f "$tmpdepfile"
;;
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"
sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -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/\(.*\)/'"$tab"'\1 \\/p
s/.\(.*\) \\/\1:/
H
$ {
s/.*/'"$tab"'/
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:^['"$tab"' ]*[^:'"$tab"' ][^:][^:]*\:['"$tab"' ]*:'"$object"'\: :' > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
tr ' ' "$nl" < "$tmpdepfile" | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
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 ' ' "$nl" | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
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::'"$tab"'\1 \\:p' >> "$depfile"
echo "$tab" >> "$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:

View File

@@ -31,14 +31,14 @@ PROJECT_NAME = libtins
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER = 1.2
PROJECT_NUMBER = @LIBTINS_VERSION@
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
OUTPUT_DIRECTORY = ../docs/
OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@/docs/
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
# 4096 sub-directories (in 2 levels) under the output directory of each output
@@ -581,7 +581,7 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = include src
INPUT = @CMAKE_CURRENT_SOURCE_DIR@/include @CMAKE_CURRENT_SOURCE_DIR@/src @CMAKE_CURRENT_SOURCE_DIR@/docs/mainpage.dox
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is

29
docs/mainpage.dox Normal file
View File

@@ -0,0 +1,29 @@
/**
* \mainpage Documentation
*
* \section intro_sec Introduction
*
* <i>libtins</i> is a high-level, multiplatform <i>C++</i> network packet
* sniffing and crafting library.
*
* Its main purpose is to provide the <i>C++</i> developer an easy, efficient,
* platform and endianess-independent way to create tools which need to
* send, receive and manipulate network packets.
*
* \section install_sec Installation
*
* Please visit the <a href="http://libtins.github.io/download/">downloads
* section</a> in order to see the installation instructions.
*
* \section tutorials_sec Tutorials
*
* If you want to learn about how the library works, please visit the
* <a href="http://libtins.github.io/tutorial/">tutorials</a> section.
*
* \section examples_sec Examples
*
* Make sure to visit the <a href="http://libtins.github.io/examples/">
* examples</a> section to see some short but illustrative examples on how
* to send and sniff packets using <i>libtins</i>.
*
*/

View File

@@ -13,6 +13,7 @@ IF(libtins_FOUND)
dns_spoof
dns_stats
wps_detect
traceroute
)
ELSE(HAVE_CXX11)
MESSAGE(WARNING "Disabling some examples since C++11 support is disabled.")
@@ -24,7 +25,6 @@ IF(libtins_FOUND)
${LIBTINS_CXX11_EXAMPLES}
beacon_display
portscan
traceroute
)
ADD_EXECUTABLE(arpspoofing EXCLUDE_FROM_ALL arpspoofing.cpp)
@@ -39,11 +39,13 @@ IF(libtins_FOUND)
ADD_EXECUTABLE(beacon_display EXCLUDE_FROM_ALL beacon_display.cpp)
if(THREADS_FOUND)
IF(HAVE_CXX11)
ADD_EXECUTABLE(traceroute EXCLUDE_FROM_ALL traceroute.cpp)
TARGET_LINK_LIBRARIES(traceroute ${CMAKE_THREAD_LIBS_INIT})
ENDIF(HAVE_CXX11)
ADD_EXECUTABLE(portscan EXCLUDE_FROM_ALL portscan.cpp)
ADD_EXECUTABLE(traceroute EXCLUDE_FROM_ALL traceroute.cpp)
TARGET_LINK_LIBRARIES(portscan ${CMAKE_THREAD_LIBS_INIT})
TARGET_LINK_LIBRARIES(traceroute ${CMAKE_THREAD_LIBS_INIT})
ELSE(THREADS_FOUND)
MESSAGE(WARNING "Disabling portscan and traceroute examples since pthreads library was not found.")
ENDIF(THREADS_FOUND)

View File

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

View File

@@ -87,10 +87,14 @@ int main(int argc, char *argv[])
return 1;
}
arp_monitor monitor;
// Sniffer configuration
SnifferConfiguration config;
config.set_promisc_mode(true);
config.set_filter("arp");
// Sniff on the provided interface in promiscuous mode
Sniffer sniffer(argv[1], Sniffer::PROMISC);
Sniffer sniffer(argv[1], config);
// Only capture arp packets
sniffer.set_filter("arp");
monitor.run(sniffer);
}

View File

@@ -47,7 +47,11 @@ private:
};
void BeaconSniffer::run(const std::string &iface) {
Sniffer sniffer(iface, Sniffer::PROMISC, "type mgt subtype beacon", true);
SnifferConfiguration config;
config.set_promisc_mode(true);
config.set_filter("type mgt subtype beacon");
config.set_rfmon(true);
Sniffer sniffer(iface, config);
sniffer.sniff_loop(make_sniffer_handler(this, &BeaconSniffer::callback));
}

4116
examples/configure vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +0,0 @@
AC_INIT(myconfig, 0.1)
AC_PROG_CXX()
AC_LANG(C++)
saved_libs="${LIBS}"
LIBS="${LIBS} -ltins"
AC_MSG_CHECKING(libtins)
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <tins/dns.h>],
[Tins::DNS dummy])],
[echo done],
[echo error; echo *** libtins is not installed. Aborting... ***; exit 1])
LIBS="${saved_libs}"
AC_CHECK_HEADERS([tins/tins.h], , [echo "*** Error: libtins' headers are absent ***"; exit 1;])
AC_OUTPUT(Makefile)

View File

@@ -55,10 +55,11 @@ int main(int argc, char *argv[])
return 1;
}
// Sniff on the provided interface in promiscuos mode
Sniffer sniffer(argv[1], Sniffer::PROMISC);
SnifferConfiguration config;
config.set_promisc_mode(true);
// Only capture udp packets sent to port 53
sniffer.set_filter("udp and dst port 53");
config.set_filter("udp and dst port 53");
Sniffer sniffer(argv[1], config);
// Start the capture
sniffer.sniff_loop(callback);

View File

@@ -90,10 +90,11 @@ int main(int argc, char *argv[])
return 1;
}
// Sniff on the provided interface in promiscuos mode
Sniffer sniffer(argv[1], Sniffer::PROMISC);
SnifferConfiguration config;
config.set_promisc_mode(true);
// Only capture udp packets sent to port 53
sniffer.set_filter("udp and dst port 53");
config.set_filter("udp and dst port 53");
Sniffer sniffer(argv[1], config);
// All packets will be sent through the provided interface
sender.default_interface(argv[1]);

View File

@@ -166,8 +166,10 @@ int main(int argc, char *argv[]) {
return 1;
}
try {
Sniffer sniffer(argv[1], Sniffer::PROMISC);
sniffer.set_filter("udp and port 53");
SnifferConfiguration config;
config.set_promisc_mode(true);
config.set_filter("udp and dst port 53");
Sniffer sniffer(argv[1], config);
dns_monitor monitor;
std::thread thread(
[&]() {

View File

@@ -30,6 +30,7 @@
#include <iostream>
#include <iomanip>
#include <vector>
#include <set>
#include <string>
#include <cstdlib>
#include <pthread.h>
@@ -49,27 +50,88 @@ using namespace Tins;
typedef std::pair<Sniffer*, std::string> sniffer_data;
class Scanner {
public:
Scanner(const NetworkInterface& interface, const IPv4Address& address,
const vector<string>& ports);
void run();
private:
void send_syns(const NetworkInterface &iface, IPv4Address dest_ip);
bool callback(PDU &pdu);
static void *thread_proc(void *param);
void launch_sniffer();
NetworkInterface iface;
IPv4Address host_to_scan;
set<uint16_t> ports_to_scan;
Sniffer sniffer;
};
Scanner::Scanner(const NetworkInterface& interface, const IPv4Address& address,
const vector<string>& ports)
: iface(interface), host_to_scan(address), sniffer(interface.name())
{
sniffer.set_filter(
"tcp and ip src " + address.to_string() + " and tcp[tcpflags] & (tcp-rst|tcp-syn) != 0"
);
for(size_t i = 0; i < ports.size(); ++i) {
ports_to_scan.insert(atoi(ports[i].c_str()));
}
}
void *Scanner::thread_proc(void *param) {
Scanner *data = (Scanner*)param;
data->launch_sniffer();
return 0;
}
void Scanner::launch_sniffer()
{
sniffer.sniff_loop(make_sniffer_handler(this, &Scanner::callback));
}
/* Our scan handler. This will receive SYNs and RSTs and inform us
* the scanned port's status.
*/
bool handler(PDU &pdu) {
bool Scanner::callback(PDU &pdu)
{
// Find the layers we want.
const IP &ip = pdu.rfind_pdu<IP>();
const TCP &tcp = pdu.rfind_pdu<TCP>();
// Ok, it's a TCP PDU. Is RST flag on? Then port is closed.
if(tcp.get_flag(TCP::RST)) {
// This indicates we should stop sniffing.
if(tcp.get_flag(TCP::SYN))
return false;
cout << "Port: " << setw(5) << tcp.sport() << " closed\n";
// Check if the host that we're scanning sent this packet and
// the source port is one of those that we scanned.
if(ip.src_addr() == host_to_scan && ports_to_scan.count(tcp.sport()) == 1) {
// Ok, it's a TCP PDU. Is RST flag on? Then port is closed.
if(tcp.get_flag(TCP::RST)) {
// This indicates we should stop sniffing.
if(tcp.get_flag(TCP::SYN))
return false;
cout << "Port: " << setw(5) << tcp.sport() << " closed\n";
}
// Is SYN flag on? Then port is open!
else if(tcp.flags() == (TCP::SYN | TCP::ACK)) {
cout << "Port: " << setw(5) << tcp.sport() << " open\n";
}
}
// Is SYN flag on? Then port is open!
else if(tcp.flags() == (TCP::SYN | TCP::ACK))
cout << "Port: " << setw(5) << tcp.sport() << " open\n";
return true;
}
void Scanner::run()
{
pthread_t thread;
// Launch our sniff thread.
pthread_create(&thread, 0, &Scanner::thread_proc, this);
// Start sending SYNs to port.
send_syns(iface, host_to_scan);
// Wait for our sniffer.
void *dummy;
pthread_join(thread, &dummy);
}
// Send syns to the given ip address, using the destination ports provided.
void send_syns(const NetworkInterface &iface, IPv4Address dest_ip, const vector<string> &ips) {
void Scanner::send_syns(const NetworkInterface &iface, IPv4Address dest_ip) {
// Retrieve the addresses.
NetworkInterface::Info info = iface.addresses();
PacketSender sender;
@@ -82,9 +144,9 @@ void send_syns(const NetworkInterface &iface, IPv4Address dest_ip, const vector<
// Just some random port.
tcp.sport(1337);
cout << "Sending SYNs..." << endl;
for(vector<string>::const_iterator it = ips.begin(); it != ips.end(); ++it) {
for(set<uint16_t>::const_iterator it = ports_to_scan.begin(); it != ports_to_scan.end(); ++it) {
// Set the new port and send the packet!
tcp.dport(atoi(it->c_str()));
tcp.dport(*it);
sender.send(ip);
}
// Wait 1 second.
@@ -93,6 +155,7 @@ void send_syns(const NetworkInterface &iface, IPv4Address dest_ip, const vector<
* by our function, which will in turn return false.
*/
tcp.set_flag(TCP::RST, 1);
tcp.sport(*ports_to_scan.begin());
// Pretend we're the scanned host...
ip.src_addr(dest_ip);
// We use an ethernet pdu, otherwise the kernel will drop it.
@@ -100,38 +163,17 @@ void send_syns(const NetworkInterface &iface, IPv4Address dest_ip, const vector<
sender.send(eth, iface);
}
void *thread_proc(void *param) {
// IP address is our parameter.
sniffer_data *data = (sniffer_data*)param;
Sniffer *sniffer = data->first;
sniffer->set_filter("tcp and ip src " + data->second + " and tcp[tcpflags] & (tcp-rst|tcp-syn) != 0");
// Sniff loop. Only sniff TCP PDUs comming from the given IP and have either RST or SYN flag on.
sniffer->sniff_loop(handler);
return 0;
}
void scan(int argc, char *argv[]) {
IPv4Address ip(argv[1]);
// Resolve the interface which will be our gateway
NetworkInterface iface(ip);
cout << "Sniffing on interface: " << iface.name() << endl;
// 300 bytes are enough to receive SYNs and RSTs.
Sniffer sniffer(iface.name(), 300);
sniffer_data data(&sniffer, argv[1]);
pthread_t thread;
// Launch our sniff thread.
pthread_create(&thread, 0, thread_proc, &data);
// Consume arguments
argv += 2;
argc -= 2;
// Start sending SYNs to port.
send_syns(iface, ip, vector<string>(argv, argv + (argc)));
// Wait for our sniffer.
void *dummy;
pthread_join(thread, &dummy);
Scanner scanner(iface, ip, vector<string>(argv, argv + (argc)));
scanner.run();
}
int main(int argc, char *argv[]) {

View File

@@ -47,10 +47,12 @@ public:
result_type trace() {
// ICMPs that aren't sent from us.
Sniffer sniffer(
iface.name(), 500, false,
"ip proto \\icmp and not src host " + iface.addresses().ip_addr.to_string()
);
SnifferConfiguration config;
config.set_snap_len(500);
config.set_promisc_mode(false);
config.set_filter(
"ip proto \\icmp and not src host " + iface.addresses().ip_addr.to_string());
Sniffer sniffer(iface.name(), config);
PacketSender sender;
// Create our handler

View File

@@ -69,6 +69,10 @@ int main(int argc, char *argv[]) {
return 1;
}
// Only sniff beacons
Sniffer sniffer(argv[1], 2000, true, "wlan type mgt subtype beacon");
SnifferConfiguration config;
config.set_snap_len(2000);
config.set_promisc_mode(true);
config.set_filter("wlan type mgt subtype beacon");
Sniffer sniffer(argv[1], config);
sniffer.sniff_loop(handler);
}

View File

@@ -1,7 +1 @@
FILE(GLOB INCLUDE_FILES "*.h")
INSTALL(
FILES ${INCLUDE_FILES}
DESTINATION include/tins
COMPONENT Headers
)
ADD_SUBDIRECTORY(dot11)
ADD_SUBDIRECTORY(tins)

View File

@@ -0,0 +1,7 @@
FILE(GLOB INCLUDE_FILES "*.h")
INSTALL(
FILES ${INCLUDE_FILES}
DESTINATION include/tins
COMPONENT Headers
)
ADD_SUBDIRECTORY(dot11)

View File

@@ -42,7 +42,8 @@ namespace Tins {
class EthernetII;
/**
* \brief Class that represents an ARP PDU.
* \class ARP
* \brief Represents an ARP PDU.
*
*/
class ARP : public PDU {

View File

@@ -43,6 +43,7 @@
namespace Tins {
/**
* \class BootP
* \brief Class representing a BootP packet.
*/
class BootP : public PDU {

View File

@@ -1,3 +1,5 @@
#ifndef TINS_CONFIG_H
#define TINS_CONFIG_H
/* Define if the compiler supports basic C++11 syntax */
#cmakedefine HAVE_CXX11
@@ -7,3 +9,5 @@
/* Have WPA2 decryption library */
#cmakedefine HAVE_WPA2_DECRYPTION
#endif // TINS_CONFIG_H

View File

@@ -85,6 +85,7 @@ namespace Tins {
IPX = 0x8137, /* IPX */
IPV6 = 0x86dd, /* IP protocol version 6 */
PPPOED = 0x8863, /* PPPoE Discovery */
PPPOES = 0x8864, /* PPPoE Session */
EAPOL = 0x888e, /* EAPOL */
LOOPBACK = 0x9000 /* used to test interfaces */
};

View File

@@ -0,0 +1,81 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_DATA_LINK_TYPE_H
#define TINS_DATA_LINK_TYPE_H
#include <pcap.h>
namespace Tins {
class EthernetII;
class RadioTap;
class Dot11;
class Dot3;
class SLL;
class Loopback;
class PPI;
/**
* \struct DataLinkType
* \brief Maps a libtins link layer PDU to a libpcap data link identifier.
*
* This is an empty class that should be instantiated with any object that
* represents a link layer PDU (EthernetII, Dot11, RadioTap, etc):
*
* \code
* // Instantiate it and pass it to PacketWriter's constructor.
* PacketWriter writer("file.pcap", DataLinkType<RadioTap>());
* \endcode
*/
template<typename T>
struct DataLinkType;
#define TINS_MAKE_DATA_LINK_TYPE(tins_type, pcap_type) \
template<> \
struct DataLinkType<tins_type> { \
static const int type = pcap_type; \
int get_type() const { \
return type; \
} \
};
TINS_MAKE_DATA_LINK_TYPE(EthernetII, DLT_EN10MB)
TINS_MAKE_DATA_LINK_TYPE(Dot3, DLT_EN10MB)
TINS_MAKE_DATA_LINK_TYPE(SLL, DLT_LINUX_SLL)
TINS_MAKE_DATA_LINK_TYPE(Loopback, DLT_LOOP)
TINS_MAKE_DATA_LINK_TYPE(PPI, DLT_PPI)
TINS_MAKE_DATA_LINK_TYPE(Dot11, DLT_IEEE802_11)
TINS_MAKE_DATA_LINK_TYPE(RadioTap, DLT_IEEE802_11_RADIO)
#undef TINS_MAKE_DATA_LINK_TYPE
} // Tins
#endif // TINS_DATA_LINK_TYPE_H

View File

@@ -40,11 +40,29 @@
namespace Tins {
/**
* \brief Class that represents the DHCP PDU.
* \class DHCP
* \brief Represents the DHCP PDU.
*
* When adding options, the "End" option is not added automatically.
* This class represents a DHCP PDU. It contains helpers methods
* which make it easy to set/get specific option values.
*
* Note that when adding options, the "End" option is not added
* automatically, so you will have to add it yourself.
*
* \sa DHCP::end
* Options can be retrieved easily from DHCP PDUs:
*
* \code
* // Sniff a packet from somewhere
* DHCP dhcp = get_dhcp_from_somewhere();
*
* // This retrieves the Domain Name Servers option and converts
* // it to a std::vector<IPv4Address>. Note that if this option
* // is not present, an option_not_found exception is thrown.
* for(const auto& address : dhcp.domain_name_servers()) {
* // address is an ip
* }
*
* \endcode
*/
class DHCP : public BootP {
public:

View File

@@ -40,7 +40,8 @@
namespace Tins {
/**
* Represents a DHCPv6 PDU.
* \class DHCPv6
* \brief Represents a DHCPv6 PDU.
*/
class DHCPv6 : public PDU {
public:

View File

@@ -47,6 +47,27 @@ namespace Tins {
/**
* \class DNS
* \brief Represents a DNS PDU.
*
* This class represents the DNS PDU, and allows easy access
* to queries and answer records.
*
* The DNS PDU is not parsed automatically while sniffing, so you will
* have to parse it manually from an UDP packet's payload, for example:
*
* \code
* // Assume we get an udp packet from somewhere.
* UDP udp = get_udp_packet();
*
* // Now:
* // 1 - Get the RawPDU layer (contains the payload).
* // 2 - Construct a DNS object over its contents.
* DNS dns = udp.rfind_pdu<RawPDU>().to<DNS>();
*
* // Now use the DNS object!
* for(const auto& query : dns.queries()) {
* // Process a query
* }
* \endcode
*/
class DNS : public PDU {
public:

View File

@@ -36,6 +36,7 @@
namespace Tins {
/**
* \class Dot1Q
* Represents an IEEE 802.1q PDU.
*/
class Dot1Q : public PDU {

View File

@@ -39,7 +39,8 @@
namespace Tins {
/**
* \brief Class representing an Ethernet II PDU.
* \class Dot3
* \brief Class representing an IEEE 802.3 PDU.
*/
class Dot3 : public PDU {
public:

View File

@@ -46,7 +46,8 @@ namespace Tins {
/** \endcond */
/**
* \brief Class that represents the EAP encapsulation over LAN.
* \class EAPOL
* \brief Represents the EAP encapsulation over LAN.
*/
class EAPOL : public PDU {
public:

View File

@@ -39,7 +39,8 @@
namespace Tins {
/**
* \brief Class representing an Ethernet II PDU.
* \class EthernetII
* \brief Represents an Ethernet II PDU.
*/
class EthernetII : public PDU {
public:

View File

@@ -5,14 +5,14 @@
* 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
@@ -55,7 +55,7 @@ class malformed_packet : public std::runtime_error {
public:
malformed_packet()
: std::runtime_error(std::string()) { }
const char* what() const throw() {
return "Malformed packet";
}
@@ -68,7 +68,7 @@ class pdu_not_found : public std::runtime_error {
public:
pdu_not_found()
: std::runtime_error(std::string()) { }
const char* what() const throw() {
return "PDU not found";
}
@@ -82,18 +82,30 @@ class invalid_interface : public std::runtime_error {
public:
invalid_interface()
: std::runtime_error(std::string()) { }
const char* what() const throw() {
return "Invalid interface";
}
};
/**
* \brief Exception thrown when a field is not present in frame.
*/
class field_not_present : public std::runtime_error {
public:
field_not_present()
: std::runtime_error(std::string()) { }
const char* what() const throw() {
return "Field not present";
}
};
/**
* \brief Exception thrown when PacketSender fails to open a socket.
*/
class socket_open_error : public std::runtime_error {
public:
socket_open_error(const std::string &msg)
socket_open_error(const std::string &msg)
: std::runtime_error(msg) { }
};
@@ -102,7 +114,7 @@ public:
*/
class socket_close_error : public std::runtime_error {
public:
socket_close_error(const std::string &msg)
socket_close_error(const std::string &msg)
: std::runtime_error(msg) { }
};
@@ -111,7 +123,7 @@ public:
*/
class socket_write_error : public std::runtime_error {
public:
socket_write_error(const std::string &msg)
socket_write_error(const std::string &msg)
: std::runtime_error(msg) { }
};
@@ -127,7 +139,7 @@ public:
};
/**
* \brief Exception thrown when an unkown link layer PDU type is
* \brief Exception thrown when an unkown link layer PDU type is
* found while sniffing.
*/
class unknown_link_type : public std::exception {

View File

@@ -43,6 +43,22 @@ namespace Tins {
/**
* \class HWAddress
* \brief Represents a hardware address.
*
* This class represents a hardware (MAC) address. It can
* be constructed from it's string representation and you can
* iterate over the bytes that compose it.
*
* For example:
*
* \code
* // Construct it from a string.
* HWAddress<6> address("00:01:fa:9e:1a:cd");
*
* // Iterate over its bytes.
* for(auto element : address) {
* // element will be each of the bytes(\x00, \x01, \xfa, etc)
* }
* \endcode
*/
template<size_t n, typename Storage = uint8_t>
class HWAddress {
@@ -79,7 +95,8 @@ public:
* \brief Constructor from a const storage_type*.
*
* If no pointer or a null pointer is provided, the address is
* initialized to 00:00:.....
* initialized to 00:00:00:00:00:00.
*
* This constructor is very usefull when passing zero initialized
* addresses as arguments to other functions. You can use a
* literal 0, which will be implicitly converted to the empty address.

View File

@@ -49,7 +49,9 @@
namespace Tins {
/** \brief Class that represents an ICMP PDU.
/**
* \class ICMP
* \brief Class that represents an ICMP PDU.
*
* ICMP is the representation of the ICMP PDU. Instances of this class
* must be sent over a level 3 PDU, this will otherwise fail.

View File

@@ -44,7 +44,8 @@
namespace Tins {
/**
* Represents an ICMPv6 PDU.
* \class ICMPv6
* \brief Represents an ICMPv6 PDU.
*/
class ICMPv6 : public PDU {
public:

View File

@@ -5,14 +5,14 @@
* 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
@@ -26,10 +26,14 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_INTERNALS_H
#define TINS_INTERNALS_H
#if TINS_IS_CXX11
#include <type_traits>
#endif
#include <sstream>
#include <string>
#include <stdint.h>
@@ -50,16 +54,16 @@ class byte_array {
public:
typedef uint8_t* iterator;
typedef const uint8_t* const_iterator;
byte_array() {
std::fill(begin(), end(), 0);
}
template<typename InputIterator>
byte_array(InputIterator start, InputIterator last) {
std::copy(start, last, data);
}
template<typename InputIterator>
byte_array(InputIterator start) {
std::copy(start, n, data);
@@ -72,23 +76,23 @@ public:
uint8_t operator[](size_t i) const{
return data[i];
}
iterator begin() {
return data;
}
iterator end() {
return data + n;
}
const_iterator begin() const {
return data;
}
const_iterator end() const {
return data + n;
}
size_t size() const {
return n;
}
@@ -106,12 +110,14 @@ struct enable_if {
template<typename T>
struct enable_if<false, T> {
};
PDU *pdu_from_flag(Constants::Ethernet::e flag, const uint8_t *buffer,
PDU *pdu_from_flag(Constants::Ethernet::e flag, const uint8_t *buffer,
uint32_t size, bool rawpdu_on_no_match = true);
PDU *pdu_from_flag(Constants::IP::e flag, const uint8_t *buffer,
PDU *pdu_from_flag(Constants::IP::e flag, const uint8_t *buffer,
uint32_t size, bool rawpdu_on_no_match = true);
PDU *pdu_from_dlt_flag(int flag, const uint8_t *buffer,
uint32_t size, bool rawpdu_on_no_match = true);
PDU *pdu_from_flag(PDU::PDUType type, const uint8_t *buffer, uint32_t size);
@@ -198,6 +204,39 @@ template<>
struct is_unsigned_integral<uint64_t> {
static const bool value = true;
};
#if TINS_IS_CXX11
// Part of C++14 standard library
template<bool B, class T = void>
using enable_if_t = typename std::enable_if<B,T>::type;
// Template metaprogramming trait to determine if a functor can accept another parameter as an argument
template <class T, class P, class=void>
struct accepts_type : std::false_type { };
template <class T, class P>
struct accepts_type<T, P, enable_if_t<
std::is_same< decltype( std::declval<T>()(std::declval<P>()) ), bool>::value
>> : std::true_type { };
// use enable_if to invoke the Packet&& version of the sniff_loop handler if possible - otherwise fail to old behavior
template <class Functor, class Packet>
bool invoke_loop_cb(Functor& f, Packet& p, typename std::enable_if<accepts_type<Functor, Packet>::value, bool>::type* = 0) {
return f(std::move(p));
}
template <class Functor, class Packet>
bool invoke_loop_cb(Functor& f, Packet& p, typename std::enable_if<!accepts_type<Functor, Packet>::value && accepts_type<Functor, Packet&>::value, bool>::type* = 0) {
return f(p);
}
template <class Functor, class Packet>
bool invoke_loop_cb(Functor& f, Packet& p, typename std::enable_if<!accepts_type<Functor, Packet>::value && !accepts_type<Functor, Packet&>::value, bool>::type* = 0) {
return f(*p.pdu());
}
#endif
} // namespace Internals
} // namespace Tins
/**

View File

@@ -42,6 +42,7 @@
namespace Tins {
/**
* \class IP
* \brief Class that represents an IP PDU.
*
* By default, IP PDUs are initialized, setting TTL to IP::DEFAULT_TTL,

View File

@@ -177,7 +177,7 @@ public:
*/
friend std::ostream &operator<<(std::ostream &output, const IPv4Address &addr);
private:
uint32_t ip_to_int(const std::string &ip);
uint32_t ip_to_int(const char* ip);
uint32_t ip_addr;
};

View File

@@ -36,6 +36,7 @@
namespace Tins {
/**
* \class IPSecAH
* \brief Represents an IPSec Authentication Header.
*/
class IPSecAH : public PDU {

View File

@@ -43,6 +43,7 @@ namespace Tins {
class PacketSender;
/**
* \class IPv6
* Represents an IPv6 PDU.
*/
class IPv6 : public PDU {

View File

@@ -40,7 +40,8 @@
namespace Tins {
/**
* \brief Class representing a LLC frame.
* \class LLC
* \brief Representing a LLC frame.
*
* This PDU follows the standard LLC frame described in the IEEE 802.2 specs.
*/

View File

@@ -86,6 +86,15 @@ public:
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \brief Check wether ptr points to a valid response for this PDU.
*
* \sa PDU::matches_response
* \param ptr The pointer to the buffer.
* \param total_sz The size of the buffer.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
/**
* \sa PDU::clone
*/

View File

@@ -40,13 +40,13 @@
#define TINS_END_PACK __pragma( pack(pop) )
#define TINS_PACKED(DECLARATION) __pragma( pack(push, 1) ) DECLARATION __pragma( pack(pop) )
#define TINS_DEPRECATED(func) __declspec(deprecated) func
#define NOEXCEPT
#define TINS_NOEXCEPT
#else
#define TINS_BEGIN_PACK
#define TINS_END_PACK __attribute__((packed))
#define TINS_PACKED(DECLARATION) DECLARATION __attribute__((packed))
#define TINS_DEPRECATED(func) func __attribute__ ((deprecated))
#define NOEXCEPT noexcept
#define TINS_NOEXCEPT noexcept
#endif
#endif

View File

@@ -31,6 +31,7 @@
#define TINS_NETWORK_INTERFACE_H
#include <string>
#include <vector>
#include <stdint.h>
#include "hw_address.h"
#include "ip_address.h"
@@ -66,6 +67,16 @@ public:
*/
static NetworkInterface default_interface();
/**
* Returns all available network interfaces.
*/
static std::vector<NetworkInterface> all();
/**
* Returns a network interface for the given index.
*/
static NetworkInterface from_index(id_type identifier);
/**
* Default constructor.
*/
@@ -106,7 +117,11 @@ public:
/**
* \brief Retrieves this interface's name.
*
*
* This name can be used as the interface name provided to the
* Sniffer class when starting a sniffing session.
*
* \sa Sniffer
* \return std::string containing this interface's name.
*/
std::string name() const;
@@ -129,6 +144,12 @@ public:
operator bool() const {
return iface_id != 0;
}
/**
* \brief Indicates whether this is a loopback device.
* @return true iff this is a loopback device.
*/
bool is_loopback() const;
/**
* \brief Compares this interface for equality.

View File

@@ -0,0 +1,157 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_OFFLINE_PACKET_FILTER_H
#define TINS_OFFLINE_PACKET_FILTER_H
#include <string>
#include <stdint.h>
#include "data_link_type.h"
namespace Tins {
class PDU;
/**
* \class OfflinePacketFilter
*
* \brief Wraps a pcap filter and matches it against a packet or buffer.
*
* This is a thin wrapper over <i>pcap_offline_filter</i>. You can use
* it to perform packet filtering outside of Sniffer instances.
*
* A potential use case would be if you are capturing packets that are
* sent from another host over UDP. You would recieve UDP packets, then
* parse their content, and apply the OfflinePacketFilter over the
* wrapped packet. For example:
*
* \code
* // Assume we get an UDP packet from somewhere.
* // Inside the payload, there will be a complete packet
* // including its link layer protocol.
* UDP udp = get_packet();
*
* // Create the filter. We'll be expecting Ethernet packets.
* OfflinePacketFilter filter("ip and port 80", DataLinkLayer<EthernetII>());
*
* // We can use this directly over the inner PDU (assuming it has one)
* // See the notes on the efficiency of doing it this way.
* if(filter.matches_filter(*udp.inner_pdu())) {
* // Matches!
* }
*
* // We can also use the payload. This version it faster and should
* // be preferred over the one above
* const RawPDU& raw = udp.rfind_pdu<RawPDU>();
* const auto& payload = raw.payload();
* if(filter.matches_filter(payload.data(), payload.size())) {
* // Matches!
* }
* \endcode
*/
class OfflinePacketFilter {
public:
/**
* Constructs an OfflinePacketFilter object.
*
* \param filter The pcap filter to use.
* \param lt The link layer type to use.
* \param snap_len The snapshot length to use.
*/
template<typename T>
OfflinePacketFilter(const std::string& filter, const DataLinkType<T>& lt,
unsigned int snap_len = 65535)
: string_filter(filter)
{
init(filter, lt.get_type(), snap_len);
}
/**
* \brief Copy constructor.
*
* Note that during copy construction the pcap filter is
* recompiled. Therefore, it might be somehow expensive to
* copy OfflinePacketFilters.
*
* \param other The filter to be copied.
*/
OfflinePacketFilter(const OfflinePacketFilter& other);
/**
* \brief Copy assignment operator.
*
* \param other The filter to be copied.
*
* \sa OfflinePacketFilter
*/
OfflinePacketFilter& operator=(const OfflinePacketFilter& other);
/**
* Releases the compiled pcap filter and handle.
*/
~OfflinePacketFilter();
/**
* \brief Applies the compiled filter on the provided buffer.
*
* This method uses <i>pcap_offline_filter</i> on the provided buffer
* and returns a bool indicating if the packet pointed by the buffer
* matches the filter.
*
* \param buffer A pointer to a buffer which holds a raw packet.
* \param total_sz The length of the buffer pointed by buffer.
* \return true iff the packet matches the filter.
*/
bool matches_filter(const uint8_t* buffer, uint32_t total_sz) const;
/**
* \brief Applies the compiled filter on the provided packet.
*
* This method checks whether the provided packet matches the filter.
* Since this uses pcap filters and they work over a raw data buffer,
* this method serialices the packet and then applies the filter.
* Therefore, this can be quite expensive to use. If you have access
* to the packet before constructing a PDU from it, it is recommended
* to use the other overload over the raw buffer.
*
* \param pdu The packet to be matched against the filter.
* \return true iff the packet matches the filter.
*/
bool matches_filter(PDU& pdu) const;
private:
void init(const std::string& pcap_filter, int link_type,
unsigned int snap_len);
pcap_t* handle;
mutable bpf_program filter;
std::string string_filter;
};
} // Tins
#endif // TINS_OFFLINE_PACKET_FILTER_H

View File

@@ -106,6 +106,7 @@ public:
}
private:
friend class BaseSniffer;
friend class SnifferIterator;
PacketWrapper(pdu_type pdu, const Timestamp &ts)
: pdu_(pdu), ts_(ts) {}
@@ -215,14 +216,14 @@ public:
/**
* Move constructor.
*/
Packet(Packet &&rhs) NOEXCEPT : pdu_(rhs.pdu()), ts(rhs.timestamp()) {
Packet(Packet &&rhs) TINS_NOEXCEPT : pdu_(rhs.pdu()), ts(rhs.timestamp()) {
rhs.pdu_ = nullptr;
}
/**
* Move assignment operator.
*/
Packet& operator=(Packet &&rhs) NOEXCEPT {
Packet& operator=(Packet &&rhs) TINS_NOEXCEPT {
if(this != &rhs) {
std::swap(pdu_, rhs.pdu_);
ts = rhs.timestamp();

View File

@@ -47,10 +47,61 @@ namespace Tins {
class PDU;
/**
* \brief Class that enables sending the created PDUs
* \class PacketSender
* \brief Sends packets through a network interface.
*
* PacketSender class is responsible for sending the packets using the
* correct PDU layer. It is responsible for opening the raw sockets.
* This class allows sending packets through a network interface.
* It can send basically two types of packets:
*
* - Those that contain a link layer PDU (EthernetII, SLL, etc). These
* will be serialized and sent through an interface that has to be
* specified. This can be done by providing it when you call
* PacketSender::send, or set a default one using
* PacketSender::default_interface.
* - Those that don't contain a link layer PDU. In this case, the
* kernel will be responsible for picking the appropriate network interface
* based on the destination address.
*
* Sending packets can be done via PacketSender::send:
*
* \code
* // Construct a packet which uses an EthernetII link layer.
* EthernetII pkt1 = ...;
*
* // Construct a packet sender, which we'll use to send packets.
* PacketSender sender;
*
* // Send it through interface eth0
* sender.send(pkt1, "eth0");
*
* // Set the default interface to eth0
* sender.default_interface("eth0");
*
* // This is now equivalent to the previous send.
* sender.send(pkt1);
*
* // Construct a packet which has no link layer protocol.
* IP ip = IP("192.168.0.1") / TCP(22, 928);
*
* // Here the kernel will figure out which interface to use and it will
* // append the appropriate link layer protocol PDU. It will also perform
* // the necessary ARP lookups in order to use the destination host's
* // hardware address.
* //
* // libtins will find which is the appropriate source IP address to use.
* // This will be done by the kernel as well, but it's required when
* // calculating checksums.
* sender.send(ip);
* \endcode
*
* PacketSender also supports sending a packet and waiting for a response.
* This can be done by using PacketSender::send_recv.
*
* This class opens sockets as it needs to, and closes them when the object
* is destructed.
*
* \sa PacketSender::send
* \sa PacketSender::send_recv
*/
class PacketSender {
public:
@@ -87,7 +138,7 @@ namespace Tins {
* \brief Move constructor.
* \param rhs The sender to be moved.
*/
PacketSender(PacketSender &&rhs) NOEXCEPT {
PacketSender(PacketSender &&rhs) TINS_NOEXCEPT {
*this = std::move(rhs);
}
@@ -95,7 +146,7 @@ namespace Tins {
* \brief Move assignment operator.
* \param rhs The sender to be moved.
*/
PacketSender& operator=(PacketSender &&rhs) NOEXCEPT {
PacketSender& operator=(PacketSender &&rhs) TINS_NOEXCEPT {
_sockets = std::move(rhs._sockets);
rhs._sockets = std::vector<int>(SOCKETS_END, INVALID_RAW_SOCKET);
#ifndef WIN32
@@ -209,9 +260,19 @@ namespace Tins {
* \brief Sends a PDU and waits for its response.
*
* This method is used to send PDUs and receive their response.
* It opens the required socket(if it's not open yet). This can be used
* to expect responses for ICMP, ARP, and such packets that are normally
* answered by the host that receives the packet.
* The packet is sent, and then a response is awaited.
* PDU::matches_pdu is called on the packet sent in order to
* check whether a packet received is a response.
*
* This will match every response to a packet. For example,
* if you send a TCP packet, any response matching the same
* IP addresses and ports will be taken as a response to it.
* This also happens for other protocols, such as ARP, ICMP,
* DHCP, DNS, IP, etc.
*
* If you send a packet and get an ICMP response indicating
* an error (such as host unreachable, ttl exceeded, etc),
* that packet will be considered a response.
*
* \param pdu The PDU to send.
* \return Returns the response PDU, 0 if not response was received.
@@ -220,12 +281,11 @@ namespace Tins {
/**
* \brief Sends a PDU and waits for its response.
*
* Sends a packet and receives a response. This overload takes
* a NetworkInterface.
*
* This method is used to send PDUs and receive their response.
* It opens the required socket(if it's not open yet). This can be used
* to expect responses for ICMP, ARP, and such packets that are normally
* answered by the host that receives the packet.
*
* \sa PacketSender::send_recv(PDU&);
* \param pdu The PDU to send.
* \param iface The network interface in which to send and receive.
* \return Returns the response PDU, 0 if not response was received.
@@ -235,9 +295,12 @@ namespace Tins {
#ifndef WIN32
/**
* \brief Receives a layer 2 PDU response to a previously sent PDU.
*
* This method is used internally. You should just use PacketSender::send_recv.
*
* This PacketSender will receive data from a raw socket, open using the corresponding flag,
* according to the given type of protocol, until a match for the given PDU is received.
* This PacketSender will receive data from a raw socket, open using
* the corresponding flag, according to the given type of protocol, until
* a match for the given PDU is received.
*
* \param pdu The PDU which will try to match the responses.
* \param link_addr The sockaddr struct which will be used to receive the PDU.
@@ -249,6 +312,8 @@ namespace Tins {
/**
* \brief Sends a level 2 PDU.
*
* This method is used internally. You should just use PacketSender::send.
*
* This method sends a layer 2 PDU, using a raw socket, open
* using the corresponding flag, according to the given type of
@@ -266,6 +331,8 @@ namespace Tins {
/**
* \brief Receives a layer 3 PDU response to a previously sent PDU.
*
* This method is used internally. You should just use PacketSender::send_recv.
*
* This PacketSender will receive data from a raw socket, open using the corresponding flag,
* according to the given type of protocol, until a match for the given PDU is received.
@@ -280,6 +347,8 @@ namespace Tins {
/**
* \brief Sends a level 3 PDU.
*
* This method is used internally. You should just use PacketSender::send.
*
* This method sends a layer 3 PDU, using a raw socket, open using the corresponding flag,
* according to the given type of protocol.

View File

@@ -33,6 +33,7 @@
#include <string>
#include <iterator>
#include <pcap.h>
#include "data_link_type.h"
#include "utils.h"
#include "cxxstd.h"
@@ -42,11 +43,40 @@ class PDU;
/**
* \class PacketWriter
* \brief Writes PDUs to a pcap format file.
*
* This class can be used to write packets into a <i>pcap</i> format
* file. It supports both writing packets one by one, or writing all
* packets in a range (provided by iterators), so you can use it
* to dump all packets in a vector.
*
* Since you might use both PDU objects and pointers to them,
* both the PacketWriter::write overload that takes a single object
* or the one that takes an iterator range accept a PDU reference type
* as well as any type that can be dereferenced until a PDU type is found.
* This means you can use both raw and smart pointers.
*
* For example:
*
* \code
* // Differents types holding PDUs
* EthernetII object;
* std::shared_ptr<PDU> smart_ptr = ...;
* std::vector<std::shared_ptr<PDU>> vt = ....;
*
* // The writer we'll use
* PacketWriter writer("/tmp/file.pcap", DataLinkType<EthernetII>());
*
* // Now write all of them
* writer.write(object);
* writer.write(smart_ptr);
* writer.write(vt.begin(), vt.end());
* \endcode
*/
class PacketWriter {
public:
/**
* \brief The type of PDUs that will be written to this file.
* \brief The type of PDUs that will be written to this file (deprecated).
* \deprecated Use DataLinkType instead of this enum.
*
* This flag should match the type of the lowest layer PDU to be
* written.
@@ -58,9 +88,40 @@ public:
DOT3 = DLT_EN10MB,
SLL = DLT_LINUX_SLL
};
/**
* \brief Constructs a PacketWriter.
*
* This method takes a DataLinkType, which indicates the link
* layer protocol that will be used on the packets to write.
*
* For example, you can write packets that contain an
* EthernetII link layer type by doing:
*
* \code
* // Construct a PacketWriter
* PacketWriter writer("/tmp/test.pcap", DataLinkType<EthernetII>());
* // Write some packet
* writer.write(packet);
* \endcode
*
* \param file_name The file in which to store the written PDUs.
* \param lt A DataLinkType that represents the link layer
* protocol to use.
* \sa PcapIdentifier.
*/
template<typename T>
PacketWriter(const std::string &file_name, const DataLinkType<T>& lt)
{
init(file_name, lt.get_type());
}
/**
* \brief Constructs a PacketWriter.
*
* \deprecated Use the PacketWriter(const std::string&, const DataLinkType<T>&)
* constructor.
*
* \param file_name The file in which to store the written PDUs.
* \param lt The link type which will be written to this file.
* \sa LinkType.
@@ -76,7 +137,7 @@ public:
*
* \param rhs The PacketWriter to be moved.
*/
PacketWriter(PacketWriter &&rhs) NOEXCEPT {
PacketWriter(PacketWriter &&rhs) TINS_NOEXCEPT {
*this = std::move(rhs);
}
@@ -88,7 +149,7 @@ public:
*
* \param rhs The PacketWriter to be moved.
*/
PacketWriter& operator=(PacketWriter &&rhs) NOEXCEPT {
PacketWriter& operator=(PacketWriter &&rhs) TINS_NOEXCEPT {
handle = 0;
dumper = 0;
std::swap(handle, rhs.handle);
@@ -98,7 +159,9 @@ public:
#endif
/**
* Destructor.
* \brief Destructor.
*
* Gracefully closes the output file.
*/
~PacketWriter();
@@ -136,6 +199,8 @@ private:
PacketWriter(const PacketWriter&);
PacketWriter& operator=(const PacketWriter&);
void init(const std::string& file_name, int link_type);
pcap_t *handle;
pcap_dumper_t *dumper;
};

View File

@@ -49,14 +49,60 @@ namespace Tins {
*/
typedef std::vector<uint8_t> byte_array;
/** \brief Base class for protocol data units.
/**
* \class PDU
* \brief Base class for protocol data units.
*
* Every PDU implementation must inherit this one. PDUs can be serialized,
* therefore allowing a PacketSender to send them through the corresponding
* sockets. PDUs are created upwards: upper layers will be children of the
* lower ones. Each PDU must provide its flag identifier. This will be most
* likely added to its parent's data, hence it should be a valid identifier.
* For example, IP should provide IPPROTO_IP.
* Every PDU implementation inherits from this class.
*
* PDUs can contain 0 or 1 inner PDU. By stacking several PDUs together,
* you can construct packets. These are created upwards: upper layers
* will be children of the lower ones.
*
* If you want to find a specific protocol within a PDU chain, you can use
* PDU::find_pdu and PDU::rfind_pdu. Both of them take a template parameter
* that indicates the PDU type you are looking for. The first one returns a
* pointer to the first object of that type, and the second one returns a
* reference (and throws if it is not found).
*
* For example:
*
* \code
* // Take a whole packet from somewhere.
* EthernetII packet = ...;
*
* // Find the IP layer
* const IP* ip = packet.find_pdu<IP>();
* if(ip) {
* // If the pointer is not null, then it will point to the IP layer
* }
*
* // Find the TCP layer. This will throw a pdu_not_found exception
* // if there is no TCP layer in this packet.
* const TCP& tcp = packet.rfind_pdu<TCP>();
* \endcode
*
* PDU objects can be serialized. Serialization converts the entire PDU
* stack into a vector of bytes. This process might modify some parameters
* on packets depending on which protocols are used in it. For example:
*
* - If the lowest protocol layer is IP (this means that there is no
* link layer protocol in the packet), then it calculates the source address
* that should be used in that IP PDU. \sa IP
* - If a protocol contains a checksum field, its value will be calculated
* and included in its serialized contents.
* - If a protocol contains a "next protocol" field, it is also set based
* on the type of the next PDU in the packet.
*
* If you want to serialize a packet, just use PDU::serialize:
*
* \code
* // Construct a packet
* EthernetII packet = EthernetII() / IP() / TCP() / RawPDU("hello");
*
* // Now serialize it. This is a std::vector<uint8_t>.
* PDU::serialization_type buffer = packet.serialize();
* \endcode
*/
class PDU {
public:
@@ -129,6 +175,7 @@ namespace Tins {
PPI,
IPSEC_AH,
IPSEC_ESP,
PKTAP,
USER_DEFINED_PDU = 1000
};
@@ -149,7 +196,7 @@ namespace Tins {
*
* \param rhs The PDU to be moved.
*/
PDU(PDU &&rhs) NOEXCEPT
PDU(PDU &&rhs) TINS_NOEXCEPT
: _inner_pdu(0)
{
std::swap(_inner_pdu, rhs._inner_pdu);
@@ -160,7 +207,7 @@ namespace Tins {
*
* \param rhs The PDU to be moved.
*/
PDU& operator=(PDU &&rhs) NOEXCEPT {
PDU& operator=(PDU &&rhs) TINS_NOEXCEPT {
std::swap(_inner_pdu, rhs._inner_pdu);
return *this;
}

View File

@@ -36,6 +36,7 @@
namespace Tins {
/**
* \class PDUCacher
* \brief PDU wrapper that caches the result of the wrapped PDU's
* serialization.
*
@@ -77,7 +78,9 @@ public:
cached_size() {}
/**
* Forwards the call to the cached PDU. \sa PDU::header_size.
* Forwards the call to the cached PDU.
*
* \sa PDU::header_size.
*/
uint32_t header_size() const {
if(cached_serialization.empty())
@@ -86,42 +89,54 @@ public:
}
/**
* Forwards the call to the cached PDU. \sa PDU::clone.
* Forwards the call to the cached PDU.
*
* \sa PDU::clone.
*/
PDUCacher *clone() const {
return new PDUCacher<T>(*this);
}
/**
* Forwards the call to the cached PDU. \sa PDU::send.
* Forwards the call to the cached PDU.
*
* \sa PDU::send.
*/
void send(PacketSender &sender, const NetworkInterface &iface) {
cached.send(sender, iface);
}
/**
* Forwards the call to the cached PDU. \sa PDU::recv_responde.
* Forwards the call to the cached PDU.
*
* \sa PDU::recv_responde.
*/
PDU *recv_response(PacketSender &sender, const NetworkInterface &iface) {
return cached.recv_response(sender, iface);
}
/**
* Forwards the call to the cached PDU. \sa PDU::matches_response.
* Forwards the call to the cached PDU.
*
* \sa PDU::matches_response.
*/
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const {
return cached.matches_response(ptr, total_sz);
}
/**
* Forwards the call to the cached PDU. \sa PDU::matches_flag.
* Forwards the call to the cached PDU.
*
* \sa PDU::matches_flag.
*/
bool matches_flag(PDUType flag) const {
return cached.matches_flag(flag);
}
/**
* Forwards the call to the cached PDU. \sa PDU::pdu_type.
* Forwards the call to the cached PDU.
*
* \sa PDU::pdu_type.
*/
PDUType pdu_type() const {
return cached.pdu_type();

109
include/tins/pktap.h Normal file
View File

@@ -0,0 +1,109 @@
/*
* Copyright (c) 2014, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_PKTAP_H
#define TINS_PKTAP_H
#include "pdu.h"
namespace Tins {
class PKTAP : public PDU {
public:
/**
* This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::PKTAP;
/**
* Default constructor.
*/
PKTAP();
/**
* \brief Constructs a PKTAP object from a buffer and adds all
* identifiable PDUs found in the buffer as children of this
* one.
*
* If there is not enough size for an IP header, a
* malformed_packet exception is thrown.
*
* \param buffer The buffer from which this PDU will be constructed.
* \param total_sz The total size of the buffer.
*/
PKTAP(const uint8_t* buffer, uint32_t total_sz);
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return pdu_flag; }
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size.
* \sa PDU::header_size
*/
uint32_t header_size() const;
/**
* \sa PDU::clone
*/
PKTAP *clone() const {
return new PKTAP(*this);
}
private:
struct pktap_header {
uint32_t length;
uint32_t next;
uint32_t dlt;
uint8_t pth_ifname[24];
uint32_t flags;
uint32_t protocol_family;
uint32_t header_length;
uint32_t trailer_length;
uint32_t pid;
uint8_t command[20];
uint32_t service_class;
uint16_t interface_type;
uint16_t interface_unit;
uint32_t epid;
uint8_t ecommand[20];
};
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
pktap_header header_;
};
} // Tins
#endif // TINS_PKTAP_H

View File

@@ -36,6 +36,7 @@
namespace Tins {
/**
* \class PPI
* \brief Represents a Per-Packet Information PDU.
*
* This PDU can only be constructed from a buffer, and

View File

@@ -40,6 +40,10 @@
#include "cxxstd.h"
namespace Tins {
/**
* \class PPPoE
* \brief Represents a Point-to-point protocol over Ethernet PDU.
*/
class PPPoE : public PDU {
public:
/**

View File

@@ -77,22 +77,25 @@ namespace Tins {
* \sa RadioTap::present()
*/
enum PresentFlags {
TSTF = 1,
FLAGS = 2,
RATE = 4,
CHANNEL = 8,
FHSS = 16,
DBM_SIGNAL = 32,
DBM_NOISE = 64,
LOCK_QUALITY = 128,
TX_ATTENUATION = 256,
DB_TX_ATTENUATION = 512,
DBM_TX_ATTENUATION = 1024,
ANTENNA = 2048,
DB_SIGNAL = 4096,
DB_NOISE = 8192,
RX_FLAGS = 16382,
CHANNEL_PLUS = 262144
TSTF = 1 << 0,
FLAGS = 1 << 1,
RATE = 1 << 2,
CHANNEL = 1 << 3,
FHSS = 1 << 4,
DBM_SIGNAL = 1 << 5,
DBM_NOISE = 1 << 6,
LOCK_QUALITY = 1 << 7,
TX_ATTENUATION = 1 << 8,
DB_TX_ATTENUATION = 1 << 9,
DBM_TX_ATTENUATION = 1 << 10,
ANTENNA = 1 << 11,
DB_SIGNAL = 1 << 12,
DB_NOISE = 1 << 13,
RX_FLAGS = 1 << 14,
TX_FLAGS = 1 << 15,
DATA_RETRIES = 1 << 17,
CHANNEL_PLUS = 1 << 18,
MCS = 1 << 19
};
/**
@@ -108,6 +111,16 @@ namespace Tins {
FAILED_FCS = 64,
SHORT_GI = 128
};
/**
* \brief The type used to represent the MCS flags field
*/
TINS_BEGIN_PACK
struct mcs_type {
uint8_t known;
uint8_t flags;
uint8_t mcs;
} TINS_END_PACK;
/**
* \brief Default constructor.
@@ -182,13 +195,13 @@ namespace Tins {
* \brief Setter for the dbm signal field.
* \param new_dbm_signal The new dbm signal.
*/
void dbm_signal(uint8_t new_dbm_signal);
void dbm_signal(int8_t new_dbm_signal);
/**
* \brief Setter for the dbm noise field.
* \param new_dbm_noise The new dbm noise.
*/
void dbm_noise(uint8_t new_dbm_noise);
void dbm_noise(int8_t new_dbm_noise);
/**
* \brief Setter for the signal quality field.
@@ -210,9 +223,27 @@ namespace Tins {
/**
* \brief Setter for the rx flag field.
* \param new_rx_flag The antenna signal.
* \param new_rx_flag The rx flags.
*/
void rx_flags(uint16_t new_rx_flag);
/**
* \brief Setter for the tx flag field.
* \param new_tx_flag The tx flags.
*/
void tx_flags(uint16_t new_tx_flag);
/**
* \brief Setter for the data retries field.
* \param new_rx_flag The data retries.
*/
void data_retries(uint8_t new_data_retries);
/**
* \brief Setter for the MCS field.
* \param new_rx_flag The MCS retries.
*/
void mcs(const mcs_type& new_mcs);
/* Getters */
@@ -220,92 +251,110 @@ namespace Tins {
* \brief Getter for the version field.
* \return The version field.
*/
uint8_t version() const { return _radio.it_version; }
uint8_t version() const;
/**
* \brief Getter for the padding field.
* \return The padding field.
*/
uint8_t padding() const { return _radio.it_pad; }
uint8_t padding() const;
/**
* \brief Getter for the length field.
* \return The length field.
*/
uint16_t length() const { return Endian::le_to_host(_radio.it_len); }
uint16_t length() const;
/**
* \brief Getter for the tsft field.
* \return The tsft field.
*/
uint64_t tsft() const { return Endian::le_to_host(_tsft); }
uint64_t tsft() const;
/**
* \brief Getter for the flags field.
* \return The flags field.
*/
FrameFlags flags() const { return (FrameFlags)_flags; }
FrameFlags flags() const;
/**
* \brief Getter for the rate field.
* \return The rate field.
*/
uint8_t rate() const { return _rate; }
uint8_t rate() const;
/**
* \brief Getter for the channel frequency field.
* \return The channel frequency field.
*/
uint16_t channel_freq() const { return Endian::le_to_host(_channel_freq); }
uint16_t channel_freq() const;
/**
* \brief Getter for the channel type field.
* \return The channel type field.
*/
uint16_t channel_type() const { return Endian::le_to_host(_channel_type); }
uint16_t channel_type() const;
/**
* \brief Getter for the dbm signal field.
* \return The dbm signal field.
*/
uint8_t dbm_signal() const { return _dbm_signal; }
int8_t dbm_signal() const;
/**
* \brief Getter for the dbm noise field.
* \return The dbm noise field.
*/
uint8_t dbm_noise() const { return _dbm_noise; }
int8_t dbm_noise() const;
/**
* \brief Getter for the signal quality field.
* \return The signal quality field.
*/
uint16_t signal_quality() const { return _signal_quality; }
uint16_t signal_quality() const;
/**
* \brief Getter for the antenna field.
* \return The antenna field.
*/
uint8_t antenna() const { return _antenna; }
uint8_t antenna() const;
/**
* \brief Getter for the db signal field.
* \return The db signal field.
*/
uint8_t db_signal() const { return _db_signal; }
uint8_t db_signal() const;
/**
* \brief Getter for the channel+ field.
* \return The channel+ field.
*/
uint32_t channel_plus() const { return Endian::le_to_host<uint32_t>(_channel_type); }
uint32_t channel_plus() const;
/**
* \brief Getter for the data retries field
* \return The data retries field.
*/
uint8_t data_retries() const;
/**
* \brief Getter for the rx flags field.
* \return The rx flags field.
*/
uint16_t rx_flags() const { return Endian::le_to_host(_rx_flags); }
uint16_t rx_flags() const;
/**
* \brief Getter for the tx flags field.
* \return The tx flags field.
*/
uint16_t tx_flags() const;
/**
* \brief Getter for the MCS field.
* \return The MCS field.
*/
mcs_type mcs() const;
/**
* \brief Getter for the present bit fields.
*
@@ -355,78 +404,110 @@ namespace Tins {
*/
PDUType pdu_type() const { return PDU::RADIOTAP; }
private:
TINS_BEGIN_PACK
#if TINS_IS_LITTLE_ENDIAN
struct flags_type {
uint32_t
tsft:1,
flags:1,
rate:1,
channel:1,
fhss:1,
dbm_signal:1,
dbm_noise:1,
lock_quality:1,
tx_attenuation:1,
db_tx_attenuation:1,
dbm_tx_power:1,
antenna:1,
db_signal:1,
db_noise:1,
rx_flags:1,
tx_flags:1,
reserved1:1,
data_retries:1,
channel_plus:1,
mcs:1,
reserved2:4,
reserved3:7,
ext:1;
} TINS_END_PACK;
#else
struct flags_type {
uint32_t
lock_quality:1,
dbm_noise:1,
dbm_signal:1,
fhss:1,
channel:1,
rate:1,
flags:1,
tsft:1,
tx_flags:1,
rx_flags:1,
db_noise:1,
db_signal:1,
antenna:1,
dbm_tx_power:1,
db_tx_attenuation:1,
tx_attenuation:1,
reserved2:4,
mcs:1,
channel_plus:1,
data_retries:1,
reserved1:1,
ext:1,
reserved3:7;
} TINS_END_PACK;
#endif
TINS_BEGIN_PACK
struct radiotap_hdr {
#if TINS_IS_LITTLE_ENDIAN
uint8_t it_version;
uint8_t it_pad;
uint16_t it_len;
union {
struct {
uint32_t tsft:1,
flags:1,
rate:1,
channel:1,
fhss:1,
dbm_signal:1,
dbm_noise:1,
lock_quality:1,
tx_attenuation:1,
db_tx_attenuation:1,
dbm_tx_attenuation:1,
antenna:1,
db_signal:1,
db_noise:1,
rx_flags:1,
reserved1:3,
channel_plus:1,
reserved2:12,
ext:1;
} flags;
uint32_t flags_32;
};
#else
uint8_t it_pad;
uint8_t it_version;
uint8_t it_version;
#endif // TINS_IS_LITTLE_ENDIAN
uint16_t it_len;
union {
struct {
uint32_t lock_quality:1,
dbm_noise:1,
dbm_signal:1,
fhss:1,
channel:1,
rate:1,
flags:1,
tsft:1,
reserved3:1,
rx_flags:1,
db_tx_attenuation:1,
dbm_tx_attenuation:1,
antenna:1,
db_signal:1,
db_noise:1,
tx_attenuation:1,
reserved2:5,
channel_plus:1,
reserved1:2,
reserved4:7,
ext:1;
} flags;
flags_type flags;
uint32_t flags_32;
};
#endif
} TINS_END_PACK;
void init();
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
uint32_t find_extra_flag_fields_size(const uint8_t* buffer, uint32_t total_sz);
template <size_t n>
void align_buffer(const uint8_t* buffer_start, const uint8_t*& buffer, uint32_t& size) {
uint32_t offset = ((buffer - buffer_start) % n);
if(offset) {
offset = n - offset;
if (offset > size) {
throw malformed_packet();
}
buffer += offset;
size -= offset;
}
}
radiotap_hdr _radio;
// present fields...
uint64_t _tsft;
uint16_t _channel_type, _channel_freq, _rx_flags, _signal_quality;
uint8_t _antenna, _flags, _rate, _dbm_signal, _dbm_noise, _channel, _max_power, _db_signal;
uint16_t _channel_type, _channel_freq, _rx_flags, _signal_quality, _tx_flags;
mcs_type _mcs;
uint8_t _antenna, _flags, _rate, _channel, _max_power, _db_signal, _data_retries;
int8_t _dbm_signal, _dbm_noise;
};
}

View File

@@ -33,13 +33,32 @@
#include <vector>
#include <string>
#include "pdu.h"
#include "cxxstd.h"
namespace Tins {
/** \brief Represents a PDU which holds raw data.
/**
* \class PDU
* \brief Represents a PDU which holds raw data.
*
* In order to send payloads over TCP, UDP, or other transport layer or
* higher level protocols, RawPDU can be used as a wrapper for raw byte arrays.
* This class is a wrapper over a byte array. It can be used to hold
* the payload sent over transport layer protocols (such as TCP or UDP).
*
* While sniffing, this class is the one that will hold transport layer
* protocols' payload. You can simply convert a RawPDU into a specific
* application layer protocol using the RawPDU::to method:
*
* \code
* // Get a RawPDU from somewhere
* RawPDU raw = get_raw_pdu();
*
* // Parse it as a DHCP PDU.
* DHCP dhcp = raw.to<DHCP>();
*
* // Or parse it as DNS. Of course this will fail if the contents
* // don't look like DNS
* DNS dns = raw.to<DNS>();
* \endcode
*/
class RawPDU : public PDU {
public:
@@ -63,6 +82,31 @@ namespace Tins {
*/
RawPDU(const uint8_t *pload, uint32_t size);
/**
* \brief Constructs a RawPDU from an iterator range.
*
* The data in the iterator range is copied into the RawPDU
* internal buffer.
*
* \param start The beginning of the iterator range.
* \param end The end of the iterator range.
*/
template<typename ForwardIterator>
RawPDU(ForwardIterator start, ForwardIterator end)
: _payload(start, end) { }
#if TINS_IS_CXX11
/**
* \brief Creates an instance of RawPDU from a payload_type.
*
* The payload is moved into the RawPDU's internal buffer.
*
* \param data The payload to use.
*/
RawPDU(payload_type&& data)
: _payload(move(data)) { }
#endif // TINS_IS_CXX11
/**
* \brief Creates an instance of RawPDU from an input string.
*

View File

@@ -36,6 +36,10 @@
#include "hw_address.h"
namespace Tins {
/**
* \class SLL
* \brief Represents a Linux cooked-mode capture (SLL) PDU.
*/
class SLL : public PDU {
public:
/**

View File

@@ -40,7 +40,8 @@
namespace Tins {
/**
* \brief Class representing a SNAP frame.
* \class SNAP
* \brief Represents a SNAP frame.
*
* Note that this PDU contains the 802.3 LLC structure + SNAP frame.
* So far only unnumbered information structure is supported.

View File

@@ -5,14 +5,14 @@
* 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
@@ -45,15 +45,16 @@
namespace Tins {
class SnifferIterator;
class SnifferConfiguration;
/**
* \class BaseSniffer
* \brief Base class for sniffers.
*
*
* This class implements the basic sniffing operations. Subclasses
* should only initialize this object using a pcap_t pointer, which
* will be used to extract packets.
*
*
* Initialization must be done using the BaseSniffer::init method.
*/
class BaseSniffer {
@@ -68,17 +69,17 @@ namespace Tins {
* \brief Move constructor.
* This constructor is available only in C++11.
*/
BaseSniffer(BaseSniffer &&rhs) NOEXCEPT
BaseSniffer(BaseSniffer &&rhs) TINS_NOEXCEPT
: handle(nullptr), mask()
{
*this = std::move(rhs);
}
/**
* \brief Move assignment operator.
* This operator is available only in C++11.
*/
BaseSniffer& operator=(BaseSniffer &&rhs) NOEXCEPT
BaseSniffer& operator=(BaseSniffer &&rhs) TINS_NOEXCEPT
{
using std::swap;
swap(handle, rhs.handle);
@@ -86,99 +87,103 @@ namespace Tins {
return *this;
}
#endif
/**
* \brief Sniffer destructor.
* This frees all memory used by the pcap handle.
*/
virtual ~BaseSniffer();
/**
* \brief Compiles a filter and uses it to capture one packet.
*
* This method returns the first valid sniffed packet that matches the
*
* This method returns the first valid sniffed packet that matches the
* sniffer's filter, or the first sniffed packet if no filter has
* been set.
*
*
* The return type is a thin wrapper over a PDU* and a Timestamp
* object. This wrapper can be both implicitly converted to a
* 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 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.
*
*
* Is not, since PtrPacket can't be copy constructed.
*
* \sa Packet::release_pdu
*
* \return A captured packet. If an error occured, PtrPacket::pdu
* will return 0. Caller takes ownership of the PDU pointer stored in
*
* \return A captured packet. If an error occured, PtrPacket::pdu
* will return 0. Caller takes ownership of the PDU pointer stored in
* the PtrPacket.
*/
PtrPacket next_packet();
/**
* \brief Starts a sniffing loop, using a callback functor for every
* sniffed packet.
*
* The functor must implement an operator with one of the
*
* The functor must implement an operator with one of the
* following signatures:
*
*
* \code
* bool(PDU&);
* bool(const PDU&);
*
* // These two are only allowed when compiling in C++11 mode
* bool(Packet&);
* bool(const Packet&);
* \endcode
*
* This functor will be called using the each of the sniffed packets
*
* This functor will be called using the each of the sniffed packets
* as its argument. Using PDU member functions that modify the PDU,
* such as PDU::release_inner_pdu, is perfectly valid.
*
* Note that if you're using a functor object, it will be copied using
*
* Note that if you're using a functor object, it will be copied using
* its copy constructor, so it should be some kind of proxy to
* another object which will process the packets(e.g. std::bind).
*
* Sniffing will stop when either max_packets are sniffed(if it is != 0),
* Sniffing will stop when either max_packets are sniffed(if it is != 0),
* or when the functor returns false.
*
* This method catches both malformed_packet and pdu_not_found exceptions,
* which allows writing much cleaner code, since you can call PDU::rfind_pdu
* without worrying about catching the exception that can be thrown. This
* without worrying about catching the exception that can be thrown. This
* allows writing code such as the following:
*
* \code
* bool callback(const PDU& pdu) {
* // If either RawPDU is not found, or construction of the DNS
* // object fails, the BaseSniffer object will trap the exceptions,
* // If either RawPDU is not found, or construction of the DNS
* // object fails, the BaseSniffer object will trap the exceptions,
* // so we don't need to worry about it.
* DNS dns = pdu.rfind_pdu<RawPDU>().to<DNS>();
* return true;
* }
* \endcode
*
*
* \param function The callback handler object which should process packets.
* \param max_packets The maximum amount of packets to sniff. 0 == infinite.
*/
template<class Functor>
void sniff_loop(Functor function, uint32_t max_packets = 0);
/**
* \brief Sets a filter on this sniffer.
* \param filter The filter to be set.
* \return True iif it was possible to apply the filter.
*/
bool set_filter(const std::string &filter);
/**
* \brief Stops sniffing loops.
*
@@ -205,13 +210,13 @@ namespace Tins {
*
* By default, packets will be parsed starting from link layer.
* However, if you're parsing a lot of traffic, then you might
* want to extract packets and push them into a queue,
* want to extract packets and push them into a queue,
* so a consumer can parse them when they're popped.
*
* This method allows doing that. If the parameter is true,
* then packets taken from this BaseSniffer will only contain
* a RawPDU which will have to entire contents of the packet.
*
*
* \param value Whether to extract RawPDUs or not.
*/
void set_extract_raw_pdus(bool value);
@@ -233,48 +238,74 @@ namespace Tins {
* Retrieves an end iterator.
*/
iterator end();
/**
* Retrieves the pcap handle used by this sniffer.
*/
pcap_t* get_pcap_handle();
/**
* Retrieves the pcap handle used by this sniffer.
*/
const pcap_t* get_pcap_handle() const;
protected:
/**
* Default constructor.
*/
BaseSniffer();
/**
* \brief Initialices this BaseSniffer.
*
* \param phandle The pcap handle to be used for sniffing.
* \param filter The pcap filter which will be applied to the
* stream.
* \param if_mask The interface's subnet mask. If 0 is provided,
* then some IP broadcast tests won't work correctly.
*/
void init(pcap_t *phandle, const std::string &filter, bpf_u_int32 if_mask);
void set_pcap_handle(pcap_t* const pcap_handle);
void set_if_mask(bpf_u_int32 if_mask);
bpf_u_int32 get_if_mask() const;
private:
BaseSniffer(const BaseSniffer&);
BaseSniffer &operator=(const BaseSniffer&);
pcap_t *handle;
bpf_u_int32 mask;
bool extract_raw;
};
/**
/**
* \class Sniffer
* \brief Sniffs packets from a network interface.
*/
class Sniffer : public BaseSniffer {
public:
/**
* \deprecated This enum is no longer necessary. You should use the
* Sniffer(const std::string&, const SnifferConfiguration&) constructor.
*/
enum promisc_type {
NON_PROMISC,
PROMISC
};
/**
* Constructs an instance of Sniffer.
* \brief Constructs an instance of Sniffer using the provided configuration.
*
* This constructor was added as a way to improve the parameter bloat
* introduced by the other ones available. You should create an instance
* of SnifferConfiguration, set the desired parameters, and then use it
* when constructing a Sniffer object.
*
* \sa SnifferConfiguration
*
* \param device The device which will be sniffed.
* \param configuration The configuration object to use to setup the sniffer.
*/
Sniffer(const std::string &device, const SnifferConfiguration& configuration);
/**
* \brief Constructs an instance of Sniffer.
*
* By default the interface won't be put into promiscuous mode, and won't
* be put into monitor mode.
*
* \deprecated Use the Sniffer(const std::string&, const SnifferConfiguration&)
* constructor.
* \param device The device which will be sniffed.
* \param max_packet_size The maximum packet size to be read.
* \param promisc bool indicating wether to put the interface in promiscuous mode.(optional)
@@ -289,23 +320,33 @@ namespace Tins {
*
* The maximum capture size is set to 65535. By default the interface won't
* be put into promiscuous mode, and won't be put into monitor mode.
*
*
* \deprecated Use the Sniffer(const std::string&, const SnifferConfiguration&)
* constructor.
* \param device The device which will be sniffed.
* \param promisc Indicates if the interface should be put in promiscuous mode.
* \param filter A capture filter to be used on the sniffing session.(optional);
* \param rfmon Indicates if the interface should be put in monitor mode.(optional);
*/
Sniffer(const std::string &device, promisc_type promisc = NON_PROMISC,
Sniffer(const std::string &device, promisc_type promisc = NON_PROMISC,
const std::string &filter = "", bool rfmon = false);
private:
void init_sniffer(const std::string &device, unsigned max_packet_size,
bool promisc = false, const std::string &filter = "", bool rfmon = false);
friend class SnifferConfiguration;
void set_snap_len(unsigned snap_len);
void set_buffer_size(unsigned buffer_size);
void set_promisc_mode(bool promisc_enabled);
void set_rfmon(bool rfmon_enabled);
};
/**
* \class FileSniffer
* \brief Reads pcap files and interprets the packets in it.
*
*
* This class acts exactly in the same way that Sniffer, but reads
* packets from a pcap file instead of an interface.
*/
@@ -316,18 +357,27 @@ namespace Tins {
* \param file_name The pcap file which will be parsed.
* \param filter A capture filter to be used on the file.(optional);
*/
FileSniffer(const std::string &file_name, const SnifferConfiguration& configuration);
/**
* \deprecated Use the constructor that takes a SnifferConfiguration instead.
*
* \brief Constructs an instance of FileSniffer.
* \param file_name The pcap file which will be parsed.
* \param filter A capture filter to be used on the file.(optional);
*/
FileSniffer(const std::string &file_name, const std::string &filter = "");
};
template<class T>
class HandlerProxy {
public:
typedef T* ptr_type;
typedef bool (T::*fun_type)(PDU&) ;
HandlerProxy(ptr_type ptr, fun_type function)
HandlerProxy(ptr_type ptr, fun_type function)
: object(ptr), fun(function) {}
bool operator()(PDU &pdu) {
return (object->*fun)(pdu);
}
@@ -335,9 +385,9 @@ namespace Tins {
ptr_type object;
fun_type fun;
};
template<class T>
HandlerProxy<T> make_sniffer_handler(T *ptr, typename HandlerProxy<T>::fun_type function)
HandlerProxy<T> make_sniffer_handler(T *ptr, typename HandlerProxy<T>::fun_type function)
{
return HandlerProxy<T>(ptr, function);
}
@@ -345,7 +395,7 @@ namespace Tins {
/**
* \brief Iterates over packets sniffed by a BaseSniffer.
*/
class SnifferIterator : public std::iterator<std::forward_iterator_tag, PDU> {
class SnifferIterator : public std::iterator<std::forward_iterator_tag, Packet> {
public:
/**
* Constructs a SnifferIterator.
@@ -379,15 +429,15 @@ namespace Tins {
* Dereferences the iterator.
* \return reference to the current packet.
*/
PDU &operator*() {
return *pkt.pdu();
Packet &operator*() {
return pkt;
}
/**
* Dereferences the iterator.
* \return pointer to the current packet.
*/
PDU *operator->() {
Packet *operator->() {
return &(**this);
}
@@ -417,13 +467,128 @@ namespace Tins {
Packet pkt;
};
/**
* \class SnifferConfiguration
* \brief Represents the configuration of a BaseSniffer object.
*
* This class can be used as an easy way to configure a Sniffer
* or FileSniffer object.
*
* It can be used by constructing an object of this type,
* setting the desired values and then passing it to the
* Sniffer or FileSniffer object's constructor. This sets
* default values for some attributes:
*
* - Snapshot length: 65535 bytes (64 KB).
* - Timeout: 1000 milliseconds.
* - Promiscuous mode: false.
*
* For any of the attributes not listed above, the associated
* pcap function which is used to set them on a pcap handle
* won't be called at all.
*
* This class can be used to configure a Sniffer object,
* like this:
*
* \code
* // Initialize the configuration.
* SnifferConfiguration config;
* config.set_filter("ip and port 80");
* config.set_promisc_mode(true);
*
* // Use it on a Sniffer object.
* Sniffer sniffer("eth0", config);
* \endcode
*/
class SnifferConfiguration {
public:
/**
* \brief The default snapshot length.
*
* This is 65535 by default.
*/
static const unsigned DEFAULT_SNAP_LEN;
/**
* \brief The default timeout.
*
* This is 1000 by default.
*/
static const unsigned DEFAULT_TIMEOUT;
/**
* Default constructs a SnifferConfiguration.
*/
SnifferConfiguration();
/**
* Sets the snapshot length option.
* \param snap_len The snapshot length to be set.
*/
void set_snap_len(unsigned snap_len);
/**
* Sets the buffer size option.
* \param buffer_size The buffer size to be set.
*/
void set_buffer_size(unsigned buffer_size);
/**
* Sets the promiscuous mode option.
* \param enabled The promiscuous mode value.
*/
void set_promisc_mode(bool enabled);
/**
* Sets a pcap filter to use on the sniffer.
* \param filter The pcap filter to be used.
*/
void set_filter(const std::string& filter);
/**
* Sets the rfmon option.
* \param enabled The rfmon option value.
*/
void set_rfmon(bool enabled);
/**
* Sets the timeout option.
* \param timeout The timeout to be set.
*/
void set_timeout(unsigned timeout);
protected:
friend class Sniffer;
friend class FileSniffer;
void configure_sniffer_pre_activation(Sniffer& sniffer) const;
void configure_sniffer_pre_activation(FileSniffer& sniffer) const;
void configure_sniffer_post_activation(Sniffer& sniffer) const;
unsigned _snap_len;
bool _has_buffer_size;
unsigned _buffer_size;
bool _has_promisc;
bool _promisc;
bool _has_rfmon;
bool _rfmon;
bool _has_filter;
std::string _filter;
unsigned _timeout;
};
template<class Functor>
void Tins::BaseSniffer::sniff_loop(Functor function, uint32_t max_packets) {
for(iterator it = begin(); it != end(); ++it) {
try {
// If the functor returns false, we're done
if(!function(*it))
#if TINS_IS_CXX11
if (!Tins::Internals::invoke_loop_cb(function, *it))
return;
#else
if(!function(*it->pdu()))
return;
#endif
}
catch(malformed_packet&) { }
catch(pdu_not_found&) { }
@@ -432,5 +597,5 @@ namespace Tins {
}
}
}
#endif // TINS_SNIFFER_H

View File

@@ -36,6 +36,10 @@
#include "small_uint.h"
namespace Tins {
/**
* \class STP
* \brief Represents a Spanning Tree Protocol PDU.
*/
class STP : public PDU {
public:
/**

View File

@@ -45,10 +45,31 @@
namespace Tins {
/**
* \brief Class that represents an TCP PDU.
* \class TCP
* \brief Represents a TCP PDU.
*
* TCP is the representation of the TCP PDU. Instances of this class
* must be sent over a level 3 PDU, this will otherwise fail.
* This class represents a TCP PDU.
*
* When sending TCP PDUs, the checksum is calculated automatically
* every time you send the packet.
*
* While sniffing, the payload sent in each packet will be wrapped
* in a RawPDU, which is set as the TCP object's inner_pdu. Therefore,
* if you are sniffing and want to see the TCP packet's payload,
* you need to do the following:
*
* \code
* // Get a packet from somewhere.
* TCP tcp = ...;
*
* // Extract the RawPDU object.
* const RawPDU& raw = tcp.rfind_pdu<RawPDU>();
*
* // Finally, take the payload (this is a vector<uint8_t>)
* const RawPDU::payload_type& payload = raw.payload();
* \endcode
*
* \sa RawPDU
*/
class TCP : public PDU {
@@ -77,7 +98,7 @@ namespace Tins {
/**
* \brief TCP options enum.
*
* This enum identifies valid options supported by TCP PDU.
* This enum defines option types supported by TCP PDU.
*/
enum OptionTypes {
EOL = 0,
@@ -119,6 +140,7 @@ namespace Tins {
*
* Creates an instance of TCP. Destination and source port can
* be provided, otherwise both will be 0.
*
* \param dport Destination port.
* \param sport Source port.
* */
@@ -128,7 +150,7 @@ namespace Tins {
* \brief Constructs TCP object from a buffer.
*
* If there is not enough size for a TCP header, or any of the
* TLV options are malformed a malformed_packet exception is
* TLV options are malformed, a malformed_packet exception is
* thrown.
*
* Any extra data will be stored in a RawPDU.
@@ -141,56 +163,56 @@ namespace Tins {
/**
* \brief Getter for the destination port field.
*
* \return The destination port in an uint16_t.
* \return The destination port field value.
*/
uint16_t dport() const { return Endian::be_to_host(_tcp.dport); }
/**
* \brief Getter for the source port field.
*
* \return The source port in an uint16_t.
* \return The source port field value.
*/
uint16_t sport() const { return Endian::be_to_host(_tcp.sport); }
/**
* \brief Getter for the sequence number field.
*
* \return The sequence number in an uint32_t.
* \return The sequence number field value.
*/
uint32_t seq() const { return Endian::be_to_host(_tcp.seq); }
/**
* \brief Getter for the acknowledge number field.
*
* \return The acknowledge number in an uint32_t.
* \return The acknowledge number field value.
*/
uint32_t ack_seq() const { return Endian::be_to_host(_tcp.ack_seq); }
/**
* \brief Getter for the window size field.
*
* \return The window size in an uint32_t.
* \return The window size field value.
*/
uint16_t window() const { return Endian::be_to_host(_tcp.window); }
/**
* \brief Getter for the checksum field.
*
* \return The checksum field in an uint16_t.
* \return The checksum field value.
*/
uint16_t checksum() const { return Endian::be_to_host(_tcp.check); }
/**
* \brief Getter for the urgent pointer field.
*
* \return The urgent pointer in an uint16_t.
* \return The urgent pointer field value.
*/
uint16_t urg_ptr() const { return Endian::be_to_host(_tcp.urg_ptr); }
/**
* \brief Getter for the data offset field.
*
* \return Data offset in an uint8_t.
* \return The data offset field value.
*/
small_uint<4> data_offset() const { return this->_tcp.doff; }
@@ -203,7 +225,24 @@ namespace Tins {
/**
* \brief Gets the value of a flag.
*
* This method gets the value of a specific flag. If you
* want to check for multiple flags at the same time,
* use TCP::flags.
*
* If you want to check if this PDU has the SYN flag on,
* you can do it like this:
*
* \code
* // Get a TCP packet from somewhere.
* TCP tcp = ...;
*
* if(tcp.get_flag(TCP::SYN)) {
* // The SYN flag is on!
* }
* \endcode
*
* \sa TCP::flags
* \param tcp_flag The polled flag.
* \return The value of the flag.
*/
@@ -219,8 +258,9 @@ namespace Tins {
*
* \code
* TCP tcp = ...;
* if(tcp.flags() == (TCP::SYN | TCP::ACK))
* if(tcp.flags() == (TCP::SYN | TCP::ACK)) {
* // It's a SYN+ACK!
* }
* \endcode
*
* \return The value of the flags field.
@@ -378,11 +418,13 @@ namespace Tins {
* same time.
*
* \code
* // Get a TCP packet from somewhere and set the flags to SYN && ACK
* TCP tcp = ...;
* tcp.flags(TCP::SYN | TCP::ACK);
* // ...
* // only set the ACK, keeping the rest of the old flags.
* tcp.flags(tcp.flags() | TCP::ACK);
*
* // Now also set the PSH flag, without modifying
* // the rest of the flags.
* tcp.flags(tcp.flags() | TCP::PSH);
* \endcode
*
* \param value The new value of the flags.

View File

@@ -340,29 +340,32 @@ void TCPStreamFollower::follow_streams(ForwardIterator start, ForwardIterator en
template<typename DataFunctor, typename EndFunctor>
bool TCPStreamFollower::callback(PDU &pdu, const DataFunctor &data_fun, const EndFunctor &end_fun) {
IP &ip = pdu.rfind_pdu<IP>();
TCP &tcp = pdu.rfind_pdu<TCP>();
IP *ip = pdu.find_pdu<IP>();
TCP *tcp = pdu.find_pdu<TCP>();
if(!ip || !tcp) {
return true;
}
TCPStream::StreamInfo info(
ip.src_addr(), ip.dst_addr(),
tcp.sport(), tcp.dport()
ip->src_addr(), ip->dst_addr(),
tcp->sport(), tcp->dport()
);
sessions_type::iterator it = sessions.find(info);
if(it == sessions.end()) {
std::swap(info.client_addr, info.server_addr);
std::swap(info.client_port, info.server_port);
if((it = sessions.find(info)) == sessions.end()) {
if(tcp.get_flag(TCP::SYN) && !tcp.get_flag(TCP::ACK)) {
if(tcp->get_flag(TCP::SYN) && !tcp->get_flag(TCP::ACK)) {
sessions.insert(
std::make_pair(
info,
TCPStream(&ip, &tcp, last_identifier++)
TCPStream(ip, tcp, last_identifier++)
)
);
}
return true;
}
}
if(it->second.update(&ip, &tcp))
if(it->second.update(ip, tcp))
data_fun(it->second);
// We're done with this stream
if(it->second.is_finished()) {

View File

@@ -36,10 +36,29 @@
namespace Tins {
/** \brief Class that represents an UDP PDU.
/**
* \class UDP
* \brief Represents an UDP PDU.
*
* UDP is the representation of the UDP PDU. Instances of this class
* must be sent over a level 3 PDU, this will otherwise fail.
* This class represents an UDP PDU.
*
* While sniffing, the payload sent in each packet will be wrapped
* in a RawPDU, which is set as the UDP object's inner_pdu. Therefore,
* if you are sniffing and want to see the UDP packet's payload,
* you need to do the following:
*
* \code
* // Get a packet from somewhere.
* UDP udp = ...;
*
* // Extract the RawPDU object.
* const RawPDU& raw = udp.rfind_pdu<RawPDU>();
*
* // Finally, take the payload (this is a vector<uint8_t>)
* const RawPDU::payload_type& payload = raw.payload();
* \endcode
*
* \sa RawPDU
*/
class UDP : public PDU {
public:

View File

@@ -36,6 +36,7 @@
#include <winsock2.h>
#include <iphlpapi.h>
#undef interface
#include "network_interface.h"
#endif
#include "macros.h"
#if defined(BSD) || defined(__FreeBSD_kernel__)
@@ -389,9 +390,8 @@ void Tins::Utils::route_entries(ForwardIterator output) {
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.interface = NetworkInterface::from_index(row->dwForwardIfIndex).name();
entry.destination = IPv4Address(row->dwForwardDest);
entry.mask = IPv4Address(row->dwForwardMask);
entry.gateway = IPv4Address(row->dwForwardNextHop);

View File

@@ -1,527 +0,0 @@
#!/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:

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