RFC 765

File Transfer Protocol specification

๐Ÿ“… published June 1980, from ietf

RFC 765: FILE TRANSFER PROTOCOL ๐ŸŽ€

Okay bestie, the title block is giving main character energy ๐Ÿ’–. This is RFC 765, titled FILE TRANSFER PROTOCOL, written by J. Postel from ISI, and dated June 1980. The header also lists it as IEN 149 โœจ. (This is part 1 of 12 ๐Ÿฆ‹.)

This part of the original doesn't include a category, status, or anything about what it obsoletes or updates, so there's nothing more to add to the title block yet ๐Ÿ™ˆ.

Introduction โœจ

Okay so FTP has four big goals ๐Ÿ’…:

  1. Promote sharing of files (computer programs and/or data) ๐Ÿ“
  2. Encourage indirect or implicit (via programs) use of remote computers ๐Ÿ–ฅ๏ธ
  3. Shield a user from variations in file storage systems among Hosts ๐Ÿ›ก๏ธ
  4. Transfer data reliably and efficiently ๐Ÿš€

FTP can be used directly by a person at a terminal, but it's honestly designed mainly for programs to use ๐Ÿค–๐Ÿซถ.

This spec is trying to meet the different needs of maxi-Hosts, mini-Hosts, and TIPs ๐ŸŒˆ, and it does that with a protocol design that's simple and easy to implement ๐Ÿ“.

This paper assumes you already know these two protocols from the ARPA Internet Protocol Handbook ๐Ÿ“š๐Ÿ’œ:

  • The Transmission Control Protocol ๐Ÿฆ‹
  • The TELNET Protocol ๐Ÿ’ป

DISCUSSION โœจ

okay bestie, this part is where we get the vocab down before things get spicy ๐ŸŽ€ we're talking terminology and the FTP model. the terms in here are only the ones that have special meaning in FTP, so some of them are super FTP-specific. if the model stuff gets confusing, feel free to jump ahead and come back. no judgment ๐Ÿซถ

TERMINOLOGY ๐Ÿ’…

ASCII

ASCII means the character set from the ARPA Internet Protocol Handbook ๐Ÿ“– in FTP, ASCII characters are the lower half of an eight-bit code set. so the most significant bit is zero. literally that's it, it's giving clean ๐Ÿงš

access controls

access controls are the rules that decide who gets to use a system and which files they can touch ๐Ÿ” they're necessary to stop unauthorized or accidental file use, so it's not optional energy. and it's the server-FTP process that gets to invoke them. the server is the bouncer, not the guest ๐Ÿ’€

byte size

there are two byte sizes that matter in FTP ๐Ÿ‘€ first, the logical byte size of the file. second, the transfer byte size, which is what gets used when data is actually sent. the transfer byte size is always 8 bits ๐ŸŒธ but here's the twist: it's not necessarily the byte size the data gets stored in on a system, and it's not necessarily the logical byte size used to read the structure of the data either. so don't mix them up, ngl it's a whole mood to get confused by ๐Ÿ™ˆ

data connection

a data connection is a simplex connection, meaning one-way, that carries data in a specified mode and type ๐Ÿฆ‹ the data can be part of a file, a whole file, or a bunch of files. the path can run between a server-DTP and a user-DTP, or between two server-DTPs. so yeah, the data connection is the main character of the transfer โœจ

data port

the passive data transfer process "listens" on the data port ๐Ÿ‘‚ it waits there for a connection from the active transfer process so the data connection can get opened. very patient, very iconic ๐Ÿซถ

EOF

EOF is the end-of-file condition. it marks where a file being transferred ends ๐Ÿ bye file

EOR

EOR is the end-of-record condition. it marks where a record being transferred ends ๐Ÿ“

error recovery

error recovery is a procedure that lets a user bounce back from certain errors, like a host system failing or a transfer process failing ๐Ÿ”„ in FTP, that can mean restarting a file transfer from a given checkpoint. "resume where we left off" is giving everything ๐Ÿ’–

FTP commands

FTP commands are the set of commands that make up the control information flowing from the user-FTP to the server-FTP process ๐ŸŽ€ basically the instructions, the talking, the "hey can you do this" messages ๐Ÿ’ฌ

file

a file is an ordered set of computer data, including programs ๐Ÿ—‚๏ธ it can be any length, and it's uniquely identified by a pathname. no two files are out here sharing identities, periodt โœจ

mode

mode is how data is transferred over the data connection ๐Ÿšš it defines the data format during the transfer, including EOR and EOF. the transfer modes defined in FTP get covered in the Section on Transmission Modes, so that's where the deets live ๐Ÿ”œ

NVT

NVT stands for the Network Virtual Terminal, as defined in the TELNET Protocol ๐Ÿ’œ it's the shared terminal language everybody agrees on so nobody's speaking gibberish to each other ๐ŸŒˆ

NVFS

NVFS is the Network Virtual File System ๐Ÿ—„๏ธ it's a concept for a standard network file system with standard commands and pathname conventions. the tea is that FTP only partially implements NVFS at this time. so it's a work in progress, and honestly relatable ๐Ÿ˜ญ

page

a file can be structured as a set of independent parts called pages ๐Ÿ“„ FTP supports sending discontinuous files as independent indexed pages. so the file can be in chunks and the chunks still know where they go. very organized, very slay ๐Ÿ’…

pathname

pathname is the character string a user has to input into a file system to identify a file ๐Ÿ—บ๏ธ it usually includes device and/or directory names, plus a file name. here's the lowkey messy part: FTP does not yet specify a standard pathname convention. so each user has to follow whatever naming rules the file systems involved in the transfer use ๐Ÿ™ƒ no cap, that's a lot of responsibility on us

record

a sequential file can be structured as a bunch of contiguous parts called records ๐Ÿ“š FTP supports record structures, but a file doesn't have to have record structure. so records are optional, not a must-have ๐Ÿ“

reply

a reply is an acknowledgment, positive or negative, sent from server to user over the TELNET connections in response to FTP commands ๐Ÿ’Œ the general form is a completion code, error codes included, followed by a text string. the codes are for programs, and the text is usually for the human, so both of them get to be seen ๐Ÿ‘‘

server-DTP

the server-DTP is the data transfer process. in its normal "active" state, it sets up the data connection with the "listening" data port, sets up parameters for transfer and storage, and moves the data when its PI tells it to ๐Ÿš€ the DTP can also go into a "passive" state where it listens for a connection on the data port instead of starting one itself. waiting for the call instead of making it, iykyk ๐Ÿงš

server-FTP process

the server-FTP process is a process, or a set of processes, that does file transfer together with a user-FTP process and possibly another server ๐Ÿ–ฅ๏ธ its functions are a protocol interpreter (PI) and a data transfer process (DTP). it's the whole squad ๐Ÿซถ

server-PI

the server-PI "listens" on Port L for a connection from a user-PI and then sets up a TELNET communication connection ๐Ÿ“ก it gets standard FTP commands from the user-PI, sends replies back, and governs the server-DTP. the server-PI is the one running the show behind the scenes ๐ŸŽฌ

TELNET connections

TELNET connections are the full-duplex communication path between a user-PI and a server-PI, running according to the TELNET Protocol ๐Ÿ” full-duplex means traffic can go both ways at once. no awkward turn-taking, just vibes ๐Ÿ’œ

type

type is the data representation type used for data transfer and storage ๐ŸŽจ type implies certain transformations between when data is stored and when it's transferred. the representation types defined in FTP are described in the Section on Establishing Data Connections, so check there for the full menu ๐Ÿฝ๏ธ

user

a user is a human being, or a process acting on behalf of a human, who wants file transfer service ๐Ÿ™‹ a human can talk straight to a server-FTP process, but using a user-FTP process is preferred because the protocol design is weighted toward automata ๐Ÿค– so the robots get the spotlight here, lowkey ๐Ÿ’…

user-DTP

the user-DTP "listens" on the data port for a connection from a server-FTP process ๐Ÿ‘‚ if two servers are transferring data between themselves, the user-DTP is inactive and just chilling ๐Ÿ˜Œ

user-FTP process

the user-FTP process is a set of functions made up of a protocol interpreter, a data transfer process, and a user interface ๐ŸŽ€ together, they do file transfer with one or more server-FTP processes. the user interface lets a local language be used in the command-reply dialogue with the user, so you can talk in your own language ๐ŸŒ

user-PI

the user-PI initiates the TELNET connection from its port U to the server-FTP process ๐Ÿ”Œ it starts FTP commands and governs the user-DTP, but only if that process is part of the file transfer. so the user-PI is basically the one who starts the conversation ๐Ÿ’–


THE FTP MODEL ๐Ÿฆ‹

okay this is the fun part, let's diagram this bestie ๐Ÿ–ผ๏ธ with all those definitions in mind, here's the model for an FTP service, shown in Figure 1:

                                        -------------
                                        |/---------\|
                                        ||   User  ||    --------
                                        ||Interface|<--->| User |
                                        |\----:----/|    --------
              ----------                |     V     |
              |/------\|  FTP Commands  |/---------\|
              ||Server|<---------------->|   User  ||
              ||  PI  ||   FTP Replies  ||    PI   ||
              |\--:---/|                |\----:----/|
              |   V    |                |     V     |
--------      |/------\|      Data      |/---------\|    --------
| File |<--->|Server|<---------------->|  User   |<--->| File |
|System|    || DTP  ||   Connection   ||   DTP   ||    |System|
--------    |\------/|                |\---------/|    --------
              ----------                -------------

              Server-FTP                   User-FTP

  NOTES: 1. The data connection may be used in either direction.
         2. The data connection need not exist all of the time.

                  Figure 1  Model for FTP Use

so the user-protocol interpreter starts the TELNET connection ๐Ÿš€ when the user kicks things off, the user-PI generates standard FTP commands and sends them to the server process over the TELNET connection. (the user can also make a direct TELNET connection to the server-FTP, from a TIP terminal for example, and type out the standard FTP commands themself, skipping the user-FTP process entirely ๐Ÿง‘โ€๐Ÿ’ป) the server-PI sends standard replies back to the user-PI over the TELNET connection in response to those commands ๐Ÿ’Œ

the FTP commands set the parameters for the data connection: data port, transfer mode, representation type, and structure ๐ŸŽ›๏ธ they also set the nature of the file system operation, like store, retrieve, append, delete, and so on. the user-DTP or its designate should "listen" on the specified data port, and the server starts the data connection and the data transfer following the parameters ๐Ÿซถ quick note, the data port doesn't need to be on the same Host that starts the FTP commands over the TELNET connection ๐ŸŒ but the user, or their user-FTP process, must make sure there's a "listen" on the specified data port ๐Ÿ‘‚ another fun fact: the data connection can be used for sending and receiving at the same time โœจ

in another situation, a user might want to transfer files between two Hosts, and neither of them is their local Host ๐Ÿ—บ๏ธ they set up TELNET connections to the two servers and then arrange a data connection between them. so the control info goes to the user-PI, but the data gets transferred between the server data transfer processes ๐Ÿ’œ here's the model for this server-server interaction:

              TELNET     ------------    TELNET
              ---------->| User-FTP |<-----------
              |          | User-PI  |           |
              |          |   "C"    |           |
              V          ------------           V
      --------------                        --------------
      | Server-FTP |   Data Connection      | Server-FTP |
      |    "A"     |<---------------------->|    "B"     |
      --------------  Port (A)     Port (B) --------------


                           Figure 2

the protocol requires that the TELNET connections stay open while data transfer is happening ๐Ÿ”’ it's the user's job to ask for the TELNET connections to be closed when they're done with the FTP service, but it's the server that actually takes the action โœ… and the server may abort the data transfer if the TELNET connections get closed without a command ๐Ÿ’€ so don't just yank the cord, bestie ๐Ÿ™ˆ

DATA TRANSFER FUNCTIONS ๐Ÿšš

Okay so the big deal here is how data actually moves between two computers ๐Ÿ’– The file goes over the data connection, while the TELNET connection just carries the commands and replies ๐Ÿฆ‹ The MODE command decides how the bits get sent, and STRUcture and TYPE decide how the data is represented. Those two things are basically independent, bestie ๐Ÿงš

"Stream" mode depends on the file structure attribute ๐ŸŒธ And if "Compressed" mode is used, the filler byte depends on the representation type ๐Ÿซถ

DATA REPRESENTATION AND STORAGE โœจ

