Documentation
¶
Overview ¶
Package tftp decodes TFTP (Trivial File Transfer Protocol) packets per RFC 1350, with the Option Extension family from RFC 2347 (envelope) + RFC 2348 (blksize) + RFC 2349 (timeout + tsize) + RFC 7440 (windowsize). TFTP is the canonical minimal file-transfer protocol; despite its 1981 vintage it remains the dominant transport for:
**PXE / network boot** — every PXE-booting machine fetches its boot loader (`pxelinux.0`, `wdsnbp.com`, `ipxe.efi`) and kernel + initrd over TFTP.
**IoT firmware updates** — most embedded devices (routers, switches, IP cameras, smart plugs, factory equipment) fetch firmware via TFTP because it fits in 2 KB of ROM.
**Network device config push** — every Cisco / Juniper / Arista shop uses TFTP for `copy running-config tftp:` and `copy tftp: flash:` workflows.
Wrap-vs-native judgement
Native. RFC 1350 + 2347 are fully public; TFTP packets have a tight 2-byte opcode + per-opcode body — no crypto, no compression, no fancy framing. Operators paste TFTP bytes (UDP destination port 69 server-side or the ephemeral port the server picked for an active transfer) from a `tcpdump -X udp port 69` line or a Wireshark Follow-UDP-Stream view and get the documented opcode + body breakdown.
What this package covers
**2-byte Opcode** (RFC 1350 §5) with **6-entry name table**: 1 RRQ (Read Request), 2 WRQ (Write Request), 3 DATA, 4 ACK, 5 ERROR, 6 OACK (Option Acknowledgment; RFC 2347).
**RRQ / WRQ body** (Types 1 + 2):
**Filename** (null-terminated UTF-8).
**Mode** (null-terminated UTF-8) — RFC 1350 defines "netascii", "octet" (the binary mode most operators use), and the deprecated "mail" mode.
**Options** (RFC 2347) — zero or more (name, value) pairs, each null-terminated. **4-entry option name table**: blksize (RFC 2348 — block-size override, default 512), timeout (RFC 2349 — retransmit timeout in seconds), tsize (RFC 2349 — transfer size in bytes; client sends 0 to request the server's value), windowsize (RFC 7440 — number of DATA blocks the sender can transmit before expecting an ACK).
**DATA body** (Type 3):
**Block Number** (uint16 BE; starts at 1, wraps to 0 after 65535 — the rollover is silently the reason for the long-standing 32 MB classic TFTP transfer cap, lifted by the windowsize + blksize options).
**Payload** (variable, up to the negotiated blksize — default 512 bytes; a short payload signals the last block).
**ACK body** (Type 4):
**Block Number** being acknowledged.
**ERROR body** (Type 5):
**Error Code** (uint16 BE) with **9-entry name table**: 0 Not defined / 1 File not found / 2 Access violation / 3 Disk full or allocation exceeded / 4 Illegal TFTP operation / 5 Unknown transfer ID / 6 File already exists / 7 No such user / 8 Option negotiation failure (RFC 2347).
**Error Message** (null-terminated UTF-8).
**OACK body** (Type 6) — same option-list layout as the options portion of RRQ/WRQ; the server replies with the option values it has agreed to.
What this package does NOT cover (deliberately out of scope)
UDP framing — feed TFTP bytes after the UDP header strip. TFTP runs on UDP destination port 69 server- side or the ephemeral port the server picked for transfer-data continuation.
TFTP state-machine reasoning (block-number windowing, retransmit-after-timeout logic, lockstep ACK ordering) — higher-level analysis.
Reassembly of the file payload across DATA blocks — each DATA block is decoded standalone; concatenating them is collector-side work.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AckBody ¶
type AckBody struct {
BlockNumber int `json:"block_number"`
}
AckBody is the decoded body of ACK (Type 4) packets.
type DataBody ¶
type DataBody struct {
BlockNumber int `json:"block_number"`
PayloadBytes int `json:"payload_bytes"`
PayloadBytesShown int `json:"payload_bytes_shown,omitempty"`
PayloadHex string `json:"payload_hex,omitempty"`
PayloadText string `json:"payload_text,omitempty"`
}
DataBody is the decoded body of DATA (Type 3) packets.
type DecodeOpts ¶
type DecodeOpts struct {
// MaxPayloadBytes caps the per-DATA hex preview. Zero
// surfaces the entire payload (which can be up to the
// negotiated blksize, often 64 KB).
MaxPayloadBytes int
}
DecodeOpts tunes the walker for output size.
func DefaultDecodeOpts ¶
func DefaultDecodeOpts() DecodeOpts
DefaultDecodeOpts returns a 256-byte payload preview cap.
type ErrorBody ¶
type ErrorBody struct {
ErrorCode int `json:"error_code"`
ErrorName string `json:"error_name"`
ErrorMessage string `json:"error_message"`
}
ErrorBody is the decoded body of ERROR (Type 5) packets.
type OackBody ¶
type OackBody struct {
Options []Option `json:"options"`
}
OackBody is the decoded body of OACK (Type 6) packets.
type Option ¶
type Option struct {
Name string `json:"name"`
NameKnown string `json:"name_known,omitempty"`
Value string `json:"value"`
}
Option is one (name, value) option pair from a RRQ / WRQ / OACK body.
type RequestBody ¶
type RequestBody struct {
Filename string `json:"filename"`
Mode string `json:"mode"`
Options []Option `json:"options,omitempty"`
}
RequestBody is the decoded body of RRQ (Type 1) or WRQ (Type 2) packets.
type Result ¶
type Result struct {
Opcode int `json:"opcode"`
OpcodeName string `json:"opcode_name"`
// One of the following is populated per opcode.
RRQ *RequestBody `json:"rrq,omitempty"`
WRQ *RequestBody `json:"wrq,omitempty"`
DATA *DataBody `json:"data,omitempty"`
ACK *AckBody `json:"ack,omitempty"`
ERROR *ErrorBody `json:"error,omitempty"`
OACK *OackBody `json:"oack,omitempty"`
TotalBytes int `json:"total_bytes"`
Notes []string `json:"notes,omitempty"`
}
Result is the top-level decoded view of a TFTP packet.