/* 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 "icmpdata.h" #include #include #include #include "boost_assert_handler.h" #include "ip/ipv4header.h" #include "ip/ipv6header.h" using I2n::Logger::GlobalLogger; using boost::asio::ip::address; IcmpData::IcmpData() : size( 0 ) , raw_data( 0 ) {} IcmpData::IcmpData(const std::size_t size_arg) : size( size_arg ) , raw_data( size_arg ) {} bool IcmpData::match_echo_reply(const uint16_t identifier, const uint16_t sequence_number) const { return false; } bool IcmpData::match_destination_unreachable(const uint16_t identifier, const uint16_t sequence_number, const address &destination_address) const { return false; } bool IcmpData::match_time_exceeded(const uint16_t identifier, const uint16_t sequence_number, const address &destination_address) const { return false; } 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; } IpHeaderPtr IcmpData::get_ip_header() const { // make stream from relevant part of payload std::stringbuf buffer; std::ostream buf_filler( &buffer ); raw_data.write( buf_filler ); std::istream stream( &buffer ); // skip 4 byte stream.seekg(4, stream.beg); // interpret as IP header int ip_version = get_ip_version(); IpHeaderPtr result; if (ip_version == 4) { Ipv4Header *result_val = new Ipv4Header(); stream >> *result_val; result.reset( result_val ); } else if (ip_version == 6) { Ipv6Header *result_val = new Ipv6Header(); stream >> *result_val; result.reset( result_val ); } else { // throw runtime error through boost_assert_handler GlobalLogger.error() << "Invalid IP version: " << ip_version << " ! Maybe data is no IP packet?"; BOOST_ASSERT( !"Invalid IP version or not IP packet!" ); } return result; } uint32_t IcmpData::calc_checksum_part() const { return raw_data.calc_checksum_part(); } void IcmpData::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::istream& IcmpData::read(std::istream &is) // read raw data { return raw_data.read(is); } std::ostream& IcmpData::write(std::ostream &os) const { return raw_data.write(os); } std::string IcmpData::to_string() const { std::stringstream buf; buf << "[IcmpData of length " << size << "]"; return buf.str(); } std::istream& operator>>( std::istream &is, IcmpData &data ) { return data.read( is ); } std::ostream& operator<<( std::ostream &os, const IcmpData &data ) { return data.write( os ); }