Data moves from a storage device on the sending Host to a storage device on the receiving Host ๐Ÿš€ But the two systems often store things differently, so the data usually needs some transforming ๐Ÿ”ฅ NVT-ASCII is a perfect example, because every system keeps it a little differently ๐Ÿ™ˆ PDP-10s usually store NVT-ASCII as five 7-bit ASCII characters, left-justified in a 36-bit word ๐Ÿ’… 360s store NVT-ASCII as 8-bit EBCDIC codes ๐Ÿ“ Multics stores it as four 9-bit characters in a 36-bit word ๐ŸŒˆ

When you're sending text between systems that are totally different, it can be a good idea to convert the characters into the standard NVT-ASCII representation โœจ The sending and receiving sites would then need to handle the transformations between the standard form and their own internal form, obviously ๐Ÿ’œ

Binary data (not character codes) is a whole other headache ๐Ÿ˜ญ Between Hosts with different word lengths, it's not always clear how the sender should send the data or how the receiver should store it ๐Ÿ’€ For example, if you send 32-bit bytes from a 32-bit word-length system to a 36-bit word-length system, it may be useful (for efficiency and usefulness reasons) to store those 32-bit bytes right-justified in a 36-bit word on the latter system ๐Ÿ‘‘ Either way, the user should get to choose the data representation and transformation functions ๐ŸŽ€ Just a heads up, FTP only provides very limited data type representations ๐Ÿซฃ If you want transformations beyond that, you have to do them yourself, directly ๐Ÿ’…

In FTP, a user picks a representation type to handle the data ๐Ÿฆ‹ The type can define a byte size for interpretation either implicitly (like ASCII or EBCDIC) or explicitly (like Local byte) โญ That size is called the "logical byte size" โœจ It has nothing to do with the byte size used for transmission over the data connection, which is the "transfer byte size", so please don't mix them up ๐Ÿ™ˆ For example, NVT-ASCII has a logical byte size of 8 bits ๐Ÿ’– If the type is Local byte, the TYPE command has an obligatory second parameter that specifies the logical byte size ๐Ÿงš The transfer byte size is always 8 bits ๐Ÿซถ

The types ASCII and EBCDIC also take an optional second parameter ๐ŸŒธ This indicates what kind of vertical format control, if any, is associated with a file ๐ŸŽ€ FTP defines the following data representation types:

ASCII Format ๐ŸŒˆ

Description

This is the default type and must be accepted by all FTP implementations ๐Ÿ’… It's mainly meant for transferring text files, unless both Hosts would find the EBCDIC type more convenient ๐Ÿ“

The sender converts the data from their internal character representation to the standard 8-bit NVT-ASCII representation (see the TELNET specification) ๐Ÿฆ‹ The receiver then converts the data from the standard form into their own internal form โœจ

Following the NVT standard, the <CRLF> sequence should be used, where necessary, to mark the end of a line of text ๐Ÿ’œ (See the discussion of file structure at the end of the Section on Data Representation and Storage ๐Ÿงš)

Using the standard NVT-ASCII representation means the data must be interpreted as 8-bit bytes ๐Ÿ‘‘

The Format parameter for ASCII and EBCDIC types is discussed below ๐Ÿซถ

EBCDIC Format ๐Ÿ’–

This type is meant for efficient transfer between Hosts that use EBCDIC for their internal character representation ๐Ÿ”ฅ

For transmission, the data is represented as 8-bit EBCDIC characters ๐ŸŒธ The character code is the only difference between the functional specifications of the EBCDIC and ASCII types ๐Ÿ™ˆ

End-of-line (as opposed to end-of-record, see the discussion of structure) will probably be rarely used with the EBCDIC type for marking structure ๐Ÿ’€ But when it is necessary, the <NL> character should be used ๐ŸŽ€

A character file can be transferred to a Host for one of three purposes: printing, storing and retrieving later, or processing ๐Ÿฆ‹ If a file is sent for printing, the receiving Host must know how the vertical format control is represented ๐Ÿซฃ If a file is stored on a Host, it must be possible to retrieve it later in exactly the same form โœจ And ideally, it ought to be possible to move a file from one Host to another and process it on the second Host without undue trouble ๐Ÿ’… A single ASCII or EBCDIC format doesn't cover all of these, so these types have a second parameter that specifies one of the following three formats ๐Ÿ‘‘

Format Parameter for ASCII and EBCDIC ๐ŸŒˆ

Non-print

This is the default format if the second (format) parameter is left out โญ Non-print format must be accepted by all FTP implementations ๐Ÿ’œ

The file doesn't need to contain any vertical format information ๐Ÿงš If it's passed to a printer process, that process may assume standard values for spacing and margins ๐Ÿ“

This format is normally used for files that are destined for processing or just storage ๐Ÿซถ

TELNET Format Controls

The file contains ASCII/EBCDIC vertical format controls (i.e., <CR>, <LF>, <NL>, <VT>, <FF>) which the printer process will interpret appropriately ๐Ÿ”ฅ <CRLF>, in exactly this sequence, also marks the end of a line ๐ŸŒธ

Carriage Control (ASA)

The file contains ASA (FORTRAN) vertical format control characters ๐Ÿ’– (See RFC 740 Appendix C and Communications of the ACM, Vol. 7, No. 10, 606 (Oct. 1964) ๐Ÿฆ‹) In a line or a record formatted according to the ASA Standard, the first character is not to be printed ๐Ÿ™ˆ Instead, it's used to decide the vertical movement of the paper that should happen before the rest of the record gets printed ๐Ÿ’…

The ASA Standard specifies these control characters:

   Character     Vertical Spacing

   blank         Move paper up one line
   0             Move paper up two lines
   1             Move paper to top of next page
   +             No movement, i.e., overprint

Clearly, a printer process needs some way to tell where the structural entity ends ๐Ÿ‘€ If a file has record structure (see below), that's no problem, since records get explicitly marked during transfer and storage ๐ŸŽ€ If the file has no record structure, the <CRLF> end-of-line sequence separates the printing lines, but these format effectors get overridden by the ASA controls ๐Ÿ‘‘

Image ๐ŸŒˆ

The data is sent as contiguous bits, which for transfer are packed into the 8-bit transfer bytes โœจ The receiving site must store the data as contiguous bits ๐Ÿงš The storage system might need to pad the file (or each record, for a record-structured file) to some convenient boundary (byte, word or block) ๐Ÿซฃ This padding must be all zeros, may only occur at the end of the file (or at the end of each record), and there must be a way to identify the padding bits so they can be stripped off when the file is retrieved ๐Ÿ˜ญ The padding transformation should be well publicized so users can process a file at the storage site ๐Ÿ“ฃ

Image type is meant for efficient storage and retrieval of files and for transferring binary data ๐Ÿ’œ It is recommended that all FTP implementations accept this type ๐Ÿซถ

Local byte Byte size ๐Ÿฆ‹

The data is transferred in logical bytes of the size given by the obligatory second parameter, Byte size ๐Ÿ’– The value of Byte size must be a decimal integer, and there is no default value ๐Ÿ”ฅ The logical byte size isn't necessarily the same as the transfer byte size ๐Ÿ™ˆ If the two sizes differ, the logical bytes should be packed contiguously, ignoring transfer byte boundaries, with any necessary padding at the end ๐ŸŒธ

When the data reaches the receiving Host, it gets transformed in a way that depends on the logical byte size and on the particular Host ๐Ÿ‘‘ This transformation must be invertible (an identical file can be retrieved if the same parameters are used) and should be well publicized by the FTP implementors ๐Ÿ’…

For example, a user sending 36-bit floating-point numbers to a Host with a 32-bit word could send the data as Local byte with a logical byte size of 36 ๐ŸŒˆ The receiving Host would then be expected to store the logical bytes so they can be easily manipulated ๐Ÿงš In this example, putting the 36-bit logical bytes into 64-bit double words should do the trick โœจ

Another example: a pair of hosts with a 36-bit word size can send data to each other in words by using TYPE L 36 ๐Ÿ“ The data would be sent in the 8-bit transmission bytes, packed so that 9 transmission bytes carry two host words ๐Ÿซถ

A note of caution about parameters: a file must be stored and retrieved with the same parameters if the retrieved version is to be identical to the version originally transmitted ๐Ÿšจ On the flip side, FTP implementations must return a file identical to the original if the parameters used to store and retrieve it are the same ๐Ÿ’–

In addition to the different representation types, FTP lets you specify the structure of a file ๐Ÿฆ‹ Three file structures are defined in FTP ๐ŸŽ€

  • file-structure, where there is no internal structure and the file is treated as a continuous sequence of data bytes ๐Ÿซง
  • record-structure, where the file is made up of sequential records ๐ŸŒธ

File-structure is the default, so you can assume it whenever the STRUcture command hasn't been used, bestie ๐Ÿ’– But both file and record structures must be accepted for "text" files (aka files with TYPE ASCII or EBCDIC) by every FTP implementation ๐Ÿซถ The structure of a file affects both its transfer mode (see the Section on Transmission Modes) and how it gets interpreted and stored ๐Ÿ“‚

The "natural" structure of a file depends on which Host stores it ๐Ÿ–ฅ๏ธ A source-code file usually lives on an IBM 360 as fixed-length records, but on a PDP-10 it's a stream of characters split into lines, for example by <CRLF> ๐ŸŒธ If files are going to move between sites this different and still be useful, one site has to be able to figure out what the other one assumes about the file ๐Ÿ”

Some sites are naturally file-oriented and others are naturally record-oriented, so things can get messy when a file with one structure lands on a Host that's oriented to the other ๐Ÿ˜ญ If a text file is sent with record-structure to a file-oriented Host, that Host should apply an internal transformation to the file based on the record structure. The transformation should be useful, but it must also be invertible, so you can get an identical file back using record structure โœจ

Now the other direction: a file sent with file-structure to a record-oriented Host. The question is what criteria the Host should use to split the file into records it can process locally ๐Ÿค” If that split is needed, the FTP implementation should use the end-of-line sequence as the delimiter: <CRLF> for ASCII, or <NL> for EBCDIC text files ๐Ÿ’… If an FTP implementation goes with this technique, it must be ready to reverse the transformation if the file gets retrieved with file-structure ๐Ÿ”

Page Structure

Okay this part is giving random access energy ๐Ÿงš To transmit files that are discontinuous, FTP defines a page structure. These are sometimes known as "random access files" or even "holey files" ๐Ÿ•ณ๏ธ In these files there's sometimes other information tied to the file as a whole (like a file descriptor), or to a section of the file (like page access controls), or both. In FTP, the sections of the file are called pages ๐Ÿ“„

To support different page sizes and their extra info, each page gets sent with a page header. The page header has these defined fields:

Header Length ๐ŸŽ€

This is the number of logical bytes in the page header, including this byte. The minimum header length is 4.

Page Index ๐Ÿฆ‹

This is the logical page number of this section of the file. It's not the transmission sequence number of the page. It's the index used to identify this page of the file ๐Ÿซง

Data Length ๐Ÿ’œ

This is the number of logical bytes in the page data. The minimum data length is 0.

Page Type ๐Ÿ‘‘

This is the type of page it is. These page types are defined:

  • 0 = Last Page This is used to indicate the end of a paged structured transmission. The header length must be 4, and the data length must be 0. ๐Ÿ
  • 1 = Simple Page This is the normal type for simple paged files with no page level associated control information. The header length must be 4. ๐ŸŒท
  • 2 = Descriptor Page This type is used to transmit the descriptive information for the file as a whole. ๐Ÿ“‹
  • 3 = Access Controled Page This type includes an additional header field for paged files with page level access control information. The header length must be 5. ๐Ÿ”

Optional Fields โœจ

Further header fields may be used to supply per page control information, for example, per page access control. Extra fields, extra vibes ๐Ÿ’…

All fields are one logical byte in length. The logical byte size is specified by the TYPE command ๐ŸŽฏ

ESTABLISHING DATA CONNECTIONS ๐Ÿ”Œ

Setting up transfers is all about getting the data connection on the right ports and picking the parameters for the transfer ๐ŸŽ€ Both the user and the server-DTPs have a default data port. The user-process default data port is the same as the control connection port, which is U. The server-process default data port is the port right next to the control connection port, which is L-1 ๐Ÿงš

The transfer byte size is 8-bit bytes. This byte size only matters for the actual transfer of the data. It has no bearing on how the data is represented inside a Host's file system ๐Ÿ—‚๏ธ

The passive data transfer process (this could be a user-DTP or a second server-DTP) shall "listen" on the data port before sending a transfer request command. The FTP request command decides the direction of the data transfer. The server, once it gets the transfer request, initiates the data connection to the port. When the connection is established, the data transfer begins between the DTPs, and the server-PI sends a confirming reply to the user-PI ๐Ÿซถ

