host/pingrotate.cpp
host/pingscheduler.cpp
icmp/icmpdata.cpp
+ icmp/icmpdata_pingfailreply.cpp
icmp/icmpechodata.cpp
icmp/icmpdestinationunreachabledata.cpp
+ icmp/icmptimeexceededdata.cpp
icmp/icmpheader.cpp
icmp/icmppacket.cpp
icmp/icmppinger.cpp
const uint16_t sequence_number) const
{ return false; }
+bool IcmpData::match_time_exceeded(const uint16_t identifier,
+ const uint16_t sequence_number) const
+{ return false; }
+
inline std::size_t IcmpData::get_size()
{ return size; }
virtual bool match_destination_unreachable(const uint16_t identifier,
const uint16_t sequence_number) const;
+ virtual bool match_time_exceeded(const uint16_t identifier,
+ const uint16_t sequence_number) const;
+
inline std::size_t get_size();
virtual std::istream& read( std::istream &is);
--- /dev/null
+/*
+ The software in this package is distributed under the GNU General
+ Public License version 2 (with a special exception described below).
+
+ A copy of GNU General Public License (GPL) is included in this distribution,
+ in the file COPYING.GPL.
+
+ As a special exception, if other files instantiate templates or use macros
+ or inline functions from this file, or you compile this file and link it
+ with other works to produce a work based on this file, this file
+ does not by itself cause the resulting work to be covered
+ by the GNU General Public License.
+
+ However the source code for this file must still be made available
+ in accordance with section (3) of the GNU General Public License.
+
+ This exception does not invalidate any other reasons why a work based
+ on this file might be covered by the GNU General Public License.
+
+ Christian Herdtweck, Intra2net AG 2015
+ Based on an example in Boost Documentation (by Christopher M. Kohlhoff)
+ and adaptation by Guilherme M. Ferreira
+ */
+
+#include "icmp/icmpdata_pingfailreply.h"
+
+
+IcmpData_PingFailReply::IcmpData_PingFailReply(const std::size_t size_arg)
+ : IcmpData( size_arg )
+{}
+
+bool IcmpData_PingFailReply::match_echo_reply(
+ const uint16_t identifier,
+ const uint16_t sequence_number) const
+{ return false; }
+
+bool IcmpData_PingFailReply::match_ping_request(
+ const uint16_t identifier,
+ const uint16_t sequence_number) const
+{
+ return identifier == get_icmp_identifier() &&
+ sequence_number == get_icmp_sequence_number();
+}
+
+
+uint16_t IcmpData_PingFailReply::get_icmp_identifier() const
+{ return get_icmp_request_data(5); }
+
+uint16_t IcmpData_PingFailReply::get_icmp_sequence_number() const
+{ return get_icmp_request_data(7); }
+
+uint16_t IcmpData_PingFailReply::get_icmp_request_data(
+ const int data_offset) const
+{
+ // payload should be the original query, which is an IP packet.
+ // first check wheter that IP packet contains an ICMP message at all
+ bool is_icmp;
+ int offset = 4; // the 4 uninteresting bytes we need to skip
+ if (IcmpData::raw_data[offset+0] == 4) // IPv4
+ {
+ is_icmp = IcmpData::raw_data[offset+9] == 1;
+ offset += 20; // 20 byte for IPv4 header
+ }
+ else if (IcmpData::raw_data[offset+0] == 6) // IPv6
+ {
+ is_icmp = IcmpData::raw_data[offset+6] == 58;
+ offset += 40; // 40 byte for IPv6 header
+ }
+
+ if ( !is_icmp )
+ return static_cast<uint16_t>(-1);
+ else
+ // if it is an icmp message, then the icmp packet comes right after
+ // the IP header. Inside the icmp packet we need bytes 5-8
+ return IcmpData::raw_data.decode16(offset+data_offset,
+ offset+data_offset+1);
+}
+
+// (created using vim -- the world's best text editor)
+
--- /dev/null
+/*
+ The software in this package is distributed under the GNU General
+ Public License version 2 (with a special exception described below).
+
+ A copy of GNU General Public License (GPL) is included in this distribution,
+ in the file COPYING.GPL.
+
+ As a special exception, if other files instantiate templates or use macros
+ or inline functions from this file, or you compile this file and link it
+ with other works to produce a work based on this file, this file
+ does not by itself cause the resulting work to be covered
+ by the GNU General Public License.
+
+ However the source code for this file must still be made available
+ in accordance with section (3) of the GNU General Public License.
+
+ This exception does not invalidate any other reasons why a work based
+ on this file might be covered by the GNU General Public License.
+
+ Christian Herdtweck, Intra2net AG 2015
+ Based on an example in Boost Documentation (by Christopher M. Kohlhoff)
+ and adaptation by Guilherme M. Ferreira
+ */
+
+
+#ifndef ICMP_DATA_PING_FAIL_REPLY_H
+#define ICMP_DATA_PING_FAIL_REPLY_H
+
+#include <stdint.h>
+#include "icmp/icmpdata.h"
+
+/**
+ * structure of DestinationUnreachable or TimeExceeded or Source Quench packets
+ * if originated from an ICMP request:
+ * +---------------------------+
+ * | reply IP header | 20/40 bytes --> not contained in here
+ * +---------------------------+
+ * | reply ICMP header: |
+ * | type | code | checksum | 4 byte --> not contained in here !
+ * | 4 uninteresting bytes | 4 byte --> contained in here!
+ * +---------------------------+
+ * | request | 20 / 40 bytes
+ * | IP header | for IP v4 / v6
+ * +---------------------------+
+ * | request ICMP packet: |
+ * | type | code | checksum | 1+1+2 byte
+ * | identifier | seq. number | 2+2 byte
+ * | data | 4 byte
+ * | data | 4 byte
+ * +---------------------------+
+ * (where "in here" means in variable raw_data of class
+ * IcmpData_PingFailReply)
+ *
+ * see also: https://tools.ietf.org/html/rfc792 (ICMP v4)
+ * https://tools.ietf.org/html/rfc4443 (ICMP v6)
+ * http://en.wikipedia.org/wiki/Internet_Control_Message_Protocol
+ * http://en.wikipedia.org/wiki/ICMPv6
+ */
+
+/**
+ * contains the request IP and ICMP header and possibly more data from request
+ */
+class IcmpData_PingFailReply : public IcmpData
+{
+public:
+ IcmpData_PingFailReply(const std::size_t size_arg);
+
+ bool match_echo_reply(const uint16_t identifier,
+ const uint16_t sequence_number) const;
+
+ // not implementing match_destination_unreachable nor match_time_exceeded
+
+ uint16_t get_icmp_identifier() const;
+
+ uint16_t get_icmp_sequence_number() const;
+
+ // not implementing print nor to_string
+
+protected:
+ uint16_t get_icmp_request_data(const int data_offset) const;
+ bool match_ping_request(const uint16_t identifier,
+ const uint16_t sequence_number) const;
+
+};
+
+#endif
+
+// (created using vim -- the world's best text editor)
+
IcmpDestinationUnreachableData::IcmpDestinationUnreachableData(
const std::size_t size_arg)
- : IcmpData( size_arg )
+ : IcmpData_PingFailReply( size_arg )
{}
-bool IcmpDestinationUnreachableData::match_echo_reply(const uint16_t identifier,
- const uint16_t sequence_number) const
-{ return false; }
-
bool IcmpDestinationUnreachableData::match_destination_unreachable(
const uint16_t identifier,
const uint16_t sequence_number) const
{
- return identifier == get_icmp_identifier() &&
- sequence_number == get_icmp_sequence_number();
+ return IcmpData_PingFailReply::match_ping_request(identifier,
+ sequence_number);
}
-
-uint16_t IcmpDestinationUnreachableData::get_icmp_identifier() const
-{ return get_icmp_request_data(5); }
-
-uint16_t IcmpDestinationUnreachableData::get_icmp_sequence_number() const
-{ return get_icmp_request_data(7); }
-
-uint16_t IcmpDestinationUnreachableData::get_icmp_request_data(
- const int data_offset) const
-{
- // payload should be the original query, which is an IP packet.
- // first check wheter that IP packet contains an ICMP message at all
- bool is_icmp;
- int offset = 4; // the 4 uninteresting bytes we need to skip
- if (IcmpData::raw_data[offset+0] == 4) // IPv4
- {
- is_icmp = IcmpData::raw_data[offset+9] == 1;
- offset += 20; // 20 byte for IPv4 header
- }
- else if (IcmpData::raw_data[offset+0] == 6) // IPv6
- {
- is_icmp = IcmpData::raw_data[offset+6] == 58;
- offset += 40; // 40 byte for IPv6 header
- }
-
- if ( !is_icmp )
- return static_cast<uint16_t>(-1);
- else
- // if it is an icmp message, then the icmp packet comes right after
- // the IP header. Inside the icmp packet we need bytes 5-8
- return IcmpData::raw_data.decode16(offset+data_offset,
- offset+data_offset+1);
-}
+bool IcmpDestinationUnreachableData::match_time_exceeded(
+ const uint16_t identifier,
+ const uint16_t sequence_number) const
+{ return false; }
/**
* @brief Prints the destination unreachable messages.
#include <stdint.h>
#include <boost/date_time/posix_time/ptime.hpp>
-#include "icmp/icmpdata.h"
+#include "icmp/icmpdata_pingfailreply.h"
-/**
- * structure of these packets (if originated from an ICMP request):
- * +---------------------------+
- * | reply IP header | 20/40 bytes --> not contained in here
- * +---------------------------+
- * | reply ICMP header: |
- * | type | code | checksum | 4 byte --> not contained in here !
- * | 4 uninteresting bytes | 4 byte --> contained in here!
- * +---------------------------+
- * | request | 20 / 40 bytes
- * | IP header | for IP v4 / v6
- * +---------------------------+
- * | request ICMP packet: |
- * | type | code | checksum | 1+1+2 byte
- * | identifier | seq. number | 2+2 byte
- * | data | 4 byte
- * | data | 4 byte
- * +---------------------------+
- * (where "in here" means in variable raw_data of class
- * IcmpDestinationUnreachableData)
- *
- * see also: https://tools.ietf.org/html/rfc792 (ICMP v4)
- * https://tools.ietf.org/html/rfc4443 (ICMP v6)
- */
/**
- * contains the request IP and ICMP header and possibly more data from request
+ * Data for a DestinationUnreachableMessage
+ *
+ * has option to interpret data as containing a Ping packet as reason for
+ * DestinationUnreachable reply
*/
-class IcmpDestinationUnreachableData : public IcmpData
+class IcmpDestinationUnreachableData : public IcmpData_PingFailReply
{
public:
IcmpDestinationUnreachableData(const std::size_t size_arg);
- bool match_echo_reply(const uint16_t identifier,
- const uint16_t sequence_number) const;
-
bool match_destination_unreachable(const uint16_t identifier,
const uint16_t sequence_number) const;
- uint16_t get_icmp_identifier() const;
-
- uint16_t get_icmp_sequence_number() const;
+ bool match_time_exceeded(const uint16_t identifier,
+ const uint16_t sequence_number) const;
/**
* @brief Prints the destination unreachable messages.
std::string to_string() const;
-protected:
- uint16_t get_icmp_request_data(const int data_offset) const;
-
};
#endif
{ return false; }
+bool IcmpEchoData::match_time_exceeded(
+ const uint16_t identifier,
+ const uint16_t sequence_number) const
+{ return false; }
+
+
bool IcmpEchoData::match_echo_reply(const uint16_t identifier,
const uint16_t sequence_number) const
{
bool match_echo_reply(const uint16_t identifier,
const uint16_t sequence_number) const;
+ bool match_time_exceeded(const uint16_t identifier,
+ const uint16_t sequence_number) const;
+
uint16_t get_identifier() const;
uint16_t get_sequence_number() const;
std::stringstream buf;
buf << "[Icmp header type=" << static_cast<int>(type)
<< ",code=" << static_cast<int>(code)
- << " (cksum:" << std::showbase << std::hex << checksum << ")]";
+ // << " (cksum:" << std::showbase << std::hex << checksum << ")"
+ << "]";
return buf.str();
}
#include "ip/ipv6header.h"
#include "icmp/icmpechodata.h"
#include "icmp/icmpdestinationunreachabledata.h"
+#include "icmp/icmptimeexceededdata.h"
using I2n::Logger::GlobalLogger;
sequence_number);
}
+bool IcmpPacket::match_time_exceeded(const uint16_t identifier,
+ const uint16_t sequence_number,
+ const address &destination_address) const
+{
+ return ip_head_ptr->get_source_address() == destination_address
+ && icmp_data_ptr->match_time_exceeded(identifier,
+ sequence_number);
+}
+
bool IcmpPacket::match_echo_reply(const uint16_t identifier,
const uint16_t sequence_number,
const address &destination_address) const
{
GlobalLogger.error() << "IP version given to constructor ("
<< static_cast<int>(ip_head_ptr->get_version()) << ") does not "
- << "match the on in input stream (" << static_cast<int>(version)
+ << "match the one in input stream (" << static_cast<int>(version)
<< ")!" << std::endl;
BOOST_ASSERT( !"Inconsistent IP version!" );
}
else if ( !is.good() )
return IcmpPacket::ReadReturnCode_BAD_STREAM;
+ // could check validity of icmp type here
+
// calculate the size of the ICMP data
std::streamsize data_length =
static_cast<std::streamsize>( ip_head_ptr->get_total_length() )
|| get_type_v6() == Icmpv6Type_DestinationUnreachable)
icmp_data_ptr.reset( new IcmpDestinationUnreachableData(
static_cast<std::size_t>(data_length)) );
+ else if (get_type_v4() == Icmpv4Type_TimeExceeded
+ || get_type_v6() == Icmpv6Type_TimeExceeded)
+ icmp_data_ptr.reset( new IcmpTimeExceededData(
+ static_cast<std::size_t>(data_length)) );
else
{ // unspecified icmp data type, will consume right amount of data
// from stream but return false for match_echo_request and
const uint16_t sequence_number,
const address &destination_address) const;
+ bool match_time_exceeded(const uint16_t identifier,
+ const uint16_t sequence_number,
+ const address &destination_address) const;
/**
* @brief print echo reply / destination unreachable message depending on
* ICMP data type
* @return void
*/
void print( const size_t &bytes_transferred,
- const boost::posix_time::ptime &time_packet_sent ) const;
+ const boost::posix_time::ptime &time_packet_sent ) const;
ReadReturnCode read(std::istream &is);
IcmpPacketReceiveTimer.cancel(); //lint !e534
}
+ else if ( icmp_packet->match_time_exceeded(
+ Identifier, SequenceNumber,
+ DestinationEndpoint.address() ) )
+ {
+ GlobalLogger.info()
+ << DestinationEndpoint.address().to_string()
+ << ": Received time exceeded" << endl;
+
+ ReplyReceived = true;
+ does_match = true;
+
+ icmp_packet->print( bytes_transferred, TimeSent );
+
+ set_ping_status( PingStatus_FailureDestinationUnreachable );
+
+ IcmpPacketReceiveTimer.cancel(); //lint !e534
+ }
else
{
GlobalLogger.info()
--- /dev/null
+/*
+ The software in this package is distributed under the GNU General
+ Public License version 2 (with a special exception described below).
+
+ A copy of GNU General Public License (GPL) is included in this distribution,
+ in the file COPYING.GPL.
+
+ As a special exception, if other files instantiate templates or use macros
+ or inline functions from this file, or you compile this file and link it
+ with other works to produce a work based on this file, this file
+ does not by itself cause the resulting work to be covered
+ by the GNU General Public License.
+
+ However the source code for this file must still be made available
+ in accordance with section (3) of the GNU General Public License.
+
+ This exception does not invalidate any other reasons why a work based
+ on this file might be covered by the GNU General Public License.
+
+ Christian Herdtweck, Intra2net AG 2015
+ Based on an example in Boost Documentation (by Christopher M. Kohlhoff)
+ and adaptation by Guilherme M. Ferreira
+ */
+
+#include "icmp/icmptimeexceededdata.h"
+
+#include <logfunc.hpp>
+using I2n::Logger::GlobalLogger;
+
+
+IcmpTimeExceededData::IcmpTimeExceededData(const std::size_t size_arg)
+ : IcmpData_PingFailReply( size_arg )
+{}
+
+bool IcmpTimeExceededData::match_time_exceeded(
+ const uint16_t identifier,
+ const uint16_t sequence_number) const
+{
+ return IcmpData_PingFailReply::match_ping_request(identifier,
+ sequence_number);
+}
+
+bool IcmpTimeExceededData::match_destination_unreachable(
+ const uint16_t identifier,
+ const uint16_t sequence_number) const
+{ return false; }
+
+void IcmpTimeExceededData::print(
+ const size_t &bytes_received,
+ const boost::posix_time::ptime &time_packet_sent,
+ const std::string &remote_address,
+ const uint32_t ttl) const
+{
+ uint16_t sequence_number = get_icmp_sequence_number();
+
+ GlobalLogger.info() << "Time exceeded pinging " << remote_address
+ << " (icmp_seq=" << sequence_number << ")!"
+ << std::endl;
+}
+
+std::string IcmpTimeExceededData::to_string() const
+{
+ return "[TimeExceededData]";
+}
+
+// (created using vim -- the world's best text editor)
+
--- /dev/null
+/*
+ The software in this package is distributed under the GNU General
+ Public License version 2 (with a special exception described below).
+
+ A copy of GNU General Public License (GPL) is included in this distribution,
+ in the file COPYING.GPL.
+
+ As a special exception, if other files instantiate templates or use macros
+ or inline functions from this file, or you compile this file and link it
+ with other works to produce a work based on this file, this file
+ does not by itself cause the resulting work to be covered
+ by the GNU General Public License.
+
+ However the source code for this file must still be made available
+ in accordance with section (3) of the GNU General Public License.
+
+ This exception does not invalidate any other reasons why a work based
+ on this file might be covered by the GNU General Public License.
+
+ Christian Herdtweck, Intra2net AG 2015
+ Based on an example in Boost Documentation (by Christopher M. Kohlhoff)
+ and adaptation by Guilherme M. Ferreira
+ */
+
+
+#ifndef ICMP_TIME_EXCEEDED_DATA_H
+#define ICMP_TIME_EXCEEDED_DATA_H
+
+#include <stdint.h>
+#include <boost/date_time/posix_time/ptime.hpp>
+#include "icmp/icmpdata_pingfailreply.h"
+
+
+/**
+ * Data for a DestinationUnreachableMessage
+ *
+ * has option to interpret data as containing a Ping packet as reason for
+ * DestinationUnreachable reply
+ */
+class IcmpTimeExceededData : public IcmpData_PingFailReply
+{
+public:
+ IcmpTimeExceededData(const std::size_t size_arg);
+
+ bool match_destination_unreachable(const uint16_t identifier,
+ const uint16_t sequence_number) const;
+
+ bool match_time_exceeded(const uint16_t identifier,
+ const uint16_t sequence_number) const;
+
+ void print( const size_t &bytes_received,
+ const boost::posix_time::ptime &time_packet_sent,
+ const std::string &remote_address,
+ const uint32_t ttl) const;
+
+ std::string to_string() const;
+
+};
+
+#endif
+
+// (created using vim -- the world's best text editor)
+
test_icmpv4header.cpp
${CMAKE_SOURCE_DIR}/src/boost_assert_handler.cpp
${CMAKE_SOURCE_DIR}/src/icmp/icmpdata.cpp
+ ${CMAKE_SOURCE_DIR}/src/icmp/icmpdata_pingfailreply.cpp
${CMAKE_SOURCE_DIR}/src/icmp/icmpechodata.cpp
${CMAKE_SOURCE_DIR}/src/icmp/icmpdestinationunreachabledata.cpp
${CMAKE_SOURCE_DIR}/src/icmp/icmpheader.cpp
test_icmpv6header.cpp
${CMAKE_SOURCE_DIR}/src/boost_assert_handler.cpp
${CMAKE_SOURCE_DIR}/src/icmp/icmpdata.cpp
+ ${CMAKE_SOURCE_DIR}/src/icmp/icmpdata_pingfailreply.cpp
${CMAKE_SOURCE_DIR}/src/icmp/icmpechodata.cpp
${CMAKE_SOURCE_DIR}/src/icmp/icmpdestinationunreachabledata.cpp
${CMAKE_SOURCE_DIR}/src/icmp/icmpheader.cpp