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

27 Commits
v4.0 ... v4.1

Author SHA1 Message Date
Matias Fontanini
559b1fb89a Update changelog for version 4.1 2018-12-10 18:11:37 -08:00
Matias Fontanini
1e78ef0752 Bump version to 4.1.0 2018-12-10 18:07:08 -08:00
Saxon Parker
602ada7820 Fix Dot1Q serialization for non-qinq packets (#319) 2018-12-01 15:56:16 -08:00
Teodoro Vargas
57ac099703 Fix serialization for QinQ (#316)
* Add QinQ Frame

* Fix serialization for QinQ
2018-10-09 14:02:01 -07:00
Ulf Wetzker
c26e4943c2 Added base class access specifier for socket_close_error (#306) 2018-08-02 09:17:07 -07:00
Stefan Schmidt
3659d89c25 Rewrote hw_address_to_string to not require a stringstream (#299) 2018-05-31 13:28:06 -07:00
Matias Fontanini
db992d42e5 Set TINS_HAVE_DOT11 as predefined in Doxyfile
Fixes #294
2018-05-18 20:41:40 -07:00
Matias Fontanini
5571a270d4 Make RadioTapParser::skip_to_field check for end of buffer (#296)
Fixes #295
2018-05-16 12:30:16 -07:00
Matias Fontanini
b18c2cefec Remove note regarding develop branch
This was useful at some point but now it's more of a burden to keep up to date. PRs should use `master` as base directly.
2018-05-09 20:33:40 -07:00
Jim Hague
3f204321ce Ensure local include directory comes before system. (#293)
If building (say) libtins 4.0 on a system with 3.4 installed, you need
the libtins include files to come from the repository include, not the
system include directory. The OpenSSL and PCAP includes may be from
the system include, so we need to ensure the libtins include is the
first on the list - which means the last on the before list.
2018-05-09 20:30:58 -07:00
Matias Fontanini
63603b8ac8 Calculate IP option sizes properly
Fixes #288
2018-04-08 08:12:52 -07:00
Kasper Laudrup
fa79582b89 Add parsing of well known IPv6 extension headers (#287)
* Add parsing of well known IPv6 extension headers

Add classes for IPv6 extension headers defined in the IPv6 protocol
specification (RFC 2460) as well as functions for creating them from
the IPv6 class' ext_header type.

The currently known extension headers are Hop-By-Hop Option,
Destination Routing, Routing and Fragment.

* Cleanup after PR #287 comments

Pull in stuff from the std namespace with "using" instead of
qualifying with std::.

Keep starting braces on the same line.

Avoid potential copy when appending to vector.
2018-03-28 21:05:01 -07:00
stubbfel
342e2c77a7 Add missing operators to address classes (#275)
* * add or-operator and a simlple unit test for hw_address, ip_address, ipv6_address
* add not-operator and a simlple unit test for hw_address, ip_address, ipv6_address
* add greater-then-operator and a simlple unit test for ipv6_address
* add new constructor and a simlple unit test for network_interface, which use a ipv6_address to find the nic
* add override the function gateway_from_ip for ipv6_address parameter (untested)

* change the ipv6_address in NotMaskAdress_Test, so that the expceted addresses are valid for the winsock api

* Delete CMakeLists.txt.user

* * add  <=, >, >= operator for HWAddress with tests

* add  <=, >, >= operator for IPv4Address with tests
* add  <=,>= operator for IPv6Address with tests

* refactoring the  & , |, ~ operator of ipv6_address to "regular" operator
2018-03-28 20:44:28 -07:00
Matias Fontanini
7848e28b62 Add version macros in config.h
Fixes #286
2018-03-20 18:50:42 -07:00
Matias Fontanini
544aa1b339 Don't assume IPv6 uses ICMPv6 underneath 2018-03-18 12:56:12 -07:00
Matias Fontanini
de4791f0c7 Allow users to specify library install dir
Fixes #273
2018-03-17 15:35:04 -07:00
Matias Fontanini
915f506f3a Use Sleep windows function passing milliseconds as parameter
Fixes #271
2018-03-14 18:47:40 -07:00
Matias Fontanini
f29566d6d9 Implement IPv6::recv_response 2018-02-25 10:42:16 -08:00
Matias Fontanini
e4f747164c Merge remote-tracking branch 'origin/master' into develop 2018-02-21 09:49:44 -08:00
Matias Fontanini
683550b297 Don't use nullptr in non C++11 code 2018-02-21 09:47:09 -08:00
Ed Catmur
971fdf7d1c Ignore (possibly malformed) options after EOL (#281) 2018-02-03 09:33:20 -08:00
Ed Catmur
1038c6f7f3 Don't call &* on PDUIterator 2018-02-03 09:32:43 -08:00
Jeff Ebert
8efc0271f5 Don't include dot11.h in tins.h if it is not configured in the library (#277) 2018-02-03 09:31:24 -08:00
Matias Fontanini
9ac5e597e6 Merge branch 'develop'
Ugh
2017-12-20 07:05:44 -08:00
Matias Fontanini
f7fc5fae1d Update CHANGES.md file using v4.0 changes 2017-12-20 07:04:55 -08:00
Matias Fontanini
f44b253a42 Fix memory leak in PDU's move assignment operator
Fixes #272
2017-12-14 14:42:46 -03:00
Matias Fontanini
8f85a6e557 Append padding to IPv6 options
Relates to #270
2017-12-12 10:33:17 -03:00
43 changed files with 838 additions and 72 deletions

View File

@@ -1,3 +1,41 @@
##### v4.1 - Tue Dec 11 02:08:48 UTC 2018
- Fix serialization for QinQ (#316)
- Added base class access specifier for socket_close_error (#306)
- Rewrote hw_address_to_string to not require a stringstream (#299)
- Make RadioTapParser::skip_to_field check for end of buffer (#296)
- Ensure local include directory comes before system. (#293)
- Calculate IP option sizes properly (#288)
- Add parsing of well known IPv6 extension headers (#287)
- Add missing operators to address classes (#275)
- Add version macros in config.h
- Don't assume IPv6 uses ICMPv6 underneath
- Allow users to specify library install dir
- Use Sleep windows function passing milliseconds as parameter
- Implement IPv6::recv_response
- Don't use nullptr in non C++11 code
- Ignore (possibly malformed) options after EOL (#281)
- Don't include dot11.h in tins.h if it is not configured in the library (#277)
- Fix memory leak in PDU's move assignment operator
- Append padding to IPv6 options
##### v4.0 - Mon Dec 4 00:04:30 UTC 2017
- Add parent PDU to each PDU.

View File

@@ -45,9 +45,10 @@ ELSE(LIBTINS_BUILD_SHARED)
ENDIF(LIBTINS_BUILD_SHARED)
# The version number.
SET(LIBTINS_VERSION_MAJOR 4)
SET(LIBTINS_VERSION_MINOR 0)
SET(LIBTINS_VERSION "${LIBTINS_VERSION_MAJOR}.${LIBTINS_VERSION_MINOR}")
SET(TINS_VERSION_MAJOR 4)
SET(TINS_VERSION_MINOR 1)
SET(TINS_VERSION_PATCH 0)
SET(LIBTINS_VERSION "${TINS_VERSION_MAJOR}.${TINS_VERSION_MINOR}")
# Required Packages
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/")
@@ -224,18 +225,19 @@ IF(DOXYGEN_FOUND)
)
ENDIF(DOXYGEN_FOUND)
# The library output directory
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
# Configuration file
CONFIGURE_FILE(
"${PROJECT_SOURCE_DIR}/include/tins/config.h.in"
"${PROJECT_SOURCE_DIR}/include/tins/config.h"
)
IF (NOT CMAKE_INSTALL_LIBDIR)
SET(CMAKE_INSTALL_LIBDIR lib)
ENDIF()
# The library output directory
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
# 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})

View File

@@ -22,9 +22,6 @@ easier.
Pull requests are very welcomed. When doing a pull request please:
* Base your PR branch on the `develop` branch. This is **almost always** pointing to the
same commit as `master`, so you shouldn't have any issues changing the destination branch
to `develop` at the time you try to do the pull request if you based your code on `master`.
* Your code will be compiled and tests will be run automatically by the travis and
* Notice that your code will be compiled and tests will be run automatically by the travis and
appveyor CI tools. If your code has issues on any of the tested platforms (GNU/Linux, Windows
and OSX), please fix it or otherwise the PR won't be merged.

View File

@@ -1366,7 +1366,8 @@ INCLUDE_FILE_PATTERNS =
# instead of the = operator.
PREDEFINED = "TINS_IS_CXX11=1" \
"TINS_HAVE_WPA2_CALLBACKS=1"
"TINS_HAVE_WPA2_CALLBACKS=1" \
"TINS_HAVE_DOT11=1"
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.

View File

@@ -88,7 +88,7 @@ void do_arp_spoofing(NetworkInterface iface,
sender.send(to_gw, iface);
sender.send(to_victim, iface);
#ifdef _WIN32
Sleep(5);
Sleep(5000);
#else
sleep(5);
#endif

View File

@@ -31,4 +31,9 @@
/* Have libpcap */
#cmakedefine TINS_HAVE_PCAP
/* Version macros */
#define TINS_VERSION_MAJOR ${TINS_VERSION_MAJOR}
#define TINS_VERSION_MINOR ${TINS_VERSION_MINOR}
#define TINS_VERSION_PATCH ${TINS_VERSION_PATCH}
#endif // TINS_CONFIG_H

View File

@@ -128,7 +128,7 @@ public:
/**
* \brief Exception thrown when PacketSender fails to close a socket.
*/
class socket_close_error : exception_base {
class socket_close_error : public exception_base {
public:
socket_close_error(const std::string& msg)
: exception_base(msg) { }
@@ -204,6 +204,15 @@ public:
option_payload_too_large() : exception_base("Option payload too large") { }
};
/**
* \brief Exception thrown when an IPv6 extension header is being
* created from invalid data
*/
class invalid_ipv6_extension_header : public exception_base {
public:
invalid_ipv6_extension_header() : exception_base("Invalid IPv6 extension header") { }
};
/**
* \brief Generic pcap error
*/

View File

@@ -59,6 +59,9 @@ TINS_API bool hw_address_equal_compare(const uint8_t* start1, const uint8_t* end
TINS_API bool hw_address_lt_compare(const uint8_t* start1, const uint8_t* end1,
const uint8_t* start2, const uint8_t* end2);
TINS_API bool hw_address_gt_compare(const uint8_t* start1, const uint8_t* end1,
const uint8_t* start2, const uint8_t* end2);
/**
* \endcond
*/
@@ -268,6 +271,39 @@ public:
return Internals::hw_address_lt_compare(begin(), end(), rhs.begin(), rhs.end());
}
/**
* \brief Compares this HWAddress for less-than equality.
*
* \param rhs The HWAddress to be compared to.
*
* \return bool indicating whether this address is equal or less-than rhs.
*/
bool operator<=(const HWAddress& rhs) const {
return !operator>(rhs);
}
/**
* \brief Compares this HWAddress for greater-than inequality.
*
* \param rhs The HWAddress to be compared to.
*
* \return bool indicating whether this address is greater-than rhs.
*/
bool operator>(const HWAddress& rhs) const {
return Internals::hw_address_gt_compare(begin(), end(), rhs.begin(), rhs.end());
}
/**
* \brief Compares this HWAddress for greater-than equality.
*
* \param rhs The HWAddress to be compared to.
*
* \return bool indicating whether this address is equal or greater-than rhs.
*/
bool operator>=(const HWAddress& rhs) const {
return !operator<(rhs);
}
/**
* \brief Apply a mask to this address
*
@@ -281,7 +317,33 @@ public:
}
return output;
}
/**
* \brief Apply a mask to this address
*
* \param mask The mask to be applied
* \return The result of applying the mask to this address
*/
HWAddress operator|(const HWAddress& mask) const {
HWAddress<n> output = *this;
for (size_t i = 0; i < n; ++i) {
output[i] = output[i] | mask[i];
}
return output;
}
/**
* \brief not operator
* \return The result of applying the mask to this address
*/
HWAddress operator~() const {
HWAddress<n> output = *this;
for (size_t i = 0; i < n; ++i) {
output[i] = ~output[i];
}
return output;
}
/**
* \brief Retrieves the size of this address.
*

View File

@@ -135,6 +135,38 @@ public:
return ip_addr_ < rhs.ip_addr_;
}
/**
* \brief Compares this address for less-than equality.
*
* \param rhs The address to be compared to.
*
* \return bool indicating whether this address is equal or less-than rhs.
*/
bool operator<=(const IPv4Address& rhs) const {
return !operator>(rhs);
}
/**
* \brief Compare this IPv4Address for greater-than inequality.
*
* \param rhs The address to be compared.
* \return bool indicating whether this address is greater-than rhs.
*/
bool operator>(const IPv4Address& rhs) const {
return ip_addr_ > rhs.ip_addr_;
}
/**
* \brief Compares this address for greater-than equality.
*
* \param rhs The address to be compared to.
*
* \return bool indicating whether this address is equal or greater-than rhs.
*/
bool operator>=(const IPv4Address& rhs) const {
return !operator<(rhs);
}
/**
* \brief Apply a mask to this address
*
@@ -142,6 +174,19 @@ public:
* \return The result of applying the mask to this address
*/
IPv4Address operator&(const IPv4Address& mask) const;
/**
* \brief Apply a mask to this address
*
* \param mask The mask to be applied
* \return The result of applying the mask to this address
*/
IPv4Address operator|(const IPv4Address& mask) const;
/**
* not operator (invert)
*/
IPv4Address operator~() const;
/**
* \brief Returns true if this is a private IPv4 address.

View File

@@ -73,6 +73,11 @@ public:
*/
typedef std::vector<ext_header> headers_type;
/**
* The type used to store an extension header option.
*/
typedef std::pair<uint8_t, std::vector<uint8_t> > header_option_type;
/**
* The values used to identify extension headers.
*/
@@ -105,6 +110,46 @@ public:
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/*
* \brief The type used to store Hop-By-Hop Extension Headers
*/
struct hop_by_hop_header {
std::vector<header_option_type> options;
static hop_by_hop_header from_extension_header(const ext_header& hdr);
};
/*
* \brief The type used to store Destination Routing Extension Headers
*/
struct destination_routing_header {
std::vector<header_option_type> options;
static destination_routing_header from_extension_header(const ext_header& hdr);
};
/**
* \brief The type used to store Routing Extension headers
*/
struct routing_header {
uint8_t routing_type;
uint8_t segments_left;
std::vector<uint8_t> data;
static routing_header from_extension_header(const ext_header& hdr);
};
/**
* \brief The type used to store Fragment Extension headers
*/
struct fragment_header {
uint16_t fragment_offset;
bool more_fragments;
uint32_t identification;
static fragment_header from_extension_header(const ext_header& hdr);
};
/**
* \brief Constructs an IPv6 object.
*
@@ -298,6 +343,14 @@ public:
* \sa PDU::send()
*/
void send(PacketSender& sender, const NetworkInterface &);
/**
* \brief Receives a matching response for this packet.
*
* \sa PDU::recv_response
* \param sender The packet sender which will receive the packet.
*/
PDU* recv_response(PacketSender& sender, const NetworkInterface &);
#endif
/**
@@ -356,6 +409,8 @@ private:
uint32_t calculate_headers_size() const;
static void write_header(const ext_header& header, Memory::OutputMemoryStream& stream);
static bool is_extension_header(uint8_t header_id);
static uint32_t get_padding_size(const ext_header& header);
static std::vector<header_option_type> parse_header_options(const uint8_t* data, size_t size);
TINS_BEGIN_PACK
struct ipv6_header {

View File

@@ -160,7 +160,40 @@ public:
bool operator<(const IPv6Address& rhs) const {
return std::lexicographical_compare(begin(), end(), rhs.begin(), rhs.end());
}
/**
* \brief Compares this address for less-than equality.
*
* \param rhs The address to be compared to.
*
* \return bool indicating whether this address is equal or less-than rhs.
*/
bool operator<=(const IPv6Address& rhs) const {
return !operator>(rhs);
}
/**
* \brief Compares this address for greater-than inequality.
*
* \param rhs The address to be compared to.
*
* \return bool indicating whether this address is greater-than rhs.
*/
bool operator>(const IPv6Address& rhs) const {
return std::lexicographical_compare(rhs.begin(), rhs.end(), begin(), end());
}
/**
* \brief Compares this address for greater-than equality.
*
* \param rhs The address to be compared to.
*
* \return bool indicating whether this address is equal or greater-than rhs.
*/
bool operator>=(const IPv6Address& rhs) const {
return !operator<(rhs);
}
/**
* \brief Helper function which copies the address into an output
* iterator.
@@ -218,7 +251,17 @@ public:
/**
* Applies a mask to an address
*/
TINS_API friend IPv6Address operator&(const IPv6Address& lhs, const IPv6Address& rhs);
IPv6Address operator&(const IPv6Address& rhs) const;
/**
* or a mask to an address
*/
IPv6Address operator|(const IPv6Address& rhs) const;
/**
* not operator (invert)
*/
IPv6Address operator~() const ;
private:
void init(const char* addr);

View File

@@ -118,6 +118,17 @@ public:
* \param ip The ip address being looked up.
*/
NetworkInterface(IPv4Address ip);
/**
* \brief Constructs a NetworkInterface from an ipv6 address.
*
* This abstracted interface will be the one that would be the gateway
* when sending a packet to the given ip.
*
* \param ip The ipv6 address being looked up.
*/
NetworkInterface(IPv6Address ipv6);
/**
* \brief Getter for this interface's identifier.

View File

@@ -131,6 +131,7 @@ public:
ARP_SOCKET,
ICMP_SOCKET,
IPV6_SOCKET,
ICMPV6_SOCKET,
SOCKETS_END
};

View File

@@ -170,6 +170,7 @@ public:
ICMPv6,
SLL,
DHCPv6,
DOT1AD,
DOT1Q,
PPPOE,
STP,
@@ -244,8 +245,9 @@ public:
* \param rhs The PDU to be moved.
*/
PDU& operator=(PDU &&rhs) TINS_NOEXCEPT {
delete inner_pdu_;
inner_pdu_ = 0;
std::swap(inner_pdu_, rhs.inner_pdu_);
rhs.inner_pdu_ = 0;
if (inner_pdu_) {
inner_pdu_->parent_pdu(this);
}

View File

@@ -106,8 +106,8 @@ private:
*/
template <typename Concrete>
bool operator==(const PDUIteratorBase<Concrete>& lhs, const PDUIteratorBase<Concrete>& rhs) {
const PDU* lhs_pdu = &*static_cast<const Concrete&>(lhs);
const PDU* rhs_pdu = &*static_cast<const Concrete&>(rhs);
const PDU* lhs_pdu = static_cast<const Concrete&>(lhs).operator->();
const PDU* rhs_pdu = static_cast<const Concrete&>(rhs).operator->();
return lhs_pdu == rhs_pdu;
}
@@ -241,7 +241,7 @@ public:
template <typename OtherIterator>
PDUIteratorRange(const PDUIteratorRange<OtherIterator>& other)
: start_(&*other.begin()), end_(&*other.end()) {
: start_(other.begin().operator->()), end_(other.end().operator->()) {
}

View File

@@ -40,7 +40,9 @@
#include <tins/llc.h>
#include <tins/icmp.h>
#include <tins/icmpv6.h>
#if defined(TINS_HAVE_DOT11)
#include <tins/dot11.h>
#endif
#include <tins/dot1q.h>
#include <tins/dot3.h>
#include <tins/ip.h>

View File

@@ -110,6 +110,14 @@ struct Route6Entry {
template<typename ForwardIterator>
void route_entries(ForwardIterator output);
/**
* \brief Retrieves entries in the routing table.
*
* \brief output ForwardIterator in which entries will be stored.
*/
template<typename ForwardIterator>
void route6_entries(ForwardIterator output);
/**
* \brief Retrieves entries in the routing table.
*
@@ -117,6 +125,7 @@ void route_entries(ForwardIterator output);
*/
TINS_API std::vector<RouteEntry> route_entries();
/**
* \brief Retrieves entries in the routing table.
*
@@ -146,6 +155,19 @@ TINS_API std::set<std::string> network_interfaces();
*/
TINS_API bool gateway_from_ip(IPv4Address ip, IPv4Address& gw_addr);
/**
* \brief Finds the gateway's IP address for the given IP
* address.
*
* \param ip The IP address for which the default gateway will
* be searched.
* \param gw_addr This parameter will contain the gateway's IP
* address in case it is found.
*
* \return bool indicating whether the lookup was successfull.
*/
TINS_API bool gateway_from_ip(IPv6Address ip, IPv6Address& gw_addr);
} // Utils
} // Tins
@@ -158,4 +180,13 @@ void Tins::Utils::route_entries(ForwardIterator output) {
}
}
template<typename ForwardIterator>
void Tins::Utils::route6_entries(ForwardIterator output) {
std::vector<Route6Entry> entries = route6_entries();
for (size_t i = 0; i < entries.size(); ++i) {
*output = entries[i];
++output;
}
}
#endif // TINS_ROUTING_UTILS_H

View File

@@ -8,10 +8,10 @@ IF(HAVE_PCAP_TIMESTAMP_PRECISION)
ADD_DEFINITIONS("-DHAVE_PCAP_TIMESTAMP_PRECISION=1")
ENDIF()
INCLUDE_DIRECTORIES(
${LIBTINS_INCLUDE_DIR}
INCLUDE_DIRECTORIES(BEFORE
${OPENSSL_INCLUDE_DIR}
${PCAP_INCLUDE_DIR}
${LIBTINS_INCLUDE_DIR}
)
set(SOURCES
@@ -219,8 +219,8 @@ SET_TARGET_PROPERTIES(tins PROPERTIES VERSION ${LIBTINS_VERSION} SOVERSION ${LIB
INSTALL(
TARGETS tins
EXPORT libtinsTargets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT dev
)
@@ -233,4 +233,4 @@ MACRO(INSTALL_HEADERS_WITH_DIRECTORY HEADER_LIST)
ENDFOREACH(HEADER)
ENDMACRO()
INSTALL_HEADERS_WITH_DIRECTORY(${HEADERS})
INSTALL_HEADERS_WITH_DIRECTORY(${HEADERS})

View File

@@ -211,6 +211,8 @@ Constants::Ethernet::e pdu_flag_to_ether_type(PDU::PDUType flag) {
return Constants::Ethernet::ARP;
case PDU::DOT1Q:
return Constants::Ethernet::VLAN;
case PDU::DOT1AD:
return Constants::Ethernet::QINQ;
case PDU::PPPOE:
return Constants::Ethernet::PPPOED;
case PDU::MPLS:
@@ -238,6 +240,9 @@ PDU::PDUType ether_type_to_pdu_flag(Constants::Ethernet::e flag) {
return PDU::ARP;
case Constants::Ethernet::VLAN:
return PDU::DOT1Q;
case Constants::Ethernet::QINQ:
case Constants::Ethernet::OLD_QINQ:
return PDU::DOT1AD;
case Constants::Ethernet::PPPOED:
return PDU::PPPOE;
//case PDU::RSNEAPOL
@@ -295,4 +300,4 @@ PDU::PDUType ip_type_to_pdu_flag(Constants::IP::e flag) {
}
} // Internals
} // Tins
} // Tins

View File

@@ -107,15 +107,10 @@ uint32_t Dot1Q::trailer_size() const {
void Dot1Q::write_serialization(uint8_t* buffer, uint32_t total_sz) {
OutputMemoryStream stream(buffer, total_sz);
if (inner_pdu()) {
Constants::Ethernet::e flag;
Constants::Ethernet::e flag = Constants::Ethernet::UNKNOWN;
PDUType type = inner_pdu()->pdu_type();
if (type == PDU::DOT1Q) {
flag = Constants::Ethernet::QINQ;
}
else {
// Set the appropriate payload type flag
flag = Internals::pdu_flag_to_ether_type(type);
}
// Set the appropriate payload type flag
flag = Internals::pdu_flag_to_ether_type(type);
if (flag != Constants::Ethernet::UNKNOWN) {
payload_type(static_cast<uint16_t>(flag));
}

View File

@@ -156,7 +156,7 @@ bool EthernetII::matches_response(const uint8_t* ptr, uint32_t total_sz) const {
void EthernetII::write_serialization(uint8_t* buffer, uint32_t total_sz) {
OutputMemoryStream stream(buffer, total_sz);
if (inner_pdu()) {
Constants::Ethernet::e flag;
Constants::Ethernet::e flag = Constants::Ethernet::UNKNOWN;
const PDUType type = inner_pdu()->pdu_type();
// Dirty trick to successfully tag PPPoE session/discovery packets
if (type == PDU::PPPOE) {
@@ -164,6 +164,17 @@ void EthernetII::write_serialization(uint8_t* buffer, uint32_t total_sz) {
flag = (pppoe->code() == 0) ? Constants::Ethernet::PPPOES
: Constants::Ethernet::PPPOED;
}
// Dirty trick: Double Dot1Q is interpreted as Dot1AD
else if (type == PDU::DOT1Q) {
flag = Internals::pdu_flag_to_ether_type(type);
if (inner_pdu()->inner_pdu()) {
const PDUType inner_type = inner_pdu()->inner_pdu()->pdu_type();
if (inner_type == PDU::DOT1Q) {
flag = Constants::Ethernet::QINQ;
}
}
}
else {
flag = Internals::pdu_flag_to_ether_type(type);
}

View File

@@ -34,32 +34,35 @@
#include <tins/exceptions.h>
using std::string;
using std::ostream;
using std::hex;
using std::ostringstream;
using std::lexicographical_compare;
using std::equal;
namespace Tins {
namespace Internals {
void storage_to_string(ostream& output, uint8_t value) {
output << hex;
if (value < 0x10) {
output << '0';
}
output << (unsigned)value;
}
string hw_address_to_string(const uint8_t* ptr, size_t count) {
ostringstream output;
string output;
output.reserve(count*3);
for (size_t i = 0; i < count; ++i) {
if (i != 0) {
output << ":";
output += ":";
}
storage_to_string(output, ptr[i]);
char j = ptr[i];
char upper = (j >> 4) & 0x0F;
if (upper > 9)
upper += 'a'-10;
else
upper += '0';
char lower = j & 0x0F;
if (lower > 9)
lower += 'a'-10;
else
lower += '0';
output += upper;
output += lower;
}
return output.str();
return output;
}
void string_to_hw_address(const string& hw_addr, uint8_t* output, size_t output_size) {
@@ -113,5 +116,10 @@ bool hw_address_lt_compare(const uint8_t* start1, const uint8_t* end1,
return lexicographical_compare(start1, end1, start2, end2);
}
bool hw_address_gt_compare(const uint8_t* start1, const uint8_t* end1,
const uint8_t* start2, const uint8_t* end2) {
return lexicographical_compare(start2, end2, start1, end1);
}
} // Internals
} // Tins

View File

@@ -321,7 +321,12 @@ void IP::add_option(const option& opt) {
uint32_t IP::calculate_options_size() const {
uint32_t options_size = 0;
for (options_type::const_iterator iter = options_.begin(); iter != options_.end(); ++iter) {
options_size += 1 + iter->data_size();
options_size += sizeof(uint8_t);
const option_identifier option_id = iter->option();
// Only add length field and data size for non [NOOP, EOL] options
if (option_id.op_class != CONTROL || option_id.number > NOOP) {
options_size += sizeof(uint8_t) + iter->data_size();
}
}
return options_size;
}

View File

@@ -153,4 +153,12 @@ IPv4Address IPv4Address::operator&(const IPv4Address& mask) const {
return IPv4Address(Endian::be_to_host(ip_addr_ & mask.ip_addr_));
}
IPv4Address IPv4Address::operator|(const IPv4Address& mask) const {
return IPv4Address(Endian::be_to_host(ip_addr_ | mask.ip_addr_));
}
IPv4Address IPv4Address::operator~() const {
return IPv4Address(Endian::be_to_host(~ip_addr_));
}
} // Tins

View File

@@ -43,6 +43,7 @@
#include <tins/memory_helpers.h>
#include <tins/detail/pdu_helpers.h>
using std::make_pair;
using std::vector;
using Tins::Memory::InputMemoryStream;
@@ -69,6 +70,49 @@ PDU::metadata IPv6::extract_metadata(const uint8_t *buffer, uint32_t total_sz) {
return metadata(header_size, pdu_flag, PDU::UNKNOWN);
}
IPv6::hop_by_hop_header IPv6::hop_by_hop_header::from_extension_header(const ext_header& hdr) {
if (TINS_UNLIKELY(hdr.option() != HOP_BY_HOP)) {
throw invalid_ipv6_extension_header();
}
hop_by_hop_header header;
header.options = parse_header_options(hdr.data_ptr(), hdr.data_size());
return header;
}
IPv6::destination_routing_header IPv6::destination_routing_header::from_extension_header(const ext_header& hdr) {
if (TINS_UNLIKELY(hdr.option() != DESTINATION_ROUTING_OPTIONS)) {
throw invalid_ipv6_extension_header();
}
destination_routing_header header;
header.options = parse_header_options(hdr.data_ptr(), hdr.data_size());
return header;
}
IPv6::routing_header IPv6::routing_header::from_extension_header(const ext_header& hdr) {
if (TINS_UNLIKELY(hdr.option() != ROUTING)) {
throw invalid_ipv6_extension_header();
}
Memory::InputMemoryStream stream(hdr.data_ptr(), hdr.data_size());
routing_header header;
header.routing_type = stream.read<uint8_t>();
header.segments_left = stream.read<uint8_t>();
header.data.assign(stream.pointer(), stream.pointer() + stream.size());
return header;
}
IPv6::fragment_header IPv6::fragment_header::from_extension_header(const ext_header& hdr) {
if (TINS_UNLIKELY(hdr.option() != FRAGMENT)) {
throw invalid_ipv6_extension_header();
}
Memory::InputMemoryStream stream(hdr.data_ptr(), hdr.data_size());
fragment_header header;
uint16_t field = stream.read_be<uint16_t>();
header.fragment_offset = field >> 3;
header.more_fragments = field & 1;
header.identification = stream.read_be<uint32_t>();
return header;
}
IPv6::IPv6(address_type ip_dst, address_type ip_src, PDU* /*child*/)
: header_(), next_header_() {
version(6);
@@ -164,6 +208,38 @@ bool IPv6::is_extension_header(uint8_t header_id) {
|| header_id == MOBILITY || header_id == NO_NEXT_HEADER;
}
uint32_t IPv6::get_padding_size(const ext_header& header) {
const uint32_t padding = (header.data_size() + sizeof(uint8_t) * 2) % 8;
return padding == 0 ? 0 : (8 - padding);
}
vector<IPv6::header_option_type> IPv6::parse_header_options(const uint8_t* data, size_t size) {
Memory::InputMemoryStream stream(data, size);
vector<header_option_type> options;
while (stream.size() > 0) {
try {
uint8_t option = stream.read<uint8_t>();
if (option == PAD_1) {
continue;
}
uint8_t size = stream.read<uint8_t>();
if (size > stream.size()) {
throw invalid_ipv6_extension_header();
}
if (option != PAD_N) {
options.push_back(make_pair(option, vector<uint8_t>(stream.pointer(),
stream.pointer() +
size)));
}
stream.skip(size);
} catch (const malformed_packet&) {
throw invalid_ipv6_extension_header();
}
}
return options;
}
void IPv6::version(small_uint<4> new_version) {
header_.version = new_version;
}
@@ -291,17 +367,21 @@ void IPv6::write_serialization(uint8_t* buffer, uint32_t total_sz) {
#ifndef BSD
void IPv6::send(PacketSender& sender, const NetworkInterface &) {
struct sockaddr_in6 link_addr;
PacketSender::SocketType type = PacketSender::IPV6_SOCKET;
sockaddr_in6 link_addr;
const PacketSender::SocketType type = PacketSender::IPV6_SOCKET;
link_addr.sin6_family = AF_INET6;
link_addr.sin6_port = 0;
memcpy((uint8_t*)&link_addr.sin6_addr, header_.dst_addr, address_type::address_size);
if (inner_pdu() && inner_pdu()->pdu_type() == PDU::ICMP) {
type = PacketSender::ICMP_SOCKET;
}
sender.send_l3(*this, (struct sockaddr*)&link_addr, sizeof(link_addr), type);
}
PDU* IPv6::recv_response(PacketSender& sender, const NetworkInterface &) {
PacketSender::SocketType type = PacketSender::IPV6_SOCKET;
if (inner_pdu() && inner_pdu()->pdu_type() == PDU::ICMPv6) {
type = PacketSender::ICMPV6_SOCKET;
}
return sender.recv_l3(*this, 0, sizeof(sockaddr_in6), type);
}
#endif
void IPv6::add_ext_header(const ext_header& header) {
@@ -337,6 +417,8 @@ uint32_t IPv6::calculate_headers_size() const {
uint32_t output = 0;
for (const_iterator iter = ext_headers_.begin(); iter != ext_headers_.end(); ++iter) {
output += static_cast<uint32_t>(iter->data_size() + sizeof(uint8_t) * 2);
output += get_padding_size(*iter);
}
return output;
}
@@ -346,6 +428,8 @@ void IPv6::write_header(const ext_header& header, OutputMemoryStream& stream) {
stream.write(header.option());
stream.write(length);
stream.write(header.data_ptr(), header.data_size());
// Append padding
stream.fill(get_padding_size(header), 0);
}
} // Tins

View File

@@ -142,13 +142,33 @@ ostream& operator<<(ostream& os, const IPv6Address& addr) {
return os << addr.to_string();
}
IPv6Address operator&(const IPv6Address& lhs, const IPv6Address& rhs) {
IPv6Address output = lhs;
IPv6Address::iterator addr_iter = output.begin();
IPv6Address IPv6Address::operator&(const IPv6Address& rhs) const {
IPv6Address result = *this;
IPv6Address::iterator addr_iter = result.begin();
for (IPv6Address::const_iterator it = rhs.begin(); it != rhs.end(); ++it, ++addr_iter) {
*addr_iter = *addr_iter & *it;
}
return output;
return result;
}
IPv6Address IPv6Address::operator|(const IPv6Address& rhs) const {
IPv6Address result = *this;
IPv6Address::iterator addr_iter = result.begin();
for (IPv6Address::const_iterator it = rhs.begin(); it != rhs.end(); ++it, ++addr_iter) {
*addr_iter = *addr_iter | *it;
}
return result;
}
IPv6Address IPv6Address::operator~() const {
IPv6Address result = *this;
for (IPv6Address::iterator addr_iter = result.begin(); addr_iter != result.end(); ++addr_iter) {
*addr_iter = ~*addr_iter;
}
return result;
}
} // Tins

View File

@@ -257,6 +257,35 @@ NetworkInterface::NetworkInterface(IPv4Address ip)
}
}
NetworkInterface::NetworkInterface(IPv6Address ipv6)
: iface_id_(0) {
typedef vector<Utils::Route6Entry> entries_type;
if (ipv6 == "::1") {
#if defined(BSD) || defined(__FreeBSD_kernel__)
iface_id_ = resolve_index("lo0");
#else
iface_id_ = resolve_index("lo");
#endif
}
else {
const Utils::Route6Entry* best_match = 0;
entries_type entries;
Utils::route6_entries(std::back_inserter(entries));
for (entries_type::const_iterator it(entries.begin()); it != entries.end(); ++it) {
if ((ipv6 & it->mask) == it->destination) {
if (!best_match || it->mask > best_match->mask || it->metric < best_match->metric) {
best_match = &*it;
}
}
}
if (!best_match) {
throw invalid_interface();
}
iface_id_ = resolve_index(best_match->interface.c_str());
}
}
string NetworkInterface::name() const {
#ifndef _WIN32
char iface_name[IF_NAMESIZE];

View File

@@ -108,6 +108,7 @@ PacketSender::PacketSender(const NetworkInterface& iface,
types_[IP_RAW_SOCKET] = IPPROTO_RAW;
types_[IPV6_SOCKET] = IPPROTO_RAW;
types_[ICMP_SOCKET] = IPPROTO_ICMP;
types_[ICMPV6_SOCKET] = IPPROTO_ICMPV6;
}
PacketSender::~PacketSender() {
@@ -251,8 +252,9 @@ void PacketSender::open_l3_socket(SocketType type) {
throw invalid_socket_type();
}
if (sockets_[type] == INVALID_RAW_SOCKET) {
const bool is_v6 = (type == IPV6_SOCKET || type == ICMPV6_SOCKET);
socket_type sockfd;
sockfd = socket((type == IPV6_SOCKET) ? AF_INET6 : AF_INET, SOCK_RAW, socktype);
sockfd = socket(is_v6 ? AF_INET6 : AF_INET, SOCK_RAW, socktype);
if (sockfd < 0) {
throw socket_open_error(make_error_string());
}
@@ -263,7 +265,7 @@ void PacketSender::open_l3_socket(SocketType type) {
#else
typedef const char* option_ptr;
#endif
const int level = (type == IPV6_SOCKET) ? IPPROTO_IPV6 : IPPROTO_IP;
const int level = (is_v6) ? IPPROTO_IPV6 : IPPROTO_IP;
if (setsockopt(sockfd, level, IP_HDRINCL, (option_ptr)&on, sizeof(on)) != 0) {
throw socket_open_error(make_error_string());
}

View File

@@ -224,7 +224,7 @@ void BaseSniffer::set_extract_raw_pdus(bool value) {
}
void BaseSniffer::set_pcap_sniffing_method(PcapSniffingMethod method) {
if (method == nullptr) {
if (method == 0) {
throw std::runtime_error("Sniffing method cannot be null");
}
pcap_sniffing_method_ = method;

View File

@@ -81,7 +81,11 @@ TCP::TCP(const uint8_t* buffer, uint32_t total_sz) {
while (stream.pointer() < header_end) {
const OptionTypes option_type = (OptionTypes)stream.read<uint8_t>();
if (option_type <= NOP) {
if (option_type == EOL) {
stream.skip(header_end - stream.pointer());
break;
}
else if (option_type == NOP) {
#if TINS_IS_CXX11
add_option(option_type, 0);
#else
@@ -309,7 +313,7 @@ void TCP::write_serialization(uint8_t* buffer, uint32_t total_sz) {
if (options_size < total_options_size) {
const uint16_t padding = total_options_size - options_size;
stream.fill(padding, 1);
stream.fill(padding, 0);
}
uint32_t check = 0;

View File

@@ -81,6 +81,7 @@ string to_string(PDU::PDUType pduType) {
ENUM_TEXT(ICMPv6);
ENUM_TEXT(SLL);
ENUM_TEXT(DHCPv6);
ENUM_TEXT(DOT1AD);
ENUM_TEXT(DOT1Q);
ENUM_TEXT(PPPOE);
ENUM_TEXT(STP);

View File

@@ -233,7 +233,7 @@ bool RadioTapParser::skip_to_field(RadioTap::PresentFlags flag) {
}
bool RadioTapParser::has_fields() const {
return current_bit_ != MAX_RADIOTAP_FIELD;
return current_bit_ != MAX_RADIOTAP_FIELD && current_ptr_ < end_;
}
bool RadioTapParser::has_field(RadioTap::PresentFlags flag) const {

View File

@@ -439,5 +439,17 @@ bool gateway_from_ip(IPv4Address ip, IPv4Address& gw_addr) {
return false;
}
bool gateway_from_ip(IPv6Address ip, IPv6Address& gw_addr) {
typedef vector<Route6Entry> entries_type;
entries_type entries =route6_entries();
for (entries_type::const_iterator it(entries.begin()); it != entries.end(); ++it) {
if ((ip & it->mask) == it->destination) {
gw_addr = it->gateway;
return true;
}
}
return false;
}
} // Utils
} // Tins

View File

@@ -58,6 +58,17 @@ TEST_F(Dot1QTest, Serialize) {
);
}
TEST_F(Dot1QTest, SerializeCraftedPacket)
{
EthernetII pkt = EthernetII() / Dot1Q(10) / IP("192.168.1.2") / TCP(23, 45) / RawPDU("asdasdasd");
PDU::serialization_type buffer = pkt.serialize();
EXPECT_EQ(buffer[12], 0x81);
EXPECT_EQ(buffer[13], 0x00);
EthernetII pkt2(&buffer[0], buffer.size());
const Dot1Q &q1 = pkt2.rfind_pdu<Dot1Q>();
EXPECT_EQ(10, q1.id());
}
TEST_F(Dot1QTest, PayloadType) {
Dot1Q dot1;
dot1.payload_type(0x9283);
@@ -86,6 +97,12 @@ TEST_F(Dot1QTest, QinQ) {
EthernetII pkt = EthernetII() / Dot1Q(10) / Dot1Q(42) / IP("192.168.1.2") /
TCP(23, 45) / RawPDU("asdasdasd");
PDU::serialization_type buffer = pkt.serialize();
// First PID of the serialized packet should be Dot1AD = 0x88a8
EXPECT_EQ(buffer[12], 0x88);
EXPECT_EQ(buffer[13], 0xa8);
// Second PID of the serialized packet chouls be Dot1Q = 0x8100
EXPECT_EQ(buffer[16], 0x81);
EXPECT_EQ(buffer[17], 0x00);
EthernetII pkt2(&buffer[0], buffer.size());
const Dot1Q& q1 = pkt2.rfind_pdu<Dot1Q>();
ASSERT_TRUE(q1.inner_pdu() != NULL);

View File

@@ -52,6 +52,7 @@ TEST_F(HWAddressTest, LessThanOperator) {
HWAddress<6> bcast = "ff:ff:ff:ff:ff:ff";
EXPECT_LT(addr2, addr1);
EXPECT_LT(addr2, bcast);
EXPECT_LE(addr1, addr1);
std::map<HWAddress<6>, int> dict;
dict[addr1] = 12;
dict[addr2] = 15;
@@ -59,6 +60,20 @@ TEST_F(HWAddressTest, LessThanOperator) {
EXPECT_EQ(dict[addr2], 15);
}
TEST_F(HWAddressTest, GreaterThanOperator) {
HWAddress<6> addr1(byte_address), addr2(empty_addr);
HWAddress<6> bcast = "ff:ff:ff:ff:ff:ff";
EXPECT_GT(addr1, addr2);
EXPECT_GT(bcast, addr2);
EXPECT_GE(addr1, addr1);
std::map<HWAddress<6>, int> dict;
dict[addr1] = 12;
dict[addr2] = 15;
EXPECT_EQ(dict[addr1], 12);
EXPECT_EQ(dict[addr2], 15);
}
TEST_F(HWAddressTest, CopyConstructor) {
HWAddress<6> addr1(byte_address), addr2(addr1);
@@ -115,3 +130,18 @@ TEST_F(HWAddressTest, Mask) {
address_type("de:ad:be:ef:00:00") & address_type("ff:ff:ff:f0:00:00")
);
}
TEST_F(HWAddressTest, OrMask) {
typedef HWAddress<6> address_type;
EXPECT_EQ(
address_type("ff:ff:ff:ff:fe:be"),
address_type("de:ad:be:ef:fe:be") | address_type("ff:ff:ff:f0:00:00")
);
}
TEST_F(HWAddressTest, NotMask) {
typedef HWAddress<6> address_type;
EXPECT_EQ(
address_type("00:00:00:0f:ff:ff"), ~address_type("ff:ff:ff:f0:00:00")
);
}

View File

@@ -47,8 +47,19 @@ TEST(IPAddressTest, LessThanOperator) {
EXPECT_LT(addr1, "192.168.1.2");
EXPECT_LT(addr1, "192.168.0.226");
EXPECT_LT(addr1, "193.0.0.0");
EXPECT_LE(addr1, addr2);
}
TEST(IPAddressTest, GreaterThanOperator) {
IPv4Address addr1(ip_string), addr2(ip_string);
EXPECT_FALSE(addr1 < addr2);
EXPECT_GT(addr1, "192.167.1.2");
EXPECT_GT(addr1, "192.167.0.226");
EXPECT_GT(addr1, "191.0.0.0");
EXPECT_GE(addr1, addr2);
}
TEST(IPAddressTest, IsPrivate) {
EXPECT_TRUE(IPv4Address("192.168.0.1").is_private());
EXPECT_TRUE(IPv4Address("192.168.133.7").is_private());
@@ -112,6 +123,26 @@ TEST(IPAddressTest, Mask) {
);
}
TEST(IPAddressTest, OrMask) {
EXPECT_EQ(
IPv4Address("255.255.255.1"),
IPv4Address("192.168.100.1") | IPv4Address("255.255.255.0")
);
EXPECT_EQ(
IPv4Address("255.255.1.2"),
IPv4Address("192.255.1.2") | IPv4Address("255.128.0.0")
);
}
TEST(IPAddressTest, NotMask) {
EXPECT_EQ(
IPv4Address("0.0.0.255"), ~IPv4Address("255.255.255.0")
);
EXPECT_EQ(
IPv4Address("0.127.255.255"),~IPv4Address("255.128.0.0")
);
}
TEST(IPv4AddressTest, Size) {
EXPECT_EQ(4UL, IPv4Address("127.0.0.1").size());
EXPECT_EQ(4UL, IPv4Address().size());

View File

@@ -23,7 +23,8 @@ using namespace Tins;
class IPTest : public testing::Test {
public:
static const uint8_t expected_packet[], fragmented_packet[],
fragmented_ether_ip_packet[], tot_len_zero_packet[];
fragmented_ether_ip_packet[], tot_len_zero_packet[],
options_packet[];
void test_equals(const IP& ip1, const IP& ip2);
void test_overwrite_source_address(IP& ip);
@@ -450,6 +451,26 @@ const uint8_t IPTest::tot_len_zero_packet[] = {
, 0, 0, 0, 0, 0
};
const uint8_t IPTest::options_packet[] = {
0, 160, 204, 59, 191, 250, 16, 54, 233, 241, 145, 224, 8, 0, 72, 0,
0, 242, 0, 1, 0, 0, 128, 17, 233, 177, 192, 168, 0, 4, 220, 113,
61, 150, 130, 11, 0, 16, 0, 0, 0, 0, 120, 120, 120, 0, 143, 243,
26, 48, 0, 210, 82, 251, 92, 3, 98, 243, 14, 149, 245, 46, 106,
244, 99, 187, 143, 32, 82, 21, 116, 83, 205, 114, 68, 236, 121, 23,
98, 220, 15, 75, 139, 145, 57, 154, 24, 92, 35, 84, 179, 123, 191,
141, 122, 43, 42, 172, 212, 85, 117, 54, 227, 157, 155, 192, 52,
206, 57, 242, 150, 236, 164, 202, 143, 4, 3, 200, 56, 106, 36, 202,
38, 4, 12, 29, 108, 72, 89, 23, 180, 94, 81, 238, 41, 84, 146, 126,
185, 84, 104, 249, 166, 43, 188, 14, 141, 89, 245, 254, 222, 236,
173, 140, 121, 146, 77, 14, 132, 36, 8, 113, 162, 92, 174, 188,
214, 148, 64, 227, 220, 34, 193, 139, 234, 144, 213, 89, 74, 95,
177, 180, 145, 26, 248, 29, 238, 146, 249, 247, 75, 26, 155, 36, 8,
188, 34, 176, 73, 92, 242, 194, 185, 67, 67, 214, 235, 137, 67,
158, 144, 27, 235, 221, 252, 44, 227, 25, 229, 172, 166, 214, 6, 6,
136, 21, 173, 84, 20, 109, 140, 182, 114, 179, 167, 196, 250, 56,
169, 152, 160, 18, 136, 245, 138, 101, 177, 107, 121, 74, 204, 180,
193, 228, 135, 37
};
TEST_F(IPTest, DefaultConstructor) {
IP ip;
@@ -854,3 +875,11 @@ TEST_F(IPTest, SerializeAfterInnerPduRemoved) {
EthernetII eth2(&buffer[0], buffer.size());
EXPECT_EQ(eth1.size(), eth2.size());
}
TEST_F(IPTest, ParseSerializeOptions) {
EthernetII packet(options_packet, sizeof(options_packet));
PDU::serialization_type serialized = packet.serialize();
const vector<uint8_t> buffer(options_packet, options_packet + sizeof(options_packet));
EXPECT_EQ(buffer, serialized);
}

View File

@@ -70,6 +70,14 @@ TEST(IPv6AddressTest, LessThanOperator) {
EXPECT_LT(IPv6Address("17f8::1"), IPv6Address("17f8:0::0:5"));
EXPECT_LT(IPv6Address("::1"), IPv6Address("::5"));
EXPECT_LT(IPv6Address("1::"), IPv6Address("2::"));
EXPECT_LE(IPv6Address("1::"), IPv6Address("1::"));
}
TEST(IPv6AddressTest, GreaterThanOperator) {
EXPECT_GT(IPv6Address("17f8:0::0:5"), IPv6Address("17f8::1"));
EXPECT_GT(IPv6Address("::5"), IPv6Address("::1"));
EXPECT_GT(IPv6Address("2::"), IPv6Address("1::"));
EXPECT_GE(IPv6Address("2::"), IPv6Address("2::"));
}
TEST(IPv6AddressTest, OutputOperator) {
@@ -124,6 +132,33 @@ TEST(IPv6AddressTest, MaskAddress) {
);
}
TEST(IPv6AddressTest, OrMaskAddress) {
EXPECT_EQ(
IPv6Address("ffff:ffff:adad:beef::"),
IPv6Address("deaf:beef:adad:beef::") | IPv6Address("ffff:ffff::")
);
EXPECT_EQ(
IPv6Address("ffff:ffef:adad:beef::"),
IPv6Address("deaf:beef:adad:beef::") | IPv6Address("ffff:ff00::")
);
EXPECT_EQ(
IPv6Address("ffff:feef:adad:beef::"),
IPv6Address("deaf:beef:adad:beef::") | IPv6Address("ffff:f000::")
);
EXPECT_EQ(
IPv6Address("ffff:feef:adad:beef::"),
IPv6Address("deaf:beef:adad:beef::") | IPv6Address("ffff:e000::")
);
}
TEST(IPv6AddressTest, NotMaskAddress) {
EXPECT_EQ(IPv6Address("::ffff:ffff:ffff:ffff:ffff:ffff"),~IPv6Address("ffff:ffff::"));
EXPECT_EQ(IPv6Address("::ff:ffff:ffff:ffff:ffff:ffff"),~IPv6Address("ffff:ffff:ff00::"));
EXPECT_EQ(IPv6Address("::fff:ffff:ffff:ffff:ffff:ffff"),~IPv6Address("ffff:ffff:f000::"));
EXPECT_EQ(IPv6Address("::1fff:ffff:ffff:ffff:ffff:ffff"),~IPv6Address("ffff:ffff:e000::"));
}
TEST(IPv6AddressTest, Size) {
EXPECT_EQ(16UL, IPv6Address("dead:beef::1").size());
EXPECT_EQ(16UL, IPv6Address().size());

View File

@@ -360,3 +360,63 @@ TEST_F(IPv6Test, OptionAddition) {
EXPECT_TRUE(ipv6.search_header(IPv6::ROUTING) != 0);
EXPECT_TRUE(ipv6.search_header(IPv6::AUTHENTICATION) != 0);
}
TEST_F(IPv6Test, HopByHopPadding) {
IPv6 ipv6_header;
ipv6_header.add_header(IPv6::ExtensionHeader::HOP_BY_HOP);
EXPECT_EQ(48UL, ipv6_header.serialize().size());
}
TEST_F(IPv6Test, HopByHopParsing) {
EthernetII pkt(hop_by_hop_options, sizeof(hop_by_hop_options));
IPv6& ipv6 = pkt.rfind_pdu<IPv6>();
const IPv6::headers_type& headers = ipv6.headers();
EXPECT_EQ(1UL, headers.size());
const IPv6::ext_header* ext_header = ipv6.search_header(IPv6::ExtensionHeader::HOP_BY_HOP);
EXPECT_TRUE(ext_header != NULL);
const IPv6::hop_by_hop_header hbh_header = IPv6::hop_by_hop_header::from_extension_header(*ext_header);
EXPECT_EQ(1UL, hbh_header.options.size());
EXPECT_EQ(5, hbh_header.options[0].first);
}
TEST_F(IPv6Test, HopByHopExtensionHeader) {
const uint8_t options[] = {42, 3, 0, 0, 0, 86, 0, 17, 2, 0, 0, 1, 2, 0, 0};
IPv6::ext_header hdr(IPv6::HOP_BY_HOP, options, options + sizeof(options));
IPv6::hop_by_hop_header header = IPv6::hop_by_hop_header::from_extension_header(hdr);
EXPECT_EQ(3UL, header.options.size());
EXPECT_EQ(42, header.options[0].first);
EXPECT_EQ(86, header.options[1].first);
EXPECT_EQ(17, header.options[2].first);
}
TEST_F(IPv6Test, DestinationRoutingExtensionHeader) {
EXPECT_THROW(IPv6::destination_routing_header::from_extension_header(IPv6::HOP_BY_HOP),
invalid_ipv6_extension_header);
IPv6::destination_routing_header header = IPv6::destination_routing_header::from_extension_header(IPv6::DESTINATION_ROUTING_OPTIONS);
EXPECT_EQ(0UL, header.options.size());
}
TEST_F(IPv6Test, RoutingExtensionHeader) {
const uint8_t header_data[] = {42, 17, 0, 0, 0, 0, 0};
IPv6::ext_header hdr(IPv6::ROUTING, header_data, header_data + sizeof(header_data));
IPv6::routing_header header = IPv6::routing_header::from_extension_header(hdr);
EXPECT_EQ(42, header.routing_type);
EXPECT_EQ(17, header.segments_left);
EXPECT_EQ(5UL, header.data.size());
}
TEST_F(IPv6Test, FragmentExtensionHeader) {
const uint8_t header_data[] = {128, 1, 0, 0, 0, 42};
IPv6::ext_header hdr(IPv6::FRAGMENT, header_data, header_data + sizeof(header_data));
IPv6::fragment_header header = IPv6::fragment_header::from_extension_header(hdr);
EXPECT_EQ(4096, header.fragment_offset);
EXPECT_TRUE(header.more_fragments);
EXPECT_EQ(42UL, header.identification);
}

View File

@@ -37,6 +37,8 @@ TEST_F(NetworkInterfaceTest, ConstructorFromString) {
TEST_F(NetworkInterfaceTest, ConstructorFromIp) {
NetworkInterface iface(IPv4Address("127.0.0.1"));
EXPECT_EQ(iface.name(), iface_name);
NetworkInterface i6face(IPv6Address("::1"));
EXPECT_EQ(i6face.name(), iface_name);
}
TEST_F(NetworkInterfaceTest, Id) {

View File

@@ -83,6 +83,14 @@ TEST_F(PDUTest, OperatorConcatOnPacket) {
EXPECT_TRUE(std::equal(raw->payload().begin(), raw->payload().end(), raw_payload.begin()));
}
#if TINS_IS_CXX11
TEST_F(PDUTest, MoveAssignment) {
IP packet = IP("192.168.0.1") / TCP(22, 52);
packet = IP("1.2.3.4");
EXPECT_TRUE(packet.inner_pdu() == 0);
}
#endif // TINS_IS_CXX11
TEST_F(PDUTest, TinsCast) {
PDU* null_pdu = 0;
TCP tcp;

View File

@@ -25,7 +25,7 @@ public:
static const uint8_t expected_packet[], expected_packet1[],
expected_packet2[], expected_packet3[],
expected_packet4[], expected_packet5[],
expected_packet6[];
expected_packet6[], expected_packet7[];
};
const uint8_t RadioTapTest::expected_packet[] = {
@@ -324,6 +324,57 @@ const uint8_t RadioTapTest::expected_packet6[] = {
164, 143, 87, 89, 97, 79, 145, 16, 48, 248, 198, 140, 48
};
const uint8_t RadioTapTest::expected_packet7[] = {
0, 255, 255, 0, 0, 240, 96, 235, 105, 143, 60, 180, 134, 221, 96,
0, 0, 0, 2, 164, 17, 64, 50, 73, 237, 197, 18, 75, 232, 197, 18,
72, 232, 197, 18, 72, 232, 71, 50, 73, 237, 125, 18, 75, 249, 195,
18, 72, 232, 197, 18, 239, 232, 197, 169, 236, 43, 206, 48, 166, 9,
84, 151, 88, 20, 229, 233, 39, 55, 108, 16, 104, 206, 107, 0, 53,
186, 70, 2, 164, 18, 0, 44, 150, 132, 3, 0, 1, 0, 0, 0, 6, 0, 1,
12, 67, 79, 56, 48, 49, 77, 49, 56, 48, 49, 57, 49, 13, 97, 122,
99, 111, 114, 114, 101, 99, 116, 105, 111, 110, 115, 5, 108, 111,
99, 97, 108, 0, 0, 6, 0, 1, 0, 0, 6, 0, 1, 0, 1, 81, 128, 0, 64, 1,
97, 12, 114, 111, 111, 116, 45, 115, 101, 114, 118, 101, 114, 115,
3, 110, 101, 116, 0, 5, 110, 115, 116, 108, 100, 12, 118, 101, 114,
105, 115, 105, 103, 110, 45, 103, 114, 115, 3, 99, 111, 109, 0,
120, 42, 86, 53, 0, 0, 7, 8, 0, 0, 3, 132, 0, 9, 58, 128, 0, 1, 81,
128, 5, 108, 111, 97, 110, 115, 0, 0, 47, 0, 1, 0, 1, 81, 128, 0,
15, 5, 108, 111, 99, 117, 115, 0, 0, 6, 32, 0, 0, 0, 0, 19, 0, 0,
47, 0, 1, 0, 1, 81, 128, 0, 14, 3, 97, 97, 97, 0, 0, 7, 26, 0, 0,
0, 0, 3, 128, 0, 0, 46, 0, 1, 0, 1, 81, 128, 0, 147, 0, 6, 8, 0, 0,
1, 81, 128, 87, 17, 30, 16, 87, 3, 225, 0, 236, 199, 0, 23, 89,
103, 40, 110, 160, 29, 93, 75, 23, 152, 78, 76, 255, 197, 241, 39,
189, 75, 31, 226, 166, 224, 55, 9, 100, 96, 27, 180, 130, 25, 199,
101, 176, 122, 115, 169, 75, 199, 174, 203, 181, 165, 16, 159, 111,
84, 166, 162, 242, 43, 255, 148, 16, 118, 212, 144, 118, 67, 113,
59, 31, 224, 181, 103, 41, 238, 3, 174, 153, 106, 80, 171, 124,
162, 186, 167, 108, 66, 140, 244, 97, 170, 127, 170, 252, 124, 139,
246, 150, 166, 208, 191, 15, 64, 250, 217, 195, 6, 39, 246, 71,
204, 248, 143, 71, 121, 44, 149, 98, 145, 203, 102, 74, 220, 240,
180, 8, 218, 171, 76, 194, 62, 241, 85, 94, 72, 28, 192, 125, 0,
46, 0, 30, 0, 1, 81, 128, 0, 147, 0, 47, 8, 1, 0, 1, 81, 128, 87,
17, 30, 16, 87, 3, 225, 0, 236, 199, 0, 159, 85, 2, 138, 56, 31,
91, 69, 9, 81, 254, 59, 65, 14, 76, 208, 107, 158, 159, 118, 92,
38, 52, 210, 139, 201, 40, 32, 135, 48, 252, 254, 64, 135, 97, 24,
253, 193, 114, 103, 214, 39, 14, 218, 50, 22, 60, 15, 208, 85, 152,
119, 21, 169, 236, 43, 206, 48, 166, 9, 84, 151, 88, 20, 229, 233,
39, 55, 108, 83, 104, 206, 107, 253, 252, 203, 24, 90, 216, 48,
191, 44, 38, 161, 228, 97, 84, 197, 138, 7, 206, 54, 244, 52, 153,
26, 232, 221, 182, 130, 29, 57, 193, 218, 124, 99, 68, 78, 161,
113, 120, 4, 155, 62, 94, 21, 89, 212, 33, 122, 42, 72, 5, 42, 172,
87, 70, 122, 0, 0, 46, 0, 1, 0, 1, 81, 128, 0, 147, 0, 47, 8, 0, 0,
1, 81, 128, 87, 17, 30, 16, 87, 3, 225, 0, 236, 199, 0, 131, 10,
126, 206, 35, 167, 184, 76, 112, 237, 170, 253, 123, 131, 162, 186,
243, 100, 237, 217, 17, 187, 90, 115, 28, 62, 89, 112, 69, 16, 227,
159, 162, 42, 212, 216, 246, 149, 118, 20, 105, 70, 196, 64, 48,
65, 216, 187, 25, 142, 138, 171, 229, 5, 251, 167, 181, 93, 62, 78,
204, 130, 147, 131, 168, 13, 120, 116, 115, 115, 107, 98, 53, 113,
111, 110, 56, 115, 110, 9, 95, 107, 101, 114, 98, 101, 114, 111,
115, 4, 95, 116, 99, 243, 21, 33, 14, 178, 86, 218, 241, 92, 120,
80, 120, 138, 155, 39, 74, 89, 32, 154, 143, 135, 103, 206, 121,
227, 234
};
TEST_F(RadioTapTest, DefaultConstructor) {
RadioTap radio;
EXPECT_TRUE((radio.flags() & RadioTap::FCS) != 0);
@@ -437,6 +488,10 @@ TEST_F(RadioTapTest, ConstructorFromBuffer5) {
EXPECT_EQ(0x05, radio.mcs().mcs);
}
TEST_F(RadioTapTest, ConstructorFromBuffer6) {
EXPECT_THROW(RadioTap(expected_packet7, sizeof(expected_packet7)), malformed_packet);
}
TEST_F(RadioTapTest, Serialize) {
RadioTap radio(expected_packet, sizeof(expected_packet));
RadioTap::serialization_type buffer = radio.serialize();

View File

@@ -13,7 +13,8 @@ using namespace Tins;
class TCPTest : public testing::Test {
public:
static const uint8_t expected_packet[], checksum_packet[],
partial_packet[];
partial_packet[],
malformed_option_after_eol_packet[];
void test_equals(const TCP& tcp1, const TCP& tcp2);
};
@@ -36,6 +37,11 @@ const uint8_t TCPTest::partial_packet[] = {
142, 210, 0, 80, 60, 158, 102, 111, 10, 2, 46, 161, 80, 24, 0, 229, 247, 192, 0, 0
};
const uint8_t TCPTest::malformed_option_after_eol_packet[] = {
127, 77, 79, 29, 241, 218, 229, 70, 95, 174, 209, 35, 96, 2, 113,
218, 0, 0, 31, 174, 0, 1, 2, 4
};
TEST_F(TCPTest, DefaultConstructor) {
TCP tcp;
@@ -271,6 +277,11 @@ TEST_F(TCPTest, SpoofedOptions) {
EXPECT_EQ(pdu.serialize().size(), pdu.size());
}
TEST_F(TCPTest, MalformedOptionAfterEOL) {
TCP tcp(malformed_option_after_eol_packet, sizeof(malformed_option_after_eol_packet));
EXPECT_EQ(0U, tcp.options().size());
}
TEST_F(TCPTest, RemoveOption) {
TCP tcp(22, 987);
uint8_t a[] = { 1,2,3,4,5,6 };