The user can also pick an alternate data port with the PORT command. Maybe they want a file dumped on a TIP line printer, or retrieved from a third party Host ๐Ÿ–จ๏ธ In that second case, the user-PI sets up TELNET connections with both server-PIs. One server is told (by an FTP command) to "listen" for a connection that the other one will start. The user-PI sends one server-PI a PORT command with the data port of the other. Finally, both get the appropriate transfer commands. The exact sequence of commands and replies between the user-controller and the servers is defined in the Section on FTP Replies ๐Ÿ“œ

In general, the server is responsible for maintaining the data connection. That means it initiates the connection and closes it ๐Ÿ”’ The exception is when the user-DTP is sending data in a transfer mode that requires the connection to be closed to indicate EOF. The server MUST close the data connection under these conditions:

  1. The server has completed sending data in a transfer mode that requires a close to indicate EOF.
  2. The server receives an ABORT command from the user.
  3. The port specification is changed by a command from the user.
  4. The TELNET connection is closed legally or otherwise.
  5. An irrecoverable error condition occurs.

Otherwise, closing is a server option. If the server uses that option, it must tell the user-process with an appropriate reply ๐Ÿ’–

TRANSMISSION MODES ๐ŸŒˆ

Next up is picking the right transmission mode ๐Ÿ“ There are three modes: one that formats the data and allows for restart procedures; one that also compresses the data for efficient transfer; and one that passes the data with little or no processing. In that last case, the mode works with the structure attribute to decide what processing happens. In compressed mode, the representation type determines the filler byte ๐Ÿซง

All data transfers must be completed with an end-of-file (EOF). The EOF can be stated explicitly or implied by closing the data connection. For files with record structure, all the end-of-record markers (EOR) are explicit, including the final one. For files sent in page structure, a "last-page" page type is used ๐Ÿ

NOTE: In the rest of this section, "byte" means "transfer byte" unless it's explicitly stated otherwise. ๐Ÿค“

For standardized transfer, the sending Host translates its internal end-of-line or end-of-record denotation into the representation the transfer mode and file structure call for. The receiving Host does the inverse translation back to its internal denotation ๐Ÿ”„ An IBM 360 record count field may not be recognized at another Host, so the end-of-record information can be sent as a two-byte control code in Stream mode, or as a flagged bit in a Block or Compressed mode descriptor. End-of-line in an ASCII or EBCDIC file with no record structure should be indicated by <CRLF> or <NL>, respectively. These transformations are extra work for some systems, so identical systems transferring non-record-structured text files might want to use a binary representation and Stream mode instead ๐Ÿฆ‹

The following transmission modes are defined in FTP:

STREAM ๐ŸŒŠ

The data is sent as a stream of bytes. There's no restriction on the representation type used, and record structures are allowed ๐Ÿ’…

In a record-structured file, EOR and EOF are each indicated by a two-byte control code. The first byte of the control code is all ones, which is the escape character. The second byte has the low order bit on and zeros elsewhere for EOR, and the second low order bit on for EOF. So the byte has value 1 for EOR and value 2 for EOF. EOR and EOF can be indicated together on the last byte transmitted by turning on both low order bits, which gives the value 3. If a byte of all ones is meant to be sent as data, it should be repeated in the second byte of the control code ๐Ÿ™ˆ

If the structure is file structure, EOF is indicated by the sending Host closing the data connection, and all bytes are data bytes ๐Ÿ”

BLOCK ๐Ÿงฑ

The file is sent as a series of data blocks, each preceded by one or more header bytes. The header bytes contain a count field and a descriptor code. The count field gives the total length of the data block in bytes, which marks the beginning of the next data block (there are no filler bits). The descriptor code defines:

  • last block in the file (EOF)
  • last block in the record (EOR)
  • restart marker (see the Section on Error Recovery and Restart)
  • suspect data (i.e., the data being transferred is suspected of errors and is not reliable)

This last code is NOT intended for error control within FTP ๐Ÿšซ It's motivated by sites that exchange certain types of data (e.g., seismic or weather data) and want to send and receive all of the data despite local errors (such as "magnetic tape read errors"), while still indicating in the transmission that certain portions are suspect. Record structures are allowed in this mode, and any representation type may be used ๐ŸŒŸ

Okay bestie, the block header is 3 bytes total ๐Ÿ’… Out of those 24 bits, the 16 low-order bits hold the byte count, and the 8 high-order bits hold the descriptor codes ๐ŸŽ€

            Block Header

               +----------------+----------------+----------------+
               | Descriptor     |    Byte Count                   |
               |         8 bits |                      16 bits    |
               +----------------+----------------+----------------+

The descriptor codes are just bit flags in that descriptor byte, and four of them have been assigned. Each code number is the decimal value of its bit ๐Ÿฆ‹

     Code     Meaning

      128     End of data block is EOR
       64     End of data block is EOF
       32     Suspected errors in data block
       16     Data block is a restart marker

You can flag more than one condition on the same block, so as many bits as needed can be set ๐ŸŒˆ ngl that's so efficient.

The restart marker lives inside the data stream as a whole number of 8-bit bytes, and they have to be printable characters in the language you're using over the TELNET connection (like default NVT-ASCII) ๐Ÿงš <SP> (a space, in whatever language you're using) must not be used WITHIN a restart marker. No spaces inside the marker, periodt ๐Ÿ™…โ€โ™€๏ธ

[page 18]

Let's say you want to send a six-character marker. Here's what goes out ๐Ÿ“ First, the header with code 16 and a byte count of 6:

            +--------+--------+--------+
            |Descrptr|  Byte count     |
            |code= 16|             = 6 |
            +--------+--------+--------+

Then the six marker characters, three per row:

            +--------+--------+--------+
            | Marker | Marker | Marker |
            | 8 bits | 8 bits | 8 bits |
            +--------+--------+--------+

            +--------+--------+--------+
            | Marker | Marker | Marker |
            | 8 bits | 8 bits | 8 bits |
            +--------+--------+--------+

COMPRESSED

Okay, compressed mode. There are three kinds of info you can send ๐Ÿ‘‘ First is regular data, sent as a plain byte string. Second is compressed data, which is either replications or filler. Third is control information, sent as a two-byte escape sequence. If you're sending n>0 bytes of regular data (up to 127), those n bytes get a header byte first. That header has its left-most bit set to 0, and the right-most 7 bits hold the number n ๐Ÿ’–

Byte string:

    1       7                8                     8
   +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+     +-+-+-+-+-+-+-+-+
   |0|       n     | |    d(1)       | ... |      d(n)     |
   +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+     +-+-+-+-+-+-+-+-+
                                 ^             ^
                                 |---n bytes---|
                                     of data

So that's the string of n data bytes d(1),..., d(n). Count n must be positive, no exceptions ๐Ÿซถ

If you want to compress a run of n copies of the same data byte d, you send these 2 bytes instead. Very iconic ๐Ÿ”ฅ

[page 19]

Replicated Byte:

     2       6               8
   +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
   |1 0|     n     | |       d       |
   +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+

Filler is the other trick ๐Ÿฆ‹ A string of n filler bytes can squash down into one single byte. The actual filler byte depends on the representation type. If the type is ASCII or EBCDIC, the filler byte is <SP> (Space, ASCII code 32, EBCDIC code 64). If the type is Image or Local byte, the filler is a zero byte.

Filler String:

     2       6
   +-+-+-+-+-+-+-+-+
   |1 1|     n     |
   +-+-+-+-+-+-+-+-+

The escape sequence is a double byte. The first byte is the escape byte, which is all zeros. The second byte holds descriptor codes, same as the ones defined in Block mode. Those codes mean the same thing here, and they apply to the string of bytes that comes right after ๐Ÿงš

Compressed mode is useful for getting more bandwidth on very large network transmissions, and it only costs a little extra CPU ๐Ÿ’… It works best for shrinking printer files, like the ones RJE Hosts generate ๐Ÿ–จ๏ธ ๐ŸŒธ

ERROR RECOVERY AND RESTART

Bestie, this part is kind of a plot twist ๐Ÿ˜ญ There's no provision for detecting bits that get lost or scrambled during data transfer. That level of error control is handled by TCP โœจ BUT there's a restart procedure to protect users from gross system failures, like a Host dying, an FTP-process crashing, or the underlying network going down ๐Ÿ’€

The restart procedure is only defined for block and compressed modes of data transfer. The sender has to insert a special marker code into the data stream, along with some marker information. That marker information only means something to the sender. It also has to be made of printable characters in the default or negotiated language of the TELNET connection (ASCII or EBCDIC) ๐ŸŽ€ The marker could represent a bit-count, a record-count, or any other info that helps a system identify a checkpoint. If the receiver implements the restart procedure, it marks that same spot in its own system, and then passes that info back to the user ๐Ÿฆ‹

[page 20]

So if a system failure happens, the user can restart the transfer by pointing at the marker with the FTP restart procedure. Here's how it plays out ๐ŸŒˆ

The sender drops an appropriate marker block into the data stream at a convenient point. The receiving Host marks the matching data point in its file system, and it tells the user the last known sender and receiver marker information. That goes either directly, or over the TELNET connection in a 110 reply, depending on who's the sender ๐Ÿ’– If there's a system failure, the user or controller process restarts the server at the last server marker. They do this by sending a restart command with the server's marker code as its argument. The restart command goes over the TELNET connection, and it's immediately followed by whatever command was running when the failure hit, like RETR, STOR or LIST ๐Ÿงš

FILE TRANSFER FUNCTIONS

Okay so here's the big picture ๐Ÿ‘‘ The communication channel from the user-PI to the server-PI is set up by a TCP connection from the user to a standard server port. The user protocol interpreter is in charge of sending FTP commands and interpreting the replies it gets back. The server-PI interprets commands, sends replies, and tells its DTP to set up the data connection and move the data ๐Ÿซถ

If the second party in the data transfer (the passive transfer process) is the user-DTP, then it's governed through the internal protocol of the user-FTP Host. If it's a second server-DTP instead, then its PI governs it, on command from the user-PI. The FTP replies get their own section next. For a few of the commands in this section, it helps to be really explicit about the possible replies ๐Ÿ“

FTP COMMANDS

ACCESS CONTROL COMMANDS

The following commands set up access control identifiers. Command codes are in parentheses ๐Ÿ”

[page 21]

USER NAME (USER)

The argument field is a TELNET string that identifies the user. The server needs this identification to access its file system. This command will normally be the first one the user sends after the TELNET connections are made, though some servers may require that. Some servers also want a password and/or an account command on top of this ๐Ÿ’… Servers can allow a new USER command at any point, to change the access control and/or accounting information. That flushes any user, password, and account info already supplied, and starts the login sequence over. Transfer parameters stay unchanged, and any file transfer in progress finishes under the old account ๐ŸŒธ

PASSWORD (PASS)

The argument field is a TELNET string with the user's password. This command must be immediately preceded by the user name command. For some sites, it completes the user's identification for access control ๐Ÿ™ˆ Password info is super sensitive, so it's generally desirable to "mask" it or suppress typeout. The server doesn't seem to have any foolproof way to do that, so it's the user-FTP process's job to hide the sensitive password information. Your client has to handle it, no excuses ๐Ÿ”ฅ

ACCOUNT (ACCT)

The argument field is a TELNET string that identifies the user's account. This command isn't necessarily tied to USER, because some sites want an account just to log in, and others only need one for specific access, like storing files. In that second case, the command can show up at any time ๐Ÿงš

Here's the reply-code tea โ˜• When account info is required for login, the reply to a successful PASSword command is 332. If account info is NOT required for login, the reply to a successful PASSword command is 230. And if the account info is needed for a command later in the dialogue, the server should

[page 22]

return a 332 or 532 reply, depending on whether it stores the command (pending receipt of the ACCounT command) or discards it. 332 is for storing, 532 is for discarding, respectively ๐Ÿฆ‹

REINITIALIZE (REIN)

This command terminates a USER. It flushes all I/O and account info, except it lets any transfer in progress finish. All parameters go back to their defaults, and the TELNET connection stays open. This is identical to the state a user is in right after the TELNET connection opens. A USER command may be expected to follow ๐ŸŒˆ

LOGOUT (QUIT)

This command terminates a USER. If no file transfer is in progress, the server closes the TELNET connection. If one is in progress, the connection stays open so the result response can come through, and then the server closes it. If the user-process is moving files for several USERs but doesn't want to close and reopen connections for each one, it should use REIN instead of QUIT ๐Ÿ’–

