TCP header checksum calculation
-
Hi All, I got stuck with TCP header checksum calculation. RFC 793 says checksum is calculated using the same algorithm as IP header checksum and includes 96-bit pseudo header + data. I have written a checksum calculation function, and it works well for IP headers, but when I apply it to the TCP packet the function produces wrong results. I have captured a TCP packet from my network, and put it into my test program. There are 2 checksum functions in the code: Checksum and ChecksumRFC. The last one is taken from RFC1071. The code is for Windows 2000, VC6.0 Could anyone explain me what I do wrong?
#include <stdio.h> #include <windows.h> // to ensure memory alignment #include <pshpack1.h> typedef struct _IP_HEADER { UCHAR HeaderLength :4; // Header length in 32-bit words UCHAR Version :4; // IP version UCHAR TypeOfService; // USHORT TotalLength; // Total datagram (header + data) length in bytes USHORT Identification; // USHORT FlagsFragment; // Flags (3 bits) + Fragment position (13bits) in datagram (in 64-bit units) UCHAR TimeToLive; // UCHAR Protocol; // Next level protocol USHORT Checksum; // IP header checksum ULONG SourceAddress; // Source address ULONG DestAddress; // Destination address } IP_HEADER, *PIP_HEADER; // // Next level protocol IDs // #define IPPROTO_TCP 6 #define IPPROTO_UDP 17 // // TCP Header (rfc 793) // typedef struct _TCP_HEADER { USHORT SourcePort; // USHORT DestPort; // ULONG SeqNumber; // Sequence number ULONG AckNumber; // Acknowledge number UCHAR Reserved :4; // Reserved must be zero UCHAR Offset :4; // TCP Header size in 32-bit words UCHAR FIN :1; // No more data from Sender UCHAR SYN :1; // Synchronize sequence number UCHAR RST :1; // Reset the connection UCHAR PSH :1; // Push function UCHAR ACK :1; // Acknowledgment field significant UCHAR URG :1; // Urgent pointer field significant UCHAR Reserved1:1; // UCHAR Reserved2:1; // USHORT Window; // Number of data octets which the sender of this segment is willing to accept USHORT Checksum; // Checksum of header + data USHORT Urgent; // } TCP_HEADER, *PTCP_HEADER; // // TCP pseudo header for checksum calculation // // to ensure memory alignment typedef struct _TCP_PSEUDOHEADER { ULONG SourceAddress; // source IP address ULONG DestAddress; // destination IP address UCHAR Zero; // must be 0 UCHAR Protocol;
-
Hi All, I got stuck with TCP header checksum calculation. RFC 793 says checksum is calculated using the same algorithm as IP header checksum and includes 96-bit pseudo header + data. I have written a checksum calculation function, and it works well for IP headers, but when I apply it to the TCP packet the function produces wrong results. I have captured a TCP packet from my network, and put it into my test program. There are 2 checksum functions in the code: Checksum and ChecksumRFC. The last one is taken from RFC1071. The code is for Windows 2000, VC6.0 Could anyone explain me what I do wrong?
#include <stdio.h> #include <windows.h> // to ensure memory alignment #include <pshpack1.h> typedef struct _IP_HEADER { UCHAR HeaderLength :4; // Header length in 32-bit words UCHAR Version :4; // IP version UCHAR TypeOfService; // USHORT TotalLength; // Total datagram (header + data) length in bytes USHORT Identification; // USHORT FlagsFragment; // Flags (3 bits) + Fragment position (13bits) in datagram (in 64-bit units) UCHAR TimeToLive; // UCHAR Protocol; // Next level protocol USHORT Checksum; // IP header checksum ULONG SourceAddress; // Source address ULONG DestAddress; // Destination address } IP_HEADER, *PIP_HEADER; // // Next level protocol IDs // #define IPPROTO_TCP 6 #define IPPROTO_UDP 17 // // TCP Header (rfc 793) // typedef struct _TCP_HEADER { USHORT SourcePort; // USHORT DestPort; // ULONG SeqNumber; // Sequence number ULONG AckNumber; // Acknowledge number UCHAR Reserved :4; // Reserved must be zero UCHAR Offset :4; // TCP Header size in 32-bit words UCHAR FIN :1; // No more data from Sender UCHAR SYN :1; // Synchronize sequence number UCHAR RST :1; // Reset the connection UCHAR PSH :1; // Push function UCHAR ACK :1; // Acknowledgment field significant UCHAR URG :1; // Urgent pointer field significant UCHAR Reserved1:1; // UCHAR Reserved2:1; // USHORT Window; // Number of data octets which the sender of this segment is willing to accept USHORT Checksum; // Checksum of header + data USHORT Urgent; // } TCP_HEADER, *PTCP_HEADER; // // TCP pseudo header for checksum calculation // // to ensure memory alignment typedef struct _TCP_PSEUDOHEADER { ULONG SourceAddress; // source IP address ULONG DestAddress; // destination IP address UCHAR Zero; // must be 0 UCHAR Protocol;
-
I can't help you. But which Packet driver do you use, i have a similar project, but not with TCP. Marco
-
Hi All, I got stuck with TCP header checksum calculation. RFC 793 says checksum is calculated using the same algorithm as IP header checksum and includes 96-bit pseudo header + data. I have written a checksum calculation function, and it works well for IP headers, but when I apply it to the TCP packet the function produces wrong results. I have captured a TCP packet from my network, and put it into my test program. There are 2 checksum functions in the code: Checksum and ChecksumRFC. The last one is taken from RFC1071. The code is for Windows 2000, VC6.0 Could anyone explain me what I do wrong?
#include <stdio.h> #include <windows.h> // to ensure memory alignment #include <pshpack1.h> typedef struct _IP_HEADER { UCHAR HeaderLength :4; // Header length in 32-bit words UCHAR Version :4; // IP version UCHAR TypeOfService; // USHORT TotalLength; // Total datagram (header + data) length in bytes USHORT Identification; // USHORT FlagsFragment; // Flags (3 bits) + Fragment position (13bits) in datagram (in 64-bit units) UCHAR TimeToLive; // UCHAR Protocol; // Next level protocol USHORT Checksum; // IP header checksum ULONG SourceAddress; // Source address ULONG DestAddress; // Destination address } IP_HEADER, *PIP_HEADER; // // Next level protocol IDs // #define IPPROTO_TCP 6 #define IPPROTO_UDP 17 // // TCP Header (rfc 793) // typedef struct _TCP_HEADER { USHORT SourcePort; // USHORT DestPort; // ULONG SeqNumber; // Sequence number ULONG AckNumber; // Acknowledge number UCHAR Reserved :4; // Reserved must be zero UCHAR Offset :4; // TCP Header size in 32-bit words UCHAR FIN :1; // No more data from Sender UCHAR SYN :1; // Synchronize sequence number UCHAR RST :1; // Reset the connection UCHAR PSH :1; // Push function UCHAR ACK :1; // Acknowledgment field significant UCHAR URG :1; // Urgent pointer field significant UCHAR Reserved1:1; // UCHAR Reserved2:1; // USHORT Window; // Number of data octets which the sender of this segment is willing to accept USHORT Checksum; // Checksum of header + data USHORT Urgent; // } TCP_HEADER, *PTCP_HEADER; // // TCP pseudo header for checksum calculation // // to ensure memory alignment typedef struct _TCP_PSEUDOHEADER { ULONG SourceAddress; // source IP address ULONG DestAddress; // destination IP address UCHAR Zero; // must be 0 UCHAR Protocol;
It may not be the problem, but you should be suspicous of any cross platform code using bitfields to pick out bits like this. The C standard does not define whether bitfields are allocated starting from the most or least significant bits of the variable. Different compilers may interpret this code differently!
UCHAR HeaderLength :4; // Header length in 32-bit words
Some compilers will use the high nibble, others the lower nibble. Its much safer to use masks and shifts:
Either
HeaderLength = (uchar_var & 0xF0) >> 4
or
HeaderLength = (uchar_var & 0x0F)
as appropriate. Stephen C. Steel Kerr Vayne Systems Ltd.