networking · advanced · ~35 min

Compute the IPv4/TCP one's-complement checksum

One's complement arithmetic + carry-fold.

Challenge

The 16-bit one's-complement "Internet checksum" is the integrity check used by IP, TCP, and UDP. Compute it over an arbitrary byte buffer.

Task

Implement uint16_t inet_checksum(const uint8_t *buf, size_t len) following these steps:

  1. Sum the buffer as 16-bit big-endian words (high byte first). If len is odd, treat the final byte as the high byte of a zero-padded word.
  2. Fold carries: while the running sum has bits above bit 16, add them back in — sum = (sum & 0xFFFF) + (sum >> 16).
  3. Return the one's complement (~sum) as a 16-bit value.

Input

  • buf, len: the bytes to checksum and their count. len may be 0 or odd.

Output

Returns the 16-bit checksum.

Example

{0x00,0x01, 0x00,0x02}   ->   0xFFFC   (words 0x0001 + 0x0002 = 0x0003; ~0x0003)
{0x12,0x34,0xAB}         ->   0x42CB   (odd length: words 0x1234 + 0xAB00)
{0xFF,0xFF, 0xFF,0xFF}   ->   0x0000   (carry-fold: 0x1FFFE -> 0xFFFF -> ~ = 0)

Edge cases

  • Empty buffer (len == 0): the checksum is 0xFFFF (~0).
  • Single / odd trailing byte: pad it into the high byte of a word.

Rules

  • Treat bytes as unsigned (signed bytes sign-extend and corrupt the sum).
  • Word order is big-endian: high byte first.

Why this matters

The 1s-complement checksum is the TCP/UDP/IP integrity check. Writing it from scratch demystifies the byte-level mechanics of every packet that crosses the internet.

Input format

A byte buffer (buf) and its length (len); len may be 0 or odd.

Output format

The 16-bit one's-complement Internet checksum.

Constraints

Treat bytes as unsigned; word order is big-endian (high byte first); fold carries before returning ~sum.

Starter code

#include <stdint.h>
#include <stddef.h>
uint16_t inet_checksum(const uint8_t *buf, size_t len) { /* TODO */ return 0; }

Common mistakes

Treating bytes as signed (sign extension wrecks the sum); forgetting to fold carries; forgetting that a 0xFFFF result is encoded as 0x0000 by sender convention (you do not need to apply that here; just return ~sum).

Edge cases to handle

Empty buffer → checksum is 0xFFFF (~0). Single byte → padded to a word.

Complexity

O(len).

Background lessons

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.