An unexpected close on the TELNET connection makes the server take the effective action of an abort (ABOR) and a logout (QUIT). Yikes, but that's how it works ๐Ÿ˜ญ

TRANSFER PARAMETER COMMANDS โœจ

okay so all the data transfer parameters come with default values ๐ŸŽ€ you only need these commands if you want to change a default. the default is whatever was specified last, and if nothing was ever specified, it's the standard default written here. that means the server MUST "remember" the defaults that apply ๐Ÿง  the commands can come in any order, MAY come in any order, but they MUST come before the FTP service request. here are the commands that set transfer parameters ๐Ÿ’…

DATA PORT (PORT) ๐Ÿ”Œ

the argument is a HOST-PORT specification for the data port used in the data connection. both the user and server data ports have defaults, so under normal circumstances this command and its reply are not needed ๐Ÿ™ˆ if you do use it, the argument is a 32-bit internet host address joined to a 16-bit TCP port address. the address info gets split into 8-bit fields, and each field's value is sent as a decimal number (as a character string). the fields are separated by commas. here's what a PORT command looks like:

PORT h1,h2,h3,h4,p1,p2

where h1 is the high order 8 bits of the internet host address.

PASSIVE (PASV) ๐Ÿฆ‹

this command asks the server-DTP to "listen" on a data port (one that isn't its default data port) and to wait for a connection instead of starting one when a transfer command arrives ๐Ÿ‘€ the response includes the host and port address the server is listening on. main character energy, honestly ๐Ÿ‘‘

REPRESENTATION TYPE (TYPE) ๐ŸŒˆ

the argument sets the representation type, which is covered in the Section on Data Representation and Storage. some types take a second parameter too. the first parameter is a single TELNET character, and so is the second Format parameter for ASCII and EBCDIC. for local byte, the second parameter is a decimal integer for Bytesize. the parameters are separated by a <SP> (Space, ASCII code 32.).

here are the codes assigned for type:

             \    /
   A - ASCII |    | N - Non-print
             |-><-| T - TELNET format effectors
   E - EBCDIC|    | C - Carriage Control (ASA)
             /    \
   I - Image

   L <byte size> - Local byte Byte size

the default representation type is ASCII Non-print ๐Ÿ’– and if you change the Format parameter and later only change the first argument, Format goes back to the Non-print default. it resets, bestie ๐Ÿ™„

FILE STRUCTURE (STRU) ๐Ÿ“

the argument is a single TELNET character code that sets the file structure, which is described in the Section on Data Representation and Storage ๐Ÿ“‚ the codes for structure are:

   F - File (no record structure)
   R - Record structure
   P - Page structure

the default structure is File ๐ŸŽ€

TRANSFER MODE (MODE) ๐Ÿšš

the argument is a single TELNET character code for the data transfer modes described in the Section on Transmission Modes ๐Ÿ›ฃ๏ธ the codes for transfer modes are:

   S - Stream
   B - Block
   C - Compressed

the default transfer mode is Stream ๐ŸŒธ

FTP SERVICE COMMANDS ๐Ÿงš

FTP service commands say what file transfer or file system function the user wants ๐Ÿซถ the argument of an FTP service command is usually a pathname. pathnames MUST follow the server site conventions (with standard defaults applying), and the language conventions of the TELNET connection. the suggested default handling is to use the last specified device, directory or file name, or the standard default for local users. the commands MAY come in any order, except that a "rename from" command MUST be followed by a "rename to" command, and the restart command MUST be followed by the interrupted service command. data sent in response to FTP service commands SHALL always go over the data connection, except for certain informative replies ๐Ÿ’Œ here are the FTP service requests ๐Ÿ’…

RETRIEVE (RETR) ๐Ÿ“ฅ

this command makes the server-DTP send a copy of the file named in the pathname to the server- or user-DTP at the other end of the data connection ๐ŸŽ the status and contents of the file at the server site SHALL be unaffected, so nothing on the server changes ๐Ÿ™Œ

STORE (STOR) ๐Ÿ“ค

this command makes the server-DTP accept the data sent over the data connection and store it as a file at the server site โœจ if the file named in the pathname already exists at the server site, its contents SHALL be replaced by the data being transferred. if the file doesn't exist yet, a new file is created at the server site ๐Ÿ†•

APPEND (with create) (APPE) ๐Ÿช„

this command makes the server-DTP accept the data sent over the data connection and store it in a file at the server site ๐Ÿ“ if the file named in the pathname exists at the server site, the data SHALL be appended to that file. otherwise, the file named in the pathname SHALL be created at the server site ๐ŸŒฑ

MAIL FILE (MLFL) ๐Ÿ’Œ

the point of this command is to let a user at the user site mail data (in the form of a file) to another user at the server site ๐Ÿ“ฌ the files being mailed go over the data connection in ASCII or EBCDIC type. (it's the user's responsibility to make sure the type is correct, so double check, bestie ๐Ÿซ ) these files SHOULD be put into the destination user's mailbox by the server, following the serving Host mail conventions. the mail MAY be marked as sent from the particular user HOST and the user named by the 'USER' command. the argument field may contain a Host system ident, or it may be empty. if the argument field is empty or blank (one or more spaces), the mail is for a printer or another designated general delivery site mail spot ๐Ÿ–จ๏ธ

MAIL (MAIL) โœ‰๏ธ

this command lets a user send mail that is NOT in a file, over the TELNET connection ๐Ÿ’ฌ the argument field MAY contain a system ident, or it MAY be empty. the ident is defined the same way as for the MLFL command. after the 'MAIL' command is received, the server treats the following lines as the text of the mail the user sent ๐Ÿ“œ the mail text ends with a line that has only a single period, which is the character sequence "CRLF.CRLF". it's suggested that a modest volume of mail service SHOULD be free, meaning it can be entered before a USER command ๐ŸŽŸ๏ธ

MAIL SEND TO TERMINAL (MSND) ๐Ÿ–ฅ๏ธ

this command works like MAIL, except the data is shown on the addressed user's terminal, if that access is currently allowed. otherwise, an error is returned ๐Ÿ™…โ€โ™€๏ธ

MAIL SEND TO TERMINAL OR MAILBOX (MSOM) ๐Ÿ“ซ

this command works like MAIL, except the data is shown on the addressed user's terminal if that access is currently allowed. otherwise, the data is placed in the user's mailbox ๐Ÿ’œ

MAIL SEND TO TERMINAL AND MAILBOX (MSAM) ๐Ÿ’ซ

this command works like MAIL, except the data is shown on the addressed user's terminal if that access is currently allowed, AND in any case, the data is placed in the user's mailbox. both at once, iconic ๐Ÿ‘‘

MAIL RECIPIENT SCHEME QUESTION (MRSQ) ๐Ÿค”

this FTP command selects a scheme for sending mail to several users at the same host ๐Ÿ“ฃ the schemes are to list the recipients first, or to send the mail first.

MAIL RECIPIENT (MRCP) ๐Ÿซต

this command identifies the individual recipients when mail is sent to multiple users at one host ๐Ÿ‘ฏโ€โ™€๏ธ

ALLOCATE (ALLO) ๐Ÿ“ฆ

some servers MAY require this command to reserve enough storage for the new file being transferred ๐Ÿ—„๏ธ the argument SHALL be a decimal integer for the number of bytes (using the logical byte size) to reserve for the file. for files sent with record or page structure, a maximum record or page size (in logical bytes) might also be needed. that's given as a decimal integer in a second argument field of the command. the second argument is optional, but when it's there, it SHOULD be separated from the first by the three TELNET characters <SP> R <SP>. this command SHALL be followed by a STORe or APPEnd command. servers that don't need the maximum file size declared beforehand SHOULD treat ALLO as a NOOP (no operation) ๐Ÿ˜ด and servers that only care about the maximum record or page size SHOULD accept a dummy value in the first argument and ignore it ๐Ÿซง

RESTART (REST) โช

the argument field is the server marker where file transfer is to be restarted ๐Ÿ“ this command does not start a transfer. instead, it "spaces" over the file up to the specified data checkpoint ๐Ÿƒโ€โ™€๏ธ this command SHALL be followed right away by the appropriate FTP service command, which SHALL make the file transfer resume โ–ถ๏ธ

RENAME FROM (RNFR) ๐Ÿท๏ธ

this command names the file that is going to be renamed. it MUST be followed immediately by a "rename to" command that gives the new file pathname ๐Ÿ’…

RENAME TO (RNTO) ๐Ÿ”

this command gives the new pathname for the file named in the immediately preceding "rename from" command ๐Ÿ’• together, the two commands rename the file โœจ

ABORT (ABOR) ๐Ÿ›‘

this command tells the server to abort the previous FTP service command and any transfer of data linked to it ๐Ÿ˜ค the abort command MAY need "special action", as discussed in the Section on FTP Commands, to make the server recognize it ๐Ÿ” if the previous command has already completed (including data transfer), no action is taken. the server MUST NOT close the TELNET connection, but the data connection MUST be closed ๐Ÿ”’

There are two cases for the server when it gets this command: (1) the FTP service command was already completed, or (2) the FTP service command is still in progress.

In the first case, the server closes the data connection (if it is open) and responds with a 226 reply, indicating that the abort command was successfully processed. ๐Ÿ’…

In the second case, the server aborts the FTP service in progress and closes the data connection, returning a 426 reply to indicate that the service request terminated in abnormally. Then the server sends a 226 reply, indicating that the abort command was successfully processed. ๐Ÿ˜ญ๐Ÿ”ฅ

DELETE (DELE) ๐Ÿ—‘๏ธ

This command causes the file specified in the pathname to be deleted at the server site. If an extra level of protection is desired (such as the query, "DO you really wish to delete?"), it SHOULD be provided by the user-FTP process. ๐Ÿ™ˆ

CHANGE WORKING DIRECTORY (CWD) ๐Ÿ“

Okay, this one is so useful. It lets the user work with a different directory or dataset for file storage or retrieval without altering their login or accounting information. โœจ Transfer parameters are similarly unchanged. The argument is a pathname specifying a directory or other system dependent file group designator. ๐Ÿฆ‹

LIST (LIST) ๐Ÿ“œ

This command causes a list to be sent from the server to the passive DTP. If the pathname specifies a directory, the server SHOULD transfer a list of files in the specified directory. If the pathname specifies a file, then the server SHOULD send current information on the file. A null argument implies the user's current working or default directory. The data transfer is over the data connection in type ASCII or type EBCDIC. (The user MUST ensure that the TYPE is appropriately ASCII or EBCDIC). ๐Ÿงš

NAME-LIST (NLST) ๐Ÿ“

This command causes a directory listing to be sent from server to user site. The pathname SHOULD specify a directory or other system-specific file group descriptor; a null argument implies the current directory. The server will return a stream of names of files and no other information. The data will be transferred in ASCII or EBCDIC type over the data connection as valid pathname strings separated by <CRLF> or <NL>. (Again, the user MUST ensure that the TYPE is correct.) ๐Ÿ’œ

SITE PARAMETERS (SITE) ๐ŸŽ€

This command is used by the server to provide services specific to its system that are essential to file transfer but not sufficiently universal to be included as commands in the protocol. The nature of these services and the specification of their syntax can be stated in a reply to the HELP SITE command. ๐ŸŒธ

STATUS (STAT) ๐Ÿ“Š

This command SHALL cause a status response to be sent over the TELNET connection in the form of a reply. The command MAY be sent during a file transfer (along with the TELNET IP and Synch signals--see the Section on FTP Commands), in which case the server will respond with the status of the operation in progress, or it MAY be sent between file transfers. In the latter case, the command MAY have an argument field. If the argument is a pathname, the command is analogous to the "list" command except that data SHALL be transferred over the TELNET connection. If a partial pathname is given, the server MAY respond with a list of file names or attributes associated with that specification. If no argument is given, the server SHOULD return general status information about the server FTP process. This SHOULD include current values of all transfer parameters and the status of connections. ๐Ÿ“กโœจ

HELP (HELP) ๐Ÿ†˜

This command SHALL cause the server to send helpful information regarding its implementation status over the TELNET connection to the user. The command MAY take an argument (e.g., any command name) and return more specific information as a response. The reply is type 211 or 214. It is suggested that HELP be allowed before entering a USER command. The server MAY use this reply to specify site-dependent parameters, e.g., in response to HELP SITE. ๐Ÿ’โ€โ™€๏ธ

NOOP (NOOP) ๐Ÿ˜ด

This command does not affect any parameters or previously entered commands. It specifies no action other than that the server send an OK reply. Very chill, very low-key. ๐Ÿซถ

The File Transfer Protocol follows the specifications of the TELNET protocol for all communications over the TELNET connection. Since the language used for TELNET communication MAY be a negotiated option, all references in the next two sections will be to the "TELNET language" and the corresponding "TELNET end of line code". Currently one MAY take these to mean NVT-ASCII and <CRLF>. No other specifications of the TELNET protocol will be cited. ๐ŸŒˆ

FTP commands are "TELNET strings" terminated by the "TELNET end of line code". The command codes themselves are alphabetic characters terminated by the character <SP> (Space) if parameters follow and TELNET-EOL otherwise. The command codes and the semantics of commands are described in this section; the detailed syntax of commands is specified in the Section on Commands, the reply sequences are discussed in the Section on Sequencing of Commands and Replies, and scenarios illustrating the use of commands are provided in the Section on Typical FTP Scenarios. ๐Ÿ“š

FTP commands MAY be partitioned as those specifying access-control identifiers, data transfer parameters, or FTP service requests. Certain commands (such as ABOR, STAT, QUIT) MAY be sent over the TELNET connection while a data transfer is in progress. Some servers MAY NOT be able to monitor the TELNET and data connections simultaneously, in which case some special action will be necessary to get the server's attention. The exact form of the "special action" is undefined; but the following ordered format is tentatively recommended: ๐Ÿšฆ

  1. User system inserts the TELNET "Interrupt Process" (IP) signal in the TELNET stream.
  2. User system sends the TELNET "Synch" signal.
  3. User system inserts the command (e.g., ABOR) in the TELNET stream.
  4. Server PI,, after receiving "IP", scans the TELNET stream for EXACTLY ONE FTP command.

(For other servers this MAY NOT be necessary, but the actions listed above SHOULD have no unusual effect.) ๐Ÿ™Œ

FTP REPLIES โœจ

Replies to File Transfer Protocol commands are devised to ensure the synchronization of requests and actions in the process of file transfer, and to guarantee that the user process always knows the state of the Server. Every command MUST generate at least one reply, although there MAY be more than one; in the latter case, the multiple replies MUST be easily distinguished. In addition, some commands occur in sequential groups, such as USER, PASS and ACCT, or RNFR and RNTO. The replies show the existence of an intermediate state if all preceding commands have been successful. A failure at any point in the sequence necessitates the repetition of the entire sequence from the beginning. ๐Ÿ”

The details of the command-reply sequence are made explicit in a set of state diagrams below. ๐Ÿ—บ๏ธ

An FTP reply consists of a three digit number (transmitted as three alphanumeric characters) followed by some text. The number is intended for use by automata to determine what state to enter next; the text is intended for the human user. It is intended that the three digits contain enough encoded information that the user-process (the User-PI) will not need to examine the text and MAY either discard it or pass it on to the user, as appropriate. In particular, the text MAY be server-dependent, so there are likely to be varying texts for each reply code. ๐Ÿค“

Formally, a reply is defined to contain the 3-digit code, followed by Space <SP>, followed by one line of text (where some maximum line length has been specified), and terminated by the TELNET end-of-line code. There will be cases, however, where the text is longer than a single line. In these cases the complete text MUST be bracketed so the User-process knows when it MAY stop reading the reply (i.e. stop processing input on the TELNET connection) and go do other things. This requires a special format on the first line to indicate that more than one line is coming, and another on the last line to designate it as the last. At least one of these MUST contain the appropriate reply code to indicate the state of the transaction. To satisfy all factions it was decided that both the first and last line codes SHOULD be the same. ๐Ÿซ 

Thus the format for multi-line replies is that the first line will begin with the exact required reply code, followed immediately by a Hyphen, "-" (also known as Minus), followed by text. The last line will begin with the same code, followed immediately by Space <SP>, optionally some text, and the TELNET end-of-line code. ๐Ÿ’–

For example:

                                123-First line
                                Second line
                                  234 A line beginning with numbers
                                123 The last line

The user-process then simply needs to search for the second occurrence of the same reply code, followed by <SP> (Space), at the beginning of a line, and ignore all intermediary lines. If an intermediary line begins with a 3-digit number, the Server MUST pad the front to avoid confusion. ๐Ÿ•ต๏ธโ€โ™€๏ธ

This scheme allows standard system routines to be used for reply information (such as for the STAT reply), with "artificial" first and last lines tacked on. In the rare cases where these routines are able to generate three digits and a Space at the beginning of any line, the beginning of each text line SHOULD be offset by some neutral text, like Space. ๐ŸŽฏ

This scheme assumes that multi-line replies MAY not be nested. We have found that, in general, nesting of replies will not occur, except for random system messages (also called spontaneous replies) which MAY interrupt another reply. System messages (i.e. those not processed by the FTP server) will NOT carry reply codes and MAY occur anywhere in the command-reply sequence. They MAY be ignored by the User-process as they are only information for the human user. ๐ŸŒท

The three digits of a reply are where the magic happens ๐Ÿ”ฎ Each one carries its own meaning, so a reply can be as simple or as detailed as the user-process needs โœจ The first digit tells you whether the response is good, bad, or only partway there. If you look at the state diagram, a super basic user-process can figure out its next move (keep going as planned, redo it, retrench, etc.) just by checking that first digit ๐Ÿ’… A more advanced user-process that wants to know roughly what kind of error happened (like a file system problem or a command syntax mistake) can check the second digit ๐Ÿง  The third digit is saved for the finest detail, like RNTO showing up without a preceding RNFR ๐ŸŽ€

There are five possible first digits, and they're giving main character ๐Ÿ‘‘

  • 1yz is a Positive Preliminary reply ๐Ÿฆ‹ It means the requested action has started, so expect another reply before sending anything new. Sending another command before the completion reply would break protocol, so server-FTP processes SHOULD queue any commands that show up while an earlier one is still running. This reply can also tell the user-process that it's okay to start paying attention to the data connections, which is clutch for implementations where monitoring at the same time is hard.
  • 2yz is a Positive Completion reply โœ… The requested action finished successfully, and a new request can start.
  • 3yz is a Positive Intermediate reply โณ The command was accepted, but the action is on hold until more info arrives. The user SHOULD send another command with that info. This reply is used in command sequence groups ๐ŸŒธ
  • 4yz is a Transient Negative Completion reply ๐Ÿ™ƒ The command wasn't accepted and nothing happened, but the problem is temporary, so the action can be requested again. The user SHOULD go back to the beginning of the command sequence, if there is one. Honestly, "transient" is a slippery word, especially since two different sites (the Server and the User-processes) have to agree on what it means. Each 4yz reply might have a slightly different time value, but the vibe is always "try again, bestie." Quick rule of thumb for telling 4yz from 5yz: it's 4yz if the command can be repeated with no change in its form or in the properties of the User or Server. So the command is spelled the same with the same arguments, the user didn't change their file access or user name, and the server didn't put up a new implementation ๐Ÿ’œ
  • 5yz is a Permanent Negative Completion reply ๐Ÿšซ The command wasn't accepted and nothing happened. The User-process is discouraged from repeating the exact same request in the same sequence. Some "permanent" errors can actually get fixed, though, so the human user might tell their User-process to restart the command sequence later on, after the spelling changes or their directory status changes ๐Ÿ“

The second digit groups replies into function categories:

  • x0z is Syntax ๐Ÿงฉ These replies cover syntax errors, commands that are syntactically correct but don't fit any functional category, and unimplemented or superfluous commands.
  • x1z is Information ๐Ÿ“š These are replies to requests for information, like status or help.
  • x2z is Connections ๐Ÿ”Œ These reply about the TELNET and data connections.
  • x3z is Authentication and accounting ๐Ÿ” These are for the login process and accounting procedures.
  • x4z is Unspecified as yet ๐Ÿซฅ Nothing's been assigned here yet!
  • x5z is File system ๐Ÿ“ These show the status of the Server file system in relation to the requested transfer or other file system action.

The third digit gives finer detail within each function category set by the second digit. The list below shows this off. The text attached to each reply is RECOMMENDED rather than mandatory, and it can even change depending on the command it goes with. The reply codes, though, MUST strictly follow the specifications in the last section. So Server implementations SHOULD NOT invent new codes for situations that are only slightly different from the ones described here. They SHOULD adapt codes that are already defined instead ๐Ÿ™…โ€โ™€๏ธ

A command like TYPE or ALLO that succeeds without giving the user-process any new information gets a 200 reply ๐Ÿ’– If a command isn't implemented by a particular Server-FTP process because it has no relevance to that computer system (like ALLO at a TOPS20 site), a Positive Completion reply is still wanted, so the simple User-process knows it can carry on. That's a 202 reply, with text like No storage allocation necessary. If the command asks for a non-site-specific action and it isn't implemented, the response is 502. Then 504 is the refinement: it's for a command that IS implemented but asks for a parameter that isn't.

Reply Codes by Function Groups

200 Command okay
500 Syntax error, command unrecognized
            [This may include errors such as command line too long.]
501 Syntax error in parameters or arguments
202 Command not implemented, superfluous at this site.
502 Command not implemented
503 Bad sequence of commands
504 Command not implemented for that parameter

110 Restart marker reply.
119 Terminal not available, will try mailbox.
211 System status, or system help reply
212 Directory status
213 File status
214 Help message
            (on how to use the server or the meaning of a particular
            non-standard command.  This reply is useful only to the
            human user.)
215 <scheme> is the preferred scheme.

120 Service ready in nnn minutes
220 Service ready for new user
221 Service closing TELNET connection
            (logged out if appropriate)
421 Service not available, closing TELNET connection.
            This may be a reply to any command if the service knows it
            must shut down.]
