From: Guilherme Maciel Ferreira Date: Fri, 4 Nov 2011 02:51:50 +0000 (-0200) Subject: Bring aboard ICMP packet factory. X-Git-Tag: v1.2~41 X-Git-Url: http://developer.intra2net.com/git/?a=commitdiff_plain;h=0fb1a7123c714e0dafc2657c2662041edcac96f6;p=pingcheck Bring aboard ICMP packet factory. - This class handles the packet creation for ICMPv4 and ICMPv6 --- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 82d52d0..089be10 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -49,9 +49,12 @@ set(SOURCES icmp/icmpechorequestmessage.cpp icmp/icmpgenericmessage.cpp icmp/icmpv4header.cpp + icmp/icmpv6header.cpp icmp/icmpmessage.cpp icmp/icmpv4packet.cpp + icmp/icmpv6packet.cpp icmp/icmppacket.cpp + icmp/icmppacketfactory.cpp icmp/icmppinger.cpp ip/ipv4header.cpp ip/ipv6header.cpp diff --git a/src/icmp/icmppacketfactory.cpp b/src/icmp/icmppacketfactory.cpp new file mode 100644 index 0000000..be9405c --- /dev/null +++ b/src/icmp/icmppacketfactory.cpp @@ -0,0 +1,143 @@ +/* + 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. + */ + +#include "icmp/icmppacketfactory.h" + +#include + +#include + +#include "icmp/icmpchecksum.h" +#include "icmp/icmpdata.h" +#include "icmp/icmptype.h" +#include "icmp/icmpv4header.h" +#include "icmp/icmpv4packet.h" +#include "icmp/icmpv6header.h" +#include "icmp/icmpv6packet.h" + +using namespace std; +using I2n::Logger::GlobalLogger; + +//----------------------------------------------------------------------------- +// IcmpPacketFactory +//----------------------------------------------------------------------------- + +IcmpPacketItem IcmpPacketFactory::create_icmp_packet( + const IpVersion version, + istream &is +) +{ + BOOST_ASSERT( (IP_VERSION_4 == version) || (IP_VERSION_6 == version) ); + + IcmpPacketItem icmp_packet; + + switch ( version ) + { + case IP_VERSION_4: + icmp_packet.reset(new Icmpv4Packet()); + break; + case IP_VERSION_6: + icmp_packet.reset(new Icmpv6Packet()); + break; + default: + BOOST_ASSERT( !"Invalid ICMP Packet Type." ); + break; + } + + if ( !icmp_packet->read( is ) ) + { + GlobalLogger.notice() << "Could not read ICMP packet." << endl; + + IcmpPacketItem icmp_packet_empty; + icmp_packet = icmp_packet_empty; + } + + return icmp_packet; +} + +IcmpPacketItem IcmpPacketFactory::create_icmp_packet_echo_request( + const IpVersion version, + const uint16_t identifier, + const uint16_t sequence_number +) +{ + BOOST_ASSERT( (IP_VERSION_4 == version) || (IP_VERSION_6 == version) ); + + IcmpPacketItem icmp_packet; + + switch (version) + { + case IP_VERSION_4: + icmp_packet = create_icmpv4_packet_echo_request( identifier, sequence_number ); + break; + case IP_VERSION_6: + icmp_packet = create_icmpv6_packet_echo_request( identifier, sequence_number ); + break; + default: + BOOST_ASSERT( !"Invalid ICMP Packet Type." ); + break; + } + + return icmp_packet; +} + +IcmpPacketItem IcmpPacketFactory::create_icmpv4_packet_echo_request( + const uint16_t identifier, + const uint16_t sequence_number +) +{ + const IcmpData icmp_data( "ping-message" ); + + Icmpv4Type type = Icmpv4Type_EchoRequest; + uint8_t code = 0; + IcmpChecksum calculator( icmp_data.begin(), icmp_data.end() ); + uint16_t checksum = calculator.compute( + type, code, identifier, sequence_number + ); + Icmpv4Header icmp_header( + type, code, checksum, identifier, sequence_number + ); + IcmpPacketItem icmp_packet(new Icmpv4Packet( icmp_header, icmp_data )); + + return icmp_packet; +} + +IcmpPacketItem IcmpPacketFactory::create_icmpv6_packet_echo_request( + const uint16_t identifier, + const uint16_t sequence_number +) +{ + const IcmpData icmp_data( "ping-message" ); + + Icmpv6Type type = Icmpv6Type_EchoRequest; + uint8_t code = 0; + IcmpChecksum calculator( icmp_data.begin(), icmp_data.end() ); + uint16_t checksum = calculator.compute( + type, code, identifier, sequence_number + ); + Icmpv6Header icmp_header( + type, code, checksum, identifier, sequence_number + ); + IcmpPacketItem icmp_packet(new Icmpv6Packet( icmp_header, icmp_data )); + + return icmp_packet; +} + + diff --git a/src/icmp/icmppacketfactory.h b/src/icmp/icmppacketfactory.h new file mode 100644 index 0000000..2d774ee --- /dev/null +++ b/src/icmp/icmppacketfactory.h @@ -0,0 +1,64 @@ +/* + 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. + */ + +#ifndef ICMP_PACKET_FACTORY_H +#define ICMP_PACKET_FACTORY_H + +#include + +#include + +#include "icmp/icmppacket.h" +#include "ip/ipversion.h" + +//----------------------------------------------------------------------------- +// IcmpPacketFactory +//----------------------------------------------------------------------------- + +/** + * @brief Class which constructs ICMP Packets, hiding from the class users the + * underlying details on how to build each packet. + */ +class IcmpPacketFactory +{ +public: + static IcmpPacketItem create_icmp_packet( + const IpVersion version, + std::istream &is + ); + static IcmpPacketItem create_icmp_packet_echo_request( + const IpVersion type, + const uint16_t identifier, + const uint16_t sequence_number + ); + +private: + static IcmpPacketItem create_icmpv4_packet_echo_request( + const uint16_t identifier, + const uint16_t sequence_number + ); + static IcmpPacketItem create_icmpv6_packet_echo_request( + const uint16_t identifier, + const uint16_t sequence_number + ); + +}; + +#endif // ICMP_PACKET_FACTORY_H diff --git a/src/icmp/icmpv4packet.cpp b/src/icmp/icmpv4packet.cpp index 0a60aa8..180d464 100644 --- a/src/icmp/icmpv4packet.cpp +++ b/src/icmp/icmpv4packet.cpp @@ -204,6 +204,8 @@ void Icmpv4Packet::print_destination_unreachable() const bool Icmpv4Packet::read( istream &is ) { + is.clear(); + is >> *this; return is.fail(); diff --git a/src/icmp/icmpv6packet.cpp b/src/icmp/icmpv6packet.cpp index ecaff54..1823d31 100644 --- a/src/icmp/icmpv6packet.cpp +++ b/src/icmp/icmpv6packet.cpp @@ -204,6 +204,8 @@ void Icmpv6Packet::print_destination_unreachable() const bool Icmpv6Packet::read( istream &is ) { + is.clear(); + is >> *this; return is.fail(); diff --git a/src/ip/ipversion.h b/src/ip/ipversion.h new file mode 100644 index 0000000..feab94b --- /dev/null +++ b/src/ip/ipversion.h @@ -0,0 +1,30 @@ +/* +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. +*/ + +#ifndef IP_VERSION_H +#define IP_VERSION_H + +enum IpVersion +{ + IP_VERSION_4, + IP_VERSION_6 +}; + +#endif // IP_VERSION_H