-
Notifications
You must be signed in to change notification settings - Fork 1
TFTP dataParser
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()
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.
H_RULE(opc, h_int_range(h_uint16(), 3, 3));This only accepts a value of exactly 3.
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).
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.
H_RULE(dataPacket, h_sequence(opc, blockNum, dataBytes, NULL));| 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
Learn Hammer
Protocol Examples
NTP
- NTP Overview
- Parsing the Header
- Parsing Data Fields
- Extension Fields and MAC
- Assembling the Parser
- Hex Input Preprocessing
- Running and Testing
DNS
TFTP
- TFTP Overview
- RRQ/WRQ Packets
- DATA Packets
- ACK Packets
- ERROR Packets
- Assembling the Parser
- Running and Testing
References
- Hammer Quick Reference
- Parsing Backends
- Unit Testing
- Using RTEMS
- Extending Hammer
- Adding a New Example
- Adding a New Binding
Further Reading