added code to parse ICMP type TimeExceeded
authorChristian Herdtweck <christian.herdtweck@intra2net.com>
Wed, 18 Mar 2015 10:46:13 +0000 (11:46 +0100)
committerChristian Herdtweck <christian.herdtweck@intra2net.com>
Wed, 18 Mar 2015 10:46:13 +0000 (11:46 +0100)
* format is identical to DestinationUnreachable and other ICMP replies
  --> created a common half-abstract base class IcmpData_PingFailReply
* added a match_time_exceeded to IcmpPacket which is called by IcmpPinger

17 files changed:
src/CMakeLists.txt
src/icmp/icmpdata.cpp
src/icmp/icmpdata.h
src/icmp/icmpdata_pingfailreply.cpp [new file with mode: 0644]
src/icmp/icmpdata_pingfailreply.h [new file with mode: 0644]
src/icmp/icmpdestinationunreachabledata.cpp
src/icmp/icmpdestinationunreachabledata.h
src/icmp/icmpechodata.cpp
src/icmp/icmpechodata.h
src/icmp/icmpheader.cpp
src/icmp/icmppacket.cpp
src/icmp/icmppacket.h
src/icmp/icmppinger.cpp
src/icmp/icmptimeexceededdata.cpp [new file with mode: 0644]
src/icmp/icmptimeexceededdata.h [new file with mode: 0644]
test/CMakeLists.test_icmpv4header.txt
test/CMakeLists.test_icmpv6header.txt

index 14801e0..9bf618b 100644 (file)
@@ -77,8 +77,10 @@ set(SOURCES
     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
index 3db5912..a6020e0 100644 (file)
@@ -44,6 +44,10 @@ bool IcmpData::match_destination_unreachable(const uint16_t identifier,
                               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;  }
 
index f53f160..042aa32 100644 (file)
@@ -52,6 +52,9 @@ public:
     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);
diff --git a/src/icmp/icmpdata_pingfailreply.cpp b/src/icmp/icmpdata_pingfailreply.cpp
new file mode 100644 (file)
index 0000000..967f273
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ 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)
+
diff --git a/src/icmp/icmpdata_pingfailreply.h b/src/icmp/icmpdata_pingfailreply.h
new file mode 100644 (file)
index 0000000..f47cc79
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ 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)
+
index c42d692..b3d7275 100644 (file)
@@ -30,54 +30,21 @@ using I2n::Logger::GlobalLogger;
 
 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.
index 7910ec3..876ab67 100644 (file)
 
 #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.
@@ -85,9 +60,6 @@ public:
 
     std::string to_string() const;
 
-protected:
-    uint16_t get_icmp_request_data(const int data_offset) const;
-
 };
 
 #endif
index 9650774..f6c7ae3 100644 (file)
@@ -54,6 +54,12 @@ bool IcmpEchoData::match_destination_unreachable(
 { 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
 {
index c6b865b..ac73adb 100644 (file)
@@ -49,6 +49,9 @@ public:
     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;
index bad7a6e..3a2047d 100644 (file)
@@ -92,7 +92,8 @@ std::string IcmpHeader::to_string() 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();
 }
 
index b90f481..b8021da 100644 (file)
@@ -35,6 +35,7 @@
 #include "ip/ipv6header.h"
 #include "icmp/icmpechodata.h"
 #include "icmp/icmpdestinationunreachabledata.h"
+#include "icmp/icmptimeexceededdata.h"
 
 
 using I2n::Logger::GlobalLogger;
@@ -101,6 +102,15 @@ bool IcmpPacket::match_destination_unreachable(const uint16_t identifier,
                                                    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
@@ -150,7 +160,7 @@ IcmpPacket::ReadReturnCode IcmpPacket::read( std::istream &is )
     {
         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!" );
     }
@@ -186,6 +196,8 @@ IcmpPacket::ReadReturnCode IcmpPacket::read( std::istream &is )
     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() )
@@ -212,6 +224,10 @@ IcmpPacket::ReadReturnCode IcmpPacket::read( std::istream &is )
               || 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
index 85cec2e..4a4253a 100644 (file)
@@ -84,6 +84,9 @@ public:
                           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
@@ -94,7 +97,7 @@ public:
      * @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);
 
index 5837062..67f3b34 100644 (file)
@@ -344,6 +344,23 @@ bool IcmpPinger::handle_receive_icmp_packet(const IcmpPacketItem icmp_packet,
 
         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()
diff --git a/src/icmp/icmptimeexceededdata.cpp b/src/icmp/icmptimeexceededdata.cpp
new file mode 100644 (file)
index 0000000..5adf940
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ 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)
+
diff --git a/src/icmp/icmptimeexceededdata.h b/src/icmp/icmptimeexceededdata.h
new file mode 100644 (file)
index 0000000..5f2fc1a
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ 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)
+
index b2697dd..1133e30 100644 (file)
@@ -3,6 +3,7 @@ add_executable(test_icmpv4header
     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
index dcfeb34..f54dd5c 100644 (file)
@@ -3,6 +3,7 @@ add_executable(test_icmpv6header
     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