From: Christian Herdtweck Date: Wed, 18 Mar 2015 18:06:32 +0000 (+0100) Subject: added more getter to IcmpPacket so can test more X-Git-Url: http://developer.intra2net.com/git/?a=commitdiff_plain;h=aadc70326fb36f210a8ffc8ad2a56e867de33f0c;p=pingcheck added more getter to IcmpPacket so can test more --- diff --git a/src/icmp/icmpdata.cpp b/src/icmp/icmpdata.cpp index a6020e0..674f1d8 100644 --- a/src/icmp/icmpdata.cpp +++ b/src/icmp/icmpdata.cpp @@ -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(IcmpData::raw_data[offset]); + int version = static_cast( (version_with_ihl & 0xF0) >> 4 ); + return version; +} + uint32_t IcmpData::calc_checksum_part() const { return raw_data.calc_checksum_part(); } diff --git a/src/icmp/icmpdata.h b/src/icmp/icmpdata.h index 042aa32..4ac3157 100644 --- a/src/icmp/icmpdata.h +++ b/src/icmp/icmpdata.h @@ -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 diff --git a/src/icmp/icmpdata_pingfailreply.cpp b/src/icmp/icmpdata_pingfailreply.cpp index 1481f05..118e369 100644 --- a/src/icmp/icmpdata_pingfailreply.cpp +++ b/src/icmp/icmpdata_pingfailreply.cpp @@ -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(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(-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(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(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) diff --git a/src/icmp/icmpdata_pingfailreply.h b/src/icmp/icmpdata_pingfailreply.h index ecdc8ae..b0ea405 100644 --- a/src/icmp/icmpdata_pingfailreply.h +++ b/src/icmp/icmpdata_pingfailreply.h @@ -76,6 +76,8 @@ public: uint8_t get_ip_ttl() const; + int get_icmp_data_offset() const; + // not implementing print nor to_string protected: diff --git a/src/icmp/icmpdestinationunreachabledata.cpp b/src/icmp/icmpdestinationunreachabledata.cpp index b3d7275..a01595c 100644 --- a/src/icmp/icmpdestinationunreachabledata.cpp +++ b/src/icmp/icmpdestinationunreachabledata.cpp @@ -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) diff --git a/src/icmp/icmppacket.cpp b/src/icmp/icmppacket.cpp index a6a6c3f..b5e76de 100644 --- a/src/icmp/icmppacket.cpp +++ b/src/icmp/icmppacket.cpp @@ -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( 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( 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(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( 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() ) { diff --git a/src/icmp/icmppacket.h b/src/icmp/icmppacket.h index 4a4253a..a89b50d 100644 --- a/src/icmp/icmppacket.h +++ b/src/icmp/icmppacket.h @@ -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 diff --git a/src/icmp/icmptimeexceededdata.cpp b/src/icmp/icmptimeexceededdata.cpp index 4eb31d4..b1ef2d5 100644 --- a/src/icmp/icmptimeexceededdata.cpp +++ b/src/icmp/icmptimeexceededdata.cpp @@ -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)