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(); }
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,
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
{
// 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);
}
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
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)
uint8_t get_ip_ttl() const;
+ int get_icmp_data_offset() const;
+
// not implementing print nor to_string
protected:
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)
}
// 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() );
}
// 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() );
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
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);
}
// 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() )
{
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
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)