Skip to content

TFTP dataParser

Elbasiouny, Mahmoud edited this page May 29, 2026 · 8 revisions

DATA packets (opcode 3) carry the actual file contents during a TFTP transfer. Each DATA packet contains a block number and a variable-length payload.

Source file: tftp.c
Hammer concepts: h_int_range · h_many · h_end_p · h_sequence · h_tell() · h_attr_bool()


DATA Packet Layout

 2 bytes    2 bytes      n bytes
+---------+---------+--------------+
| Opcode  | Block # |    Data      |
+---------+---------+--------------+

According to the RFC:

  • Opcode - 2 bytes, value 3
  • Block # - 2 bytes, starts at 1 and increments with each packet (range 1–65535)
  • Data - 0 to 512 bytes of file content

A DATA packet with fewer than 512 bytes of data signals the end of the transfer.


Step 1: Opcode

H_RULE(opc, h_int_range(h_uint16(), 3, 3));

This only accepts a value of exactly 3.


Step 2: Block Number

H_RULE(blockNum, h_int_range(h_uint16(), 1, UINT16_MAX));

The block number starts at 1, so 0 is invalid. The maximum value is 65535 (UINT16_MAX).


Step 3: Data Payload with h_many and h_end_p

The data field contains zero or more bytes, followed by the end of input:

H_RULE(dataBytes, h_sequence(h_many(h_uint8()), h_attr_bool(h_tell(), validate_dataBytes, NULL), h_end_p(), NULL));

h_many matches zero or more occurrences of h_uint8(), consuming all remaining bytes. h_attr_bool attaches a predicate function, which returns true or false, to a parser. The function is evaluated over the parser's result, the parser in this example is h_tell(), and the function is validate_dataBytes. The parse only succeeds if the attribute function returns true. h_tell() returns the current location of the abstract syntax tree cursor as a uint number of bits. The Function validate_dataBytes takes the value of h_tell() and checks to see if that is within the acceptable range for a data packet's data field.

bool validate_dataBytes(HParseResult *result, void* user_data){
    return result && result->ast && ((result->ast->uint)-32) <= (512*8);
}

32 bits are subtracted from the h_tell() value due to the leading 4 bytes of the packet (opcode + block number) being dedicated to packet identification (4 bytes × 8 bits = 32 bits). The max value of the data field is 512 bytes, which is equal to (512 * 8 bits). h_end_p() then asserts there is no unconsumed input.


Step 4: Assemble the DATA Parser

H_RULE(dataPacket, h_sequence(opc, blockNum, dataBytes, NULL));

Summary

Concept Hammer Function Why It Matters in TFTP
Exact value match h_int_range(p, 3, 3) Opcode must be exactly 3
Value range h_int_range(p, 1, MAX) Block number starts at 1
Zero or more h_many Data payload is variable length
End-of-input h_end_p Ensures all bytes are consumed
Parser position h_tell() Determining how many bits have been parsed
Functional verification h_attr_bool() Uses conditional functions on parser output

Next: ACK Packets

Previous: RRQ/WRQ Packets

Clone this wiki locally