# Copyright (c) 2021 by the Zeek Project. See LICENSE for details. # # Trivial File Transfer Protocol # # Specs from https://tools.ietf.org/html/rfc1350 module TFTP; import spicy; # Common header for all messages: # # 2 bytes # --------------- # | TFTP Opcode | # --------------- public type Packet = unit { # public top-level entry point for parsing op: uint16 &convert=Opcode($$); switch (self.op) { Opcode::RRQ -> rrq: Request(True); Opcode::WRQ -> wrq: Request(False); Opcode::DATA -> data: Data; Opcode::ACK -> ack: Acknowledgement; Opcode::ERROR -> error: Error; }; }; # TFTP supports five types of packets [...]: # # opcode operation # 1 Read request (RRQ) # 2 Write request (WRQ) # 3 Data (DATA) # 4 Acknowledgment (ACK) # 5 Error (ERROR) type Opcode = enum { RRQ = 0x01, WRQ = 0x02, DATA = 0x03, ACK = 0x04, ERROR = 0x05, }; # Figure 5-1: RRQ/WRQ packet # # 2 bytes string 1 byte string 1 byte # ------------------------------------------------ # | Opcode | Filename | 0 | Mode | 0 | # ------------------------------------------------ type Request = unit(is_read: bool) { filename: bytes &until=b"\x00"; mode: bytes &until=b"\x00"; on %done { } }; # Figure 5-2: DATA packet # # 2 bytes 2 bytes n bytes # ---------------------------------- # | Opcode | Block # | Data | # ---------------------------------- type Data = unit { num: uint16; data: bytes &eod; }; # Figure 5-3: ACK packet # # 2 bytes 2 bytes # --------------------- # | Opcode | Block # | # --------------------- type Acknowledgement = unit { num: uint16; }; # Figure 5-4: ERROR packet # # 2 bytes 2 bytes string 1 byte # ----------------------------------------- # | Opcode | ErrorCode | ErrMsg | 0 | # ----------------------------------------- type Error = unit { code: uint16; msg: bytes &until=b"\x00"; };