125 Data connection already open; transfer starting
225 Data connection open; no transfer in progress
425 Can't open data connection
226 Closing data connection;
            requested file action successful (for example, file transfer
            or file abort.)
426 Connection closed; transfer aborted.
227 Entering Passive Mode.  h1,h2,h3,h4,p1,p2

230 User logged in, proceed
530 Not logged in
331 User name okay, need password
332 Need account for login
532 Need account for storing files

150 File status okay; about to open data connection.
151 User not local; Will forward to <user>@<host>.
152 User Unknown; Mail will be forwarded by the operator.
250 Requested file action okay, completed.
350 Requested file action pending further information
450 Requested file action not taken:
            file unavailable (e.g. file busy)
550 Requested action not taken:
            file unavailable (e.g. file not found, no access)
451 Requested action aborted: local error in processing
551 Requested action aborted: page type unknown
452 Requested action not taken:
            insufficient storage space in system
552 Requested file action aborted:
            exceeded storage allocation (for current directory or
            dataset)
553 Requested action not taken:
            file name not allowed
354 Start mail input; end with <CR><LF>.<CR><LF>

For 110, the text is exact and is NOT left up to each implementation. It MUST read MARK yyyy = mmmm, where yyyy is the User-process data stream marker and mmmm is the server's equivalent marker. Note the spaces between the markers and the = ๐Ÿ”–

Numeric Order List of Reply Codes

Same codes, sorted by number, for when you're hunting for one ๐Ÿ” The 110 note above still applies: it MUST read MARK yyyy = mmmm, with the spaces around the =.

110 Restart marker reply.
119 Terminal not available, will try mailbox.
120 Service ready in nnn minutes
125 Data connection already open; transfer starting
150 File status okay; about to open data connection.
151 User not local; Will forward to <user>@<host>.
152 User Unknown; Mail will be forwarded by the operator.
200 Command okay
202 Command not implemented, superfluous at this site.
211 System status, or system help reply
212 Directory status
213 File status
214 Help message
            (on how to use the server or the meaning of a particular
            non-standard command.  This reply is useful only to the
            human user.)
215 <scheme> is the preferred scheme.
220 Service ready for new user
221 Service closing TELNET connection
            (logged out if appropriate)
225 Data connection open; no transfer in progress
226 Closing data connection;
            requested file action successful (for example, file transfer
            or file abort.)
227 Entering Passive Mode.  h1,h2,h3,h4,p1,p2
         230 User logged in, proceed
         250 Requested file action okay, completed.
         331 User name okay, need password
         332 Need account for login
         350 Requested file action pending further information
         354 Start mail input; end with <CR><LF>.<CR><LF>
         421 Service not available, closing TELNET connection.
            This may be a reply to any command if the service knows it
            must shut down.]
         425 Can't open data connection
         426 Connection closed; transfer aborted.
         450 Requested file action not taken:
            file unavailable (e.g. file busy)
         451 Requested action aborted: local error in processing
         452 Requested action not taken:
            insufficient storage space in system
         500 Syntax error, command unrecognized
            [This may include errors such as command line too long.]
         501 Syntax error in parameters or arguments
         502 Command not implemented
         503 Bad sequence of commands
         504 Command not implemented for that parameter
         530 Not logged in
         532 Need account for storing files
         550 Requested action not taken:
            file unavailable (e.g. file not found, no access)
         551 Requested action aborted: page type unknown
         552 Requested file action aborted:
            exceeded storage allocation (for current directory or
            dataset)
         553 Requested action not taken:
            file name not allowed

