From 0f51bea349fd7d644365755c7a79763fe4a23dd6 Mon Sep 17 00:00:00 2001 From: Guilherme Maciel Ferreira Date: Mon, 24 Oct 2011 22:15:01 -0200 Subject: [PATCH] Bring aboard ICMPv6 header class --- src/icmp/icmptype.h | 1 + src/icmp/icmpv6header.cpp | 192 +++++++++++++++++++++++++++++++++++++++++++++ src/icmp/icmpv6header.h | 88 +++++++++++++++++++++ 3 files changed, 281 insertions(+), 0 deletions(-) create mode 100644 src/icmp/icmpv6header.cpp create mode 100644 src/icmp/icmpv6header.h diff --git a/src/icmp/icmptype.h b/src/icmp/icmptype.h index 0ecb645..b414731 100644 --- a/src/icmp/icmptype.h +++ b/src/icmp/icmptype.h @@ -28,6 +28,7 @@ enum Icmpv4Type enum Icmpv6Type { + Icmpv6Type_First = 0, // ICMPv6 Error Messages Icmpv6Type_DestinationUnreachable = 1, Icmpv6Type_PacketTooBig = 2, diff --git a/src/icmp/icmpv6header.cpp b/src/icmp/icmpv6header.cpp new file mode 100644 index 0000000..47b3afa --- /dev/null +++ b/src/icmp/icmpv6header.cpp @@ -0,0 +1,192 @@ +// Copyright (c) 2003-2010 Christopher M. Kohlhoff +// Modifications (c) 2011 by Guilherme Maciel Ferreira / Intra2net AG +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#include "icmp/icmpv6header.h" + +#include "icmp/icmpdestinationunreachablemessage.h" +#include "icmp/icmpechoreplymessage.h" +#include "icmp/icmpechorequestmessage.h" +#include "icmp/icmpgenericmessage.h" + +using namespace std; +using boost::shared_ptr; + +//----------------------------------------------------------------------------- +// Icmpv6Header +//----------------------------------------------------------------------------- + +Icmpv6Header::Icmpv6Header() : + MessageFormat() +{ +} + +Icmpv6Header::Icmpv6Header( + Icmpv6Type type, + uint8_t code, + uint16_t checksum, + uint16_t identifier, + uint16_t sequence_number +) : + MessageFormat() +{ + set_icmp_message_format( type ); + + set_type( type ); + set_code( code ); + set_checksum( checksum ); + set_identifier( identifier ); + set_sequence_number( sequence_number ); +} + +Icmpv6Type Icmpv6Header::get_type() const +{ + return get_icmp_message_format()->get_type_v6(); +} + +void Icmpv6Header::set_type( Icmpv6Type type ) +{ + get_icmp_message_format()->set_type_v6( type ); +} + +uint8_t Icmpv6Header::get_code() const +{ + return get_icmp_message_format()->get_code(); +} + +void Icmpv6Header::set_code( uint8_t code ) +{ + get_icmp_message_format()->set_code( code ); +} + +uint16_t Icmpv6Header::get_checksum() const +{ + return get_icmp_message_format()->get_checksum(); +} + +void Icmpv6Header::set_checksum( uint16_t checksum ) +{ + get_icmp_message_format()->set_checksum( checksum ); +} + +uint16_t Icmpv6Header::get_identifier() const +{ + return get_icmp_message_format()->get_identifier(); +} + +void Icmpv6Header::set_identifier( uint16_t identifier ) +{ + get_icmp_message_format()->set_identifier( identifier ); +} + +uint16_t Icmpv6Header::get_sequence_number() const +{ + return get_icmp_message_format()->get_sequence_number(); +} + +void Icmpv6Header::set_sequence_number( uint16_t sequence_number ) +{ + get_icmp_message_format()->set_sequence_number( sequence_number ); +} + +shared_ptr Icmpv6Header::get_icmp_message_format() const +{ + BOOST_ASSERT( MessageFormat.get() != NULL ); + + return MessageFormat; +} + +void Icmpv6Header::set_icmp_message_format( const Icmpv6Type type ) +{ + BOOST_ASSERT( MessageFormat.get() == NULL ); + + if ( MessageFormat.get() == NULL ) + { + switch ( type ) + { + case Icmpv6Type_EchoReply: + MessageFormat.reset( new IcmpEchoReplyMessage ); + break; + case Icmpv6Type_EchoRequest: + MessageFormat.reset( new IcmpEchoRequestMessage ); + break; + case Icmpv6Type_DestinationUnreachable: + MessageFormat.reset( + new IcmpDestinationUnreachableMessage + ); + break; + case Icmpv6Type_PacketTooBig: + case Icmpv6Type_TimeExceeded: + case Icmpv6Type_ParameterProblem: + case Icmpv6Type_RouterSolicitation: + case Icmpv6Type_RouterAdvertisement: + case Icmpv6Type_NeighborSolicitation: + case Icmpv6Type_NeighborAdvertisement: + case Icmpv6Type_RedirectMessage: + case Icmpv6Type_RouterRenumbering: + case Icmpv6Type_ICMPNodeInformationQuery: + case Icmpv6Type_ICMPNodeInformationResponse: + case Icmpv6Type_InverseNeighborDiscoverySolicitationMessage: + case Icmpv6Type_InverseNeighborDiscoveryAdvertisementMessage: + case Icmpv6Type_MulticastListenerDiscovery: + case Icmpv6Type_HomeAgentAddressDiscoveryRequestMessage: + case Icmpv6Type_HomeAgentAddressDiscoveryReplyMessage: + case Icmpv6Type_MobilePrefixSolicitation: + case Icmpv6Type_MobilePrefixAdvertisement: + case Icmpv6Type_CertificationPathSolicitation: + case Icmpv6Type_CertificationPathAdvertisement: + case Icmpv6Type_MulticastRouterAdvertisement: + case Icmpv6Type_MulticastRouterSolicitation: + case Icmpv6Type_MulticastRouterTermination: + case Icmpv6Type_Generic: + MessageFormat.reset( new IcmpGenericMessage ); + break; + case Icmpv6Type_InvalidLast: + default: + BOOST_ASSERT( false ); + break; + } + + MessageFormat->init( type ); + } + + BOOST_ASSERT( MessageFormat.get() != NULL ); + BOOST_ASSERT( MessageFormat->get_type_v6() != Icmpv6Type_InvalidLast ); +} + +void Icmpv6Header::set_icmp_message_format( std::istream &is ) +{ + // read the first byte, which contains the type of the ICMP message + uint8_t first_byte = 0; + (void) is.read( reinterpret_cast(&first_byte), 1 ); + + // must keep the stream intact, so place the read byte back + (void) is.putback( first_byte ); + + // now select the message format for the given type + Icmpv6Type header_type = static_cast( first_byte ); + set_icmp_message_format( header_type ); +} + +std::istream& operator>>( + std::istream &is, + Icmpv6Header &header +) +{ + // 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<<( + std::ostream &os, + const Icmpv6Header &header +) +{ + // delegate the writing of the fields to a specialized encoder + return header.get_icmp_message_format()->write( os ); +} diff --git a/src/icmp/icmpv6header.h b/src/icmp/icmpv6header.h new file mode 100644 index 0000000..227348d --- /dev/null +++ b/src/icmp/icmpv6header.h @@ -0,0 +1,88 @@ +// Copyright (c) 2003-2010 Christopher M. Kohlhoff +// Modifications (c) 2011 by Guilherme Maciel Ferreira / Intra2net AG +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef ICMPV6_HEADER_H +#define ICMPV6_HEADER_H + +#include + +#include +#include + +#include + +#include "icmp/icmpmessage.h" +#include "icmp/icmptype.h" + +//----------------------------------------------------------------------------- +// Icmpv6Header +//----------------------------------------------------------------------------- + +/** + * @brief This class represents the ICMP version 6 Header. + * + * The ICMP Generic Header Format is: + * + * @code + * 0 8 16 31 + * +---------------+---------------+------------------------------+ --- + * | | | | ^ + * | type | code | checksum | 4 bytes + * | | | | v + * +---------------+---------------+------------------------------+ --- + * | | + * | specific to each message | + * | | + * +-------------------------------+------------------------------+ + * @endcode + */ +class Icmpv6Header +{ +public: + Icmpv6Header(); + Icmpv6Header( + Icmpv6Type type, + uint8_t code, + uint16_t checksum, + uint16_t identifier, + uint16_t sequence_number + ); + + Icmpv6Type get_type() const; + void set_type( const Icmpv6Type 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 ); + + boost::shared_ptr get_icmp_message_format() const; + void set_icmp_message_format( const Icmpv6Type type ); + void set_icmp_message_format( std::istream &is ); + + friend std::istream& operator>>( + std::istream &is, + Icmpv6Header &header + ); + friend std::ostream& operator<<( + std::ostream &os, + const Icmpv6Header &header + ); + +private: + /// Changeable pointer to different ICMP messages types. + boost::shared_ptr MessageFormat; + +}; + +#endif // ICMPV6_HEADER_H -- 1.7.1