#include <logfunc.hpp>
 
-#include "icmp/icmpchecksum.h"
-#include "icmp/icmpdata.h"
-#include "icmp/icmpv4header.h"
-#include "icmp/icmptype.h"
-#include "ip/ipv4header.h"
+#include "icmp/icmppacketfactory.h"
+#include "ip/ipversion.h"
 
 using namespace std;
 using boost::asio::const_buffers_1;
 {
     ++SequenceNumber;
 
-    Icmpv4Packet icmp_echo_request_packet = create_echo_request( SequenceNumber );
+    IcmpPacketItem icmp_packet_echo_request = IcmpPacketFactory::create_icmp_packet_echo_request(
+            IP_VERSION_4, Identifier, SequenceNumber );
 
     BOOST_ASSERT( PingerStatus == PingStatus_NotSent );
-    send_echo_request( icmp_echo_request_packet );
+    send_echo_request( icmp_packet_echo_request );
 }
 
-Icmpv4Packet IcmpPinger::create_echo_request(
-        const uint16_t sequence_number
-) const
-{
-    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
-    );
-
-    return Icmpv4Packet( icmp_header, icmp_data );
-}
-
-void IcmpPinger::send_echo_request( const Icmpv4Packet &icmp_packet )
+void IcmpPinger::send_echo_request( const IcmpPacketItem icmp_packet )
 {
     boost::asio::streambuf request_buffer;
     ostream os( &request_buffer );
-    os << icmp_packet;
+    icmp_packet->write( os );
 
     TimeSent = microsec_clock::universal_time();
 
         }
 
         // Decode the reply packet.
-        Icmpv4Packet icmp_packet;
-        if (! (is >> icmp_packet) )
+        IcmpPacketItem icmp_packet = IcmpPacketFactory::create_icmp_packet( IP_VERSION_4, is );
+        if ( !icmp_packet )
         {
             GlobalLogger.notice() << "Warning: ignoring broken ICMP packet"
                 << endl;
         // expected sequence number, and destination host address (receive just
         // the ICMP packets from the host we had ping).
 
-        if ( icmp_packet.match_echo_reply(
+        if ( icmp_packet->match_echo_reply(
                                 Identifier, SequenceNumber,
                                 DestinationEndpoint.address() ) )
         {
             ReceivedReply = true;
 
-            icmp_packet.print_echo_reply( bytes_transferred, TimeSent );
+            icmp_packet->print_echo_reply( bytes_transferred, TimeSent );
 
             set_ping_status( PingStatus_SuccessReply );
 
             IcmpPacketReceiveTimer.cancel();
         }
-        else if ( icmp_packet.match_destination_unreachable(
+        else if ( icmp_packet->match_destination_unreachable(
                                      Identifier, SequenceNumber,
                                      DestinationEndpoint.address() ) )
         {
             ReceivedReply = true;
 
-            icmp_packet.print_destination_unreachable();
+            icmp_packet->print_destination_unreachable();
 
             set_ping_status( PingStatus_FailureDestinationUnreachable );