mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 10:45:57 +01:00
Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5e52091ecf | ||
|
|
dafb299ea3 | ||
|
|
659bec56d7 | ||
|
|
8c1bea6f84 | ||
|
|
d8d1dc003b | ||
|
|
c2bb52b82f | ||
|
|
1f5456b18b | ||
|
|
dc702f4fd6 | ||
|
|
2a8101eef3 | ||
|
|
20702ddaff | ||
|
|
f4e2701705 | ||
|
|
776ae4e83b | ||
|
|
2158c7a92e | ||
|
|
b53bad7b29 | ||
|
|
6c92bcdad1 | ||
|
|
b949e56d15 | ||
|
|
18ff3e7b6a | ||
|
|
559b1fb89a | ||
|
|
1e78ef0752 | ||
|
|
602ada7820 | ||
|
|
57ac099703 | ||
|
|
eb7628eca4 | ||
|
|
c26e4943c2 | ||
|
|
7e90c8be6a | ||
|
|
3659d89c25 | ||
|
|
db992d42e5 | ||
|
|
5571a270d4 | ||
|
|
b18c2cefec | ||
|
|
3f204321ce | ||
|
|
63603b8ac8 | ||
|
|
fa79582b89 | ||
|
|
342e2c77a7 | ||
|
|
7848e28b62 | ||
|
|
544aa1b339 | ||
|
|
de4791f0c7 | ||
|
|
915f506f3a | ||
|
|
f29566d6d9 | ||
|
|
e4f747164c | ||
|
|
683550b297 | ||
|
|
971fdf7d1c | ||
|
|
1038c6f7f3 | ||
|
|
8efc0271f5 | ||
|
|
9ac5e597e6 | ||
|
|
f7fc5fae1d | ||
|
|
f44b253a42 | ||
|
|
8f85a6e557 |
54
CHANGES.md
54
CHANGES.md
@@ -1,3 +1,57 @@
|
||||
##### v4.2 - Fri Mar 8 04:15:13 UTC 2019
|
||||
|
||||
- Updated location of installed CMake files in unix systems (#331)
|
||||
|
||||
- Fix check to detect cross compilation (#330)
|
||||
|
||||
- Allow getting a PDU's advertised size and use it in `PacketWriter` (#324)
|
||||
|
||||
- Install DLLs in right directory (#326)
|
||||
|
||||
- Add missing Dot11 tagged option types (#305)
|
||||
|
||||
- Add support for DLT_RAW (#313)
|
||||
|
||||
- Fix potential invalid memory accesses when parsing RadioTap (#322)
|
||||
|
||||
##### 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.
|
||||
|
||||
@@ -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 2)
|
||||
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,22 @@ 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()
|
||||
IF (NOT CMAKE_INSTALL_BINDIR)
|
||||
SET(CMAKE_INSTALL_BINDIR bin)
|
||||
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})
|
||||
@@ -306,6 +311,12 @@ ENDIF()
|
||||
# CMake project configuration export
|
||||
# **********************************
|
||||
|
||||
if(UNIX)
|
||||
set(CONF_CMAKE_INSTALL_DIR lib/cmake/libtins)
|
||||
else()
|
||||
set(CONF_CMAKE_INSTALL_DIR CMake)
|
||||
endif()
|
||||
|
||||
# Add all targets to the build-tree export set
|
||||
EXPORT(
|
||||
TARGETS tins
|
||||
@@ -332,13 +343,13 @@ INSTALL(
|
||||
FILES
|
||||
"${PROJECT_BINARY_DIR}/libtinsConfig.cmake"
|
||||
"${PROJECT_BINARY_DIR}/libtinsConfigVersion.cmake"
|
||||
DESTINATION CMake
|
||||
DESTINATION ${CONF_CMAKE_INSTALL_DIR}
|
||||
COMPONENT dev
|
||||
)
|
||||
|
||||
# Install the export set for use with the install-tree
|
||||
INSTALL(
|
||||
EXPORT libtinsTargets
|
||||
DESTINATION CMake
|
||||
DESTINATION ${CONF_CMAKE_INSTALL_DIR}
|
||||
COMPONENT dev
|
||||
)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -79,14 +79,14 @@ function(cxx11_check_feature FEATURE_NAME RESULT_VAR)
|
||||
set(_SRCFILE_FAIL "${_SRCFILE_BASE}_fail.cpp")
|
||||
set(_SRCFILE_FAIL_COMPILE "${_SRCFILE_BASE}_fail_compile.cpp")
|
||||
|
||||
if (CROSS_COMPILING)
|
||||
if (CMAKE_CROSSCOMPILING)
|
||||
try_compile(${RESULT_VAR} "${_bindir}" "${_SRCFILE}"
|
||||
COMPILE_DEFINITIONS "${CXX11_COMPILER_FLAGS}")
|
||||
if (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||
try_compile(${RESULT_VAR} "${_bindir}_fail" "${_SRCFILE_FAIL}"
|
||||
COMPILE_DEFINITIONS "${CXX11_COMPILER_FLAGS}")
|
||||
endif (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||
else (CROSS_COMPILING)
|
||||
else (CMAKE_CROSSCOMPILING)
|
||||
try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
|
||||
"${_bindir}" "${_SRCFILE}"
|
||||
COMPILE_DEFINITIONS "${CXX11_COMPILER_FLAGS}")
|
||||
@@ -105,7 +105,7 @@ function(cxx11_check_feature FEATURE_NAME RESULT_VAR)
|
||||
set(${RESULT_VAR} FALSE)
|
||||
endif (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
|
||||
endif (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||
endif (CROSS_COMPILING)
|
||||
endif (CMAKE_CROSSCOMPILING)
|
||||
if (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL_COMPILE})
|
||||
try_compile(_TMP_RESULT "${_bindir}_fail_compile" "${_SRCFILE_FAIL_COMPILE}"
|
||||
COMPILE_DEFINITIONS "${CXX11_COMPILER_FLAGS}")
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -41,6 +41,7 @@ class Dot3;
|
||||
class SLL;
|
||||
class Loopback;
|
||||
class PPI;
|
||||
class IP;
|
||||
|
||||
/**
|
||||
* \struct DataLinkType
|
||||
@@ -73,6 +74,7 @@ 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)
|
||||
TINS_MAKE_DATA_LINK_TYPE(IP, DLT_RAW)
|
||||
|
||||
#undef TINS_MAKE_DATA_LINK_TYPE
|
||||
|
||||
|
||||
@@ -127,9 +127,148 @@ public:
|
||||
ERP_INFORMATION,
|
||||
TS_DELAY,
|
||||
TCLAS_PROCESSING,
|
||||
QOS_CAPABILITY = 46,
|
||||
HT_CAPABILITY,
|
||||
QOS_CAPABILITY,
|
||||
RSN = 48,
|
||||
EXT_SUPPORTED_RATES = 50,
|
||||
AP_CHANNEL_REPORT,
|
||||
NEIGHBOR_REPORT,
|
||||
RCPI,
|
||||
MOBILITY_DOMAIN_MDE,
|
||||
FAST_BSS_TRANSITION_FTE,
|
||||
TIMEOUT_INTERVAL,
|
||||
RIC_DATA_RDE,
|
||||
DSE_REG_LOC,
|
||||
SUPPORTED_OP_CLASSES,
|
||||
EXT_CH_SWITCH_ANNOUNCEMENT,
|
||||
HT_OPERATION,
|
||||
SEC_CH_OFFSET,
|
||||
BSS_AVG_ACCESS_DELAY,
|
||||
ANTENNA,
|
||||
RSNI,
|
||||
MEASUREMENT_PILOT_TRANSMISSION,
|
||||
BSS_AVAIL_ADMISSION_CAPACITY,
|
||||
BSS_AC_ACCESS_DELAY,
|
||||
TIME_ADVERTISEMENT,
|
||||
RM_ENABLED_CAP,
|
||||
MULTIPLE_BSSID,
|
||||
BSS_2040_COEX,
|
||||
BSS_2040_INTOLERANT_CH_REPORT,
|
||||
OVERLAPPING_BSS_SCAN_PARAM,
|
||||
RIC_DESCRIPTOR,
|
||||
MGMT_MIC,
|
||||
EVENT_REQ = 78,
|
||||
EVENT_REPORT,
|
||||
DIAG_REQ,
|
||||
DIAG_REPORT,
|
||||
LOCATION_PARAMS,
|
||||
NONTRANSMITTED_BSSID_CAP,
|
||||
SSID_LIST,
|
||||
MULTIPLE_BSSID_INDEX,
|
||||
FMS_DESCRIPTOR,
|
||||
FMS_REQ,
|
||||
FMS_RESP,
|
||||
QOS_TRAFFIC_CAP,
|
||||
BSS_MAX_IDLE_PERIOD,
|
||||
TFS_REQ,
|
||||
TFS_RESP,
|
||||
WNM_SLEEP_MODE,
|
||||
TIM_BROADCAST_REQ,
|
||||
TIM_BROADCAST_RESP,
|
||||
COLLOCATED_INTERFERENCE_REPORT,
|
||||
CH_USAGE,
|
||||
TIME_ZONE,
|
||||
DMS_REQ,
|
||||
DMS_RESP,
|
||||
LINK_ID,
|
||||
WAKEUP_SCHEDULE,
|
||||
CH_SWITCH_TIMING,
|
||||
PTI_CONTROL,
|
||||
TPU_BUFFER_STATUS,
|
||||
INTERWORKING,
|
||||
ADVERTISEMENT_PROTOCOL,
|
||||
EXPEDITED_BANDWIDTH_REQ,
|
||||
QOS_MAP,
|
||||
ROAMING_CONSORTIUM,
|
||||
EMERG_ALERT_ID,
|
||||
MESH_CONFIG,
|
||||
MESH_ID,
|
||||
MESH_LINK_METRIC_REPORT,
|
||||
CONGESTION_NOTIFICATION,
|
||||
MESH_PEERING_MGMT,
|
||||
MESH_CH_SWITCH_PARAMS,
|
||||
MESH_AWAKE_WINDOW,
|
||||
BEACON_TIMING,
|
||||
MCCAOP_SETUP_REQ,
|
||||
MCCAOP_SETUP_REPLY,
|
||||
MCCAOP_ADVERTISEMENT,
|
||||
MCCAOP_TEARDOWN,
|
||||
GANN,
|
||||
RANN,
|
||||
EXT_CAP,
|
||||
PREQ = 130,
|
||||
PREP,
|
||||
PERR,
|
||||
PXU = 137,
|
||||
PXUC,
|
||||
AUTH_MESH_PEER_EX,
|
||||
MIC,
|
||||
DEST_URI,
|
||||
UAPSD_COEX,
|
||||
DMG_WAKEUP_SCHEDULE,
|
||||
EXT_SCHEDULE,
|
||||
STA_AVAIL,
|
||||
DMG_TSPEC,
|
||||
NEXT_DMG_ATI,
|
||||
DMG_CAP,
|
||||
DMG_OP = 151,
|
||||
DMG_BSS_PARAM_CHG,
|
||||
DMG_BEAM_REFINEMENT,
|
||||
CH_MEASUREMENT_FEEDBACK,
|
||||
AWAKE_WINDOW = 157,
|
||||
MULTIBAND,
|
||||
ADDBA_ESXT,
|
||||
NEXTPCP_LIST,
|
||||
PCP_HANDOVER,
|
||||
DMG_LINK_MARGIN,
|
||||
SWITCHING_STREAM,
|
||||
SESSION_TRANSITION,
|
||||
DYNAMIC_TONE_PAIRING_REPORT,
|
||||
CLUSTER_REPORT,
|
||||
RELAY_CAP,
|
||||
RELAY_TRANSFER_PARAM_SET,
|
||||
BEAMLINK_MAINTENANCE,
|
||||
MULTIPLE_MAC_SUBLAYERS,
|
||||
UPID,
|
||||
DMG_LINK_ADAPTATION_ACK,
|
||||
MCCAOP_ADV_OVERVIEW = 174,
|
||||
QUIET_PERIOD_REQ,
|
||||
QUIET_PERIOD_RESP = 177,
|
||||
QMF_POLICY = 181,
|
||||
ECAPC_POLICY = 182,
|
||||
CLUSTER_TIME_OFFSET,
|
||||
INTRA_ACCESS_CAT_PRIORITY,
|
||||
SCS_DESCRIPTOR,
|
||||
QLOAD_REPORT,
|
||||
HCCA_TXOP_UPDATE_COUNT,
|
||||
HIGHER_LAYER_STREAM_ID,
|
||||
GCR_GROUP_ADDR,
|
||||
ANTENNA_SECTOR_ID_PATTERN,
|
||||
VHT_CAP,
|
||||
VHT_OP,
|
||||
EXT_BSS_LOAD,
|
||||
WIDE_BANDWIDTH_CH_SWITCH,
|
||||
TRANSMIT_POWER_ENVELOPE,
|
||||
CH_SWITCH_WRAPPER,
|
||||
AID,
|
||||
QUIET_CHANNEL,
|
||||
OP_MODE_NOTIFY,
|
||||
UPSIM,
|
||||
REDUCED_NEIGHBOR_REPORT,
|
||||
TVHT_OP,
|
||||
DEV_LOC = 204,
|
||||
WHITE_SPACE_MAP,
|
||||
FINE_TUNING_MEASUREMENT_PARAMS,
|
||||
VENDOR_SPECIFIC = 221
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -281,6 +281,10 @@ public:
|
||||
|
||||
/* Getters */
|
||||
|
||||
uint32_t advertised_size() const {
|
||||
return static_cast<uint32_t>(tot_len());
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the header length field.
|
||||
*
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -131,6 +131,7 @@ public:
|
||||
ARP_SOCKET,
|
||||
ICMP_SOCKET,
|
||||
IPV6_SOCKET,
|
||||
ICMPV6_SOCKET,
|
||||
SOCKETS_END
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -279,6 +281,12 @@ public:
|
||||
*/
|
||||
uint32_t size() const;
|
||||
|
||||
/** \brief The whole chain of PDU's advertised size, including this one.
|
||||
*
|
||||
* Returns the sum of this and all children PDU's advertised size.
|
||||
*/
|
||||
virtual uint32_t advertised_size() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the inner PDU.
|
||||
* \return The current inner PDU. Might be a null pointer.
|
||||
|
||||
@@ -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->()) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -114,7 +114,11 @@ public:
|
||||
RadioTap::option current_option();
|
||||
|
||||
/**
|
||||
* Gets the pointer at which the current option is located
|
||||
* \brief Gets the pointer at which the current option is located
|
||||
*
|
||||
* A past-the-end pointer may be returned in case of malformed input or
|
||||
* end of data. Its validity must be checked (e.g. using
|
||||
* \ref RadioTapParser.has_fields) before dereference.
|
||||
*/
|
||||
const uint8_t* current_option_ptr() const;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,9 @@ SET_TARGET_PROPERTIES(tins PROPERTIES VERSION ${LIBTINS_VERSION} SOVERSION ${LIB
|
||||
INSTALL(
|
||||
TARGETS tins
|
||||
EXPORT libtinsTargets
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
COMPONENT dev
|
||||
)
|
||||
|
||||
@@ -233,4 +234,4 @@ MACRO(INSTALL_HEADERS_WITH_DIRECTORY HEADER_LIST)
|
||||
ENDFOREACH(HEADER)
|
||||
ENDMACRO()
|
||||
|
||||
INSTALL_HEADERS_WITH_DIRECTORY(${HEADERS})
|
||||
INSTALL_HEADERS_WITH_DIRECTORY(${HEADERS})
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
96
src/ipv6.cpp
96
src/ipv6.cpp
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -70,12 +70,12 @@ void PacketWriter::write(Packet& packet) {
|
||||
}
|
||||
|
||||
void PacketWriter::write(PDU& pdu, const struct timeval& tv) {
|
||||
PDU::serialization_type buffer = pdu.serialize();
|
||||
struct pcap_pkthdr header;
|
||||
memset(&header, 0, sizeof(header));
|
||||
header.ts = tv;
|
||||
header.len = static_cast<bpf_u_int32>(pdu.advertised_size());
|
||||
PDU::serialization_type buffer = pdu.serialize();
|
||||
header.caplen = static_cast<bpf_u_int32>(buffer.size());
|
||||
header.len = static_cast<bpf_u_int32>(buffer.size());
|
||||
pcap_dump((u_char*)dumper_, &header, &buffer[0]);
|
||||
}
|
||||
|
||||
|
||||
@@ -85,6 +85,14 @@ uint32_t PDU::size() const {
|
||||
return sz;
|
||||
}
|
||||
|
||||
uint32_t PDU::advertised_size() const {
|
||||
uint32_t result = header_size() + trailer_size();
|
||||
if (inner_pdu_) {
|
||||
result += inner_pdu()->advertised_size();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void PDU::send(PacketSender &, const NetworkInterface &) {
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -65,7 +65,7 @@ const RadioTapParser::FieldMetadata RadioTapParser::RADIOTAP_METADATA[] = {
|
||||
};
|
||||
|
||||
const uint32_t RadioTapParser::MAX_RADIOTAP_FIELD = sizeof(RADIOTAP_METADATA) /
|
||||
sizeof(FieldMetadata) + 1;
|
||||
sizeof(FieldMetadata);
|
||||
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
TINS_BEGIN_PACK
|
||||
@@ -135,9 +135,6 @@ void align_buffer(const uint8_t* buffer_start, const uint8_t*& buffer, uint32_t
|
||||
uint32_t offset = (buffer - buffer_start) & (n - 1);
|
||||
if (offset) {
|
||||
offset = n - offset;
|
||||
if (TINS_UNLIKELY(offset > size)) {
|
||||
throw malformed_packet();
|
||||
}
|
||||
buffer += offset;
|
||||
}
|
||||
}
|
||||
@@ -233,7 +230,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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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")
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 };
|
||||
|
||||
Reference in New Issue
Block a user