-
Notifications
You must be signed in to change notification settings - Fork 77
Feature Request: Option to suppress 'tsize' in OACK (workaround for buggy UEFI PXE clients) #125
Description
Hi Dmitri,
First off, thanks for pin/tftp - it's been great for building a PXE boot server. We're using it to serve iPXE binaries (~1.1MB) to UEFI clients during network boot.
We've hit a specific issue with UEFI firmware TFTP implementations (Aptio V/AMI) that we're hoping you might have insight on.
Environment
- Library: pin/tftp v3.1.0
- Clients: Multiple UEFI clients (Gigabyte Aero 15XV8 Laptop/Aptio 2019, Lenovo m715q-1, brand new ASUS Prime B760M-A AX LGA 1700 w BIOS Ver / Date: 1812 x64 / 01/21/2025) - all exhibit identical behavior.
The Issue
UEFI TFTP clients send an RRQ with tsize=0 and blksize=1468.
- If the server responds with an OACK containing
tsize=<actual_size>, the client immediately sends ERROR code 8 ("User aborted") and disconnects. - The client then retries the request without the
tsizeoption. - The server responds with an OACK (only
blksize), and the transfer succeeds.
It appears these UEFI stacks request tsize but panic/crash if they actually receive it (perhaps due to buffer allocation logic in the firmware).
Workaround Attempts
- Wrapped Reader: We wrapped our file in a struct that hides
io.Seeker(exposing onlyio.Reader). We expected this to cause the library to omittsize.- Result: The OACK correctly omitted
tsize, but the client failed with "NBP filesize is 0 bytes" and did not retry. It seems these clients interpret "no tsize response to a tsize request" as "0 bytes".
- Result: The OACK correctly omitted
- Current Solution: We are currently accepting the "Fail-then-Retry" behavior. It works, but the initial failure creates noise in our error logs (WARN) and adds a ~1-2s delay to the boot process.
Investigation
I noticed in sender.go that tsize is automatically added to the options if the Reader implements Size() or Seek().
Feature Request
Would it be possible to add a hook or option to explicitly suppress tsize from the OACK, even if the Reader supports it?
Something like:
rf.(tftp.OutgoingTransfer).SuppressTSize()This would allow servers to negotiate blksize (for speed) while hiding tsize (to prevent UEFI crashes) without breaking the Reader interface needed for efficient retransmits.
Packet Capture Evidence
Request 1 (Fail):
Client: RRQ "file.efi" tsize=0 blksize=1468
Server: OACK tsize=1125376 blksize=1468
Client: ERROR code=8 (User Aborted)
Request 2 (Success):
Client: RRQ "file.efi" blksize=1468
Server: OACK blksize=1468
Client: ACK (Transfer begins)
Happy to provide packet captures or test builds if needed. Thanks for your time!