mirror of
https://github.com/ipxe/ipxe
synced 2026-06-29 00:07:28 +03:00
[test] Fix RFC 1071 checksum calculation for big-endian targets
Calculation of the TCP/IP checksum is fundamentally endian-agnostic: the checksum is designed to be symmetric so that both big-endian and little-endian systems can use native addition in any word size without any byte swapping. The result is then stored into the checksum field in the packet header as a native-endian value. The reference algorithm presented in RFC 1071 (and used in our test suite) is implicitly little-endian: the trailing byte is on a 16-bit word boundary and is added to the least significant byte of the 16-bit checksum value. Fix by shifting the trailing byte by 8 bits on big-endian targets. Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -140,8 +140,12 @@ TCPIP_RANDOM_TEST ( partial, 0xcafebabe, 121, 5 );
|
||||
* negative zero (0xffff) if the input data is zero length (or all
|
||||
* zeros) but positive zero (0x0000) for any other data which sums to
|
||||
* zero.
|
||||
*
|
||||
* A shift is applied to the trailing byte to ensure that the correct
|
||||
* result is calculated on a big-endian system.
|
||||
*/
|
||||
static uint16_t rfc_tcpip_chksum ( const void *data, size_t len ) {
|
||||
unsigned int shift = ( ( __BYTE_ORDER == __BIG_ENDIAN ) ? 8 : 0 );
|
||||
unsigned long sum = 0xffff;
|
||||
|
||||
while ( len > 1 ) {
|
||||
@@ -151,7 +155,7 @@ static uint16_t rfc_tcpip_chksum ( const void *data, size_t len ) {
|
||||
}
|
||||
|
||||
if ( len > 0 )
|
||||
sum += *( ( uint8_t * ) data );
|
||||
sum += ( *( ( uint8_t * ) data ) << shift );
|
||||
|
||||
while ( sum >> 16 )
|
||||
sum = ( ( sum & 0xffff ) + ( sum >> 16 ) );
|
||||
|
||||
Reference in New Issue
Block a user