From d8e3150b7c110fb30b2d99aa8b93f61c023606dd Mon Sep 17 00:00:00 2001 From: Guilherme Maciel Ferreira Date: Sat, 18 Feb 2012 12:21:18 -0200 Subject: [PATCH] Documentation for TCP header. --- src/tcp/tcpheader.cpp | 250 ++++++++++++++++++++++++++++++++++++++++++++++++- src/tcp/tcpheader.h | 6 +- 2 files changed, 251 insertions(+), 5 deletions(-) diff --git a/src/tcp/tcpheader.cpp b/src/tcp/tcpheader.cpp index 5f743ad..df56c7f 100644 --- a/src/tcp/tcpheader.cpp +++ b/src/tcp/tcpheader.cpp @@ -40,90 +40,246 @@ using boost::asio::ip::address_v6; static const size_t TcpHeaderSizeInBytes = 20; +/** + * @brief Create a TCP header object. + */ TcpHeader::TcpHeader() : Payload( TcpHeaderSizeInBytes ) { } +/** + * @brief Identify the segment's sending end point. + * + * @return The source TCP port. + */ uint16_t TcpHeader::get_source_port() const { return Payload.decode16( 0, 1 ); } +/** + * @brief Identify the segment's receiving end point. + * + * @return The destination TCP port. + */ uint16_t TcpHeader::get_destination_port() const { return Payload.decode16( 2, 3 ); } +/** + * @brief Identify the amount of bytes sent by one end point. + * + * @details If the SYN flag is set, then this is the initial sequence number. + * The sequence number of the actual first data byte and the acknowledged number + * in the corresponding ACK are then this sequence number plus 1. + * If the SYN flag is clear, then this is the accumulated sequence number of + * the first data byte of this segment for the current session. + * + * @return The sequence number. + */ uint32_t TcpHeader::get_sequence_number() const { return Payload.decode32( 4, 7 ); } +/** + * @brief Identify the amount of bytes received by one end point. + * + * @details If the ACK flag is set then the value of this field is the next + * sequence number that the receiver is expecting. This acknowledges receipt of + * all prior bytes (if any). The first ACK sent by each end acknowledges the + * other end's initial sequence number itself, but no data. + * + * @return The acknowledgment number. + */ uint32_t TcpHeader::get_acknowledgment_number() const { return Payload.decode32( 8, 11 ); } +/** + * @brief The TCP header length (a.k.a data offset) tells how many 32-bit words + * are contained in the TCP header (e.g. 5 words is equivalent to 20 bytes). + * + * @details The minimum size header is 5 words and the maximum is 15 words thus + * giving the minimum size of 20 bytes and maximum of 60 bytes, allowing for up + * to 40 bytes of options in the header. + * + * @return The header length in 32-bit words. + */ uint8_t TcpHeader::get_header_length() const { return ( Payload[12] & 0xF0 ) >> 4; } +/** + * @brief The CWR flag is used to signal congestion when Explicit Congestion + * Notification is used, as specified in RFC 3168. + * + * @details CWR is set by the TCP sender to signal Congestion Window Reduced to + * the TCP receiver so that it knows the sender has slowed down and can stop + * sending the ECN-Echo. + * + * @return @c true if the flag is on, or @c false otherwise. + */ bool TcpHeader::get_congestion_window_reduced() const { return ( Payload[13] & 0x80 ); } +/** + * @brief The ECE flag is used to signal congestion when Explicit Congestion + * Notification is used, as specified in RFC 3168. + * + * @details If the SYN flag is clear, ECE is set by the TCP receiver to signal + * an ECN-Echo to the TCP sender to tell it to slow down when the TCP receiver + * gets a congestion indication from the network. + * If the SYN flag is set, that the TCP peer is ECN capable. + * + * @return @c true if the flag is on, or @c false otherwise. + */ bool TcpHeader::get_ecn_echo() const { return ( Payload[13] & 0x40 ); } +/** + * @brief URG is set to 1 if the Urgent Pointer is in use. + * + * @details The Urgent Pointer is used to indicate a byte offset from the + * current sequence number at which urgent data are to be found. This facility + * is in lieu of interrupt messages. + * + * @return @c true if the flag is on, or @c false otherwise. + */ bool TcpHeader::get_urgent() const { return ( Payload[13] & 0x20 ); } +/** + * @brief ACK bit is set to 1 to indicate that the Acknowledgment Number is + * valid. + * + * @details All packets after the initial SYN packet sent by the client should + * have this flag set. + * + * @return @c true if the flag is on, or @c false otherwise. + */ bool TcpHeader::get_acknowledgment() const { return ( Payload[13] & 0x10 ); } +/** + * @brief PSH bit indicates pushed data. + * + * @details The receiver is hereby kindly requested to deliver the data to the + * application upon arrival and not to buffer it until a full buffer has been + * received. + * + * @return @c true if the flag is on, or @c false otherwise. + */ bool TcpHeader::get_push() const { return ( Payload[13] & 0x08 ); } +/** + * @brief RST bit is used to abruptly reset a connection that has become + * confused due to a host crash or some other reason. RST is also used to reject + * an invalid segment or refuse an attempt to open a connection. + * + * @return @c true if the flag is on, or @c false otherwise. + */ bool TcpHeader::get_reset() const { return ( Payload[13] & 0x04 ); } +/** + * @brief SYN bit is used to establish connections. + * + * @details Only the first segment sent from each end point should have this + * flag set. The connection request has SYN=1 and ACK=0 to indicate that the + * piggyback acknowledgment field is not in use. The connection reply does bear + * an acknowledgment, however, so it has SYN=1 and ACK=1. In essence, the SYN + * bit is used to denote both CONNECTION REQUEST and CONNECTION ACCEPTED, with + * the ACK bit used to distinguish between those two possibilities. + * + * @return @c true if the flag is on, or @c false otherwise. + */ bool TcpHeader::get_synchronize() const { return ( Payload[13] & 0x02 ); } +/** + * @brief FIN bit is used to release a connection. + * + * @details It specifies that the sender has no more data to transmit. However, + * after closing a connection, the closing end point may continue receive data + * indefinitely. Both SYN and FIN segments have sequence numbers and are thus + * guaranteed to be processed in the correct order. + * + * @return @c true if the flag is on, or @c false otherwise. + */ bool TcpHeader::get_finish() const { return ( Payload[13] & 0x01 ); } +/** + * @brief The Window Size field tells how many bytes may be sent starting at the + * byte acknowledged. + * + * @details Flow control in TCP is handled using a variable-sized sliding + * window. A window size of 0 says that the bytes up to and including the + * acknowledgment number - 1 have been received, but that the receiver has not + * had a chance to consume the data and would like no more data for the moment. + * The receiver can later grant permission to send by transmitting a segment + * with the same acknowledgment number and a nonzero window size. + * + * @return The amount of bytes the receiver is willing to receive. + */ uint16_t TcpHeader::get_window_size() const { return Payload.decode16( 14, 15 ); } +/** + * @brief The 16-bit checksum is used for error-checking of the header and data + * + * @return A 16-bit checksum. + */ uint16_t TcpHeader::get_checksum() const { return Payload.decode16( 16, 17 ); } +/** + * @brief Calculate the TCP checksum for IPv4 addresses, as defined in RFC 793. + * + * @details The checksum field is the 16 bit one's complement of the one's + * complement sum of all 16 bit words in the header and text. If a segment + * contains an odd number of header and text octets to be checksummed, the last + * octet is padded on the right with zeros to form a 16 bit word for checksum + * purposes. The pad is not transmitted as part of the segment. While + * computing the checksum, the checksum field itself is replaced with zeros. + * + * @param src_addr The 32-bits compromising the source IPv4 address. + * @param dest_addr The 32-bits compromising the destination IPv4 address. + * @param tcp_payload_data The payload data (not the header). + * @param tcp_payload_size_in_bytes The amount of bytes present in the payload. + * + * @return The one's complement checksum of the TCP header and the given payload. + */ uint16_t TcpHeader::calculate_tcp_checksum( const address_v4::bytes_type &src_addr, const address_v4::bytes_type &dest_addr, - const uint8_t* tcp_payload_data, + const uint8_t *tcp_payload_data, const uint16_t tcp_payload_size_in_bytes ) { set_checksum( 0 ); @@ -168,10 +324,25 @@ uint16_t TcpHeader::calculate_tcp_checksum( return cksum; } +/** + * @brief Calculate the TCP checksum for IPv6 addresses, as defined in RFC 2460. + * + * @details Any transport or other upper-layer protocol that includes the + * addresses from the IP header in its checksum computation must be modified + * for use over IPv6, to include the 128-bit IPv6 addresses instead of 32-bit + * IPv4 addresses. + * + * @param src_addr The 128-bits compromising the source IPv6 address. + * @param dest_addr The 128-bits compromising the destination IPv6 address. + * @param tcp_payload_data The payload data (not the header). + * @param tcp_payload_size_in_bytes The amount of bytes present in the payload. + * + * @return The one's complement checksum of the TCP header and the given payload. + */ 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 uint8_t *tcp_payload_data, const uint16_t tcp_payload_size_in_bytes ) { set_checksum( 0 ); @@ -215,26 +386,51 @@ uint16_t TcpHeader::calculate_tcp_checksum( return cksum; } +/** + * @see get_source_port + * + * @param port The source TCP port. + */ void TcpHeader::set_source_port( const uint16_t port ) { Payload.encode16( 0, 1, port ); } +/** + * @see get_destination_port + * + * @param port The destination TCP port. + */ void TcpHeader::set_destination_port( const uint16_t port ) { Payload.encode16( 2, 3, port ); } +/** + * @see get_sequence_number + * + * @param seq_num The sequence number. + */ void TcpHeader::set_sequence_number( const uint32_t seq_num ) { Payload.encode32( 4, 7, seq_num ); } +/** + * @see get_acknowledgment_number + * + * @param ack_num The acknowledgment number. + */ void TcpHeader::set_acknowledgment_number( const uint32_t ack_num ) { Payload.encode32( 8, 11, ack_num ); } +/** + * @see get_header_length + * + * @param offset The header length in 32-bit words. + */ void TcpHeader::set_header_length( const uint8_t offset ) { uint8_t high_nimble = static_cast( ( offset << 4 ) & 0xF0 ); @@ -242,59 +438,109 @@ void TcpHeader::set_header_length( const uint8_t offset ) Payload[12] = high_nimble | lower_nimble; } +/** + * @see get_congestion_window_reduced + * + * @param bit @c true if the flag is on, or @c false otherwise. + */ void TcpHeader::set_congestion_window_reduced( bool bit ) { uint8_t bit_mask = bit ? 0x80 : 0x00; Payload[13] = Payload[13] | bit_mask; } +/** + * @see get_ecn_echo + * + * @param bit @c true if the flag is on, or @c false otherwise. + */ void TcpHeader::set_ecn_echo( bool bit ) { uint8_t bit_mask = bit ? 0x40 : 0x00 ; Payload[13] = Payload[13] | bit_mask; } +/** + * @see get_urgent + * + * @param bit @c true if the flag is on, or @c false otherwise. + */ void TcpHeader::set_urgent( bool bit ) { uint8_t bit_mask = bit ? 0x20 : 0x00 ; Payload[13] = Payload[13] | bit_mask; } +/** + * @see get_acknowledgment + * + * @param bit @c true if the flag is on, or @c false otherwise. + */ void TcpHeader::set_acknowledgment( bool bit ) { uint8_t bit_mask = bit ? 0x10 : 0x00 ; Payload[13] = Payload[13] | bit_mask; } +/** + * @see get_push + * + * @param bit @c true if the flag is on, or @c false otherwise. + */ void TcpHeader::set_push( bool bit ) { uint8_t bit_mask = bit ? 0x08 : 0x00 ; Payload[13] = Payload[13] | bit_mask; } +/** + * @see get_reset + * + * @param bit @c true if the flag is on, or @c false otherwise. + */ void TcpHeader::set_reset( bool bit ) { uint8_t bit_mask = bit ? 0x04 : 0x00 ; Payload[13] = Payload[13] | bit_mask; } +/** + * @see get_synchronize + * + * @param bit @c true if the flag is on, or @c false otherwise. + */ void TcpHeader::set_synchronize( bool bit ) { uint8_t bit_mask = bit ? 0x02 : 0x00 ; Payload[13] = Payload[13] | bit_mask; } +/** + * @see get_finish + * + * @param bit @c true if the flag is on, or @c false otherwise. + */ void TcpHeader::set_finish( bool bit ) { uint8_t bit_mask = bit ? 0x01 : 0x00 ; Payload[13] = Payload[13] | bit_mask; } +/** + * @see get_window_size + * + * @param wnd_size The amount of bytes this end point is willing to receive. + */ void TcpHeader::set_window_size( const uint16_t wnd_size ) { Payload.encode16( 14, 15, wnd_size ); } +/** + * @see get_checksum + * + * @param sum The 16-bit checksum of header and data. + */ void TcpHeader::set_checksum( const uint16_t sum ) { Payload.encode16( 16, 17, sum ); diff --git a/src/tcp/tcpheader.h b/src/tcp/tcpheader.h index 33cd52d..3f985b2 100644 --- a/src/tcp/tcpheader.h +++ b/src/tcp/tcpheader.h @@ -53,9 +53,9 @@ on this file might be covered by the GNU General Public License. * | acknowledgment number (if ACK set) | 20 bytes * | | | * +-------+-------+-+-+-+-+-+-+-+-+------------------------------+ | - * | data | reser-|C|E|U|A|P|R|S|F| | | - * |offset | ved |W|C|R|C|S|S|Y|I| window size | | - * | | |R|E|G|K|H|T|N|N| | | + * | TCP | reser-|C|E|U|A|P|R|S|F| | | + * | header| ved |W|C|R|C|S|S|Y|I| window size | | + * |length | |R|E|G|K|H|T|N|N| | | * +---------------+-+-+-+-+-+-+-+-+------------------------------+ | * | | | | * | checksum | urgent pointer (if URG set) | | -- 1.7.1