DECLARATIVE SPECIFICATIONS โœจ

MINIMUM IMPLEMENTATION ๐Ÿ’–

Okay so, to keep FTP from throwing a pile of needless error messages at everyone, the following minimum implementation is required for all servers ๐Ÿซถ

         TYPE - ASCII Non-print
         MODE - Stream
         STRUCTURE - File, Record
         COMMANDS - USER, QUIT, PORT,
                    TYPE, MODE, STRU,
                      for the default values
                    RETR, STOR,
                    NOOP.

The default values for transfer parameters are:

         TYPE - ASCII Non-print
         MODE - Stream
         STRU - File

All Hosts must accept the above as the standard defaults. No cap, that's the baseline everybody has to be able to handle ๐ŸŒธ

CONNECTIONS ๐Ÿ”Œ

The server protocol interpreter shall "listen" on Port L. The user or user protocol interpreter shall initiate the full-duplex TELNET connection. Server- and user- processes should follow the conventions of the TELNET protocol as specified in the ARPA Internet Protocol Handbook. Servers are under no obligation to provide for editing of command lines and may specify that it be done in the user Host. The TELNET connection shall be closed by the server at the user's request after all transfers and replies are completed. โœจ

The user-DTP must "listen" on the specified data port, which may be the default user port (U) or a port specified in the PORT command. The server shall initiate the data connection from his own default data port (L-1) using the specified user data port. The direction of the transfer and the port used will be determined by the FTP service command. ๐Ÿฆ‹

When data is to be transferred between two servers, A and B (refer to Figure 2), the user-PI, C, sets up TELNET connections with both server-PI's. One of the servers, say A, is then sent a PASV command telling him to "listen" on his data port rather than initiate a connection when he receives a transfer service command. When the user-PI receives an acknowledgment to the PASV command, which includes the identity of the host and port being listened on, the user-PI then sends A's port, a, to B in a PORT command; a reply is returned. The user-PI may then send the corresponding service commands to A and B. Server B initiates the connection and the transfer proceeds. The command-reply sequence is listed below where the messages are vertically synchronous but horizontally asynchronous: ๐Ÿ‘‘

         User-PI - Server A                User-PI - Server B
         ------------------                ------------------

         C->A : Connect                    C->B : Connect
         C->A : PASV
         A->C : 227 Entering Passive Mode. A1,A2,A3,A4,a1,a2
                                           C->B : PORT A1,A2,A3,A4,a1,a2
                                           B->C : 200 Okay
         C->A : STOR                       C->B : RETR
                    B->A : Connect to HOST-A, PORT-a

The data connection shall be closed by the server under the conditions described in the Section on Establishing Data Connections. If the server wishes to close the connection after a transfer where it is not required, he should do so immediately after the file transfer is completed. He should not wait until after a new transfer command is received because the user-process will have already tested the data connection to see if it needs to do a "listen"; (recall that the user must "listen" on a closed data port BEFORE sending the transfer request). To prevent a race condition here, the server sends a reply (226) after closing the data connection (or if the connection is left open, a "file transfer completed" reply (250)), and the user-PI should wait for one of these replies before issuing a new transfer command. ๐Ÿ™ˆ

COMMANDS ๐ŸŽ€

The commands are TELNET character strings transmitted over the TELNET connections as described in the Section on FTP Commands. The command functions and semantics are described in the Section on Access Control Commands, Transfer Parameter Commands, FTP Service Commands, and Miscellaneous Commands. The command syntax is specified here. ๐Ÿ’…

The commands begin with a command code followed by an argument field. The command codes are four or fewer alphabetic characters. Upper and lower case alphabetic characters are to be treated identically. Thus any of the following may represent the retrieve command:

         RETR    Retr    retr    ReTr    rETr

This also applies to any symbols representing parameter values, such as A or a for ASCII TYPE. The command codes and the argument fields are separated by one or more spaces. ๐Ÿ“

The argument field consists of a variable length character string ending with the character sequence <CRLF> (Carriage Return, Linefeed) for NVT-ASCII representation; for other negotiated languages a different end of line character might be used. It should be noted that the server is to take NO action until the end of line code is received. โญ

The syntax is specified below in NVT-ASCII. All characters in the argument field are ASCII characters, including any ASCII represented decimal integers. Square brackets denote an optional argument field. If the option is not taken, the appropriate default is implied. ๐Ÿงš

The following are the FTP commands:

         USER <SP> <username> <CRLF>
         PASS <SP> <password> <CRLF>
         ACCT <SP> <account information> <CRLF>
         REIN <CRLF>
         QUIT <CRLF>
         PORT <SP> <Host-port> <CRLF>
         PASV <CRLF>
         TYPE <SP> <type code> <CRLF>
         STRU <SP> <structure code> <CRLF>
         MODE <SP> <mode code> <CRLF>
         RETR <SP> <pathname> <CRLF>
         STOR <SP> <pathname> <CRLF>
         APPE <SP> <pathname> <CRLF>
         MLFL [<SP> <ident>] <CRLF>
         MAIL [<SP> <ident>] <CRLF>
         MSND [<SP> <ident>] <CRLF>
         MSOM [<SP> <ident>] <CRLF>
         MSAM [<SP> <ident>] <CRLF>
         MRSQ [<SP> <scheme>] <CRLF>
         MRCP <SP> <ident> <CRLF>
         ALLO <SP> <decimal integer>
             [<SP> R <SP> <decimal integer>] <CRLF>
         REST <SP> <marker> <CRLF>
         RNFR <SP> <pathname> <CRLF>
         RNTO <SP> <pathname> <CRLF>
         ABOR <CRLF>
         DELE <SP> <pathname> <CRLF>
         CWD <SP> <pathname> <CRLF>
         LIST [<SP> <pathname>] <CRLF>
         NLST [<SP> <pathname>] <CRLF>
         SITE <SP> <string> <CRLF>
         STAT [<SP> <pathname>] <CRLF>
         HELP [<SP> <string>] <CRLF>
         NOOP <CRLF>

The syntax of the above argument fields (using BNF notation where applicable) is: ๐Ÿงฉ

         <username> ::= <string>
         <password> ::= <string>
         <account information> ::= <string>
         <string> ::= <char> | <char><string>
         <char> ::= any of the 128 ASCII characters except <CR> and <LF>
         <marker> ::= <pr string>
         <pr string> ::= <pr char> | <pr char><pr string>
         <pr char> ::= printable characters, any
                       ASCII code 33 through 126
         <byte size> ::= any decimal integer 1 through 255
         <Host-port> ::= <Host-number>,<Port-number>
         <Host-number> ::= <number>,<number>,<number>,<number>
         <Port-number> ::= <number>,<number>
         <number> ::= any decimal integer 0 through 255
         <ident> ::= <string>
         <scheme> ::= R | T | ?
         <form code> ::= N | T | C
         <type code> ::= A [<SP> <form code>]
                       | E [<SP> <form code>]
                       | I
                       | L <SP> <byte size>
         <structure code> ::= F | R | P
         <mode code> ::= S | B | C
         <pathname> ::= <string>

SEQUENCING OF COMMANDS AND REPLIES ๐Ÿ”ฅ

The communication between the user and server is intended to be an alternating dialogue. As such, the user issues an FTP command and the server responds with a prompt primary reply. The user should wait for this initial primary success or failure response before sending further commands. ๐Ÿฆ‹

Certain commands require a second reply for which the user should also wait. These replies may, for example, report on the progress or completion of file transfer or the closing of the data connection. They are secondary replies to file transfer commands. โœจ

One important group of informational replies is the connection greetings. Under normal circumstances, a server will send a 220 reply, "awaiting input", when the connection is completed. The user should wait for this greeting message before sending any commands. If the server is unable to accept input right away, he should send a 120 "expected delay" reply immediately and a 220 reply when ready. The user will then know not to hang up if there is a delay. ๐ŸŒˆ

The table below lists alternative success and failure replies for each command. These must be strictly adhered to; a server may substitute text in the replies, but the meaning and action implied by the code numbers and by the specific command reply sequence cannot be altered. ๐Ÿซถ

Command-Reply Sequences ๐Ÿ’œ

In this section, the command-reply sequence is presented. Each command is listed with its possible replies; command groups are listed together. Preliminary replies are listed first (with their succeeding replies indented and under them), then positive and negative completion, and finally intermediary replies with the remaining commands from the sequence following. This listing forms the basis for the state diagrams, which will be presented separately. ๐Ÿ˜ญ

            Connection Establishment
               120
                  220
               220
               421
            Login
               USER
                  230
                  530
                  500, 501, 421
                  331, 332
               PASS
                  230
                  202
                  530
                  500, 501, 503, 421
                  332
               ACCT
                  230
                  202
                  530
                  500, 501, 503, 421
            Logout
               QUIT
                  221
                  500
               REIN
                  120
                     220
                  220
                  421
                  500, 502
            Transfer parameters
               PORT
                  200
                  500, 501, 421, 530
               PASV
                  227
                  500, 501, 502, 421, 530
               MODE, TYPE, STRU
                  200
                  500, 501, 504, 421, 530
            File action commands
               ALLO
                  200
                  202
                  500, 501, 504, 421, 530
               REST
                  500, 501, 502, 421, 530
                  350
               STOR
                  125, 150
                     (110)
                     226, 250
                     425, 426, 451, 551, 552
                  532, 450, 452, 553
                  500, 501, 421, 530
               RETR
                  125, 150
                     (110)
                     226, 250
                     425, 426, 451
                  450, 550
                  500, 501, 421, 530
               LIST, NLST
                  125, 150
                     226, 250
                     425, 426, 451
                  450
                  500, 501, 502, 421, 530
               APPE
                  125, 150
                     (110)
                     226, 250
                     425, 426, 451, 551, 552
                  532, 450, 550, 452, 553
                  500, 501, 502, 421, 530
               MLFL
                  125, 150, 151, 152
                     226, 250
                     425, 426, 451, 552
                  532, 450, 550, 452, 553
                  500, 501, 502, 421, 530
               RNFR
                  450, 550
                  500, 501, 502, 421, 530
                  350
               RNTO
                  250
                  532, 553
                  500, 501, 502, 503, 421, 530
               DELE, CWD
                  250
                  450, 550
                  500, 501, 502, 421, 530
               ABOR
                  225, 226
                  500, 501, 502, 421
               MAIL, MSND
                  151, 152
                     354
                        250
                        451, 552
                  354
                     250
                     451, 552
                  450, 550, 452, 553
                  500, 501, 502, 421, 530
               MSOM, MSAM
                  119, 151, 152
                     354
                        250
                        451, 552
                  354
                     250
                     451, 552
                  450, 550, 452, 553
                  500, 501, 502, 421, 530
               MRSQ
                  200, 215
                  500, 501, 502, 421, 530
               MRCP
                  151, 152
                     200
                  200
                  450, 550, 452, 553
                  500, 501, 502, 503, 421
            Informational commands
               STAT
                  211, 212, 213
                  450
                  500, 501, 502, 421, 530
               HELP
                  211, 214
                  500, 501, 502, 421
            Miscellaneous commands
               SITE
                  200
                  202
                  500, 501, 530
               NOOP
                  200
                  500 421

STATE DIAGRAMS โœจ

okay so this part is where the vibe gets visual ๐ŸŽจ bestie, we're doing state diagrams for a super simple-minded FTP implementation ๐Ÿง  and the only thing it looks at is the first digit of each reply code ๐Ÿ”ข. Every command or command sequence gets one diagram, and the commands are grouped by building a little model for each one and then clumping together the ones with structurally identical models ๐Ÿซถ

For each command or sequence there are three possible outcomes: success (S), failure (F), and error (E) ๐Ÿ’€. In the diagrams we use B for "begin" ๐Ÿš€ and W for "wait for reply" โณ

We start with the diagram for the biggest group of FTP commands ๐Ÿ‘‘

                               1,3    +---+
                          ----------->| E |
                         |            +---+
                         |
      +---+    cmd    +---+    2      +---+
      | B |---------->| W |---------->| S |
      +---+           +---+           +---+
                         |
                         |     4,5    +---+
                          ----------->| F |
                                      +---+

