- TCP checksum is a 16-bit field in TCP header used for error detection
- Same as IP checksum,
TCP checksum is the 16-bit one’s complement of the one’s
complement sum of all 16-bit words in the computation data.
- Checksum 图:
- TCP checksum computing includes:
- UDP 数据报和 TCP 段中使用的校验和的计算都包含一个 12 字节长的伪首部.
12 bytes TCP 伪首部 (12 bytes TCP pseudo header,
from the IP header and computed), includes:
- ipHdr srcIP 4 bytes
- ipHdr dstIP 4 bytes
- 1 reserved byte: 0x00
- 1 byte protocol: from ipHdr: 0x06 for TCP
- 2 byte computed TCP length
- TCP “Pseudo Header” For Checksum Calculation 图:
- Original TCP segment(length: is above TCP length), might+ padding,
includes:
- TCP header
- TCP data, includes:
- TCP data
- Padded as needed with zero bytes at the end to make a multiple
of two bytes
TCP “Pseudo Header” For Checksum Calculation
Field Name |
Bytes |
Description |
Source Address |
4 |
The 32-bit IP address of the originator of the datagram, taken from the IP header |
Destination Address |
4 |
The 32-bit IP address of the intended recipient of the datagram, also from the IP header |
Reserved |
1 |
8 bits of zeroes |
Protocol |
1 |
The Protocol field from the IP header. This indicates what higher-layer protocol is carried in the IP datagram. Of course, we already know what this protocol is, it’s TCP! So, this field will normally have the value 6 |
TCP Length |
2 |
The length of the TCP segment, including both header and data. Note that this is not a specific field in the TCP header; it is computed |
/**
* 计算 TCP 首部中使用的校验和
* @param cleanChecksum true to cleanup original checksum before compute
* @param ipHdr IP首部
* @return in network byte order
*/
uint16_t computeChecksum(
bool const cleanChecksum, IpHdr const* const ipHdr) const
{
// get computed TCP length, also is original TCP segment length
size_t const protocolSize = ipHdr->computeProtocolSize();
size_t const n = 12 + protocolSize;
uint8_t data[n];
// ipHdr srcIP
::memcpy(data, &(ipHdr->sourceIpAddress), 4);
// ipHdr dstIP
::memcpy(data + 4, &(ipHdr->destinationIpAddress), 4);
// reserved
data[8] = 0x00;
// protocol
data[9] = ipHdr->protocol;
// computed TCP length
data[10] = (protocolSize & 0xff00) >> 8;
data[11] = protocolSize & 0xff;
// original TCP segment
tcphdr* const tcpHdr = reinterpret_cast<tcphdr*>(data + 12);
::memcpy(tcpHdr, this->tcpHdr, protocolSize);
// cleanup original checksum when need
if (cleanChecksum) {
tcpHdr->check = 0;
}
// compute
return ethpacket::ComputeChecksum(
reinterpret_cast<uint16_t const*>(data), n);
}