- IcmpType enum separated from the IcmpHeader class, thus it has its own header without requiring to add the IcmpHeader's header file
- the IcmpHeader class delegates the parsing polymorphically to specialized IcmpMessage classes (i.e. allowing the parsing of Destination unreachable messages)
- IcmpHeader class does not requires the Payload member variable anymore, once it delegates the parsing to IcmpMessage classes
config/host.cpp
dns/dnsresolver.cpp
dns/hostaddress.cpp
+ icmp/icmpdestinationunreachablemessage.cpp
+ icmp/icmpechoreplymessage.cpp
+ icmp/icmpechorequestmessage.cpp
+ icmp/icmpgenericmessage.cpp
+ icmp/icmpmessage.cpp
icmp/icmpheader.cpp
icmp/icmppacket.cpp
icmp/ipv4header.cpp
--- /dev/null
+#include "icmp/icmpdestinationunreachablemessage.h"
+
+using namespace std;
+
+//-----------------------------------------------------------------------------
+// IcmpDestinationUnreachableMessage
+//-----------------------------------------------------------------------------
+
+const int IcmpDestinationUnreachableMessage::MessageSizeInBytes = 44;
+
+IcmpDestinationUnreachableMessage::IcmpDestinationUnreachableMessage()
+{
+ fill( Payload, Payload + sizeof(Payload), 0 );
+
+ set_type( IcmpType_InvalidLast );
+ set_code( 0 );
+ set_checksum( 0 );
+ set_identifier( 0 );
+ set_sequence_number( 0 );
+}
+
+IcmpDestinationUnreachableMessage::IcmpDestinationUnreachableMessage(
+ const IcmpType type,
+ const uint8_t code,
+ const uint16_t checksum,
+ const uint16_t identifier,
+ const uint16_t sequence_number
+)
+{
+ fill( Payload, Payload + sizeof(Payload), 0 );
+
+ set_type( type );
+ set_code( code );
+ set_checksum( checksum );
+ set_identifier( identifier );
+ set_sequence_number( sequence_number );
+}
+
+IcmpDestinationUnreachableMessage::~IcmpDestinationUnreachableMessage()
+{
+}
+
+IcmpType IcmpDestinationUnreachableMessage::get_type() const
+{
+ IcmpType type = static_cast<IcmpType> ( Payload[ 0 ] );
+
+ return type;
+}
+
+void IcmpDestinationUnreachableMessage::set_type( IcmpType type )
+{
+ uint8_t n = static_cast<uint8_t> ( type );
+
+ Payload[ 0 ] = n;
+}
+
+uint8_t IcmpDestinationUnreachableMessage::get_code() const
+{
+ return Payload[ 1 ];
+}
+
+void IcmpDestinationUnreachableMessage::set_code( uint8_t code )
+{
+ Payload[ 1 ] = code;
+}
+
+uint16_t IcmpDestinationUnreachableMessage::get_checksum() const
+{
+ return decode( 2, 3 );
+}
+
+void IcmpDestinationUnreachableMessage::set_checksum( uint16_t checksum )
+{
+ encode( 2, 3, checksum );
+}
+
+uint16_t IcmpDestinationUnreachableMessage::get_identifier() const
+{
+ return decode( 32, 33 );
+}
+
+void IcmpDestinationUnreachableMessage::set_identifier(
+ const uint16_t identifier
+)
+{
+ encode( 32, 33, identifier );
+}
+
+uint16_t IcmpDestinationUnreachableMessage::get_sequence_number() const
+{
+ return decode( 34, 35 );
+}
+
+void IcmpDestinationUnreachableMessage::set_sequence_number(
+ const uint16_t sequence_number
+)
+{
+ encode( 34, 35, sequence_number );
+}
+
+std::istream& IcmpDestinationUnreachableMessage::read( std::istream &is )
+{
+ return is.read(
+ reinterpret_cast<char *> ( Payload ),
+ IcmpDestinationUnreachableMessage::MessageSizeInBytes
+ );
+}
+
+std::ostream& IcmpDestinationUnreachableMessage::write(
+ std::ostream &os
+) const
+{
+ return os.write(
+ reinterpret_cast<const char *> ( Payload ),
+ IcmpDestinationUnreachableMessage::MessageSizeInBytes
+ );
+}
+
+uint16_t IcmpDestinationUnreachableMessage::decode( int left_byte, int right_byte ) const
+{
+ return ( Payload[ left_byte ] << 8 ) + Payload[ right_byte ];
+}
+
+void IcmpDestinationUnreachableMessage::encode( int left_byte, int right_byte, uint16_t value )
+{
+ Payload[ left_byte ] = static_cast<uint8_t> ( value >> 8 );
+ Payload[ right_byte ] = static_cast<uint8_t> ( value & 0xFF );
+}
--- /dev/null
+#ifndef ICMP_DESTINATION_UNREACHABLE_MESSAGE_HPP
+#define ICMP_DESTINATION_UNREACHABLE_MESSAGE_HPP
+
+#include <stdint.h>
+
+#include <istream>
+#include <ostream>
+
+#include "icmp/icmpmessage.h"
+
+//-----------------------------------------------------------------------------
+// IcmpDestinationUnreachableMessage
+//-----------------------------------------------------------------------------
+//
+// ICMP Destination Unreachable Message Format
+
+// 0 8 16 31
+// +---------------+---------------+------------------------------+ ---
+// | | | | ^
+// | type | code | checksum | |
+// | | | | |
+// +---------------+---------------+------------------------------+ 8 bytes
+// | | |
+// | unused | |
+// | | v
+// +-------------------------------+------------------------------+ ---
+// | | ^
+// | Internet Protocol (IP) Header | 20 bytes
+// | | v
+// +-------------------------------+------------------------------+ ---
+// | | ^
+// | Original ICMP Data Datagram | 20 bytes
+// | | v
+// +-------------------------------+------------------------------+ ---
+//
+//-----------------------------------------------------------------------------
+
+class IcmpDestinationUnreachableMessage : public IcmpMessage
+{
+public:
+ IcmpDestinationUnreachableMessage();
+ IcmpDestinationUnreachableMessage(
+ const IcmpType type,
+ const uint8_t code,
+ const uint16_t checksum,
+ const uint16_t identifier,
+ const uint16_t sequence_number
+ );
+ virtual ~IcmpDestinationUnreachableMessage();
+
+ IcmpType get_type() const;
+ void set_type( const IcmpType type );
+
+ uint8_t get_code() const;
+ void set_code( const uint8_t code );
+
+ uint16_t get_checksum() const;
+ void set_checksum( const uint16_t checksum );
+
+ uint16_t get_identifier() const;
+ void set_identifier( const uint16_t identifier );
+
+ uint16_t get_sequence_number() const;
+ void set_sequence_number( const uint16_t sequence_number );
+
+ std::istream& read( std::istream &is );
+ std::ostream& write( std::ostream &os ) const;
+
+private:
+ uint16_t decode( int left_byte, int right_byte ) const;
+ void encode( int left_byte, int right_byte, uint16_t value );
+
+private:
+ static const int MessageSizeInBytes;
+ uint8_t Payload[ 44 ];
+
+};
+
+#endif // ICMP_DESTINATION_UNREACHABLE_MESSAGE_HPP
--- /dev/null
+#include "icmp/icmpechoreplymessage.h"
+
+using namespace std;
+
+//-----------------------------------------------------------------------------
+// IcmpEchoReplyMessage
+//-----------------------------------------------------------------------------
+
+const int IcmpEchoReplyMessage::MessageSizeInBytes = 8;
+
+IcmpEchoReplyMessage::IcmpEchoReplyMessage()
+{
+ fill( Payload, Payload + sizeof(Payload), 0 );
+
+ set_type( IcmpType_InvalidLast );
+ set_code( 0 );
+ set_checksum( 0 );
+ set_identifier( 0 );
+ set_sequence_number( 0 );
+}
+
+IcmpEchoReplyMessage::IcmpEchoReplyMessage(
+ const IcmpType type,
+ const uint8_t code,
+ const uint16_t checksum,
+ const uint16_t identifier,
+ const uint16_t sequence_number
+)
+{
+ fill( Payload, Payload + sizeof(Payload), 0 );
+
+ set_type( type );
+ set_code( code );
+ set_checksum( checksum );
+ set_identifier( identifier );
+ set_sequence_number( sequence_number );
+}
+
+IcmpEchoReplyMessage::~IcmpEchoReplyMessage()
+{
+}
+
+IcmpType IcmpEchoReplyMessage::get_type() const
+{
+ IcmpType type = static_cast<IcmpType> ( Payload[ 0 ] );
+
+ return type;
+}
+
+void IcmpEchoReplyMessage::set_type( IcmpType type )
+{
+ uint8_t n = static_cast<uint8_t> ( type );
+
+ Payload[ 0 ] = n;
+}
+
+uint8_t IcmpEchoReplyMessage::get_code() const
+{
+ return Payload[ 1 ];
+}
+
+void IcmpEchoReplyMessage::set_code( uint8_t code )
+{
+ Payload[ 1 ] = code;
+}
+
+uint16_t IcmpEchoReplyMessage::get_checksum() const
+{
+ return decode( 2, 3 );
+}
+
+void IcmpEchoReplyMessage::set_checksum( uint16_t checksum )
+{
+ encode( 2, 3, checksum );
+}
+
+uint16_t IcmpEchoReplyMessage::get_identifier() const
+{
+ return decode( 4, 5 );
+}
+
+void IcmpEchoReplyMessage::set_identifier(
+ const uint16_t identifier
+)
+{
+ encode( 4, 5, identifier );
+}
+
+uint16_t IcmpEchoReplyMessage::get_sequence_number() const
+{
+ return decode( 6, 7 );
+}
+
+void IcmpEchoReplyMessage::set_sequence_number(
+ const uint16_t sequence_number
+)
+{
+ encode( 6, 7, sequence_number );
+}
+
+std::istream& IcmpEchoReplyMessage::read( std::istream &is )
+{
+ return is.read(
+ reinterpret_cast<char *> ( Payload ),
+ IcmpEchoReplyMessage::MessageSizeInBytes
+ );
+}
+
+std::ostream& IcmpEchoReplyMessage::write( std::ostream &os ) const
+{
+ return os.write(
+ reinterpret_cast<const char *> ( Payload ),
+ IcmpEchoReplyMessage::MessageSizeInBytes
+ );
+}
+
+uint16_t IcmpEchoReplyMessage::decode( int left_byte, int right_byte ) const
+{
+ return ( Payload[ left_byte ] << 8 ) + Payload[ right_byte ];
+}
+
+void IcmpEchoReplyMessage::encode( int left_byte, int right_byte, uint16_t value )
+{
+ Payload[ left_byte ] = static_cast<uint8_t> ( value >> 8 );
+ Payload[ right_byte ] = static_cast<uint8_t> ( value & 0xFF );
+}
--- /dev/null
+#ifndef ICMP_ECHO_REPLY_MESSAGE_HPP
+#define ICMP_ECHO_REPLY_MESSAGE_HPP
+
+#include <stdint.h>
+
+#include <istream>
+#include <ostream>
+
+#include "icmp/icmpmessage.h"
+
+//-----------------------------------------------------------------------------
+// IcmpEchoReplyMessage
+//-----------------------------------------------------------------------------
+//
+// ICMP Echo Reply Message Format
+//
+// 0 8 16 31
+// +---------------+---------------+------------------------------+ ---
+// | | | | ^
+// | type | code | checksum | |
+// | | | | |
+// +---------------+---------------+------------------------------+ 8 bytes
+// | | | |
+// | identifier | sequence number | |
+// | | | v
+// +-------------------------------+------------------------------+ ---
+// | |
+// | data (n bytes) |
+// | |
+// +-------------------------------+------------------------------+
+//
+//-----------------------------------------------------------------------------
+
+class IcmpEchoReplyMessage : public IcmpMessage
+{
+public:
+ IcmpEchoReplyMessage();
+ IcmpEchoReplyMessage(
+ const IcmpType type,
+ const uint8_t code,
+ const uint16_t checksum,
+ const uint16_t identifier,
+ const uint16_t sequence_number
+ );
+ virtual ~IcmpEchoReplyMessage();
+
+ IcmpType get_type() const;
+ void set_type( const IcmpType type );
+
+ uint8_t get_code() const;
+ void set_code( const uint8_t code );
+
+ uint16_t get_checksum() const;
+ void set_checksum( const uint16_t checksum );
+
+ uint16_t get_identifier() const;
+ void set_identifier( const uint16_t identifier );
+
+ uint16_t get_sequence_number() const;
+ void set_sequence_number( const uint16_t sequence_number );
+
+ std::istream& read( std::istream &is );
+ std::ostream& write( std::ostream &os ) const;
+
+private:
+ uint16_t decode( int left_byte, int right_byte ) const;
+ void encode( int left_byte, int right_byte, uint16_t value );
+
+private:
+ static const int MessageSizeInBytes;
+ uint8_t Payload[ 8 ];
+
+};
+
+#endif // ICMP_ECHO_REPLY_MESSAGE_HPP
--- /dev/null
+#include "icmp/icmpechorequestmessage.h"
+
+using namespace std;
+
+//-----------------------------------------------------------------------------
+// IcmpEchoRequestMessage
+//-----------------------------------------------------------------------------
+
+const int IcmpEchoRequestMessage::MessageSizeInBytes = 8;
+
+IcmpEchoRequestMessage::IcmpEchoRequestMessage()
+{
+ fill( Payload, Payload + sizeof(Payload), 0 );
+
+ set_type( IcmpType_InvalidLast );
+ set_code( 0 );
+ set_checksum( 0 );
+ set_identifier( 0 );
+ set_sequence_number( 0 );
+}
+
+IcmpEchoRequestMessage::IcmpEchoRequestMessage(
+ const IcmpType type,
+ const uint8_t code,
+ const uint16_t checksum,
+ const uint16_t identifier,
+ const uint16_t sequence_number
+)
+{
+ fill( Payload, Payload + sizeof(Payload), 0 );
+
+ set_type( type );
+ set_code( code );
+ set_checksum( checksum );
+ set_identifier( identifier );
+ set_sequence_number( sequence_number );
+}
+
+IcmpEchoRequestMessage::~IcmpEchoRequestMessage()
+{
+}
+
+IcmpType IcmpEchoRequestMessage::get_type() const
+{
+ IcmpType type = static_cast<IcmpType> ( Payload[ 0 ] );
+
+ return type;
+}
+
+void IcmpEchoRequestMessage::set_type( IcmpType type )
+{
+ uint8_t n = static_cast<uint8_t> ( type );
+
+ Payload[ 0 ] = n;
+}
+
+uint8_t IcmpEchoRequestMessage::get_code() const
+{
+ return Payload[ 1 ];
+}
+
+void IcmpEchoRequestMessage::set_code( uint8_t code )
+{
+ Payload[ 1 ] = code;
+}
+
+uint16_t IcmpEchoRequestMessage::get_checksum() const
+{
+ return decode( 2, 3 );
+}
+
+void IcmpEchoRequestMessage::set_checksum( uint16_t checksum )
+{
+ encode( 2, 3, checksum );
+}
+
+uint16_t IcmpEchoRequestMessage::get_identifier() const
+{
+ return decode( 4, 5 );
+}
+
+void IcmpEchoRequestMessage::set_identifier(
+ const uint16_t identifier
+)
+{
+ encode( 4, 5, identifier );
+}
+
+uint16_t IcmpEchoRequestMessage::get_sequence_number() const
+{
+ return decode( 6, 7 );
+}
+
+void IcmpEchoRequestMessage::set_sequence_number(
+ const uint16_t sequence_number
+)
+{
+ encode( 6, 7, sequence_number );
+}
+
+std::istream& IcmpEchoRequestMessage::read( std::istream &is )
+{
+ return is.read(
+ reinterpret_cast<char *> ( Payload ),
+ IcmpEchoRequestMessage::MessageSizeInBytes
+ );
+}
+
+std::ostream& IcmpEchoRequestMessage::write( std::ostream &os ) const
+{
+ return os.write(
+ reinterpret_cast<const char *> ( Payload ),
+ IcmpEchoRequestMessage::MessageSizeInBytes
+ );
+}
+
+uint16_t IcmpEchoRequestMessage::decode( int left_byte, int right_byte ) const
+{
+ return ( Payload[ left_byte ] << 8 ) + Payload[ right_byte ];
+}
+
+void IcmpEchoRequestMessage::encode( int left_byte, int right_byte, uint16_t value )
+{
+ Payload[ left_byte ] = static_cast<uint8_t> ( value >> 8 );
+ Payload[ right_byte ] = static_cast<uint8_t> ( value & 0xFF );
+}
--- /dev/null
+#ifndef ICMP_ECHO_REQUEST_MESSAGE_HPP
+#define ICMP_ECHO_REQUEST_MESSAGE_HPP
+
+#include <stdint.h>
+
+#include <istream>
+#include <ostream>
+
+#include "icmp/icmpmessage.h"
+
+//-----------------------------------------------------------------------------
+// IcmpEchoRequestMessage
+//-----------------------------------------------------------------------------
+//
+// ICMP Echo Request Message Format
+//
+// 0 8 16 31
+// +---------------+---------------+------------------------------+ ---
+// | | | | ^
+// | type | code | checksum | |
+// | | | | |
+// +---------------+---------------+------------------------------+ 8 bytes
+// | | | |
+// | identifier | sequence number | |
+// | | | v
+// +-------------------------------+------------------------------+ ---
+// | |
+// | data (n bytes) |
+// | |
+// +-------------------------------+------------------------------+
+//
+//-----------------------------------------------------------------------------
+
+class IcmpEchoRequestMessage : public IcmpMessage
+{
+public:
+ IcmpEchoRequestMessage();
+ IcmpEchoRequestMessage(
+ const IcmpType type,
+ const uint8_t code,
+ const uint16_t checksum,
+ const uint16_t identifier,
+ const uint16_t sequence_number
+ );
+ virtual ~IcmpEchoRequestMessage();
+
+ IcmpType get_type() const;
+ void set_type( const IcmpType type );
+
+ uint8_t get_code() const;
+ void set_code( const uint8_t code );
+
+ uint16_t get_checksum() const;
+ void set_checksum( const uint16_t checksum );
+
+ uint16_t get_identifier() const;
+ void set_identifier( const uint16_t identifier );
+
+ uint16_t get_sequence_number() const;
+ void set_sequence_number( const uint16_t sequence_number );
+
+ std::istream& read( std::istream &is );
+ std::ostream& write( std::ostream &os ) const;
+
+private:
+ uint16_t decode( int left_byte, int right_byte ) const;
+ void encode( int left_byte, int right_byte, uint16_t value );
+
+private:
+ static const int MessageSizeInBytes;
+ uint8_t Payload[ 8 ];
+
+};
+
+#endif // ICMP_ECHO_REQUEST_MESSAGE_HPP
--- /dev/null
+#include "icmp/icmpgenericmessage.h"
+
+//-----------------------------------------------------------------------------
+// IcmpGenericMessage
+//-----------------------------------------------------------------------------
+
+IcmpGenericMessage::IcmpGenericMessage()
+{
+ set_type( IcmpType_InvalidLast );
+ set_code( 0 );
+ set_checksum( 0 );
+ set_identifier( 0 );
+ set_sequence_number( 0 );
+}
+
+IcmpGenericMessage::IcmpGenericMessage(
+ const IcmpType type,
+ const uint8_t code,
+ const uint16_t checksum,
+ const uint16_t identifier,
+ const uint16_t sequence_number
+)
+{
+ set_type( type );
+ set_code( code );
+ set_checksum( checksum );
+ set_identifier( identifier );
+ set_sequence_number( sequence_number );
+}
+
+IcmpGenericMessage::~IcmpGenericMessage()
+{
+}
+
+IcmpType IcmpGenericMessage::get_type() const
+{
+ return IcmpType_InvalidLast;
+}
+
+void IcmpGenericMessage::set_type( IcmpType )
+{
+}
+
+uint8_t IcmpGenericMessage::get_code() const
+{
+ return 0;
+}
+
+void IcmpGenericMessage::set_code( uint8_t )
+{
+}
+
+uint16_t IcmpGenericMessage::get_checksum() const
+{
+ return 0;
+}
+
+void IcmpGenericMessage::set_checksum( uint16_t )
+{
+}
+
+uint16_t IcmpGenericMessage::get_identifier() const
+{
+ return 0;
+}
+
+void IcmpGenericMessage::set_identifier( uint16_t )
+{
+}
+
+uint16_t IcmpGenericMessage::get_sequence_number() const
+{
+ return 0;
+}
+
+void IcmpGenericMessage::set_sequence_number( uint16_t )
+{
+}
+
+std::istream& IcmpGenericMessage::read( std::istream &is )
+{
+ return is;
+}
+
+std::ostream& IcmpGenericMessage::write( std::ostream &os ) const
+{
+ return os;
+}
--- /dev/null
+#ifndef ICMP_GENERIC_MESSAGE_HPP
+#define ICMP_GENERIC_MESSAGE_HPP
+
+#include <stdint.h>
+
+#include <istream>
+#include <ostream>
+
+#include "icmp/icmpmessage.h"
+
+//-----------------------------------------------------------------------------
+// IcmpGenericMessage
+//-----------------------------------------------------------------------------
+
+/**
+ * This class intends to handle ICMP messages that the application do not
+ * want to read. It acts like a stub.
+ */
+class IcmpGenericMessage : public IcmpMessage
+{
+public:
+ IcmpGenericMessage();
+ IcmpGenericMessage(
+ const IcmpType type,
+ const uint8_t code,
+ const uint16_t checksum,
+ const uint16_t identifier,
+ const uint16_t sequence_number
+ );
+ virtual ~IcmpGenericMessage();
+
+ IcmpType get_type() const;
+ void set_type( const IcmpType type );
+
+ uint8_t get_code() const;
+ void set_code( const uint8_t code );
+
+ uint16_t get_checksum() const;
+ void set_checksum( const uint16_t checksum );
+
+ uint16_t get_identifier() const;
+ void set_identifier( const uint16_t identifier );
+
+ uint16_t get_sequence_number() const;
+ void set_sequence_number( const uint16_t sequence_number );
+
+ std::istream& read( std::istream &is );
+ std::ostream& write( std::ostream &os ) const;
+
+};
+
+#endif // ICMP_GENERIC_MESSAGE_HPP
#include "icmp/icmpheader.h"
+#include "icmp/icmpdestinationunreachablemessage.h"
+#include "icmp/icmpechoreplymessage.h"
+#include "icmp/icmpechorequestmessage.h"
+#include "icmp/icmpgenericmessage.h"
+
+using namespace std;
+using boost::shared_ptr;
+
//-----------------------------------------------------------------------------
// IcmpHeader
//-----------------------------------------------------------------------------
-IcmpHeader::IcmpHeader()
+IcmpHeader::IcmpHeader() :
+ MessageFormat()
{
- std::fill( Payload, Payload + sizeof(Payload), 0 );
}
IcmpHeader::IcmpHeader(
- IcmpHeader::IcmpType type,
+ IcmpType type,
uint8_t code,
uint16_t checksum,
uint16_t identifier,
uint16_t sequence_number
-)
+) :
+ MessageFormat()
{
- std::fill( Payload, Payload + sizeof(Payload), 0 );
+ set_icmp_message_format( type );
set_type( type );
set_code( code );
set_sequence_number( sequence_number );
}
-IcmpHeader::IcmpType IcmpHeader::get_type() const
+IcmpType IcmpHeader::get_type() const
{
- uint8_t n = Payload[ 0 ];
- IcmpHeader::IcmpType type = static_cast<IcmpHeader::IcmpType> ( n );
-
- return type;
+ return get_icmp_message_format()->get_type();
}
-void IcmpHeader::set_type( IcmpHeader::IcmpType type )
+void IcmpHeader::set_type( IcmpType type )
{
- uint8_t n = type;
-
- Payload[ 0 ] = n;
+ get_icmp_message_format()->set_type( type );
}
uint8_t IcmpHeader::get_code() const
{
- return Payload[ 1 ];
+ return get_icmp_message_format()->get_code();
}
void IcmpHeader::set_code( uint8_t code )
{
- Payload[ 1 ] = code;
+ get_icmp_message_format()->set_code( code );
}
uint16_t IcmpHeader::get_checksum() const
{
- return decode( 2, 3 );
+ return get_icmp_message_format()->get_checksum();
}
void IcmpHeader::set_checksum( uint16_t checksum )
{
- encode( 2, 3, checksum );
+ get_icmp_message_format()->set_checksum( checksum );
}
uint16_t IcmpHeader::get_identifier() const
{
- return decode( 4, 5 );
+ return get_icmp_message_format()->get_identifier();
}
void IcmpHeader::set_identifier( uint16_t identifier )
{
- encode( 4, 5, identifier );
+ get_icmp_message_format()->set_identifier( identifier );
}
uint16_t IcmpHeader::get_sequence_number() const
{
- return decode( 6, 7 );
+ return get_icmp_message_format()->get_sequence_number();
}
void IcmpHeader::set_sequence_number( uint16_t sequence_number )
{
- encode( 6, 7, sequence_number );
+ get_icmp_message_format()->set_sequence_number( sequence_number );
+}
+
+shared_ptr<IcmpMessage> IcmpHeader::get_icmp_message_format() const
+{
+ BOOST_ASSERT( MessageFormat.get() != NULL );
+
+ return MessageFormat;
+}
+
+void IcmpHeader::set_icmp_message_format( IcmpType type )
+{
+ BOOST_ASSERT( MessageFormat.get() == NULL );
+
+ if ( MessageFormat.get() == NULL )
+ {
+ switch ( type )
+ {
+ case IcmpType_EchoReply:
+ MessageFormat.reset( new IcmpEchoReplyMessage );
+ break;
+ case IcmpType_EchoRequest:
+ MessageFormat.reset( new IcmpEchoRequestMessage );
+ break;
+ case IcmpType_DestinationUnreachable:
+ MessageFormat.reset(
+ new IcmpDestinationUnreachableMessage );
+ break;
+ default:
+ MessageFormat.reset( new IcmpGenericMessage );
+ break;
+ }
+ }
+}
+
+void IcmpHeader::set_icmp_message_format( std::istream &is )
+{
+ // read the first byte, which contains the type of the ICMP message
+ char first_byte;
+ is.read( &first_byte, 1 );
+
+ // must keep the stream intact, so place the read byte back
+ is.putback( first_byte );
+
+ // now select the message format for the given type
+ IcmpType header_type = static_cast<IcmpType> ( first_byte );
+ set_icmp_message_format( header_type );
}
std::istream& operator>>(
IcmpHeader &header
)
{
- return is.read( reinterpret_cast<char *> ( header.Payload ), 8 );
+ // select the message format which will parse the fields
+ header.set_icmp_message_format( is );
+
+ // delegate the parsing of the fields to a specialized decoder
+ return header.get_icmp_message_format()->read( is );
}
std::ostream& operator<<(
const IcmpHeader &header
)
{
- return os.write( reinterpret_cast<const char *> ( header.Payload ), 8 );
-}
-
-uint16_t IcmpHeader::decode( int left_byte, int right_byte ) const
-{
- return ( Payload[ left_byte ] << 8 ) + Payload[ right_byte ];
-}
-
-void IcmpHeader::encode( int left_byte, int right_byte, uint16_t value )
-{
- Payload[ left_byte ] = static_cast<uint8_t> ( value >> 8 );
- Payload[ right_byte ] = static_cast<uint8_t> ( value & 0xFF );
+ // delegate the writing of the fields to a specialized encoder
+ return header.get_icmp_message_format()->write( os );
}
#include <istream>
#include <ostream>
+#include <boost/shared_ptr.hpp>
+
+#include "icmp/icmpmessage.h"
+#include "icmp/icmptype.h"
+
//-----------------------------------------------------------------------------
// IcmpHeader
//-----------------------------------------------------------------------------
-// ICMP header format
+//
+// ICMP Generic Header Format
//
// 0 8 16 31
-// +---------------+---------------+------------------------------+ ---
-// | | | | ^
-// | type | code | checksum | |
-// | | | | |
-// +---------------+---------------+------------------------------+ 8 bytes
-// | | | |
-// | identifier | sequence number | |
-// | | | v
-// +-------------------------------+------------------------------+ ---
+// +---------------+---------------+------------------------------+ ---
+// | | | | ^
+// | type | code | checksum | 4 bytes
+// | | | | v
+// +---------------+---------------+------------------------------+ ---
+// | |
+// | specific to each message |
+// | |
+// +-------------------------------+------------------------------+
//
//-----------------------------------------------------------------------------
class IcmpHeader
{
public:
- enum IcmpType
- {
- IcmpType_EchoReply = 0,
- IcmpType_DestinationUnreachable = 3,
- IcmpType_SourceQuench = 4,
- IcmpType_Redirect = 5,
- IcmpType_EchoRequest = 8,
- IcmpType_TimeExceeded = 11,
- IcmpType_ParameterProblem = 12,
- IcmpType_TimestampRequest = 13,
- IcmpType_TimestampReply = 14,
- IcmpType_InfoRequest = 15,
- IcmpType_InfoReply = 16,
- IcmpType_AddressRequest = 17,
- IcmpType_AddressReply = 18
- };
-
-public:
IcmpHeader();
IcmpHeader(
IcmpType type,
uint16_t get_sequence_number() const;
void set_sequence_number( const uint16_t sequence_number );
+ boost::shared_ptr<IcmpMessage> get_icmp_message_format() const;
+ void set_icmp_message_format( IcmpType type );
+ void set_icmp_message_format( std::istream &is );
+
friend std::istream& operator>>(
std::istream &is,
IcmpHeader &header
);
private:
- uint16_t decode( int left_byte, int right_byte ) const;
- void encode( int left_byte, int right_byte, uint16_t value );
-
-private:
- uint8_t Payload[ 8 ];
+ boost::shared_ptr<IcmpMessage> MessageFormat;
};
--- /dev/null
+#include "icmp/icmpmessage.h"
+
+//-----------------------------------------------------------------------------
+// IcmpMessage
+//-----------------------------------------------------------------------------
+
+IcmpMessage::IcmpMessage()
+{
+}
+
+IcmpMessage::~IcmpMessage()
+{
+}
--- /dev/null
+#ifndef ICMP_MESSAGE_HPP
+#define ICMP_MESSAGE_HPP
+
+#include <stdint.h>
+
+#include <istream>
+#include <ostream>
+
+#include "icmp/icmptype.h"
+
+//-----------------------------------------------------------------------------
+// IcmpMessage
+//-----------------------------------------------------------------------------
+
+class IcmpMessage
+{
+public:
+ IcmpMessage();
+ virtual ~IcmpMessage();
+
+ virtual IcmpType get_type() const = 0;
+ virtual void set_type( const IcmpType type ) = 0;
+
+ virtual uint8_t get_code() const = 0;
+ virtual void set_code( const uint8_t code ) = 0;
+
+ virtual uint16_t get_checksum() const = 0;
+ virtual void set_checksum( const uint16_t checksum ) = 0;
+
+ virtual uint16_t get_identifier() const = 0;
+ virtual void set_identifier( const uint16_t identifier ) = 0;
+
+ virtual uint16_t get_sequence_number() const = 0;
+ virtual void set_sequence_number( const uint16_t sequence_number ) = 0;
+
+ virtual std::istream& read( std::istream &is ) = 0;
+ virtual std::ostream& write( std::ostream &os ) const = 0;
+
+};
+
+#endif // ICMP_MESSAGE_HPP
}
bool IcmpPacket::match(
- IcmpHeader::IcmpType type,
+ IcmpType type,
uint16_t identifier,
uint16_t sequence_number
) const
#include "icmp/ipv4header.h"
#include "icmp/icmpheader.h"
#include "icmp/icmpdata.h"
+#include "icmp/icmptype.h"
//-----------------------------------------------------------------------------
// IcmpPacket
IcmpData get_icmp_data() const;
bool match(
- IcmpHeader::IcmpType type,
+ IcmpType type,
uint16_t identifier,
uint16_t sequence_number
) const;
--- /dev/null
+#ifndef ICMP_TYPE_H
+#define ICMP_TYPE_H
+
+enum IcmpType
+{
+ IcmpType_EchoReply = 0,
+ IcmpType_DestinationUnreachable = 3,
+ IcmpType_SourceQuench = 4,
+ IcmpType_Redirect = 5,
+ IcmpType_EchoRequest = 8,
+ IcmpType_TimeExceeded = 11,
+ IcmpType_ParameterProblem = 12,
+ IcmpType_TimestampRequest = 13,
+ IcmpType_TimestampReply = 14,
+ IcmpType_InfoRequest = 15,
+ IcmpType_InfoReply = 16,
+ IcmpType_AddressRequest = 17,
+ IcmpType_AddressReply = 18,
+ IcmpType_InvalidLast = 42
+};
+
+#endif /* ICMP_TYPE_H */