From: Christian Herdtweck Date: Thu, 12 Mar 2015 14:51:58 +0000 (+0100) Subject: now working again: creating echo requests and parsing replies X-Git-Url: http://developer.intra2net.com/git/?a=commitdiff_plain;h=747c13ca81bcbe99efd27c27ef97c93261357518;p=pingcheck now working again: creating echo requests and parsing replies also: * created a to_string method for easier output * in constructors of IP headers set version right away * compare that version to the one received in IcmpPacket::read --- diff --git a/src/host/messagepayload.cpp b/src/host/messagepayload.cpp index c095c8e..4e931ce 100644 --- a/src/host/messagepayload.cpp +++ b/src/host/messagepayload.cpp @@ -398,7 +398,7 @@ void MessagePayload::encode_string( const int first_byte_index, BOOST_ASSERT( 0 < PayloadSizeInBytes ); BOOST_ASSERT( Payload.capacity() == PayloadSizeInBytes ); BOOST_ASSERT( ( 0 <= first_byte_index ) && ( first_byte_index < static_cast(PayloadSizeInBytes) ) ); - BOOST_ASSERT( first_byte_index +length < static_cast(PayloadSizeInBytes) ); + BOOST_ASSERT( first_byte_index +length <= static_cast(PayloadSizeInBytes) ); const uint8_t *data_converted = reinterpret_cast(&value[0]); for (int index=0; index #include +#include #include #include #include "host/messagepayload.h" @@ -70,6 +71,13 @@ public: const uint32_t ttl) const {} + virtual std::string to_string() const + { + std::stringstream buf; + buf << "[IcmpData of length " << size << "]"; + return buf.str(); + } + protected: IcmpData(const std::size_t size_arg) diff --git a/src/icmp/icmpechodata.h b/src/icmp/icmpechodata.h index ae31517..324b82c 100644 --- a/src/icmp/icmpechodata.h +++ b/src/icmp/icmpechodata.h @@ -45,11 +45,12 @@ class IcmpEchoData : public IcmpData public: IcmpEchoData(const uint16_t identifier, const uint16_t sequence_number, const std::string &optional_data) - : IcmpData(12) + : IcmpData( 4 + optional_data.length() ) { IcmpData::raw_data.encode16(0, 1, identifier); IcmpData::raw_data.encode16(2, 3, sequence_number); IcmpData::raw_data.encode_string(4, optional_data); + GlobalLogger.debug() << "Done creating echo request" << std::endl; } IcmpEchoData(const std::size_t size_arg) @@ -95,6 +96,17 @@ public: << " time=" << elapsed_time << " ms" << std::endl; } + std::string to_string() const + { + std::stringstream buf; + buf << "[EchoData ID=" << std::showbase << std::hex << get_identifier() + << ",seq.nr=" << std::noshowbase << std::dec<< get_sequence_number() + << ",data of size " << IcmpData::size-4; + //for (int idx=4; idx < IcmpData::size; ++idx) + // buf << IcmpData::raw_data[idx]; + buf << "]"; + return buf.str(); + } }; #endif diff --git a/src/icmp/icmpheader.h b/src/icmp/icmpheader.h index b9922d9..98d02fa 100644 --- a/src/icmp/icmpheader.h +++ b/src/icmp/icmpheader.h @@ -25,8 +25,12 @@ #include #include +#include #include +#include +using I2n::Logger::GlobalLogger; + /** @brief first 4 byte of ICMP header (v4 and v6) * * In ICMP v4, the first 4 bytes are standardized, the other 4 depend on @@ -77,10 +81,11 @@ public: checksum = static_cast( ~sum ); } - bool write(std::ostream &os) const + std::ostream& write(std::ostream &os) const { - os << type << code << checksum; - return os.good(); + uint8_t checksum_lsb = static_cast(checksum & 0x00FF); + uint8_t checksum_msb = static_cast((checksum & 0xFF00) >> 8); + os << type << code << checksum_msb << checksum_lsb; } // returns the amount of data represented by this class; @@ -88,10 +93,19 @@ public: uint16_t get_header_length() const { return 4; } + std::string to_string() const + { + std::stringstream buf; + buf << "[Icmp header type=" << static_cast(type) + << ",code=" << static_cast(code) + << " (cksum:" << std::showbase << std::hex << checksum << ")]"; + return buf.str(); + } + protected: uint8_t type; uint8_t code; - uint16_t checksum; // to be used in check_integrity + uint16_t checksum; }; diff --git a/src/icmp/icmppacket.cpp b/src/icmp/icmppacket.cpp index f92bdec..5862e65 100644 --- a/src/icmp/icmppacket.cpp +++ b/src/icmp/icmppacket.cpp @@ -23,6 +23,7 @@ #include "icmp/icmppacket.h" #include +#include #include #include @@ -47,7 +48,17 @@ IcmpPacket::ReadReturnCode IcmpPacket::read( std::istream &is ) return IcmpPacket::ReadReturnCode_BAD_STREAM; // try to read ip header - uint8_t version = static_cast( is.peek() ); + uint8_t version_with_ihl = static_cast( is.peek() ); + uint8_t version = (version_with_ihl & 0xF0) >> 4; + + if ( version != ip_head_ptr->get_version() ) + { + GlobalLogger.error() << "IP version given to constructor (" + << static_cast(ip_head_ptr->get_version()) << ") does not " + << "match the on in input stream (" << static_cast(version) + << ")!" << std::endl; + BOOST_ASSERT( !"Inconsistent IP version!" ); + } if (version == 4) { Ipv4Header *new_header = new Ipv4Header(); @@ -60,8 +71,12 @@ IcmpPacket::ReadReturnCode IcmpPacket::read( std::istream &is ) is >> *new_header; ip_head_ptr.reset( new_header ); } - else // pingcheck-type error throwing + else + { // pingcheck-type error throwing + GlobalLogger.error() << "Invalid IP version: " + << static_cast(version) << "!" << std::endl; BOOST_ASSERT( !"Invalid IP version!" ); + } if ( is.eof() ) return IcmpPacket::ReadReturnCode_NOT_ENOUGH_DATA; @@ -77,9 +92,10 @@ IcmpPacket::ReadReturnCode IcmpPacket::read( std::istream &is ) return IcmpPacket::ReadReturnCode_BAD_STREAM; // calculate the size of the ICMP data - std::streamsize data_length = static_cast( ip_head_ptr->get_total_length() ) - - static_cast( ip_head_ptr->get_header_length() ) - - static_cast( icmp_header.get_header_length() ); + std::streamsize data_length = + static_cast( ip_head_ptr->get_total_length() ) + - static_cast( ip_head_ptr->get_header_length() ) + - static_cast( icmp_header.get_header_length() ); // try to read that amount of data if ( data_length < 0 ) @@ -184,4 +200,17 @@ std::ostream& operator<<( return os; } + +std::string IcmpPacket::to_string() const +{ + std::stringstream buf; + buf << "[IcmpPacket: "; + buf << ip_head_ptr->to_string() << ", "; + buf << icmp_header.to_string() << ", "; + buf << icmp_data_ptr->to_string(); + buf << "]"; + return buf.str(); +} + + // (created using vim -- the world's best text editor) diff --git a/src/icmp/icmppacket.h b/src/icmp/icmppacket.h index d726ca5..c2d0389 100644 --- a/src/icmp/icmppacket.h +++ b/src/icmp/icmppacket.h @@ -63,11 +63,18 @@ public: static std::string return_code_to_string( const ReadReturnCode &code ); - IcmpPacket() + IcmpPacket(const icmp::socket::protocol_type &protocol) : ip_head_ptr() , icmp_header() , icmp_data_ptr() - {} + { + if ( icmp::v4() == protocol ) + ip_head_ptr.reset( new Ipv4Header() ); + else if ( icmp::v6() == protocol ) + ip_head_ptr.reset( new Ipv6Header() ); + else // pingcheck-type throwing of exceptions: + BOOST_ASSERT( !"Invalid IP version, need 4 or 6!" ); + } // IP header is created with only 0s, is not used in write, anyway IcmpPacket(const icmp::socket::protocol_type &protocol, @@ -148,6 +155,8 @@ public: ReadReturnCode read(std::istream &is); bool write(std::ostream &os) const; + + std::string to_string() const; }; typedef boost::shared_ptr IcmpPacketItem; diff --git a/src/icmp/icmppacketfactory.cpp b/src/icmp/icmppacketfactory.cpp index ddfd9fe..1b4ccf4 100644 --- a/src/icmp/icmppacketfactory.cpp +++ b/src/icmp/icmppacketfactory.cpp @@ -143,7 +143,7 @@ IcmpPacketItem IcmpPacketFactory::create_icmp_packet( IcmpPacketItem icmp_packet; if ( icmp::v4() == protocol || icmp::v6() == protocol ) - icmp_packet.reset( new IcmpPacket() ); + icmp_packet.reset( new IcmpPacket( protocol ) ); else { GlobalLogger.warning() << "ICMP packet creation failed: " @@ -163,9 +163,6 @@ IcmpPacketItem IcmpPacketFactory::create_icmp_packet( // read all data into backup ostream backup_filler(&data_backup); backup_filler << is.rdbuf(); - //GlobalLogger.debug() << "Copied ICMP raw data (" - // << data_backup.str().size(); - // << " bytes) for dumping in case of broken packet" << endl; // create a new stream from backup buffer // and use that in read @@ -231,6 +228,8 @@ IcmpPacketItem IcmpPacketFactory::create_icmp_packet_echo_request( IcmpPacketItem icmp_packet( new IcmpPacket( protocol, icmp_header, icmp_data ) ); + GlobalLogger.debug() << "IcmpPacketFactory: created " + << icmp_packet->to_string() << std::endl; return icmp_packet; } diff --git a/src/icmp/icmppinger.cpp b/src/icmp/icmppinger.cpp index 496738e..5837062 100644 --- a/src/icmp/icmppinger.cpp +++ b/src/icmp/icmppinger.cpp @@ -211,6 +211,7 @@ bool IcmpPinger::send_echo_request( const IcmpPacketItem icmp_packet ) << DestinationEndpoint.address().to_string() << ": sending ping" << endl; const_buffers_1 data = request_buffer.data(); + // Block until send the data bytes_sent = PacketDistributor->get_socket()->send_to( data, DestinationEndpoint ); if ( bytes_sent != buffer_size( data ) ) @@ -512,6 +513,9 @@ void IcmpPacketDistributor::handle_receive( } else { + GlobalLogger.debug() << "Succesfully parsed ICMP packet" + << std::endl; + // check which pinger wants this packet bool packet_matches = false; BOOST_FOREACH( const IcmpPingerItem &pinger, PingerList ) diff --git a/src/ip/ipheader.h b/src/ip/ipheader.h index 1fff074..a103884 100644 --- a/src/ip/ipheader.h +++ b/src/ip/ipheader.h @@ -43,6 +43,8 @@ public: virtual ~IpHeader() {} + virtual std::string to_string() const + { return "[IP header]"; } }; typedef boost::shared_ptr IpHeaderPtr; diff --git a/src/ip/ipv4header.cpp b/src/ip/ipv4header.cpp index 299b4e4..a4649ab 100644 --- a/src/ip/ipv4header.cpp +++ b/src/ip/ipv4header.cpp @@ -28,6 +28,11 @@ static const size_t Ipv4HeaderSizeInBytes_withoutOptions = 20; Ipv4Header::Ipv4Header() : Payload( Ipv4HeaderSizeInBytes_withoutOptions ) { + // encode a 4 into the first 4 bits + Payload.encode1(0, 0, 0); + Payload.encode1(0, 1, 1); + Payload.encode1(0, 2, 0); + Payload.encode1(0, 3, 0); } /** diff --git a/src/ip/ipv6header.cpp b/src/ip/ipv6header.cpp index ca03580..4faa518 100644 --- a/src/ip/ipv6header.cpp +++ b/src/ip/ipv6header.cpp @@ -28,6 +28,11 @@ static const size_t Ipv6HeaderSizeInBytes = 40; Ipv6Header::Ipv6Header() : Payload( Ipv6HeaderSizeInBytes ) { + // encode a 6 into the first 4 bits + Payload.encode1(0, 0, 0); + Payload.encode1(0, 1, 1); + Payload.encode1(0, 2, 1); + Payload.encode1(0, 3, 0); } /** diff --git a/src/main.cpp b/src/main.cpp index 003622b..2f6be63 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -390,7 +390,6 @@ void signal_checker( const boost::system::error_code &error ) } else { // re-schedule timer - GlobalLogger.debug() << "Setting another signal timer" << endl; signal_data.check_timer->expires_from_now( SIGNAL_CHECK_INTERVAL ); signal_data.check_timer->async_wait( signal_checker ); } @@ -522,12 +521,12 @@ int main( int argc, const char *argv[] ) if ( ret_code == 0 ) { + GlobalLogger.info() << "starting io_service main loop" << endl; // call boost::asio main event loop, catching exceptions while ( !signal_data.stopped ) { try { - GlobalLogger.info() << "starting/continuing io_service main loop" << endl; io_service->run(); } catch ( const std::exception &ex ) @@ -547,6 +546,7 @@ int main( int argc, const char *argv[] ) signal_data.stopped = true; break; } + GlobalLogger.info() << "continuing io_service main loop" << endl; } }