Networking in C · intermediate · ~12 min
Locate and extract the hostname stored inside a TLS Server Name Indication (SNI) extension.
Read two big-endian lengths, check one type byte, then perform a bounds-checked copy of the host bytes.
SNI is the one plaintext hostname in a TLS session. It is the field that monitors and filters rely on.
TLS encrypts almost everything in a connection. The one exception is the ClientHello — the very first message the client sends.
The ClientHello goes out before any encryption keys exist, so it travels in the clear. Inside it sits the SNI extension (Server Name Indication), which names the host the client wants to reach. That hostname is plaintext.
This is the field every passive TLS monitor, SNI-based filter, and traffic classifier reads.
The payload is a short, fixed sequence of length-prefixed fields:
[server_name_list_len : 2] big-endian
[name_type : 1] 0x00 = host_name
[name_len : 2] big-endian
[host bytes ...]
All multi-byte lengths are big-endian — also called network byte order. Big-endian means the most significant byte comes first. For example, the two bytes 0x01 0x2C represent the value 300 (1 * 256 + 44).
Implement this function:
int extract_sni(const uint8_t *ext, size_t n, char *out, size_t cap);
It must:
0x00 (host_name).out.Validate every length against n (the input size) and the host length against cap (the output buffer size). Never read past the input. Never write past the output.
list_len (2 bytes), type (1 byte, must be 0x00), name_len (2 bytes), then the host bytes.n (input size) and cap (output buffer size).