This diagram models the commands:

   ABOR, ALLO, DELE, CWD, HELP, MODE, MRCP, MRSQ, NOOP, PASV,
   QUIT, SITE, PORT, STAT, STRU, TYPE.

The other big group has a very similar diagram, just with a little loop-back ๐Ÿ” at the wait state ๐Ÿ’…

                               3      +---+
                          ----------->| E |
                         |            +---+
                         |
      +---+    cmd    +---+    2      +---+
      | B |---------->| W |---------->| S |
      +---+       --->+---+           +---+
                 |     | |
                 |     | |     4,5    +---+
                 |  1  |  ----------->| F |
                  -----               +---+

This diagram models the commands:

   APPE, LIST, MLFL, NLST, REIN, RETR, STOR.

Note that this second model could also be used to represent the first group of commands ๐Ÿค” the only difference is that in the first group the 100 series replies are unexpected and therefore treated as error, while the second group expects (some may require) 100 series replies ๐Ÿซง

Next up are the diagrams for command sequences ๐ŸŽ€ and the simplest one is the rename sequence ๐Ÿท๏ธ

      +---+   RNFR    +---+    1,2    +---+
      | B |---------->| W |---------->| E |
      +---+           +---+        -->+---+
                       | |        |
                3      | | 4,5    |
         --------------  ------   |
        |                      |  |   +---+
        |               ------------->| S |
        |              |   1,3 |  |   +---+
        |             2|  --------
        |              | |     |
        V              | |     |
      +---+   RNTO    +---+ 4,5 ----->+---+
      |   |---------->| W |---------->| F |
      +---+           +---+           +---+

A very similar diagram models the Mail and Send commands ๐Ÿ“ฌ

                   ----  1
                  |    |
      +---+  cmd   -->+---+     2     +---+
      | B |---------->| W |---------->| E |
      +---+           +---+        -->+---+
                       | |        |
                3      | | 4,5    |
         --------------  ------   |
        |                      |  |   +---+
        |               ------------->| S |
        |              |   1,3 |  |   +---+
        |             2|  --------
        |              | |     |
        V              | |     |
      +---+   text    +---+ 4,5 ----->+---+
      |   |---------->| W |---------->| F |
      +---+           +---+           +---+

This diagram models the commands:

   MAIL, MSND, MSOM, MSAM.

Note that the "text" here is a series of lines sent from the user to the server ๐Ÿ’Œ with no response expected until the last line is sent. Recall that the last line must consist only of a single period ๐Ÿซถ


The next diagram is a simple model of the Restart command ๐Ÿ”„

      +---+   REST    +---+    1,2    +---+
      | B |---------->| W |---------->| E |
      +---+           +---+        -->+---+
                       | |        |
                3      | | 4,5    |
         --------------  ------   |
        |                      |  |   +---+
        |               ------------->| S |
        |              |   3   |  |   +---+
        |             2|  --------
        |              | |     |
        V              | |     |
      +---+   cmd     +---+ 4,5 ----->+---+
      |   |---------->| W |---------->| F |
      +---+        -->+---+           +---+
                  |      |
                  |  1   |
                   ------

Where "cmd" is APPE, STOR, RETR, or MLFL.

We note that the above three models are similar ๐Ÿ‘ฏ in fact the Mail diagram and the Rename diagram are structurally identical. The Restart differs from the other two only in the treatment of 100 series replies at the second stage.


The most complicated diagram is for the Login sequence ๐ŸŒช๏ธ hold onto your hat

                            1
      +---+   USER    +---+------------->+---+
      | B |---------->| W | 2       ---->| E |
      +---+           +---+------  |  -->+---+
                       | |       | | |
                     3 | | 4,5   | | |
         --------------   -----  | | |
        |                      | | | |
        |                      | | | |
        |                 ---------  |
        |               1|     | |   |
        V                |     | |   |
      +---+   PASS    +---+ 2  |  ------>+---+
      |   |---------->| W |------------->| S |
      +---+           +---+   ---------->+---+
                       | |   | |     |
                     3 | |4,5| |     |
         --------------   --------   |
        |                    | |  |  |
        |                    | |  |  |
        |                 -----------
        |             1,3|   | |  |
        V                |  2| |  |
      +---+   ACCT    +---+--  |   ----->+---+
      |   |---------->| W | 4,5 -------->| F |
      +---+           +---+------------->+---+

Finally we have a generalized diagram ๐ŸŒˆ that could be used to model the command and reply interchange ๐Ÿ’ฌ

               ------------------------------------
              |                                    |
      Begin   |                                    |
        |     V                                    |
        |   +---+  cmd   +---+ 2         +---+     |
         -->|   |------->|   |---------->|   |     |
            |   |        | W |           | S |-----|
         -->|   |     -->|   |-----      |   |     |
        |   +---+    |   +---+ 4,5 |     +---+     |
        |     |      |    | |      |               |
        |     |      |   1| |3     |     +---+     |
        |     |      |    | |      |     |   |     |
        |     |       ----  |       ---->| F |-----
        |     |             |            |   |
        |     |             |            +---+
         -------------------
              |
              |
              V
             End

TYPICAL FTP SCENARIO โœจ

Okay so picture this ๐Ÿงš a user at Host U wants to send files to Host S or grab some back ๐Ÿ’– Usually the user doesn't talk to the server directly. A mediating user-FTP process handles it ๐Ÿ’… Here's what a typical run looks like. The user-FTP prompts are in parentheses, ----> means a command going from Host U to Host S, and <---- means a reply coming back from Host S ๐Ÿซถ

      LOCAL COMMANDS BY USER              ACTION INVOLVED

      ftp (host) multics<CR>         Connect to Host S, port L,
                                     establishing TELNET connections
                                     <---- 220 Service ready <CRLF>
      username Doe <CR>              USER Doe<CRLF>---->
                                     <---- 331 User name ok,
                                               need password<CRLF>
      password mumble <CR>           PASS mumble<CRLF>---->
                                     <---- 230 User logged in.<CRLF>
      retrieve (local type) ASCII<CR>
      (local pathname) test 1 <CR>   User-FTP opens local file in ASCII.
      (for.pathname) test.pl1<CR>    RETR test.pl1<CRLF> ---->
                                     <---- 150 File status okay;
                                           about to open data connection
                                     Server makes data connection
                                     to port U
      <CRLF>
                                     <---- 226 Closing data connection,
                                         file transfer successful<CRLF>
      type Image<CR>                 TYPE I<CRLF> ---->
                                     <---- 200 Command OK<CRLF>
      store (local type) image<CR>
      (local pathname) file dump<CR> User-FTP opens local file in Image.
      (for.pathname) >udd>cn>fd<CR>  STOR >udd>cn>fd<CRLF> ---->
                                     <---- 450 Access denied<CRLF>
      terminate                      QUIT <CRLF> ---->
                                     Server closes all
                                     connections.

CONNECTION ESTABLISHMENT ๐Ÿ”Œ

