added more getter to IcmpPacket so can test more
authorChristian Herdtweck <christian.herdtweck@intra2net.com>
Wed, 18 Mar 2015 18:06:32 +0000 (19:06 +0100)
committerChristian Herdtweck <christian.herdtweck@intra2net.com>
Wed, 18 Mar 2015 18:06:32 +0000 (19:06 +0100)
src/icmp/icmpdata.cpp
src/icmp/icmpdata.h
src/icmp/icmpdata_pingfailreply.cpp
src/icmp/icmpdata_pingfailreply.h
src/icmp/icmpdestinationunreachabledata.cpp
src/icmp/icmppacket.cpp
src/icmp/icmppacket.h
src/icmp/icmptimeexceededdata.cpp

index a6020e0..674f1d8 100644 (file)
@@ -48,9 +48,17 @@ bool IcmpData::match_time_exceeded(const uint16_t identifier,
                                    const uint16_t sequence_number) const
 {  return false;  }
 
-inline std::size_t IcmpData::get_size()
+std::size_t IcmpData::get_size() const
 {  return size;  }
 
+int IcmpData::get_ip_version() const
+{
+    int offset = 4;   // the 4 uninteresting bytes we need to skip
+    uint8_t version_with_ihl = static_cast<uint8_t>(IcmpData::raw_data[offset]);
+    int version = static_cast<int>( (version_with_ihl & 0xF0) >> 4 );
+    return version;
+}
+
 uint32_t IcmpData::calc_checksum_part() const
 {  return raw_data.calc_checksum_part();  }
 
index 042aa32..4ac3157 100644 (file)
@@ -55,12 +55,11 @@ public:
     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);
-    virtual std::ostream& write(std::ostream &os) const;
+    // including 4 bytes from ICMPv4 header
+    std::size_t get_size() const;
 
     uint32_t calc_checksum_part() const;
