RFC 783
TFTP Protocol (revision 2)
RFC 783: THE TFTP PROTOCOL (REVISION 2) ๐
Okay bestie, this one is the RFC for TFTP Revision 2, written by K. R. Sollins at MIT in June 1981 ๐ง. It's a Network Working Group document, Request for Comments number 783. It Updates IEN 133 ๐ , so it builds on that earlier note instead of replacing it.
Summary โจ
TFTP is a super simple protocol for transferring files ๐ฆ. That's where the name comes from: Trivial File Transfer Protocol, or TFTP. Every nonterminal packet gets acknowledged separately. This document describes the protocol and its packet types, and it also explains the reasons behind some of the design choices. Very smart, very intentional ๐.
ACKNOWLEDGEMENTS ๐ซถ
The protocol was originally designed by Noel Chiappa ๐ธ. Then he redesigned it with Bob Baldwin and Dave Clark, with comments from Steve Szymanski. This revision includes changes that came out of discussions and suggestions from Larry Allen, Noel Chiappa, Dave Clark, Geoff Cooper, Mike Greenwald, Liza Martin, David Reed, Craig Milo Rogers (of UCS-ISI), Kathy Yellick, and the author ๐.
The acknowledgement and retransmission scheme was inspired by TCP, and the error mechanism came from PARC's EFTP abort message ๐ฅ.
This research was supported by the Advanced Research Projects Agency of the Department of Defense. It was monitored by the Office of Naval Research under contract number N00014-75-C-0661 ๐.
1. Purpose ๐
TFTP is a simple protocol for transferring files, which is why it got the name Trivial File Transfer Protocol, or TFTP ๐. It's built on top of the Internet User Datagram Protocol (UDP or Datagram) [2], so you can use it to move files between machines on different networks that run UDP. (This doesn't rule out running TFTP on top of other datagram protocols, btw.) It's designed to be small and easy to implement, so it's missing most of the features you'd find in a regular FTP. The only things it can do are read and write files (or mail) to and from a remote server. It can't list directories, and it doesn't currently have any provisions for user authentication ๐. Like other Internet protocols, it passes 8 bit bytes of data ๐ .
Three transfer modes are supported right now: netasciiยน, octetยฒ, and mail. Netascii means netascii characters, octet means raw 8 bit bytes, and mail means netascii characters sent to a user rather than to a file โจ. Additional modes can be defined by pairs of cooperating hosts, which is very cute of them ๐.
ยน This is ASCII as defined in "USA Standard Code for Information Interchange" [1], with the modifications specified in "Telnet Protocol Specification" [3]. Note that it is 8 bit ASCII. The term "netascii" will be used throughout this document to mean this particular version of ASCII. ยฒ This replaces the "binary" mode of previous versions of this
2. Overview of the Protocol ๐ฆ
Every transfer begins with a request to read or write a file, and that request also serves to ask for a connection ๐. If the server grants the request, the connection opens and the file gets sent in fixed length blocks of 512 bytes. Each data packet contains one block of data, and it must be acknowledged by an acknowledgment packet before the next packet can be sent. A data packet with less than 512 bytes signals the end of a transfer ๐.
If a packet gets lost in the network, the intended recipient will time out and may retransmit its last packet (which may be data or an acknowledgment). That makes the sender of the lost packet retransmit the lost packet too ๐. The sender only has to keep one packet on hand for retransmission, because the lock step acknowledgment guarantees that all older packets have been received ๐ง . Both machines in a transfer count as senders and receivers. One sends data and receives acknowledgments. The other sends acknowledgments and receives data. Iconic teamwork ๐ฏโโ๏ธ.
Most errors cause the connection to terminate ๐. An error gets signalled by sending an error packet. That packet isn't acknowledged and isn't retransmitted (so a TFTP server or user may terminate after sending an error message), which means the other end of the connection may never get it. That's why timeouts are used to detect such a termination when the error packet has been lost โฐ. Errors come from three kinds of events: not being able to satisfy the request (for example, file not found, access violation, or no such user), receiving a packet that can't be explained by a delay or duplication in the network (for example, an incorrectly formed packet), and losing access to a necessary resource (for example, disk full, or access denied during a transfer) ๐ญ.
TFTP recognizes only one error condition that does not cause termination: the source port of a received packet being incorrect. In that case, an error packet is sent to the originating host ๐ โโ๏ธ.
This protocol is very restrictive, and that's on purpose, to keep implementation simple ๐. For example, the fixed length blocks make allocation straightforward. The lock step acknowledgement provides flow control and removes the need to reorder incoming data packets. Genius, honestly ๐.
3. Relation to other Protocols ๐ง
As mentioned, TFTP is designed to be implemented on top of the Datagram protocol. Datagram is implemented on the Internet protocol, so packets will have an Internet header, a Datagram header, and a TFTP header ๐. Packets may also have a header (LNI, ARPA header, etc.) to get them through the local transport medium ๐. As shown in Figure 3-1, the order of the contents of a packet is: local medium header (if used), Internet header, Datagram header, TFTP header, and then the rest of the TFTP packet. (That rest may or may not be data, depending on the type of packet specified in the TFTP header.) TFTP doesn't specify any of the values in the Internet header ๐. The source and destination port fields of the Datagram header (its format is given in the appendix) are used by TFTP, and the length field reflects the size of the TFTP packet ๐.
The transfer identifiers (TID's) used by TFTP get passed to the Datagram layer to be used as ports, so they must be between 0 and 65,535 ๐ข. How TID's get initialized is discussed in the section on the initial connection protocol ๐ซ.
The TFTP header consists of a 2 byte opcode field that indicates the packet's type (for example, DATA, ERROR, etc.) ๐ท๏ธ. These opcodes, and the formats of the various types of packets, are discussed further in the section on TFTP packets ๐ฆ.
Figure 3-1: Order of Headers
---------------------------------------------------
| Local Medium | Internet | Datagram | TFTP |
---------------------------------------------------
4. Initial Connection Protocol ๐ธ
A transfer is established by sending a request (WRQ to write onto a foreign file system, or RRQ to read from it) and receiving a positive reply. For a write, that reply is an acknowledgment packet. For a read, it's the first data packet ๐. In general, an acknowledgment packet contains the block number of the data packet it's acknowledging. Each data packet has a block number associated with it. Block numbers are consecutive and begin with one ๐ข. Since the positive response to a write request is an acknowledgment packet, in this special case the block number will be zero. (Normally, since an acknowledgment packet is acknowledging a data packet, the acknowledgment packet will contain the block number of the data packet being acknowledged.) If the reply is an error packet, then the request has been denied ๐ซ.
To create a connection, each end of the connection chooses a TID for itself, to be used for the whole duration of that connection ๐ฆ. The TID's chosen for a connection should be randomly chosen, so that the probability that the same number gets chosen twice in immediate succession is very low ๐ฒ. Every packet has the two TID's of the ends of the connection associated with it: the source TID and the destination TID. These TID's are handed to the supporting UDP (or other datagram protocol) as the source and destination ports ๐. A requesting host chooses its source TID as described above, and sends its initial request to the known TID 69 decimal (105 octal) on the serving host ๐ฎ. Under normal operation, the response to the request uses a TID chosen by the server as its source TID, and the TID the requestor chose for the previous message as its destination TID. The two chosen TID's are then used for the rest of the transfer ๐.
Here's an example of the steps used to establish a connection to write a file ๐. WRQ, ACK, and DATA are the names of the write request, acknowledgment, and data types of packets, respectively. The appendix has a similar example for reading a file ๐.
- Host A sends a "WRQ" to host B with source= A's TID, destination= 69.
- Host B sends an "ACK" (with block number= 0) to host A with source= B's TID, destination= A's TID.
At this point the connection has been established, and Host A can send the first data packet with a sequence number of 1 ๐. In the next step, and in all the steps after that, the hosts should make sure that the source TID matches the value that was agreed on in steps 1 and 2. If a source TID doesn't match, the packet should be discarded as erroneously sent from somewhere else. An error packet should be sent to the source of the incorrect packet, without disturbing the transfer ๐ก๏ธ.
This can only be done if TFTP actually receives a packet with an incorrect TID. If the supporting protocols don't allow it, this particular error condition won't come up ๐คทโโ๏ธ.
The following example shows the protocol working correctly in a situation where the above can happen ๐. Host A sends a request to host B. Somewhere in the network, the request packet gets duplicated, and as a result, two acknowledgments come back to host A, with different TID's chosen on host B in response to the two requests ๐. When the first response arrives, host A continues the connection. When the second response to the request arrives, it should be rejected, but there's no reason to terminate the first connection ๐ โโ๏ธ. So if different TID's are chosen for the two connections on host B, and host A checks the source TID's of the messages it receives, the first connection can be maintained while the second is rejected by returning an error packet ๐.
5. TFTP Packets ๐ฆ
TFTP supports five types of packets, all of which have been mentioned above ๐:
opcode operation
1 Read request (RRQ)
2 Write request (WRQ)
3 Data (DATA)
4 Acknowledgment (ACK)
5 Error (ERROR)
The TFTP header of a packet contains the opcode associated with that packet ๐ท๏ธ.
Figure 5-1: RRQ/WRQ packet
2 bytes string 1 byte string 1 byte
------------------------------------------------
| Opcode | Filename | 0 | Mode | 0 |
------------------------------------------------
RRQ and WRQ packets (opcodes 1 and 2 respectively) have the format
Okay so the file name is a sequence of bytes in netascii, and it gets closed off with a zero byte ๐ Figure 5-1 shows the layout. Next up is the mode field. It holds the string "netascii", "octet", or "mail" (any mix of upper and lower case works too, like "NETASCII" or "NetAscii") to tell you which of the three modes defined in the protocol you're using ๐
A host that gets netascii mode data must translate it into its own format.
Octet mode is for moving a file that's in the 8-bit format of the machine sending it ๐ฆ Every type of machine is assumed to have one 8-bit format that's most common, and that's the one that gets picked. Like, on a DEC-20 (a 36-bit machine), that's four 8-bit bytes per word with four bits of breakage ๐ If a host gets an octet file and sends it back, the returned file has to be identical to the original, no exceptions ๐ญ
Mail mode uses the name of a mail recipient instead of a file, and it must begin with a WRQ. Other than that, it's exactly the same as netascii mode ๐ The recipient string should look like "username" or "username@hostname". The second form lets a relay computer do mail forwarding, which is giving main character energy ๐
The stuff above assumes both sides are in the same mode, but they don't have to be, bestie ๐ Picture a storage server. It has no reason to translate netascii into its own text form. The sender could ship files in netascii, and the storage server could just save them as they are, in 8-bit format โจ Another situation is a problem that already exists on DEC-20 systems. Neither netascii nor octet reads every bit in a word. You could make a special mode that reads all the bits in a word, with the receiver storing the info in 8-bit format ๐ง When that file gets pulled back from the storage site, it has to be restored to its original form to be useful, so the reverse mode needs to be built too. The user site will have to remember some info to pull that off ๐ซถ In both of these examples, the request packets would ask for octet mode from the foreign host, but the local host would be running some other mode. TFTP doesn't specify any machine or application specific modes, but one would still be compatible with this specification ๐
It's also possible to define other modes for cooperating pairs of hosts, although that has to be done with care โ ๏ธ Nobody is required to implement these. There's no central authority that defines these modes or hands out their names ๐
2 bytes 2 bytes n bytes
----------------------------------
| Opcode | Block # | Data |
----------------------------------
Figure 5-2 is the DATA packet, and this is where the actual file data moves around ๐ฆ DATA packets have opcode 3, plus a block number and a data field. Block numbers start at one and go up by one for each new block of data. That rule means the program can use one number to tell new packets apart from duplicates, which is so smart ๐ง The data field is anywhere from zero to 512 bytes long. If it's 512 bytes, the block isn't the last one. If it's from zero to 511 bytes, that's the end of the transfer (check the Normal Termination section for the details ๐ธ).
Every packet except the ones used for termination gets acknowledged individually, unless a timeout happens ๐ Sending a DATA packet counts as the acknowledgment for the ACK packet of the previous DATA packet. WRQ and DATA packets get acknowledged by ACK or ERROR packets, while RRQ and ACK packets get acknowledged by DATA or ERROR packets ๐ฅ
2 bytes 2 bytes
---------------------
| Opcode | Block # |
---------------------
ACK packets are the ones that say "got it" ๐ท Figure 5-3 shows the layout, and the opcode is 4. The block number in an ACK echoes the block number of the DATA packet it's acknowledging. A WRQ gets acknowledged with an ACK packet whose block number is zero ๐
2 bytes 2 bytes string 1 byte
-----------------------------------------
| Opcode | ErrorCode | ErrMsg | 0 |
-----------------------------------------
ERROR packets (opcode 5) look like Figure 5-4 ๐ญ An ERROR packet can act as the acknowledgment for any other type of packet. The error code is an integer that tells you what kind of error happened, and the table of values and meanings is in the appendix. (Heads up: several error codes were added to this version of the document ๐) The error message is meant for humans to read, so it should be in netascii. Like every other string, it ends with a zero byte ๐
6. Normal Termination ๐ธ
The end of a transfer is marked by a DATA packet with between 0 and 511 bytes of data (aka a datagram length under 516) ๐ That packet gets acknowledged by an ACK packet, same as every other DATA packet. The host acknowledging the final DATA packet can close its side of the connection once it sends the final ACK. BUT dallying is encouraged ๐ Dallying means the host sending the final ACK waits a bit before closing, so it can resend that final ACK if it got lost. The acknowledger will know the ACK was lost if it gets the final DATA packet again ๐ The host sending the last DATA has to keep resending it until it gets acknowledged or until the sending host times out ๐ช If the response is an ACK, the transfer finished successfully โจ If the sender times out and isn't willing to retransmit anymore, the transfer might still have finished successfully, and then the acknowledger or the network may have had a problem afterward. It's also possible the transfer didn't work at all ๐ Either way, the connection has been closed.
7. Premature Termination ๐ฆ
If a request can't be granted, or some error happens during the transfer, an ERROR packet (opcode 5) gets sent ๐ This is only a courtesy, though. It won't be retransmitted or acknowledged, so it might never arrive ๐ญ Timeouts must also be used to detect errors. Don't skip them, babe ๐ซถ
I. Appendix ๐
Order of Headers
2 bytes
----------------------------------------------------------
| Local Medium | Internet | Datagram | TFTP Opcode |
----------------------------------------------------------
TFTP Formats
Type Op # Format without header
2 bytes string 1 byte string 1 byte
-----------------------------------------------
RRQ/ | 01/02 | Filename | 0 | Mode | 0 |
WRQ -----------------------------------------------
2 bytes 2 bytes n bytes
---------------------------------
DATA | 03 | Block # | Data |
---------------------------------
2 bytes 2 bytes
-------------------
ACK | 04 | Block # |
--------------------
2 bytes 2 bytes string 1 byte
----------------------------------------
ERROR | 05 | ErrorCode | ErrMsg | 0 |
----------------------------------------
Initial Connection Protocol for reading a file
- Host A sends a
"RRQ"to host B withsource= A's TIDanddestination= 69๐ฆ - Host B sends a
"DATA"(withblock number= 1) to host A withsource= B's TIDanddestination= A's TID๐
Error Codes
Value Meaning
0 Not defined, see error message (if any).
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.
Internet User Datagram Header [2] ๐
Footnote 3 is attached to this heading.
Format
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Length | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Values of Fields
Source Port Picked by originator of packet.
Dest. Port Picked by destination machine (69 for RRQ or WRQ).
Length Number of bytes in packet after Datagram header.
Checksum Reference 2 describes rules for computing checksum.
Field contains zero if unused.
Note: TFTP passes transfer identifiers (TID's) to the Internet User Datagram protocol to be used as the source and destination ports. ๐
Footnote 3: This has been included only for convenience. TFTP need not be implemented on top of the Internet User Datagram Protocol.
Footnote 4: The implementor of this should be sure that the correct algorithm is used here.
References ๐
๐ฆ where this page comes from
- ietf: rfc783 1981-06
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms