--- /dev/null
+/*
+ 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 "tcp/tcpsegmentfactory.h"
+
+#include <boost/assert.hpp>
+
+#include <logfunc.hpp>
+
+#include "tcp/tcpheader.h"
+#include "tcp/tcpipv4segment.h"
+
+using namespace std;
+using boost::asio::ip::address;
+using I2n::Logger::GlobalLogger;
+
+//-----------------------------------------------------------------------------
+// TcpSegmentFactory
+//-----------------------------------------------------------------------------
+
+TcpSegmentItem TcpSegmentFactory::create_tcp_segment(
+ const IpVersion version,
+ std::istream &is
+)
+{
+ BOOST_ASSERT( (IP_VERSION_4 == version) || (IP_VERSION_6 == version) );
+
+ TcpSegmentItem tcp_segment;
+
+ switch ( version )
+ {
+ case IP_VERSION_4:
+ tcp_segment.reset( new TcpIpv4Segment() );
+ break;
+#ifdef IPV6_WORKING
+ case IP_VERSION_6:
+ tcp_segment.reset( new TcpIpv6Segment() );
+ break;
+#endif
+ default:
+ BOOST_ASSERT( !"Invalid TCP Segment Type." );
+ break;
+ }
+
+ if ( !tcp_segment->read( is ) )
+ {
+ GlobalLogger.notice() << "Could not read TCP Segment." << endl;
+
+ // TODO why good packets reports as bad?
+ //IcmpPacketItem icmp_packet_empty;
+ //tcp_segment = icmp_packet_empty;
+ }
+
+ return tcp_segment;
+}
+
+
+TcpSegmentItem TcpSegmentFactory::create_tcp_segment_ack_request(
+ const IpVersion version,
+ const uint32_t source_address,
+ const uint32_t destination_address,
+ const uint16_t source_port,
+ const uint16_t destination_port,
+ const uint16_t sequence_number
+)
+{
+ BOOST_ASSERT( (IP_VERSION_4 == version) || (IP_VERSION_6 == version) );
+
+ TcpSegmentItem tcp_segment;
+
+ switch (version)
+ {
+ case IP_VERSION_4:
+ tcp_segment = create_tcp_ipv4_segment_ack_request(
+ source_address, destination_address,
+ source_port, destination_port, sequence_number );
+ break;
+#ifdef IPV6_WORKING
+ case IP_VERSION_6:
+ tcp_segment = create_tcp_ipv6_segment_ack_request(
+ source_address, destination_address,
+ source_port, destination_port, sequence_number );
+ break;
+#endif
+ default:
+ BOOST_ASSERT( !"Invalid TCP Segment Type." );
+ break;
+ }
+
+ return tcp_segment;
+}
+
+TcpSegmentItem TcpSegmentFactory::create_tcp_ipv4_segment_ack_request(
+ const uint32_t source_address,
+ const uint32_t destination_address,
+ const uint16_t source_port,
+ const uint16_t destination_port,
+ const uint16_t sequence_number
+)
+{
+ // (5 words of 32 bits = 5 * 4 bytes = 20 bytes)
+ const uint8_t header_size_in_words = 5; // size in units of 32 bits
+ const uint16_t window_size_in_octets = 32768;
+
+ // Create an TCP header for an ACK request.
+ TcpHeader tcp_header;
+ tcp_header.set_source_port( source_port ); // assign a random ephemeral port number
+ tcp_header.set_destination_port( destination_port );
+ tcp_header.set_sequence_number( sequence_number );
+ tcp_header.set_header_length( header_size_in_words );
+ tcp_header.set_acknowledgment( true );
+ tcp_header.set_window_size( window_size_in_octets ); // window size
+
+ // Calculate the checksum of the TCP header
+ uint16_t cksum = tcp_header.calculate_tcp_checksum(
+ source_address, destination_address, NULL, 0
+ );
+ tcp_header.set_checksum( cksum );
+
+ TcpSegmentItem tcp_segment( new TcpIpv4Segment( tcp_header ) );
+
+ return tcp_segment;
+}
+
+TcpSegmentItem TcpSegmentFactory::create_tcp_ipv6_segment_ack_request(
+ const address source_address,
+ const address destination_address,
+ const uint16_t source_port,
+ const uint16_t destination_port,
+ const uint16_t sequence_number
+)
+{
+#ifdef IPV6_WORKING
+ // (5 words of 32 bits = 5 * 4 bytes = 20 bytes)
+ const uint8_t header_size_in_words = 5; // size in units of 32 bits
+ const uint16_t window_size_in_octets = 32768;
+
+ // Create an TCP header for an ACK request.
+ TcpHeader tcp_header;
+ tcp_header.set_source_port( source_port ); // assign a random ephemeral port number
+ tcp_header.set_destination_port( destination_port );
+ tcp_header.set_sequence_number( sequence_number );
+ tcp_header.set_header_length( header_size_in_words );
+ tcp_header.set_acknowledgment( true );
+ tcp_header.set_window_size( window_size_in_octets ); // window size
+
+ // Calculate the checksum
+ uint32_t src_address = source_address.to_v6().to_ulong();
+ uint32_t dst_address = destination_address.to_v6().to_ulong();
+ uint16_t cksum = tcp_header.calculate_tcp_checksum(
+ src_address, dst_address, NULL, 0
+ );
+ tcp_header.set_checksum( cksum );
+
+ TcpSegmentItem tcp_segment( new TcpIpv6Segment( tcp_header ) );
+#endif
+ TcpSegmentItem tcp_segment;
+ return tcp_segment;
+}
--- /dev/null
+/*
+ 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 TCP_SEGMENT_FACTORY_H
+#define TCP_SEGMENT_FACTORY_H
+
+#include <stdint.h>
+
+#include <iostream>
+
+#include <boost/asio.hpp>
+
+#include "ip/ipversion.h"
+#include "tcp/tcpsegment.h"
+
+//-----------------------------------------------------------------------------
+// TcpSegmentFactory
+//-----------------------------------------------------------------------------
+
+/**
+ * @brief Class which constructs TCP Segments, hiding from the class users the
+ * underlying details on how to build each segment.
+ */
+class TcpSegmentFactory
+{
+public:
+ static TcpSegmentItem create_tcp_segment(
+ const IpVersion version,
+ std::istream &is
+ );
+ static TcpSegmentItem create_tcp_segment_ack_request(
+ const IpVersion version,
+ const uint32_t source_address,
+ const uint32_t destination_address,
+ const uint16_t source_port,
+ const uint16_t destination_port,
+ const uint16_t sequence_number
+ );
+
+private:
+ static TcpSegmentItem create_tcp_ipv4_segment_ack_request(
+ const uint32_t source_address,
+ const uint32_t destination_address,
+ const uint16_t source_port,
+ const uint16_t destination_port,
+ const uint16_t sequence_number
+ );
+ static TcpSegmentItem create_tcp_ipv6_segment_ack_request(
+ const boost::asio::ip::address source_address,
+ const boost::asio::ip::address destination_address,
+ const uint16_t source_port,
+ const uint16_t destination_port,
+ const uint16_t sequence_number
+ );
+
+};
+
+#endif // TCP_SEGMENT_FACTORY_H