--- /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 PSEUDO_IPV6_HEADER_H
+#define PSEUDO_IPV6_HEADER_H
+
+//-----------------------------------------------------------------------------
+// PseudoIpv6Header
+//-----------------------------------------------------------------------------
+
+/**
+ * @brief This class represents a pseudo IPv6 header used to compute checksum of
+ * transport layer protocols.
+ *
+ * When TCP runs over IPv6, the method used to compute the checksum is defined
+ * in RFC 2460.
+ *
+ * Pseudo IPv6 header format used by TCP and UDP checksums:
+ *
+ * @code
+ * 0 23 24 31
+ * +--------------------------------------------------------------+ ---
+ * | | ^
+ * | | |
+ * | | |
+ * | | |
+ * | | |
+ * | source IPv6 address | |
+ * | | |
+ * | | |
+ * | | |
+ * | | |
+ * | | |
+ * | | |
+ * +--------------------------------------------------------------+ |
+ * | | |
+ * | | |
+ * | | |
+ * | | |
+ * | | 40 bytes
+ * | destination IPv6 address | |
+ * | | |
+ * | | |
+ * | | |
+ * | | |
+ * | | |
+ * | | |
+ * +--------------------------------------------------------------+ |
+ * | | |
+ * | upper-layer packet length in bytes | |
+ * | | |
+ * +-----------------------------------------------+--------------+ |
+ * | | | |
+ * | zero | next header | |
+ * | | | v
+ * +-----------------------------------------------+--------------+ ---
+ * @endcode
+ */
+class PseudoIpv6Header
+{
+public:
+ /// Source IPv6 address
+ uint8_t source_address[16];
+ /// Destination IPv6 address
+ uint8_t destination_address[16];
+ /// The length of the upper-layer header and data (e.g. TCP header plus
+ /// TCP data).
+ uint32_t next_packet_length_in_bytes;
+ /// Zero has 24 bits split among three 8 bits, once there is no uint24_t
+ uint8_t zero_byte[3];
+ /// The header of the next protocol
+ uint8_t next_header;
+
+};
+
+#endif // PSEUDO_IPV6_HEADER_H
#include <boost/assert.hpp>
#include "ip/pseudoipv4header.h"
+#include "ip/pseudoipv6header.h"
using namespace std;
using boost::asio::ip::address_v4;
+using boost::asio::ip::address_v6;
//-----------------------------------------------------------------------------
// TcpHeader
return cksum;
}
+uint16_t TcpHeader::calculate_tcp_checksum(
+ const address_v6::bytes_type &src_addr,
+ const address_v6::bytes_type &dest_addr,
+ const uint8_t* tcp_payload_data,
+ const uint16_t tcp_payload_size_in_bytes )
+{
+ set_checksum( 0 );
+ uint16_t tcp_segment_size_in_bytes = static_cast< uint16_t > (
+ TcpHeaderSizeInBytes + tcp_payload_size_in_bytes
+ );
+
+ PseudoIpv6Header pseudo_header;
+ BOOST_ASSERT( src_addr.size() == sizeof(pseudo_header.source_address) );
+ BOOST_ASSERT( dest_addr.size() == sizeof(pseudo_header.destination_address) );
+ copy( src_addr.begin(), src_addr.end(), pseudo_header.source_address );
+ copy( dest_addr.begin(), dest_addr.end(), pseudo_header.destination_address );
+ fill_n( pseudo_header.zero_byte, 3, 0 );
+ pseudo_header.next_header = IPPROTO_TCP;
+ pseudo_header.next_packet_length_in_bytes = tcp_segment_size_in_bytes;
+
+ uint8_t *pseudo_header_data = reinterpret_cast<uint8_t *>( &pseudo_header );
+ size_t pseudo_header_size_in_bytes = sizeof(pseudo_header);
+
+ uint8_t *tcp_header_data = Payload.get();
+ size_t tcp_header_size_in_bytes = TcpHeaderSizeInBytes;
+
+ uint8_t tcp_buffer[65536];
+ size_t tcp_buffer_size_in_bytes = sizeof(tcp_buffer);
+ fill( tcp_buffer, tcp_buffer + tcp_buffer_size_in_bytes, 0 );
+
+ copy( pseudo_header_data, pseudo_header_data + pseudo_header_size_in_bytes,
+ tcp_buffer );
+ copy( tcp_header_data, tcp_header_data + tcp_header_size_in_bytes,
+ tcp_buffer + pseudo_header_size_in_bytes );
+ copy( tcp_payload_data, tcp_payload_data + tcp_payload_size_in_bytes,
+ tcp_buffer + pseudo_header_size_in_bytes + tcp_header_size_in_bytes );
+
+ uint16_t cksum = calculate_checksum(
+ reinterpret_cast<uint16_t *>( tcp_buffer ),
+ pseudo_header_size_in_bytes + TcpHeaderSizeInBytes + tcp_payload_size_in_bytes
+ );
+
+ cksum = ntohs( cksum );
+
+ return cksum;
+}
+
void TcpHeader::set_source_port( const uint16_t port )
{
Payload.encode16( 0, 1, port );
const uint8_t *tcp_payload_data,
const uint16_t tcp_payload_size_in_bytes
);
+ uint16_t calculate_tcp_checksum(
+ const boost::asio::ip::address_v6::bytes_type &src_addr,
+ const boost::asio::ip::address_v6::bytes_type &dest_addr,
+ const uint8_t *tcp_payload_data,
+ const uint16_t tcp_payload_size_in_bytes
+ );
void set_source_port( const uint16_t port );
void set_destination_port( const uint16_t port );