networking · intermediate · ~25 min

Parse the fixed fields of a mock IPv4 header

Bit extraction from packed fields, plus big-endian 2-byte read.

Challenge

Given a mock IPv4 header in a byte buffer, extract three fields: the version, the internet header length (IHL), and the total length. This tests parsing only — no socket is opened.

The first 4 bytes of the 20-byte header (RFC 791) are laid out as:

byte 0:    [ version: 4 bits ][ IHL: 4 bits ]
byte 1:    [ DSCP / ECN — ignore for this exercise ]
bytes 2-3: total length, big-endian

Task

Implement int parse_ipv4_header(const unsigned char *buf, size_t len, int *out_version, int *out_ihl, unsigned *out_total_len) that extracts the version (high nibble of byte 0), IHL (low nibble of byte 0), and total length (big-endian bytes 2-3).

Input

  • buf, len: the header bytes and how many are available.
  • out_version, out_ihl, out_total_len: out-pointers for the three fields.

Output

Returns 1 on success (all three fields written), or 0 if len < 4 or any output pointer is NULL.

Example

{0x45, 0x00, 0x05, 0xDC}   ->   1, version=4, ihl=5, total_len=1500

Edge cases

  • len < 4: return 0.
  • Any NULL output pointer: return 0.

Rules

  • No htons / ntohs — assemble the big-endian length yourself: (buf[2] << 8) | buf[3].
  • No allocations.

Why this matters

Every packet capture tool, every firewall, every Wireshark plug-in parses IPv4 headers. The structure is fiddly: a 4-bit version, a 4-bit IHL, a big-endian total length — exactly the kind of byte-extraction work where junior engineers regularly produce subtle bugs.

Input format

Header bytes (buf) and available length (len), plus out-pointers out_version, out_ihl, out_total_len.

Output format

Returns 1 with the three fields written, or 0 if len < 4 or any output pointer is NULL.

Constraints

No allocations; no htons/ntohs — assemble the big-endian length yourself. Version is the high nibble of byte 0, IHL the low nibble.

Starter code

#include <stddef.h>
int parse_ipv4_header(const unsigned char *buf, size_t len,
                      int *out_version,
                      int *out_ihl,
                      unsigned *out_total_len) { /* TODO */ return 0; }

Common mistakes

Reading total_len as host byte order. Mixing the version and IHL nibbles. Forgetting the length check.

Edge cases to handle

len < 4; NULL output pointers; version != 4.

Complexity

O(1).

Background lessons

Up next

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