So the FTP control connection gets set up over TCP, linking the user process port U with the server process port L ๐Ÿ’œ This protocol is given service port 21 (that's 25 in octal), which means L=21 ๐ŸŽ€

APPENDIX ON MAIL ๐Ÿ’Œ

Okay, the main commands for sending mail are MAIL and MLFL ๐Ÿ“ฌ Whatever gets transmitted with them ends up in the recipient's mailbox ๐Ÿ’–

      MAIL <SP> <recipient name> <CRLF>

If it's accepted, the server sends back a 354 reply and treats every line after that as message text. The text ends with a line that has only a period on it, and then the server sends a 250 completion reply. All kinds of errors can happen here ๐Ÿ˜ญ

      MLFL <SP> <recipient name> <CRLF>

If it's accepted, MLFL acts like a STOR command, except the data is treated as message text. Errors are possible here too ๐Ÿ™ˆ

There are two preliminary replies a server can send to say it's taking mail for someone whose mailbox isn't on that server ๐Ÿฆ‹

      151 User not local; Will forward to <user>@<host>.

This means the server knows the mailbox is on another host and will take responsibility for forwarding the mail there โœจ For example, at BBN (or ISI) there are several hosts that each keep a list of lots of users across several hosts. Those hosts can accept mail for anyone on their list and pass it along to the right host ๐ŸŒˆ

      152 User Unknown; Mail will be forwarded by the operator.

This one means the host doesn't recognize the user name, but it'll still accept the mail and have the operator try to deliver it ๐Ÿ“ It's handy when the name is misspelled, but it can be a total disservice if the mail really can't be delivered ๐Ÿ’€

Three FTP commands let you "send" a message to a user's terminal while they're logged in ๐Ÿ“Ÿ There are also variants that mail it normally, whether or not the user is logged in ๐Ÿ’…

Heads up: these three are the terminal and mailbox variants, so check which one you actually want before you send ๐Ÿ‘‘
      MSND -- SeND to terminal.

This returns a 450 failure reply if the addressee is refusing messages or isn't logged in ๐Ÿ™…โ€โ™€๏ธ

      MSOM -- Send to terminal Or Mailbox.

This returns a 119 notification reply if the terminal can't be reached ๐Ÿ“จ

      MSAM -- Send to terminal And Mailbox.

This returns a 119 notification reply if the terminal can't be reached ๐Ÿ“จ

Okay this part is important ๐Ÿซถ For MSOM and MSAM, the mailing is what decides success, not the sending. MSOM as implemented uses a 119 reply (on top of the usual success or failure code) to say that the SEND failed and the server is trying to mail the message instead ๐Ÿ’Œ There are no matching variants for MLFL, since messages sent that way are usually short ๐Ÿฆ‹

There are also two FTP commands that let you mail the text of one message to several recipients at once ๐ŸŽ€ Doing it this way is way more efficient than sending the same text over and over for every extra recipient at a site ๐Ÿš€

There are two basic ways to send one text to several recipients ๐Ÿ’– In the first, you specify all the recipients first and then send the text. In the second, it's flipped: you send the text first and then list the recipients. Both schemes are needed, because neither one alone is best for every system, as we'll see later ๐Ÿงš To pick a scheme you use the MRSQ command, then give MRCP commands to specify recipients, and use MAIL or MLFL to furnish the text ๐Ÿ’…

Scheme Selection: MRSQ ๐ŸŽฏ

MRSQ is how a user program can check whether MRSQ/MRCP is implemented, pick a particular scheme, reset its state, and even do a bit of basic negotiation ๐ŸŒธ Its format is like the TYPE command:

         MRSQ [<SP> <scheme>] <CRLF>

         <scheme> = a single character.  The following are defined:
            R  Recipients first.  If not implemented, T must be.
            T  Text first.  If this is not implemented, R must be.
            ?  Request for preference.  Must always be implemented.

            No argument means a "selection" of none of the schemes (the
            default).

         Replies:
            200 OK, we'll use specified scheme.
            215 <scheme> This is the scheme I prefer.
            501 I understand MRSQ but can't use that scheme.
            5xx Command unrecognized or unimplemented.

There are three things to know about MRSQ ๐Ÿ‘‘ First, an MRSQ with no argument must always return a 200 reply and put things back to the default, where no scheme is selected. Any other reply means MRSQ, and therefore MRCP, isn't understood or can't be carried out properly ๐Ÿ˜ญ

Second, using "?" as the <scheme> asks the FTP server to send back a 215 reply that names its preferred scheme โœจ The format of that reply is simple:

         215 <SP> <scheme> [<SP> <arbitrary text>] <CRLF>

Any other reply, like a 4xx or 5xx, means MRSQ and MRCP aren't implemented, because "?" must always be implemented if MRSQ is ๐Ÿ™ˆ

Third, MRSQ always has the side effect of resetting every scheme back to its initial state ๐Ÿ”„ That reset has to happen no matter what the reply is, whether it's 200, 215, or 501 ๐Ÿ’– What a reset actually involves gets explained when we talk about how each scheme works ๐Ÿฆ‹

Message Text Specification: MAIL/MLFL ๐Ÿ’Œ

Whichever scheme (if any) is selected, a MAIL or MLFL with a non-null argument works exactly as it always did, and the MRSQ/MRCP commands don't affect them ๐ŸŽ€ Still, those normal MAIL/MLFL commands do have the same side effect as MRSQ: they "reset" the current scheme to its initial state ๐Ÿงน

It's only when the argument is null, like MAIL<CRLF> or MLFL<CRLF>, that the scheme in use really matters ๐ŸŒˆ Instead of throwing an error (which is what most servers do right now), the server accepts message text for this "null" specification. What it does with that text depends on which scheme is in effect, and that's covered in "Scheme Mechanics" ๐Ÿ’œ

Recipient specification: MRCP ๐Ÿ“ฎ

To name recipients (that's the idents) and get an acknowledgment, or a refusal, for each name, you use this command:

         MRCP <SP> <ident> <CRLF>

         Reply for no scheme:
            503 No scheme specified yet; use MRSQ.
         Replies for scheme T are identical to those for MAIL/MLFL.
         Replies for scheme R (recipients first):
            200 OK, name stored.
            452 Recipient table full, this name not stored.
            553 Recipient name rejected.
            4xx Temporary error, try this name again later.
            5xx Permanent error, report to sender.

Using this command with no scheme selected is an error ๐Ÿ™…โ€โ™€๏ธ You have to give an MRSQ <scheme> first if you want to use MRCP ๐Ÿ’…

Scheme mechanics: MRSQ R (Recipients first) ๐Ÿงš

In the recipients-first scheme, MRCP is how you give names that the FTP server stores in a list or table ๐Ÿ“ Usually each MRCP gets either a 200 for acceptance or a 4xx/5xx code for rejection โœจ All the 5xx codes are permanent rejections (like "user not known"), and those should get reported to the human sender ๐Ÿ˜ญ The 4xx codes generally mean a temporary error that might get fixed later โณ None of the 4xx/5xx replies mess with the MRCP commands before or after them, except for 452, which means no more MRCP's will succeed unless a message gets sent to the recipients already stored, or a reset is done ๐Ÿšซ

To send the message text to the stored recipients, you give a MAIL or MLFL with no argument, which is just MAIL<CRLF> or MLFL<CRLF> ๐Ÿ’Œ Sending the text works exactly like a normal MAIL/MLFL. A positive acknowledgment at the end of transmission means the message went to ALL the recipients remembered with MRCP ๐ŸŽ‰ A failure code means it should count as failed for ALL of those recipients ๐Ÿ’€ This holds whatever the specific error code is, and whether the reply means success or failure, all the stored recipient names get flushed and forgotten, so everything goes back to its initial state ๐Ÿงน Purging the recipient name list also has to happen as the "reset" side effect of any use of MRSQ ๐Ÿ”„

A 452 reply to an MRCP can be handled like this: send a MAIL/MLFL for the message to the currently stored recipients, then send more MRCP's and another MAIL/MLFL, and keep going as many times as needed ๐Ÿ” For example, if a server only had room for 10 names, a 50-recipient message would get sent 5 times, each time to 10 different recipients ๐ŸŒธ

If a user tries to send message text (MAIL/MLFL with no argument) before any MRCP has succeeded, it should be treated exactly like a "normal" MAIL/MLFL with a null recipient ๐Ÿ˜ญ Some servers will return an error of some type, like "550 Null recipient". ๐Ÿ’…

Go peek at Example 1 for MRSQ R in action, bestie ๐ŸŽ€

Scheme mechanics: MRSQ T (Text first) ๐Ÿ’Œ

okay so in the text-first scheme, you send MAIL/MLFL with no argument to specify the message text, and the server stores it away ๐Ÿ“ฆ. After that, any MRCP's are treated like MAIL/MLFL commands, except none of the text transfer manipulations happen. The stored message text gets sent to the recipient you named, and you get back the same reply code an actual MAIL/MLFL would have returned. (Note ANY 2xx code means success, so don't panic about the exact number ๐Ÿ˜Œ)

The stored message text isn't forgotten until the next MAIL/MLFL or MRSQ shows up. Those will either swap it for new text or flush it entirely ๐Ÿงน. Any use of MRSQ resets this scheme by flushing the stored text, and so does any use of MAIL/MLFL with a non-null argument.

If an MRCP shows up before any message text has been stored, the user is basically trying to send a null message ๐Ÿ™ˆ. Some servers might allow that, and others would throw back an error code.

Go check out Example 2 for MRSQ T in action ๐Ÿ’–

Why two schemes anyway? ๐Ÿค”

Because neither scheme is perfect for every system ๐Ÿ’…. MRSQ R is all about "bulk" mailing, since everything gets saved up and then mailed at once. This is super useful for systems like ITS, where the FTP server doesn't write mail itself and instead hands it off to a central mailer demon of great power โšก. The more information (like recipients) attached to a single hand-off, the more efficiently mail gets delivered.

MRSQ T, on the other hand, is built for FTP servers that want to deliver mail directly, one by one, incrementally ๐Ÿฆ‹. That way they can return an individual success/failure reply code for each recipient. Those outcomes can depend on messy file system stuff like exceeding disk allocation, mailbox access conflicts, and so forth. If they tried to copy MRSQ R's bulk mailing, they'd have to make sure a success reply to MAIL/MLFL really meant the mail had been delivered to ALL recipients specified, not just some ๐Ÿ˜ฌ

Notes ๐Ÿ“

  • Because these commands aren't required in the minimum implementation of FTP, you have to be ready for sites that don't recognize either MRSQ or MRCP. "MRSQ" and "MRSQ ?" are explicitly designed as tests to see whether either scheme is implemented. MRCP isn't, and a failure return of the "unimplemented" variety could get confused with "No scheme selected yet", or even with "Recipient unknown". Be safe, be sure, use MRSQ! ๐Ÿ›ก๏ธ
  • There's no way to indicate, in a positive response to "MRSQ ?", that the server's preferred "scheme" is the default state, meaning none of the multi-recipient schemes. The reasoning is that in that case it would be pointless to implement MRSQ/MRCP at all, so the response would be negative ๐Ÿ™ƒ
  • One reason MAIL/MLFL is restricted to null arguments with this multi-recipient extension is the ambiguity a non-null argument would cause. For example, say MRSQ R was in effect, some MRCP's had been given, and then a MAIL FOO<CRLF> was done. There'd be no way to tell a failure reply for mailbox "FOO" apart from a global failure for all recipients specified ๐Ÿ˜ตโ€๐Ÿ’ซ. A similar mess exists for MRSQ T. It wouldn't be clear whether the text was stored and the mailbox failed, or the other way around, or both.
  • "Resets" are done by all MRSQ's and "normal" MAIL/MLFL's, to avoid confusion and overly complicated implementation. The MRSQ command implies a change or uncertainty of status, and the latter commands would otherwise need some independent mechanisms to avoid clobbering the data bases (e.g., the message text storage area) used by the T/R schemes. However, once a scheme is selected, it stays "in effect", just like a "TYPE A" stays selected. The recommended way to do a reset without changing the current selection is with "MRSQ ?". Remember that "MRSQ" alone reverts to the no-scheme state ๐Ÿ”„
  • It's permissible to intersperse other FTP commands among the MRSQ/MRCP/MAIL sequences ๐Ÿงš

Example 1 ๐ŸŽ€

Example of MRSQ R (Recipients first)

This is how MRSQ R gets used. First, the user has to establish that the server actually implements MRSQ ๐Ÿ‘€

U: MRSQ
S: 200 OK, no scheme selected.

An MRSQ with a null argument always returns a 200 if it's implemented, selecting the "scheme" of null, meaning none of them. If MRSQ weren't implemented, a code of 4xx or 5xx would come back.

U: MRSQ R
S: 200 OK, using that scheme

All's well, so now the recipients can be specified ๐Ÿ’…

U: MRCP Foo
S: 200 OK

U: MRCP Raboof
S: 553 Who's that?  No such user here.

U: MRCP bar
S: 200 OK

Well, two out of three ain't bad ๐Ÿ˜ญ Notice that the demise of "Raboof" has zero effect on the storage of "Foo" or "bar". Now to furnish the message text, by giving a MAIL or MLFL with no argument:

U: MAIL
S: 354 Type mail, ended by <CRLF>.<CRLF>
U: Blah blah blah blah....etc etc etc
U: .
S: 250 Mail sent.

The text has now been sent to both "Foo" and "bar" ๐Ÿ’Œ

Example 2 ๐Ÿฆ‹

Example of MRSQ T (Text first)

Using the same message as the previous example:

U: MRSQ ?
S: 215 T Text first, please.

MRSQ is indeed implemented, and the server says it prefers "T". That doesn't have to stop the user from trying something else ๐Ÿ™ƒ

U: MRSQ R
S: 501 Sorry, I really can't do that.

It's possible it could have understood "R" too, but generally it's best to use the "preferred" scheme, since the server knows which one is most efficient for its particular site. Anyway:

U: MRSQ T
S: 200 OK, using that scheme.

Scheme "T" is now selected, so the text has to be sent next ๐Ÿ“

U: MAIL
S: 354 Type mail, ended by <CRLF>.<CRLF>
U: Blah blah blah blah....etc etc etc
U: .
S: 250 Mail stored.

Now recipients can be specified:

U: MRCP Foo
S: 250 Stored mail sent.

U: MRCP Raboof
S: 553 Who's that?  No such user here.

U: MRCP bar
S: 250 Stored mail sent.

Again, the text has now been sent to both "Foo" and "bar", and it still stays stored โœจ A new message can go out with another MAIL/MRCP... sequence, but the fastidious or paranoid could choose to do:

U: MRSQ ?
S: 215 T Text first, please.

Which resets things without changing the scheme in effect ๐Ÿงผ


APPENDIX ON PAGE STRUCTURE ๐ŸŒˆ

The need for FTP to support page structure mostly comes from needing to transmit files efficiently between TOPS20 systems, especially the files used by NLS ๐Ÿ’œ

The TOPS20 file system is built around the concept of pages. The system level is most efficient at manipulating files as pages ๐Ÿง  System level programs provide an interface to the file system so that many applications can view files as sequential streams of characters. However, a few applications use the underlying page structures directly, and some of these create holey files ๐Ÿ•ณ๏ธ

A TOPS20 file is just a bunch of words pointed to by a page table. If those words contain CRLF's, fine, but that doesn't mean "record" to TOPS20 ๐Ÿ™…โ€โ™€๏ธ

A TOPS20 disk file consists of four things: a pathname, a page table, a (possibly empty) set of pages, and a set of attributes ๐Ÿ“

The pathname is specified in the RETR or STOR command. It includes the directory name, file name, file name extension, and version number.

The page table contains up to 2**18 entries. Each entry may be EMPTY, or may point to a page. If it isn't empty, there are also some page-specific access bits. Not all pages of a file need the same access protection ๐Ÿ”

A page is a contiguous set of 512 words of 36 bits each.

The attributes of the file, in the File Descriptor Block (FDB), contain things like creation time, write time, read time, writer's byte-size, end of file pointer, count of reads and writes, backup system tape numbers, etc. ๐Ÿ“‹

Note that there is NO requirement that pages in the page table be contiguous. There may be empty page table slots between occupied ones. Also, the end of file pointer is simply a number. There's no requirement that it actually point at the "last" datum in the file. Ordinary sequential I/O calls in TOPS20 will leave the end of file pointer after the last datum written, but other operations may cause it not to be, if a particular programming system requires that ๐Ÿคทโ€โ™€๏ธ

In fact, both of these special cases, "holey" files and end-of-file pointers not at the end of the file, occur with NLS data files ๐ŸŽ€

The TOPS20 paged files can be sent with the FTP transfer parameters TYPE L 36, STRU P, and MODE S (in fact any mode could be used) ๐Ÿš€

Each page of information has a header. Each header field, which is a logical byte, is a TOPS20 word, since the TYPE is L 36 ๐Ÿ’… The header fields are:

  • Word 0: Header Length.
    • The header length is 5.
  • Word 1: Page Index.
    • If the data is a disk file page, this is the number of that page in the file's page map. Empty pages (holes) in the file are simply not sent. Note that a hole is NOT the same as a page of zeros ๐Ÿ•ณ๏ธ
  • Word 2: Data Length.
    • The number of data words in this page, following the header. Thus the total length of the transmission unit is the Header Length plus the Data Length.
  • Word 3: Page Type.
    • A code for what type of chunk this is. A data page is type 3, the FDB page is type 2.
  • Word 4: Page Access Control.
    • The access bits associated with the page in the file's page map. (This full word quantity is put into AC2 of an SPACS by the program reading from net to disk.)

After the header come Data Length data words. Data Length is currently either 512 for a data page or 21 for an FDB. Trailing zeros in a disk file page may be discarded, making Data Length less than 512 in that case ๐Ÿซง

Data transfers are implemented like the layers of an onion ๐Ÿง… Some characters are packaged into a line. Some lines are packaged into a file. The file is broken into other manageable units for transmission. Those units have compression applied to them. The units may be flagged by restart markers. On the other end, the process is reversed โœจ

๐Ÿ“ฆ where this page comes from