+    int get_ip_version() const;
 
     virtual void print( const size_t &bytes_received,
                         const boost::posix_time::ptime &time_packet_sent,
@@ -69,6 +68,9 @@ public:
 
     virtual std::string to_string() const;
 
+    virtual std::istream& read( std::istream &is);
+    virtual std::ostream& write(std::ostream &os) const;
+
     friend std::istream& operator>>(
             std::istream &is,
             IcmpData &data
index 1481f05..118e369 100644 (file)
@@ -67,33 +67,13 @@ uint16_t IcmpData_PingFailReply::get_icmp_request_data(
 {
     // 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 = false;
-    int offset = 4;   // the 4 uninteresting bytes we need to skip
-    uint8_t version_with_ihl = static_cast<uint8_t>(IcmpData::raw_data[offset]);
-    uint8_t version = (version_with_ihl & 0xF0) >> 4;
-
-    if (version == 4)   // IPv4
-    {
-        is_icmp = IcmpData::raw_data[offset+9] == 1;
-        offset += 20;     // 20 byte for IPv4 header
-    }
-    else if (version == 6)   // IPv6
-    {
-        is_icmp = IcmpData::raw_data[offset+6] == 58;
-        offset += 40;     // 40 byte for IPv6 header
-    }
-    else
-    {
-        GlobalLogger.error() << "Request IP header is neither IPv4 nor v6!"
-                             << std::endl;
-        BOOST_ASSERT( !"Source IP header is neither IPv4 nor v6!" );
-    }
+    int offset = get_icmp_data_offset();
 
-    if ( !is_icmp )
+    if (offset == -1)
         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 given byte offset
+        // the IP header. Inside the icmp packet we need the given byte offset
         return IcmpData::raw_data.decode16(offset+icmp_start_byte,
                                            offset+icmp_start_byte+1);
 }
@@ -109,8 +89,7 @@ uint16_t IcmpData_PingFailReply::get_icmp_request_data(
 uint8_t IcmpData_PingFailReply::get_ip_ttl() const
 {
     int offset = 4;   // the 4 uninteresting bytes we need to skip
-    uint8_t version_with_ihl = static_cast<uint8_t>(IcmpData::raw_data[offset]);
-    uint8_t version = (version_with_ihl & 0xF0) >> 4;
+    int version = IcmpData::get_ip_version();
 
     if (version == 4)   // IPv4
         offset += 8;    // byte 8 within IP header
@@ -126,5 +105,42 @@ uint8_t IcmpData_PingFailReply::get_ip_ttl() const
     return IcmpData::raw_data[offset];
 }
 
+/** @brief get byte index of start of ICMP request data after IP header
+ *
+ * @returns -1 if this data is not a
+ * @throws boost assertion if data does not start with an IP header of version
+ *   4 or 6
+ */
+int IcmpData_PingFailReply::get_icmp_data_offset() const
+{
+    bool is_icmp = false;
+    int offset = 4;   // the 4 uninteresting bytes we need to skip
+    uint8_t version_with_ihl = static_cast<uint8_t>(IcmpData::raw_data[offset]);
+    uint8_t version = (version_with_ihl & 0xF0) >> 4;
+
+    if (version == 4)   // IPv4
+    {
+        is_icmp = IcmpData::raw_data[offset+9] == 1;
+        offset += 20;     // 20 byte for IPv4 header
+    }
+    else if (version == 6)   // IPv6
+    {
+        is_icmp = IcmpData::raw_data[offset+6] == 58;
+        offset += 40;     // 40 byte for IPv6 header
+    }
+    else
+    {
+        GlobalLogger.error() << "Request IP header is neither IPv4 nor v6!"
+                             << std::endl;
+        BOOST_ASSERT( !"Source IP header is neither IPv4 nor v6!" );
+    }
+
+    if (is_icmp)
+        return offset;
+    else
+        return -1;
+}
+
+
 // (created using vim -- the world's best text editor)
 
index ecdc8ae..b0ea405 100644 (file)
@@ -76,6 +76,8 @@ public:
 
     uint8_t get_ip_ttl() const;
 
+    int get_icmp_data_offset() const;
+
     // not implementing print nor to_string
 
 protected:
index b3d7275..a01595c 100644 (file)
@@ -66,7 +66,18 @@ void IcmpDestinationUnreachableData::print(
 
 std::string IcmpDestinationUnreachableData::to_string() const
 {
-    return "[DestUnrchbleData]";
+    if (IcmpData_PingFailReply::get_icmp_data_offset() == -1)
+        // not icmp!
+        return "[DestUnrchbleData from non-ICMP request]";
+    else
+    {
+        std::stringstream buf;
+        buf << "[DestUnrchbleData: ID=" << std::showbase << std::hex
+            << IcmpData_PingFailReply::get_icmp_identifier() << ",seq.nr="
+            << std::noshowbase << std::dec
+            << IcmpData_PingFailReply::get_icmp_sequence_number() << "]";
+        return buf.str();
+    }
 }
 
 // (created using vim -- the world's best text editor)
index a6a6c3f..b5e76de 100644 (file)
@@ -79,7 +79,7 @@ IcmpPacket::IcmpPacket(const icmp::socket::protocol_type &protocol,
 }
 
 // returns Icmpv4Type_InvalidLast if is actually v6 and not v4
-Icmpv4Type IcmpPacket::get_type_v4()
+Icmpv4Type IcmpPacket::get_type_v4() const
 {
     if (ip_head_ptr->get_version() == 4)
         return static_cast<Icmpv4Type>( icmp_header.get_type() );
@@ -88,7 +88,7 @@ Icmpv4Type IcmpPacket::get_type_v4()
 }
 
 // returns Icmpv6Type_InvalidLast if is actually v4 and not v6
-Icmpv6Type IcmpPacket::get_type_v6()
+Icmpv6Type IcmpPacket::get_type_v6() const
 {
     if (ip_head_ptr->get_version() == 6)
         return static_cast<Icmpv6Type>( icmp_header.get_type() );
@@ -96,6 +96,27 @@ Icmpv6Type IcmpPacket::get_type_v6()
         return Icmpv6Type_InvalidLast;   // invalid
 }
 
+uint8_t IcmpPacket::get_icmp_code() const
+{
+    return icmp_header.get_code();
+}
+
+std::size_t IcmpPacket::get_icmp_size() const
+{
+    return static_cast<std::size_t>(icmp_header.get_header_length())
+             + icmp_data_ptr->get_size();
+}
+
+address IcmpPacket::get_source_address() const
+{
+    return ip_head_ptr->get_source_address();
+}
+
+address IcmpPacket::get_destination_address() const
+{
+    return ip_head_ptr->get_destination_address();
+}
+
 
 bool IcmpPacket::check_integrity() { return false; } // not implemented yet
 
@@ -120,6 +141,14 @@ bool IcmpPacket::match_echo_reply(const uint16_t identifier,
                       const uint16_t sequence_number,
                       const address &destination_address) const
 {
+    // ensure is not a EchoRequest but a EchoReply
+    int version = ip_head_ptr->get_version();
+    uint8_t type = icmp_header.get_type();
+    if (version == 4 && type != Icmpv4Type_EchoReply)
+        return false;
+    if (version == 6 && type != Icmpv6Type_EchoReply)
+        return false;
+
     return ip_head_ptr->get_source_address() == destination_address
        &&  icmp_data_ptr->match_echo_reply(identifier, sequence_number);
 }
@@ -160,6 +189,7 @@ IcmpPacket::ReadReturnCode IcmpPacket::read( std::istream &is )
     // try to read ip header
     uint8_t version_with_ihl = static_cast<uint8_t>( is.peek() );
     uint8_t version = (version_with_ihl & 0xF0) >> 4;
+      // ( this is the same as icmp_data_ptr->get_ip_version() )
 
     if ( version != ip_head_ptr->get_version() )
     {
index 4a4253a..a89b50d 100644 (file)
@@ -70,8 +70,12 @@ public:
                const IcmpHeader &icmp_header_arg,
                const IcmpDataPtr &icmp_data_arg);
 
-    Icmpv4Type get_type_v4();
-    Icmpv6Type get_type_v6();
+    Icmpv4Type get_type_v4() const;
+    Icmpv6Type get_type_v6() const;
+    uint8_t get_icmp_code() const;
+    address get_source_address() const;
+    address get_destination_address() const;
+    std::size_t get_icmp_size() const;    // ICMP header + data
 
     bool check_integrity();   // not implemented yet
 
index 4eb31d4..b1ef2d5 100644 (file)
@@ -62,12 +62,19 @@ void IcmpTimeExceededData::print(
 
 std::string IcmpTimeExceededData::to_string() const
 {
-    std::stringstream buf;
-    buf << "[TimeExceededData: ID=" << std::showbase << std::hex
-        << IcmpData_PingFailReply::get_icmp_identifier() << ",seq.nr="
-        << IcmpData_PingFailReply::get_icmp_sequence_number() << "]";
-
-    return buf.str();
+    if (IcmpData_PingFailReply::get_icmp_data_offset() == -1)
+        // not icmp!
+        return "[TimeExceededData from non-ICMP request]";
+    else
+    {
+        std::stringstream buf;
+        buf << "[TimeExceededData: ID=" << std::showbase << std::hex
+            << IcmpData_PingFailReply::get_icmp_identifier() << ",seq.nr="
+            << std::noshowbase << std::dec
+            << IcmpData_PingFailReply::get_icmp_sequence_number() << "]";
+
+        return buf.str();
+    }
 }
 
 // (created using vim -- the world's best text editor)