summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormsoulier <msoulier@63283fd4-ec1e-0410-9879-cb7f675518da>2006-10-03 19:11:18 +0000
committermsoulier <msoulier@63283fd4-ec1e-0410-9879-cb7f675518da>2006-10-03 19:11:18 +0000
commitcfa8e61fa3d0dcd3d5916ae1e29aded60651dd93 (patch)
tree6b35382fd1925fcc6686cfe36a9fc347cd4e9612
parentb72d23ebc3d2d25e2a4230f4664e719a88f65485 (diff)
downloadtftpy-cfa8e61fa3d0dcd3d5916ae1e29aded60651dd93.tar.gz
Restructuring
git-svn-id: https://tftpy.svn.sourceforge.net/svnroot/tftpy/trunk@3 63283fd4-ec1e-0410-9879-cb7f675518da
-rw-r--r--LICENSE61
-rw-r--r--MANIFEST.in1
-rw-r--r--README14
-rw-r--r--bin/tftpy_client.py0
-rw-r--r--doc/rfc1350.txt551
-rw-r--r--doc/rfc2347.txt395
-rw-r--r--doc/rfc2348.txt283
-rwxr-xr-xlib/tftpy.py497
-rwxr-xr-xlib/tftpy_twisted.py19
-rw-r--r--setup.py21
10 files changed, 1842 insertions, 0 deletions
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..7ba1969
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,61 @@
+http://www.opensource.org/licenses/pythonpl.php
+
+IMPORTANT: PLEASE READ THE FOLLOWING AGREEMENT CAREFULLY.
+
+BY CLICKING ON "ACCEPT" WHERE INDICATED BELOW, OR BY COPYING, INSTALLING OR
+OTHERWISE USING PYTHON 1.6, beta 1 SOFTWARE, YOU ARE DEEMED TO HAVE AGREED TO
+THE TERMS AND CONDITIONS OF THIS LICENSE AGREEMENT.
+
+1. This LICENSE AGREEMENT is between the Corporation for National Research
+Initiatives, having an office at 1895 Preston White Drive, Reston, VA 20191
+("CNRI"), and the Individual or Organization ("Licensee") accessing and
+otherwise using Python 1.6, beta 1 software in source or binary form and its
+associated documentation, as released at the www.python.org Internet site on
+August 4, 2000 ("Python 1.6b1").
+
+2. Subject to the terms and conditions of this License Agreement, CNRI hereby
+grants Licensee a non-exclusive, royalty-free, world-wide license to
+reproduce, analyze, test, perform and/or display publicly, prepare derivative
+works, distribute, and otherwise use Python 1.6b1 alone or in any derivative
+version, provided, however, that CNRIs License Agreement is retained in Python
+1.6b1, alone or in any derivative version prepared by Licensee.
+
+Alternately, in lieu of CNRIs License Agreement, Licensee may substitute the
+following text (omitting the quotes): "Python 1.6, beta 1, is made available
+subject to the terms and conditions in CNRIs License Agreement. This Agreement
+may be located on the Internet using the following unique, persistent
+identifier (known as a handle): 1895.22/1011. This Agreement may also be
+obtained from a proxy server on the Internet using the
+URL:http://hdl.handle.net/1895.22/1011".
+
+3. In the event Licensee prepares a derivative work that is based on or
+incorporates Python 1.6b1or any part thereof, and wants to make the derivative
+work available to the public as provided herein, then Licensee hereby agrees
+to indicate in any such work the nature of the modifications made to Python
+1.6b1.
+
+4. CNRI is making Python 1.6b1 available to Licensee on an "AS IS" basis. CNRI
+MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE,
+BUT NOT LIMITATION, CNRI MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY
+OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF
+PYTHON 1.6b1WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.
+
+5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE SOFTWARE FOR
+ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF
+USING, MODIFYING OR DISTRIBUTING PYTHON 1.6b1, OR ANY DERIVATIVE THEREOF, EVEN
+IF ADVISED OF THE POSSIBILITY THEREOF.
+
+6. This License Agreement will automatically terminate upon a material breach
+of its terms and conditions.
+
+7. This License Agreement shall be governed by and interpreted in all respects
+by the law of the State of Virginia, excluding conflict of law provisions.
+Nothing in this License Agreement shall be deemed to create any relationship
+of agency, partnership, or joint venture between CNRI and Licensee. This
+License Agreement does not grant permission to use CNRI trademarks or trade
+name in a trademark sense to endorse or promote products or services of
+Licensee, or any third party.
+
+8. By clicking on the "ACCEPT" button where indicated, or by copying,
+installing or otherwise using Python 1.6b1, Licensee agrees to be bound by the
+terms and conditions of this License Agreement.
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..1aba38f
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1 @@
+include LICENSE
diff --git a/README b/README
new file mode 100644
index 0000000..bc1c064
--- /dev/null
+++ b/README
@@ -0,0 +1,14 @@
+Copyright, Michael P. Soulier, 2006.
+
+This is a simple tftp library for Python. The project has no hosting as of
+yet, so for now, simply direct any problems to me at
+msoulier@digitaltorque.ca.
+
+This library was developed against Python 2.4.1. If you have a previous
+version, don't bother contacting me. You're welcome to backport it if you
+like.
+
+License is the CNRI Python License.
+http://www.opensource.org/licenses/pythonpl.php
+
+See LICENSE in this distribution.
diff --git a/bin/tftpy_client.py b/bin/tftpy_client.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bin/tftpy_client.py
diff --git a/doc/rfc1350.txt b/doc/rfc1350.txt
new file mode 100644
index 0000000..f114928
--- /dev/null
+++ b/doc/rfc1350.txt
@@ -0,0 +1,551 @@
+
+ RFC 1350 (RFC1350)
+
+ Internet RFC/STD/FYI/BCP Archives
+
+[ [1]RFC Index | [2]RFC Search | [3]Usenet FAQs | [4]Web FAQs | [5]Documents
+ | [6]Cities ]
+
+ Alternate Formats: [7]rfc1350.txt | [8]rfc1350.txt.pdf
+
+ RFC 1350 - The TFTP Protocol (Revision 2)
+ _________________________________________________________________
+
+
+Network Working Group K. Sollins
+Request For Comments: 1350 MIT
+STD: 33 July 1992
+Obsoletes: [9]RFC 783
+
+ THE TFTP PROTOCOL (REVISION 2)
+
+Status of this Memo
+
+ This RFC specifies an IAB standards track protocol for the Internet
+ community, and requests discussion and suggestions for improvements.
+ Please refer to the current edition of the "IAB Official Protocol
+ Standards" for the standardization state and status of this protocol.
+ Distribution of this memo is unlimited.
+
+Summary
+
+ TFTP is a very simple protocol used to transfer files. It is from
+ this that its name comes, Trivial File Transfer Protocol or TFTP.
+ Each nonterminal packet is acknowledged separately. This document
+ describes the protocol and its types of packets. The document also
+ explains the reasons behind some of the design decisions.
+
+Acknowlegements
+
+ The protocol was originally designed by Noel Chiappa, and was
+ redesigned by him, Bob Baldwin and Dave Clark, with comments from
+ Steve Szymanski. The current revision of the document includes
+ modifications stemming from discussions with and suggestions from
+ Larry Allen, Noel Chiappa, Dave Clark, Geoff Cooper, Mike Greenwald,
+ Liza Martin, David Reed, Craig Milo Rogers (of USC-ISI), Kathy
+ Yellick, and the author. The acknowledgement and retransmission
+ scheme was inspired by TCP, and the error mechanism was suggested by
+ PARC's EFTP abort message.
+
+ The May, 1992 revision to fix the "Sorcerer's Apprentice" protocol
+ bug [4] and other minor document problems was done by Noel Chiappa.
+
+ This research was supported by the Advanced Research Projects Agency
+ of the Department of Defense and was monitored by the Office of Naval
+ Research under contract number N00014-75-C-0661.
+
+1. Purpose
+
+ TFTP is a simple protocol to transfer files, and therefore was named
+ the Trivial File Transfer Protocol or TFTP. It has been implemented
+ on top of the Internet User Datagram protocol (UDP or Datagram) [2]
+
+ so it may be used to move files between machines on different
+ networks implementing UDP. (This should not exclude the possibility
+ of implementing TFTP on top of other datagram protocols.) It is
+ designed to be small and easy to implement. Therefore, it lacks most
+ of the features of a regular FTP. The only thing it can do is read
+ and write files (or mail) from/to a remote server. It cannot list
+ directories, and currently has no provisions for user authentication.
+ In common with other Internet protocols, it passes 8 bit bytes of
+ data.
+
+ Three modes of transfer are currently supported: netascii (This is
+ ascii as defined in "USA Standard Code for Information Interchange"
+ [1] with the modifications specified in "Telnet Protocol
+ Specification" [3].) Note that it is 8 bit ascii. The term
+ "netascii" will be used throughout this document to mean this
+ particular version of ascii.); octet (This replaces the "binary" mode
+ of previous versions of this document.) raw 8 bit bytes; mail,
+ netascii characters sent to a user rather than a file. (The mail
+ mode is obsolete and should not be implemented or used.) Additional
+ modes can be defined by pairs of cooperating hosts.
+
+ Reference [4] (section 4.2) should be consulted for further valuable
+ directives and suggestions on TFTP.
+
+2. Overview of the Protocol
+
+ Any transfer begins with a request to read or write a file, which
+ also serves to request a connection. If the server grants the
+ request, the connection is opened and the file is sent in fixed
+ length blocks of 512 bytes. Each data packet contains one block of
+ data, and must be acknowledged by an acknowledgment packet before the
+ next packet can be sent. A data packet of less than 512 bytes
+ signals termination of a transfer. If a packet gets lost in the
+ network, the intended recipient will timeout and may retransmit his
+ last packet (which may be data or an acknowledgment), thus causing
+ the sender of the lost packet to retransmit that lost packet. The
+ sender has to keep just one packet on hand for retransmission, since
+ the lock step acknowledgment guarantees that all older packets have
+ been received. Notice that both machines involved in a transfer are
+ considered senders and receivers. One sends data and receives
+ acknowledgments, the other sends acknowledgments and receives data.
+
+ Most errors cause termination of the connection. An error is
+ signalled by sending an error packet. This packet is not
+ acknowledged, and not retransmitted (i.e., a TFTP server or user may
+ terminate after sending an error message), so the other end of the
+ connection may not get it. Therefore timeouts are used to detect
+ such a termination when the error packet has been lost. Errors are
+
+ caused by three types of events: not being able to satisfy the
+ request (e.g., file not found, access violation, or no such user),
+ receiving a packet which cannot be explained by a delay or
+ duplication in the network (e.g., an incorrectly formed packet), and
+ losing access to a necessary resource (e.g., disk full or access
+ denied during a transfer).
+
+ TFTP recognizes only one error condition that does not cause
+ termination, the source port of a received packet being incorrect.
+ In this case, an error packet is sent to the originating host.
+
+ This protocol is very restrictive, in order to simplify
+ implementation. For example, the fixed length blocks make allocation
+ straight forward, and the lock step acknowledgement provides flow
+ control and eliminates the need to reorder incoming data packets.
+
+3. Relation to other Protocols
+
+ As mentioned TFTP is designed to be implemented on top of the
+ Datagram protocol (UDP). Since Datagram is implemented on the
+ Internet protocol, packets will have an Internet header, a Datagram
+ header, and a TFTP header. Additionally, the packets may have a
+ header (LNI, ARPA header, etc.) to allow them through the local
+ transport medium. As shown in Figure 3-1, the order of the contents
+ of a packet will be: local medium header, if used, Internet header,
+ Datagram header, TFTP header, followed by the remainder of the TFTP
+ packet. (This may or may not be data depending on the type of packet
+ as specified in the TFTP header.) TFTP does not specify any of the
+ values in the Internet header. On the other hand, the source and
+ destination port fields of the Datagram header (its format is given
+ in the appendix) are used by TFTP and the length field reflects the
+ size of the TFTP packet. The transfer identifiers (TID's) used by
+ TFTP are passed to the Datagram layer to be used as ports; therefore
+ they must be between 0 and 65,535. The initialization of TID's is
+ discussed in the section on initial connection protocol.
+
+ The TFTP header consists of a 2 byte opcode field which indicates
+ the packet's type (e.g., DATA, ERROR, etc.) These opcodes and the
+ formats of the various types of packets are discussed further in the
+ section on TFTP packets.
+
+ ---------------------------------------------------
+ | Local Medium | Internet | Datagram | TFTP |
+ ---------------------------------------------------
+
+ Figure 3-1: Order of Headers
+
+4. Initial Connection Protocol
+
+ A transfer is established by sending a request (WRQ to write onto a
+ foreign file system, or RRQ to read from it), and receiving a
+ positive reply, an acknowledgment packet for write, or the first data
+ packet for read. In general an acknowledgment packet will contain
+ the block number of the data packet being acknowledged. Each data
+ packet has associated with it a block number; block numbers are
+ consecutive and begin with one. Since the positive response to a
+ write request is an acknowledgment packet, in this special case the
+ block number will be zero. (Normally, since an acknowledgment packet
+ is acknowledging a data packet, the acknowledgment packet will
+ contain the block number of the data packet being acknowledged.) If
+ the reply is an error packet, then the request has been denied.
+
+ In order to create a connection, each end of the connection chooses a
+ TID for itself, to be used for the duration of that connection. The
+ TID's chosen for a connection should be randomly chosen, so that the
+ probability that the same number is chosen twice in immediate
+ succession is very low. Every packet has associated with it the two
+ TID's of the ends of the connection, the source TID and the
+ destination TID. These TID's are handed to the supporting UDP (or
+ other datagram protocol) as the source and destination ports. A
+ requesting host chooses its source TID as described above, and sends
+ its initial request to the known TID 69 decimal (105 octal) on the
+ serving host. The response to the request, under normal operation,
+ uses a TID chosen by the server as its source TID and the TID chosen
+ for the previous message by the requestor as its destination TID.
+ The two chosen TID's are then used for the remainder of the transfer.
+
+ As an example, the following shows the steps used to establish a
+ connection to write a file. Note that WRQ, ACK, and DATA are the
+ names of the write request, acknowledgment, and data types of packets
+ respectively. The appendix contains a similar example for reading a
+ file.
+
+ 1. Host A sends a "WRQ" to host B with source= A's TID,
+ destination= 69.
+
+ 2. Host B sends a "ACK" (with block number= 0) to host A with
+ source= B's TID, destination= A's TID.
+
+ At this point the connection has been established and the first data
+ packet can be sent by Host A with a sequence number of 1. In the
+ next step, and in all succeeding steps, the hosts should make sure
+ that the source TID matches the value that was agreed on in steps 1
+ and 2. If a source TID does not match, the packet should be
+ discarded as erroneously sent from somewhere else. An error packet
+ should be sent to the source of the incorrect packet, while not
+ disturbing the transfer. This can be done only if the TFTP in fact
+ receives a packet with an incorrect TID. If the supporting protocols
+ do not allow it, this particular error condition will not arise.
+
+ The following example demonstrates a correct operation of the
+ protocol in which the above situation can occur. Host A sends a
+ request to host B. Somewhere in the network, the request packet is
+ duplicated, and as a result two acknowledgments are returned to host
+ A, with different TID's chosen on host B in response to the two
+ requests. When the first response arrives, host A continues the
+ connection. When the second response to the request arrives, it
+ should be rejected, but there is no reason to terminate the first
+ connection. Therefore, if different TID's are chosen for the two
+ connections on host B and host A checks the source TID's of the
+ messages it receives, the first connection can be maintained while
+ the second is rejected by returning an error packet.
+
+5. TFTP Packets
+
+ TFTP supports five types of packets, all of which have been mentioned
+ above:
+
+ opcode operation
+ 1 Read request (RRQ)
+ 2 Write request (WRQ)
+ 3 Data (DATA)
+ 4 Acknowledgment (ACK)
+ 5 Error (ERROR)
+
+ The TFTP header of a packet contains the opcode associated with
+ that packet.
+
+ 2 bytes string 1 byte string 1 byte
+ ------------------------------------------------
+ | Opcode | Filename | 0 | Mode | 0 |
+ ------------------------------------------------
+
+ Figure 5-1: RRQ/WRQ packet
+
+ RRQ and WRQ packets (opcodes 1 and 2 respectively) have the format
+ shown in Figure 5-1. The file name is a sequence of bytes in
+ netascii terminated by a zero byte. The mode field contains the
+ string "netascii", "octet", or "mail" (or any combination of upper
+ and lower case, such as "NETASCII", NetAscii", etc.) in netascii
+ indicating the three modes defined in the protocol. A host which
+ receives netascii mode data must translate the data to its own
+ format. Octet mode is used to transfer a file that is in the 8-bit
+ format of the machine from which the file is being transferred. It
+ is assumed that each type of machine has a single 8-bit format that
+ is more common, and that that format is chosen. For example, on a
+ DEC-20, a 36 bit machine, this is four 8-bit bytes to a word with
+ four bits of breakage. If a host receives a octet file and then
+ returns it, the returned file must be identical to the original.
+ Mail mode uses the name of a mail recipient in place of a file and
+ must begin with a WRQ. Otherwise it is identical to netascii mode.
+ The mail recipient string should be of the form "username" or
+ "username@hostname". If the second form is used, it allows the
+ option of mail forwarding by a relay computer.
+
+ The discussion above assumes that both the sender and recipient are
+ operating in the same mode, but there is no reason that this has to
+ be the case. For example, one might build a storage server. There
+ is no reason that such a machine needs to translate netascii into its
+ own form of text. Rather, the sender might send files in netascii,
+ but the storage server might simply store them without translation in
+ 8-bit format. Another such situation is a problem that currently
+ exists on DEC-20 systems. Neither netascii nor octet accesses all
+ the bits in a word. One might create a special mode for such a
+ machine which read all the bits in a word, but in which the receiver
+ stored the information in 8-bit format. When such a file is
+ retrieved from the storage site, it must be restored to its original
+ form to be useful, so the reverse mode must also be implemented. The
+ user site will have to remember some information to achieve this. In
+ both of these examples, the request packets would specify octet mode
+ to the foreign host, but the local host would be in some other mode.
+ No such machine or application specific modes have been specified in
+ TFTP, but one would be compatible with this specification.
+
+ It is also possible to define other modes for cooperating pairs of
+
+ hosts, although this must be done with care. There is no requirement
+ that any other hosts implement these. There is no central authority
+ that will define these modes or assign them names.
+
+ 2 bytes 2 bytes n bytes
+ ----------------------------------
+ | Opcode | Block # | Data |
+ ----------------------------------
+
+ Figure 5-2: DATA packet
+
+ Data is actually transferred in DATA packets depicted in Figure 5-2.
+ DATA packets (opcode = 3) have a block number and data field. The
+ block numbers on data packets begin with one and increase by one for
+ each new block of data. This restriction allows the program to use a
+ single number to discriminate between new packets and duplicates.
+ The data field is from zero to 512 bytes long. If it is 512 bytes
+ long, the block is not the last block of data; if it is from zero to
+ 511 bytes long, it signals the end of the transfer. (See the section
+ on Normal Termination for details.)
+
+ All packets other than duplicate ACK's and those used for
+ termination are acknowledged unless a timeout occurs [4]. Sending a
+ DATA packet is an acknowledgment for the first ACK packet of the
+ previous DATA packet. The WRQ and DATA packets are acknowledged by
+ ACK or ERROR packets, while RRQ
+
+ 2 bytes 2 bytes
+ ---------------------
+ | Opcode | Block # |
+ ---------------------
+
+ Figure 5-3: ACK packet
+
+ and ACK packets are acknowledged by DATA or ERROR packets. Figure
+ 5-3 depicts an ACK packet; the opcode is 4. The block number in
+ an ACK echoes the block number of the DATA packet being
+ acknowledged. A WRQ is acknowledged with an ACK packet having a
+ block number of zero.
+
+ 2 bytes 2 bytes string 1 byte
+ -----------------------------------------
+ | Opcode | ErrorCode | ErrMsg | 0 |
+ -----------------------------------------
+
+ Figure 5-4: ERROR packet
+
+ An ERROR packet (opcode 5) takes the form depicted in Figure 5-4. An
+ ERROR packet can be the acknowledgment of any other type of packet.
+ The error code is an integer indicating the nature of the error. A
+ table of values and meanings is given in the appendix. (Note that
+ several error codes have been added to this version of this
+ document.) The error message is intended for human consumption, and
+ should be in netascii. Like all other strings, it is terminated with
+ a zero byte.
+
+6. Normal Termination
+
+ The end of a transfer is marked by a DATA packet that contains
+ between 0 and 511 bytes of data (i.e., Datagram length < 516). This
+ packet is acknowledged by an ACK packet like all other DATA packets.
+ The host acknowledging the final DATA packet may terminate its side
+ of the connection on sending the final ACK. On the other hand,
+ dallying is encouraged. This means that the host sending the final
+ ACK will wait for a while before terminating in order to retransmit
+ the final ACK if it has been lost. The acknowledger will know that
+ the ACK has been lost if it receives the final DATA packet again.
+ The host sending the last DATA must retransmit it until the packet is
+ acknowledged or the sending host times out. If the response is an
+ ACK, the transmission was completed successfully. If the sender of
+ the data times out and is not prepared to retransmit any more, the
+ transfer may still have been completed successfully, after which the
+ acknowledger or network may have experienced a problem. It is also
+ possible in this case that the transfer was unsuccessful. In any
+ case, the connection has been closed.
+
+7. Premature Termination
+
+ If a request can not be granted, or some error occurs during the
+ transfer, then an ERROR packet (opcode 5) is sent. This is only a
+ courtesy since it will not be retransmitted or acknowledged, so it
+ may never be received. Timeouts must also be used to detect errors.
+
+I. Appendix
+
+Order of Headers
+
+ 2 bytes
+ ----------------------------------------------------------
+ | Local Medium | Internet | Datagram | TFTP Opcode |
+ ----------------------------------------------------------
+
+TFTP Formats
+
+ Type Op # Format without header
+
+ 2 bytes string 1 byte string 1 byte
+ -----------------------------------------------
+ RRQ/ | 01/02 | Filename | 0 | Mode | 0 |
+ WRQ -----------------------------------------------
+ 2 bytes 2 bytes n bytes
+ ---------------------------------
+ DATA | 03 | Block # | Data |
+ ---------------------------------
+ 2 bytes 2 bytes
+ -------------------
+ ACK | 04 | Block # |
+ --------------------
+ 2 bytes 2 bytes string 1 byte
+ ----------------------------------------
+ ERROR | 05 | ErrorCode | ErrMsg | 0 |
+ ----------------------------------------
+
+Initial Connection Protocol for reading a file
+
+ 1. Host A sends a "RRQ" to host B with source= A's TID,
+ destination= 69.
+
+ 2. Host B sends a "DATA" (with block number= 1) to host A with
+ source= B's TID, destination= A's TID.
+
+Error Codes
+
+ Value Meaning
+
+ 0 Not defined, see error message (if any).
+ 1 File not found.
+ 2 Access violation.
+ 3 Disk full or allocation exceeded.
+ 4 Illegal TFTP operation.
+ 5 Unknown transfer ID.
+ 6 File already exists.
+ 7 No such user.
+
+Internet User Datagram Header [2]
+
+ (This has been included only for convenience. TFTP need not be
+ implemented on top of the Internet User Datagram Protocol.)
+
+ Format
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Source Port | Destination Port |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Length | Checksum |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ Values of Fields
+
+ Source Port Picked by originator of packet.
+
+ Dest. Port Picked by destination machine (69 for RRQ or WRQ).
+
+ Length Number of bytes in UDP packet, including UDP header.
+
+ Checksum Reference 2 describes rules for computing checksum.
+ (The implementor of this should be sure that the
+ correct algorithm is used here.)
+ Field contains zero if unused.
+
+ Note: TFTP passes transfer identifiers (TID's) to the Internet User
+ Datagram protocol to be used as the source and destination ports.
+
+References
+
+ [1] USA Standard Code for Information Interchange, USASI X3.4-1968.
+
+ [2] Postel, J., "User Datagram Protocol," [10]RFC 768, USC/Information
+ Sciences Institute, 28 August 1980.
+
+ [3] Postel, J., "Telnet Protocol Specification," [11]RFC 764,
+ USC/Information Sciences Institute, June, 1980.
+
+ [4] Braden, R., Editor, "Requirements for Internet Hosts --
+ Application and Support", [12]RFC 1123, USC/Information Sciences
+ Institute, October 1989.
+
+Security Considerations
+
+ Since TFTP includes no login or access control mechanisms, care must
+ be taken in the rights granted to a TFTP server process so as not to
+ violate the security of the server hosts file system. TFTP is often
+ installed with controls such that only files that have public read
+ access are available via TFTP and writing files via TFTP is
+ disallowed.
+
+Author's Address
+
+ Karen R. Sollins
+ Massachusetts Institute of Technology
+ Laboratory for Computer Science
+ 545 Technology Square
+ Cambridge, MA 02139-1986
+
+ Phone: (617) 253-6006
+
+ EMail: [13]SOLLINS@LCS.MIT.EDU
+
+
+ Comments about this RFC:
+ * [14]RFC 1350: How to setup TFTP across firewall. Why to spawn
+ connections on several different... by WahJava (2/7/2006)
+ * [15]RFC 1350: Since there is no master slave arrangement. What happens
+ if both ends of the... by pg (3/30/2005)
+ * [16]RFC 1350: What happens when the TFTP client or server detects that
+ the ethernet link which... by Sekhar Nori (12/29/2003)
+ * [17]RFC 1350: This RFC may benefit from an update in the style of PPP or
+ SSCOP protocol... by Chris (10/4/2004)
+ * [18]RFC 1350: What happens if the server receives any packet other than
+ RRQ/WRQ in the initial... by Orgad (10/24/2003)
+ * [19]RFC 1350: In the following para,it is considered duplication of the
+ acknowledgment packet... by KiranKumar (1/1/2006)
+ * [20]RFC 1350: What happens if the data on the file is a multiple 512
+ bytes? When will the... by yara (2/23/2005)
+ * [21]RFC 1350: I tried WhiteHorn TFTP server (www.whitehorns.net) and
+ really liked it. Does... by bartley (7/29/2005)
+ * [22]RFC 1350: I'd like to see more discussion about the benefits and
+ drawbacks of using... by Mike Cepek (4/19/2005)
+ * [23]RFC 1350: Any words on the ipv6 support in TFTP..It might be not the
+ correct question here... by Piyush Yaduvanshi (2/23/2006)
+
+ Previous: [24]RFC 1349 - Type of Service in the Internet Protocol Suite
+ Next: [25]RFC 1351 - SNMP Administrative Model
+
+ _________________________________________________________________
+
+ [ [26]RFC Index | [27]RFC Search | [28]Usenet FAQs | [29]Web FAQs |
+ [30]Documents | [31]Cities ]
+
+References
+
+ 1. http://www.faqs.org/rfcs/
+ 2. http://www.faqs.org/rfcs/rfcsearch.html
+ 3. http://www.faqs.org/faqs/
+ 4. http://www.faqs.org/contrib/
+ 5. http://www.faqs.org/docs/
+ 6. http://www.city-data.com/
+ 7. http://www.faqs.org/ftp/rfc/rfc1350.txt
+ 8. http://www.faqs.org/ftp/rfc/pdf/rfc1350.txt.pdf
+ 9. http://www.faqs.org/rfcs/rfc783.html
+ 10. http://www.faqs.org/rfcs/rfc768.html
+ 11. http://www.faqs.org/rfcs/rfc764.html
+ 12. http://www.faqs.org/rfcs/rfc1123.html
+ 13. mailto:SOLLINS@LCS.MIT.EDU
+ 14. http://www.faqs.org/qa/rfcc-2889.html
+ 15. http://www.faqs.org/qa/rfcc-1841.html
+ 16. http://www.faqs.org/qa/rfcc-433.html
+ 17. http://www.faqs.org/qa/rfcc-1281.html
+ 18. http://www.faqs.org/qa/rfcc-255.html
+ 19. http://www.faqs.org/qa/rfcc-2798.html
+ 20. http://www.faqs.org/qa/rfcc-1734.html
+ 21. http://www.faqs.org/qa/rfcc-2297.html
+ 22. http://www.faqs.org/qa/rfcc-1916.html
+ 23. http://www.faqs.org/qa/rfcc-2933.html
+ 24. http://www.faqs.org/rfcs/rfc1349.html
+ 25. http://www.faqs.org/rfcs/rfc1351.html
+ 26. http://www.faqs.org/rfcs/
+ 27. http://www.faqs.org/rfcs/rfcsearch.html
+ 28. http://www.faqs.org/faqs/
+ 29. http://www.faqs.org/contrib/
+ 30. http://www.faqs.org/docs/
+ 31. http://www.city-data.com/
diff --git a/doc/rfc2347.txt b/doc/rfc2347.txt
new file mode 100644
index 0000000..dbc0f8c
--- /dev/null
+++ b/doc/rfc2347.txt
@@ -0,0 +1,395 @@
+
+
+
+
+
+
+Network Working Group G. Malkin
+Request for Commments: 2347 Bay Networks
+Updates: 1350 A. Harkin
+Obsoletes: 1782 Hewlett Packard Co.
+Category: Standards Track May 1998
+
+
+ TFTP Option Extension
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1998). All Rights Reserved.
+
+Abstract
+
+ The Trivial File Transfer Protocol [1] is a simple, lock-step, file
+ transfer protocol which allows a client to get or put a file onto a
+ remote host. This document describes a simple extension to TFTP to
+ allow option negotiation prior to the file transfer.
+
+Introduction
+
+ The option negotiation mechanism proposed in this document is a
+ backward-compatible extension to the TFTP protocol. It allows file
+ transfer options to be negotiated prior to the transfer using a
+ mechanism which is consistent with TFTP's Request Packet format. The
+ mechanism is kept simple by enforcing a request-respond-acknowledge
+ sequence, similar to the lock-step approach taken by TFTP itself.
+
+ While the option negotiation mechanism is general purpose, in that
+ many types of options may be negotiated, it was created to support
+ the Blocksize option defined in [2]. Additional options are defined
+ in [3].
+
+Packet Formats
+
+ TFTP options are appended to the Read Request and Write Request
+ packets. A new type of TFTP packet, the Option Acknowledgment
+ (OACK), is used to acknowledge a client's option negotiation request.
+ A new error code, 8, is hereby defined to indicate that a transfer
+
+
+
+Malkin & Harkin Standards Track [Page 1]
+
+RFC 2347 TFTP Option Extension May 1998
+
+
+ should be terminated due to option negotiation.
+
+ Options are appended to a TFTP Read Request or Write Request packet
+ as follows:
+
+ +-------+---~~---+---+---~~---+---+---~~---+---+---~~---+---+-->
+ | opc |filename| 0 | mode | 0 | opt1 | 0 | value1 | 0 | <
+ +-------+---~~---+---+---~~---+---+---~~---+---+---~~---+---+-->
+
+ >-------+---+---~~---+---+
+ < optN | 0 | valueN | 0 |
+ >-------+---+---~~---+---+
+
+ opc
+ The opcode field contains either a 1, for Read Requests, or 2,
+ for Write Requests, as defined in [1].
+
+ filename
+ The name of the file to be read or written, as defined in [1].
+ This is a NULL-terminated field.
+
+ mode
+ The mode of the file transfer: "netascii", "octet", or "mail",
+ as defined in [1]. This is a NULL-terminated field.
+
+ opt1
+ The first option, in case-insensitive ASCII (e.g., blksize).
+ This is a NULL-terminated field.
+
+ value1
+ The value associated with the first option, in case-
+ insensitive ASCII. This is a NULL-terminated field.
+
+ optN, valueN
+ The final option/value pair. Each NULL-terminated field is
+ specified in case-insensitive ASCII.
+
+ The options and values are all NULL-terminated, in keeping with the
+ original request format. If multiple options are to be negotiated,
+ they are appended to each other. The order in which options are
+ specified is not significant. The maximum size of a request packet
+ is 512 octets.
+
+ The OACK packet has the following format:
+
+
+
+
+
+
+
+Malkin & Harkin Standards Track [Page 2]
+
+RFC 2347 TFTP Option Extension May 1998
+
+
+ +-------+---~~---+---+---~~---+---+---~~---+---+---~~---+---+
+ | opc | opt1 | 0 | value1 | 0 | optN | 0 | valueN | 0 |
+ +-------+---~~---+---+---~~---+---+---~~---+---+---~~---+---+
+
+ opc
+ The opcode field contains a 6, for Option Acknowledgment.
+
+ opt1
+ The first option acknowledgment, copied from the original
+ request.
+
+ value1
+ The acknowledged value associated with the first option. If
+ and how this value may differ from the original request is
+ detailed in the specification for the option.
+
+ optN, valueN
+ The final option/value acknowledgment pair.
+
+Negotiation Protocol
+
+ The client appends options at the end of the Read Request or Write
+ request packet, as shown above. Any number of options may be
+ specified; however, an option may only be specified once. The order
+ of the options is not significant.
+
+ If the server supports option negotiation, and it recognizes one or
+ more of the options specified in the request packet, the server may
+ respond with an Options Acknowledgment (OACK). Each option the
+ server recognizes, and accepts the value for, is included in the
+ OACK. Some options may allow alternate values to be proposed, but
+ this is an option specific feature. The server must not include in
+ the OACK any option which had not been specifically requested by the
+ client; that is, only the client may initiate option negotiation.
+ Options which the server does not support should be omitted from the
+ OACK; they should not cause an ERROR packet to be generated. If the
+ value of a supported option is invalid, the specification for that
+ option will indicate whether the server should simply omit the option
+ from the OACK, respond with an alternate value, or send an ERROR
+ packet, with error code 8, to terminate the transfer.
+
+ An option not acknowledged by the server must be ignored by the
+ client and server as if it were never requested. If multiple options
+ were requested, the client must use those options which were
+ acknowledged by the server and must not use those options which were
+ not acknowledged by the server.
+
+
+
+
+
+Malkin & Harkin Standards Track [Page 3]
+
+RFC 2347 TFTP Option Extension May 1998
+
+
+ When the client appends options to the end of a Read Request packet,
+ three possible responses may be returned by the server:
+
+ OACK - acknowledge of Read Request and the options;
+
+ DATA - acknowledge of Read Request, but not the options;
+
+ ERROR - the request has been denied.
+
+ When the client appends options to the end of a Write Request packet,
+ three possible responses may be returned by the server:
+
+ OACK - acknowledge of Write Request and the options;
+
+ ACK - acknowledge of Write Request, but not the options;
+
+ ERROR - the request has been denied.
+
+ If a server implementation does not support option negotiation, it
+ will likely ignore any options appended to the client's request. In
+ this case, the server will return a DATA packet for a Read Request
+ and an ACK packet for a Write Request establishing normal TFTP data
+ transfer. In the event that a server returns an error for a request
+ which carries an option, the client may attempt to repeat the request
+ without appending any options. This implementation option would
+ handle servers which consider extraneous data in the request packet
+ to be erroneous.
+
+ Depending on the original transfer request there are two ways for a
+ client to confirm acceptance of a server's OACK. If the transfer was
+ initiated with a Read Request, then an ACK (with the data block
+ number set to 0) is sent by the client to confirm the values in the
+ server's OACK packet. If the transfer was initiated with a Write
+ Request, then the client begins the transfer with the first DATA
+ packet, using the negotiated values. If the client rejects the OACK,
+ then it sends an ERROR packet, with error code 8, to the server and
+ the transfer is terminated.
+
+ Once a client acknowledges an OACK, with an appropriate non-error
+ response, that client has agreed to use only the options and values
+ returned by the server. Remember that the server cannot request an
+ option; it can only respond to them. If the client receives an OACK
+ containing an unrequested option, it should respond with an ERROR
+ packet, with error code 8, and terminate the transfer.
+
+
+
+
+
+
+
+Malkin & Harkin Standards Track [Page 4]
+
+RFC 2347 TFTP Option Extension May 1998
+
+
+Examples
+
+ Read Request
+
+ client server
+ -------------------------------------------------------
+ |1|foofile|0|octet|0|blksize|0|1432|0| --> RRQ
+ <-- |6|blksize|0|1432|0| OACK
+ |4|0| --> ACK
+ <-- |3|1| 1432 octets of data | DATA
+ |4|1| --> ACK
+ <-- |3|2| 1432 octets of data | DATA
+ |4|2| --> ACK
+ <-- |3|3|<1432 octets of data | DATA
+ |4|3| --> ACK
+
+ Write Request
+
+ client server
+ -------------------------------------------------------
+ |2|barfile|0|octet|0|blksize|0|2048|0| --> RRQ
+ <-- |6|blksize|0|2048|0| OACK
+ |3|1| 2048 octets of data | --> DATA
+ <-- |4|1| ACK
+ |3|2| 2048 octets of data | --> DATA
+ <-- |4|2| ACK
+ |3|3|<2048 octets of data | --> DATA
+ <-- |4|3| ACK
+
+Security Considerations
+
+ The basic TFTP protocol has no security mechanism. This is why it
+ has no rename, delete, or file overwrite capabilities. This document
+ does not add any security to TFTP; however, the specified extensions
+ do not add any additional security risks.
+
+References
+
+ [1] Sollins, K., "The TFTP Protocol (Revision 2)", STD 33, RFC 1350,
+ October 1992.
+
+ [2] Malkin, G., and A. Harkin, "TFTP Blocksize Option", RFC 2348,
+ May 1998.
+
+ [3] Malkin, G., and A. Harkin, "TFTP Timeout Interval and Transfer
+ Size Options", RFC 2349, May 1998.
+
+
+
+
+
+Malkin & Harkin Standards Track [Page 5]
+
+RFC 2347 TFTP Option Extension May 1998
+
+
+Authors' Addresses
+
+ Gary Scott Malkin
+ Bay Networks
+ 8 Federal Street
+ Billerica, MA 01821
+
+ Phone: (978) 916-4237
+ EMail: gmalkin@baynetworks.com
+
+
+ Art Harkin
+ Internet Services Project
+ Information Networks Division
+ 19420 Homestead Road MS 43LN
+ Cupertino, CA 95014
+
+ Phone: (408) 447-3755
+ EMail: ash@cup.hp.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Malkin & Harkin Standards Track [Page 6]
+
+RFC 2347 TFTP Option Extension May 1998
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (1998). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Malkin & Harkin Standards Track [Page 7]
+
diff --git a/doc/rfc2348.txt b/doc/rfc2348.txt
new file mode 100644
index 0000000..b38c56d
--- /dev/null
+++ b/doc/rfc2348.txt
@@ -0,0 +1,283 @@
+
+
+
+
+
+
+Network Working Group G. Malkin
+Request for Commments: 2348 Bay Networks
+Updates: 1350 A. Harkin
+Obsoletes: 1783 Hewlett Packard Co.
+Category: Standards Track May 1998
+
+
+ TFTP Blocksize Option
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1998). All Rights Reserved.
+
+Abstract
+
+ The Trivial File Transfer Protocol [1] is a simple, lock-step, file
+ transfer protocol which allows a client to get or put a file onto a
+ remote host. One of its primary uses is the booting of diskless
+ nodes on a Local Area Network. TFTP is used because it is very
+ simple to implement in a small node's limited ROM space. However,
+ the choice of a 512-octet blocksize is not the most efficient for use
+ on a LAN whose MTU may 1500 octets or greater.
+
+ This document describes a TFTP option which allows the client and
+ server to negotiate a blocksize more applicable to the network
+ medium. The TFTP Option Extension mechanism is described in [2].
+
+Blocksize Option Specification
+
+ The TFTP Read Request or Write Request packet is modified to include
+ the blocksize option as follows. Note that all fields except "opc"
+ are NULL-terminated.
+
+ +-------+---~~---+---+---~~---+---+---~~---+---+---~~---+---+
+ | opc |filename| 0 | mode | 0 | blksize| 0 | #octets| 0 |
+ +-------+---~~---+---+---~~---+---+---~~---+---+---~~---+---+
+
+ opc
+ The opcode field contains either a 1, for Read Requests, or 2,
+ for Write Requests, as defined in [1].
+
+
+
+Malkin & Harkin Standards Track [Page 1]
+
+RFC 2348 TFTP Blocksize Option May 1998
+
+
+ filename
+ The name of the file to be read or written, as defined in [1].
+
+ mode
+ The mode of the file transfer: "netascii", "octet", or "mail",
+ as defined in [1].
+
+ blksize
+ The Blocksize option, "blksize" (case in-sensitive).
+
+ #octets
+ The number of octets in a block, specified in ASCII. Valid
+ values range between "8" and "65464" octets, inclusive. The
+ blocksize refers to the number of data octets; it does not
+ include the four octets of TFTP header.
+
+ For example:
+
+ +-------+--------+---+--------+---+--------+---+--------+---+
+ | 1 | foobar | 0 | octet | 0 | blksize| 0 | 1428 | 0 |
+ +-------+--------+---+--------+---+--------+---+--------+---+
+
+ is a Read Request, for the file named "foobar", in octet (binary)
+ transfer mode, with a block size of 1428 octets (Ethernet MTU, less
+ the TFTP, UDP and IP header lengths).
+
+ If the server is willing to accept the blocksize option, it sends an
+ Option Acknowledgment (OACK) to the client. The specified value must
+ be less than or equal to the value specified by the client. The
+ client must then either use the size specified in the OACK, or send
+ an ERROR packet, with error code 8, to terminate the transfer.
+
+ The rules for determining the final packet are unchanged from [1].
+ The reception of a data packet with a data length less than the
+ negotiated blocksize is the final packet. If the blocksize is
+ greater than the amount of data to be transfered, the first packet is
+ the final packet. If the amount of data to be transfered is an
+ integral multiple of the blocksize, an extra data packet containing
+ no data is sent to end the transfer.
+
+Proof of Concept
+
+ Performance tests were run on the prototype implementation using a
+ variety of block sizes. The tests were run on a lightly loaded
+ Ethernet, between two HP-UX 9000, in "octet" mode, on 2.25MB files.
+ The average (5x) transfer times for paths with (g-time) and without
+ (n-time) a intermediate gateway are graphed as follows:
+
+
+
+
+Malkin & Harkin Standards Track [Page 2]
+
+RFC 2348 TFTP Blocksize Option May 1998
+
+
+ |
+ 37 + g
+ |
+ 35 +
+ |
+ 33 +
+ |
+ 31 +
+ |
+ 29 +
+ |
+ 27 +
+ | g blocksize n-time g-time
+ 25 + --------- ------ ------
+ s | n 512 23.85 37.05
+ e 23 + g 1024 16.15 25.65
+ c | 1428 13.70 23.10
+ o 21 + 2048 10.90 16.90
+ n | 4096 6.85 9.65
+ d 19 + 8192 4.90 6.15
+ s |
+ 17 + g
+ | n
+ 15 +
+ | n
+ 13 +
+ |
+ 11 + n
+ | g
+ 9 +
+ |
+ 7 + n
+ | g
+ 5 + n
+ "
+ 0 +------+------+--+---+------+------+---
+ 512 1K | 2K 4K 8K
+ 1428
+ blocksize (octets)
+
+ The comparisons between transfer times (without a gateway) between
+ the standard 512-octet blocksize and the negotiated blocksizes are:
+
+ 1024 2x -32%
+ 1428 2.8x -42%
+ 2048 4x -54%
+ 4096 8x -71%
+ 8192 16x -80%
+
+
+
+Malkin & Harkin Standards Track [Page 3]
+
+RFC 2348 TFTP Blocksize Option May 1998
+
+
+ As was anticipated, the transfer time decreases with an increase in
+ blocksize. The reason for the reduction in time is the reduction in
+ the number of packets sent. For example, by increasing the blocksize
+ from 512 octets to 1024 octets, not only are the number of data
+ packets halved, but the number of acknowledgement packets is also
+ halved (along with the number of times the data transmitter must wait
+ for an ACK). A secondary effect is the efficiency gained by reducing
+ the per-packet framing and processing overhead.
+
+ Of course, if the blocksize exceeds the path MTU, IP fragmentation
+ and reassembly will begin to add more overhead. This will be more
+ noticable the greater the number of gateways in the path.
+
+Security Considerations
+
+ The basic TFTP protocol has no security mechanism. This is why it
+ has no rename, delete, or file overwrite capabilities. This document
+ does not add any security to TFTP; however, the specified extensions
+ do not add any additional security risks.
+
+References
+
+ [1] Sollins, K., "The TFTP Protocol (Revision 2)", STD 33, RFC 1350,
+ October 1992.
+
+ [2] Malkin, G., and A. Harkin, "TFTP Option Extension", RFC 2347,
+ May 1998.
+
+Authors' Addresses
+
+ Gary Scott Malkin
+ Bay Networks
+ 8 Federal Street
+ Billerica, MA 10821
+
+ Phone: (978) 916-4237
+ EMail: gmalkin@baynetworks.com
+
+
+ Art Harkin
+ Networked Computing Division
+ Hewlett-Packard Company
+ 19420 Homestead Road MS 43LN
+ Cupertino, CA 95014
+
+ Phone: (408) 447-3755
+ EMail: ash@cup.hp.com
+
+
+
+
+Malkin & Harkin Standards Track [Page 4]
+
+RFC 2348 TFTP Blocksize Option May 1998
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (1998). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Malkin & Harkin Standards Track [Page 5]
+
diff --git a/lib/tftpy.py b/lib/tftpy.py
new file mode 100755
index 0000000..a881dfe
--- /dev/null
+++ b/lib/tftpy.py
@@ -0,0 +1,497 @@
+#!/usr/bin/python
+
+"""This library implements the tftp protocol, based on rfc 1350.
+http://www.faqs.org/rfcs/rfc1350.html
+At the moment it implements only a client class.
+"""
+
+import struct, random, socket, sys, logging, time
+from optparse import OptionParser
+
+# Make sure that this is at least Python 2.4
+verlist = sys.version_info
+if not verlist[0] >= 2 or not verlist[1] >= 4:
+ raise AssertionError, "Requires at least Python 2.4"
+
+# Change this as desired. FIXME - make this a command-line arg
+LOG_LEVEL = logging.INFO
+MIN_BLKSIZE = 8
+DEF_BLKSIZE = 512
+MAX_BLKSIZE = 65536
+SOCK_TIMEOUT = 5
+MAX_DUPS = 20
+
+# Initialize the logger.
+logging.basicConfig(
+ level=LOG_LEVEL,
+ format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
+ datefmt='%m-%d %H:%M')
+logger = logging.getLogger('tftplib')
+
+class TftpException(Exception):
+ pass
+
+def tftpassert(condition, msg):
+ if not condition:
+ raise TftpException, msg
+
+class TftpPacket(object):
+ def __init__(self):
+ self.opcode = 0
+ self.buffer = None
+
+ def encode(self):
+ """The encode method of a TftpPacket takes keyword arguments specific
+ to the type of packet, and packs an appropriate buffer in network-byte
+ order suitable for sending over the wire.
+
+ This is an abstract method."""
+ raise NotImplementedError, "Abstract method"
+
+ def decode(self):
+ """The decode method of a TftpPacket takes a buffer off of the wire in
+ network-byte order, and decodes it, populating internal properties as
+ appropriate. This can only be done once the first 2-byte opcode has
+ already been decoded, but the data section does include the entire
+ datagram.
+
+ This is an abstract method."""
+ raise NotImplementedError, "Abstract method"
+
+class TftpPacketInitial(TftpPacket):
+ """This class is a common parent class for the RRQ and WRQ packets, as they share
+ quite a bit of code."""
+ def __init__(self):
+ TftpPacket.__init__(self)
+ self.filename = None
+ self.mode = None
+ self.options = {}
+
+ def encode(self):
+ """Encode the packet's buffer from the instance variables."""
+ tftpassert(self.filename, "filename required in initial packet")
+ tftpassert(self.mode, "mode required in initial packet")
+
+ format = "!H"
+ length = len(self.filename)
+ format += "%ds" % length
+ format += "B"
+ if self.mode == "octet":
+ format += "5s"
+ else:
+ raise AssertionError, "Unsupported mode: %s" % mode
+ format += "B"
+ logger.debug("format is %s" % format)
+ logger.debug("size of struct is %d" % struct.calcsize(format))
+
+ self.buffer = struct.pack(format, self.opcode, self.filename, 0, self.mode, 0)
+ return self
+
+ def decode(self):
+ tftpassert(self.buffer, "Can't decode, buffer is empty")
+
+ # FIXME - this shares a lot of code with decode_with_options
+ nulls = 0
+ # 2 byte opcode, followed by filename and mode strings, optionally followed
+ # by options.
+ format = ""
+ nulls = length = tlength = 0
+ logger.debug("about to iterate buffer counting nulls")
+ for c in self.buffer:
+ if ord(c) == 0:
+ nulls += 1
+ logger.debug("found a null at length %d, now have %d" % (length, nulls))
+ length = 0
+ format += "%dsx" % length
+ # At 2 nulls, we want to mark that position for decoding.
+ if nulls == 2:
+ break
+ length += 1
+ tlength += 1
+ logger.debug("hopefully found end of mode at length %d" % tlength)
+ # length should now be the end of the mode.
+ tftpassert(nulls == 2, "malformed packet")
+ shortbuf = self.buffer[2:tlength]
+ mystruct = struct.unpack(format, shortbuf)
+ for key in mystruct:
+ logger.debug("option name is %s, value is %s" % (key, mystruct[key]))
+
+ tftpassert(len(mystruct) == 2, "malformed packet")
+ self.options = self.decode_with_options(self.buffer[tlength:])
+ return self
+
+ def decode_with_options(self, buffer):
+ """This method decodes the section of the buffer that contains an
+ unknown number of options. It returns a dictionary of option names and
+ values."""
+ nulls = 0
+ format = ""
+ options = {}
+
+ # Count the nulls in the buffer. Each one terminates a string.
+ self.debug("about to iterate options buffer counting nulls")
+ length = 0
+ for c in buffer:
+ if ord(c) == 0:
+ self.debug("found a null at length %d" % length)
+ if length > 0:
+ format += "%dsx" % length
+ length = 0
+ else:
+ raise TftpException, "Invalid options buffer"
+ length += 1
+
+ # Unpack the buffer.
+ mystruct = struct.unpack(format, buffer)
+ for key in mystruct:
+ self.debug("option name is %s, value is %s" % (key, mystruct[key]))
+
+ tftpassert(len(mystruct) % 2 == 0, "packet with odd number of option/value pairs")
+
+ for i in range(0, len(mystruct), 2):
+ options[mystruct[i]] = mystruct[i+1]
+
+ return options
+
+class TftpPacketRRQ(TftpPacketInitial):
+ """
+ 2 bytes string 1 byte string 1 byte
+ -----------------------------------------------
+RRQ/ | 01/02 | Filename | 0 | Mode | 0 |
+WRQ -----------------------------------------------
+ """
+ def __init__(self):
+ TftpPacketInitial.__init__(self)
+ self.opcode = 1
+
+class TftpPacketWRQ(TftpPacketInitial):
+ """
+ 2 bytes string 1 byte string 1 byte
+ -----------------------------------------------
+RRQ/ | 01/02 | Filename | 0 | Mode | 0 |
+WRQ -----------------------------------------------
+ """
+ def __init__(self):
+ TftpPacketInitial.__init__(self)
+ self.opcode = 2
+
+class TftpPacketDAT(TftpPacket):
+ """
+ 2 bytes 2 bytes n bytes
+ ---------------------------------
+DATA | 03 | Block # | Data |
+ ---------------------------------
+ """
+ def __init__(self):
+ TftpPacket.__init__(self)
+ self.opcode = 3
+ self.blocknumber = 0
+ self.data = None
+
+ def encode(self):
+ """Encode the DAT packet. This method populates self.buffer, and returns
+ self for easy method chaining."""
+ tftpassert(len(self.data) > 0, "no point encoding empty data packet")
+ format = "!HH%ds" % len(self.data)
+ self.buffer = struct.pack(format, self.opcode, self.blocknumber, self.data)
+ return self
+
+ def decode(self):
+ """Decode self.buffer into instance variables. It returns self for
+ easy method chaining."""
+ # We know the first 2 bytes are the opcode. The second two are the
+ # block number.
+ (self.blocknumber,) = struct.unpack("!H", self.buffer[2:4])
+ logger.info("decoding DAT packet, block number %d" % self.blocknumber)
+ logger.debug("should be %d bytes in the packet total" % len(self.buffer))
+ # Everything else is data.
+ self.data = self.buffer[4:]
+ logger.debug("found %d bytes of data" \
+ % len(self.data))
+ return self
+
+class TftpPacketACK(TftpPacket):
+ """
+ 2 bytes 2 bytes
+ -------------------
+ACK | 04 | Block # |
+ --------------------
+ """
+ def __init__(self):
+ TftpPacket.__init__(self)
+ self.opcode = 4
+ self.blocknumber = 0
+
+ def encode(self):
+ logger.debug("encoding ACK: opcode = %d, block = %d" \
+ % (self.opcode, self.blocknumber))
+ self.buffer = struct.pack("!HH", self.opcode, self.blocknumber)
+ return self
+
+ def decode(self):
+ self.opcode, self.blocknumber = struct.unpack("!HH", self.buffer)
+ logger.debug("decoded ACK packet: opcode = %d, block = %d" \
+ % (self.opcode, self.blocknumber))
+ return self
+
+class TftpPacketERR(TftpPacket):
+ """
+ 2 bytes 2 bytes string 1 byte
+ ----------------------------------------
+ERROR | 05 | ErrorCode | ErrMsg | 0 |
+ ----------------------------------------
+ Error Codes
+
+ Value Meaning
+
+ 0 Not defined, see error message (if any).
+ 1 File not found.
+ 2 Access violation.
+ 3 Disk full or allocation exceeded.
+ 4 Illegal TFTP operation.
+ 5 Unknown transfer ID.
+ 6 File already exists.
+ 7 No such user.
+ """
+ def __init__(self):
+ TftpPacket.__init__(self)
+ self.opcode = 5
+ self.errorcode = 0
+ self.errmsg = None
+ self.errmsgs = {
+ 1: "File not found",
+ 2: "Access violation",
+ 3: "Disk full or allocation exceeded",
+ 4: "Illegal TFTP operation",
+ 5: "Unknown transfer ID",
+ 6: "File already exists",
+ 7: "No such user"
+ }
+
+ def encode(self):
+ """Encode the DAT packet based on instance variables, populating self.buffer,
+ returning self."""
+ format = "!HH%dsx" % len(self.errmsgs[self.errorcode])
+ self.debug("encoding ERR packet with format %s" % format)
+ self.buffer = struct.pack(format,
+ self.opcode,
+ self.errorcode,
+ self.errmsgs[self.errorcode])
+ return self
+
+ def decode(self):
+ "Decode self.buffer, populating instance variables and return self."
+ tftpassert(len(self.buffer) >= 5, "malformed ERR packet")
+ format = "!HH%dsx" % len(self.buffer)-5
+ self.opcode, self.errorcode, self.errmsg = struct.unpack(format, self.buffer)
+ logger.error("ERR packet - errorcode: %d, message: %s" \
+ % (errorcode, self.errmsg))
+ return self
+
+class TftpPacketFactory(object):
+ """This class generates TftpPacket objects."""
+ def __init__(self):
+ self.classes = {
+ 1: TftpPacketRRQ,
+ 2: TftpPacketWRQ,
+ 3: TftpPacketDAT,
+ 4: TftpPacketACK,
+ 5: TftpPacketERR
+ }
+
+ def create(self, opcode):
+ tftpassert(self.classes.has_key(opcode), "Unsupported opcode: %d" % opcode)
+ packet = self.classes[opcode]()
+ logger.debug("packet is %s" % packet)
+ return packet
+
+ def parse(self, buffer):
+ """This method is used to parse an existing datagram into its
+ corresponding TftpPacket object."""
+ logger.debug("parsing a %d byte packet" % len(buffer))
+ (opcode,) = struct.unpack("!H", buffer[:2])
+ logger.debug("opcode is %d" % opcode)
+ packet = self.create(opcode)
+ packet.buffer = buffer
+ return packet.decode()
+
+class Tftp(object):
+ """This class is the base class for the tftp client and server. Any shared
+ code should be in this class."""
+ def __init__(self):
+ self.options = None
+
+class TftpClient(Tftp):
+ """This class is an implementation of a tftp client."""
+ def __init__(self, host, port, options):
+ """This constructor returns an instance of TftpClient, taking the
+ remote host, the remote port, and the filename to fetch."""
+ Tftp.__init__(self)
+ self.host = host
+ self.port = port
+ self.options = options
+
+ def download(self, filename, output, packethook=None):
+ """This method initiates a tftp download from the configured remote
+ host, requesting the filename passed."""
+ # Open the output file.
+ outputfile = open(output, "wb")
+ recvpkt = None
+ curblock = 0
+ dups = {}
+ start_time = time.time()
+ bytes = 0
+
+ tftp_factory = TftpPacketFactory()
+ sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ sock.settimeout(SOCK_TIMEOUT)
+
+ logger.debug("Sending tftp download request to %s" % self.host)
+ pkt = TftpPacketRRQ()
+ pkt.filename = filename
+ pkt.mode = "octet" # FIXME - shouldn't hardcode this
+ sock.sendto(pkt.encode().buffer, (self.host, self.port))
+
+ # FIXME - need to do option negotiation here
+
+ # Read the initial response datagram to see if we're in business.
+ (buffer, (raddress, rport)) = sock.recvfrom(MAX_BLKSIZE)
+ recvpkt = tftp_factory.parse(buffer)
+
+ while isinstance(recvpkt, TftpPacketDAT):
+ logger.debug("Received %d bytes from %s:%s" \
+ % (len(buffer), raddress, rport))
+ # FIXME - check sender port and ip address
+ # FIXME - can we refactor this into below?
+ logger.debug("recvpkt.blocknumber = %d" % recvpkt.blocknumber)
+ logger.debug("curblock = %d" % curblock)
+ if recvpkt.blocknumber == curblock+1:
+ logger.debug("good, received block %d in sequence" % recvpkt.blocknumber)
+ curblock += 1
+ # ACK the packet, and save the data.
+ logger.info("sending ACK to block %d" % curblock)
+ logger.debug("ip = %s, port = %s" % (self.host, self.port))
+ ackpkt = TftpPacketACK()
+ ackpkt.blocknumber = curblock
+ sock.sendto(ackpkt.encode().buffer, (self.host, self.port))
+
+ logger.debug("writing %d bytes to output file" % len(recvpkt.data))
+ outputfile.write(recvpkt.data)
+ bytes += len(recvpkt.data)
+ # If there is a packethook defined, call it.
+ if packethook:
+ packethook(recvpkt)
+ # Check for end-of-file, any less than full data packet.
+ if len(recvpkt.data) < DEF_BLKSIZE:
+ logger.info("end of file detected")
+ break
+
+ elif recvpkt.blocknumber == curblock:
+ logger.warn("dropping duplicate block %d" % curblock)
+ if dups.has_key(curblock):
+ dups[curblock] += 1
+ else:
+ dups[curblock] = 1
+ if dups[curblock] >= MAX_DUPS:
+ raise TftpException, "Max duplicates for block %d reached" % curblock
+ logger.debug("ACKing block %d again, just in case" % curblock)
+ ackpkt = TftpPacketACK()
+ ackpkt.blocknumber = curblock
+ sock.sendto(ackpkt.encode().buffer, (self.host, self.port))
+
+ else:
+ msg = "Whoa! Received block %d but expected %d" % (recvpkt.blocknumber,
+ curblock+1)
+ logger.error(msg)
+ raise TftpException, msg
+
+ (buffer, (raddress, rport)) = sock.recvfrom(MAX_BLKSIZE)
+ logger.info("Received %d bytes from %s:%s" % (len(buffer),
+ raddress,
+ rport))
+ recvpkt = tftp_factory.parse(buffer)
+ # FIXME - check sender port and ip address
+
+ # end while
+ # Check for errors
+ if isinstance(recvpkt, TftpPacketERR):
+ logger.error("received ERR packet")
+
+ end_time = time.time()
+ duration = end_time - start_time
+ outputfile.close()
+ logger.info("Downloaded %d bytes in %d seconds" % (bytes, duration))
+ bps = (bytes * 8.0) / duration
+ kbps = bps / 1024.0
+ logger.info("Average rate: %.2f kbps" % kbps)
+ dupcount = 0
+ for key in dups:
+ dupcount += dups[key]
+ logger.info("Received %d duplicate packets" % dupcount)
+
+def main():
+ usage=""
+ parser = OptionParser(usage=usage)
+ parser.add_option('-t',
+ '--test',
+ action='store_true',
+ dest='test',
+ help='run test case(s)',
+ default=False)
+ parser.add_option('-H',
+ '--host',
+ action='store',
+ dest='host',
+ help='remote host or ip address')
+ parser.add_option('-p',
+ '--port',
+ action='store',
+ dest='port',
+ help='remote port to use (default: 69)',
+ default=69)
+ parser.add_option('-f',
+ '--filename',
+ action='store',
+ dest='filename',
+ help='filename to fetch')
+ parser.add_option('-b',
+ '--blocksize',
+ action='store',
+ dest='blocksize',
+ help='udp packet size to use (default: 512)',
+ default=512)
+ parser.add_option('-o',
+ '--output',
+ action='store',
+ dest='output',
+ help='output file (default: out)',
+ default='out')
+ options, args = parser.parse_args()
+ if options.test:
+ options.host = "216.191.234.113"
+ options.port = 20001
+ options.filename = 'ipp510main.bin'
+ options.output = 'ipp510main.bin'
+ if not options.host or not options.filename:
+ parser.print_help()
+ sys.exit(1)
+
+ class Progress(object):
+ def __init__(self, out):
+ self.progress = 0
+ self.out = out
+ def progresshook(self, pkt):
+ self.progress += len(pkt.data)
+ self.out("Downloaded %d bytes" % self.progress)
+
+ progresshook = Progress(logger.info).progresshook
+
+ tclient = TftpClient(options.host,
+ options.port,
+ options.blocksize)
+ tclient.download(options.filename,
+ options.output,
+ progresshook)
+
+if __name__ == '__main__':
+ main()
diff --git a/lib/tftpy_twisted.py b/lib/tftpy_twisted.py
new file mode 100755
index 0000000..b8a80df
--- /dev/null
+++ b/lib/tftpy_twisted.py
@@ -0,0 +1,19 @@
+#!/usr/bin/python
+
+from twisted.internet import reactor, protocol
+
+class TFTPProtocol(protocol.DatagramProtocol):
+ pass
+
+class TFTPProtocolFactory(protocol.ClientFactory):
+ protocol = TFTPProtocol
+
+def main():
+ host = '216.191.234.113'
+ port = 20001
+
+ reactor.listenUDP(port, TFTPProtocolFactory())
+ reactor.run()
+
+if __name__ == '__main__':
+ main()
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..aa94ed4
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+
+from distutils.core import setup
+
+setup(name='tftpy',
+ version='0.1',
+ description='Python TFTP library',
+ author='Michael P. Soulier',
+ author_email='msoulier@digitaltorque.ca',
+ url='http://digitaltorque.ca',
+ py_modules=['lib/tftpy'],
+ scripts=['bin/tftpy_client.py'],
+ classifiers=[
+ 'Development Status :: Alpha',
+ 'License :: OSI Approved :: CNRI Python License',
+ 'Topic :: Networking :: TFTP',
+ 'Intended Audience :: Developers',
+ 'Operating System :: POSIX',
+ 'Environment :: Console',
+ ]
+ )