Home | History | Annotate | Download | only in TftpServer
      1 /** @file
      2   Definitions for the TFTP server.
      3 
      4   Copyright (c) 2011, 2012, Intel Corporation
      5   All rights reserved. This program and the accompanying materials
      6   are licensed and made available under the terms and conditions of the BSD License
      7   which accompanies this distribution.  The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #ifndef _TFTP_SERVER_H_
     16 #define _TFTP_SERVER_H_
     17 
     18 #include <errno.h>
     19 #include <stdio.h>
     20 #include <stdlib.h>
     21 #include <string.h>
     22 #include <Uefi.h>
     23 
     24 #include <Guid/EventGroup.h>
     25 
     26 #include <Library/BaseMemoryLib.h>
     27 #include <Library/DebugLib.h>
     28 #include <Library/MemoryAllocationLib.h>
     29 #include <Library/PcdLib.h>
     30 #include <Library/TimerLib.h>
     31 #include <Library/UefiApplicationEntryPoint.h>
     32 #include <Library/UefiBootServicesTableLib.h>
     33 #include <Library/UefiLib.h>
     34 #include <Protocol/BlockIo.h>
     35 
     36 #include <netinet/in.h>
     37 #include <netinet6/in6.h>
     38 
     39 #include <sys/EfiSysCall.h>
     40 #include <sys/poll.h>
     41 #include <sys/socket.h>
     42 #include <sys/stat.h>
     43 
     44 //------------------------------------------------------------------------------
     45 //  Macros
     46 //------------------------------------------------------------------------------
     47 
     48 #if defined(_MSC_VER)           /* Handle Microsoft VC++ compiler specifics. */
     49 #define DBG_ENTER()             DEBUG (( DEBUG_ENTER_EXIT, "Entering " __FUNCTION__ "\n" )) ///<  Display routine entry
     50 #define DBG_EXIT()              DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ "\n" ))  ///<  Display routine exit
     51 #define DBG_EXIT_DEC(Status)    DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ ", Status: %d\n", Status ))      ///<  Display routine exit with decimal value
     52 #define DBG_EXIT_HEX(Status)    DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ ", Status: 0x%08x\n", Status ))  ///<  Display routine exit with hex value
     53 #define DBG_EXIT_STATUS(Status) DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ ", Status: %r\n", Status ))      ///<  Display routine exit with status value
     54 #define DBG_EXIT_TF(Status)     DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ ", returning %s\n", (FALSE == Status) ? L"FALSE" : L"TRUE" ))  ///<  Display routine with TRUE/FALSE value
     55 #else   //  _MSC_VER
     56 #define DBG_ENTER()
     57 #define DBG_EXIT()
     58 #define DBG_EXIT_DEC(Status)
     59 #define DBG_EXIT_HEX(Status)
     60 #define DBG_EXIT_STATUS(Status)
     61 #define DBG_EXIT_TF(Status)
     62 #endif  //  _MSC_VER
     63 
     64 #define DIM(x)    ( sizeof ( x ) / sizeof ( x[0] ))   ///<  Compute the number of entries in an array
     65 
     66 //------------------------------------------------------------------------------
     67 //  Constants
     68 //------------------------------------------------------------------------------
     69 
     70 #define ACK_SHIFT               4           ///<  Number of samples in ACK average
     71 
     72 #define DEBUG_WINDOW            0x00000001  ///<  Display the window messages
     73 #define DEBUG_TX_PACKET         0x00000002  ///<  Display the transmit packet messages
     74 #define DEBUG_FILE_BUFFER       0x00000004  ///<  Display the file buffer messages
     75 #define DEBUG_SERVER_TIMER      0x00000008  ///<  Display the socket poll messages
     76 #define DEBUG_TFTP_REQUEST      0x00000010  ///<  Display the TFTP request messages
     77 #define DEBUG_PORT_WORK         0x00000020  ///<  Display the port work messages
     78 #define DEBUG_SOCKET_POLL       0x00000040  ///<  Display the socket poll messages
     79 #define DEBUG_TFTP_PORT         0x00000080  ///<  Display the TFTP port messages
     80 #define DEBUG_TX                0x00000100  ///<  Display transmit messages
     81 #define DEBUG_RX                0x00000200  ///<  Display receive messages
     82 #define DEBUG_TFTP_ACK          0x00000400  ///<  Display the TFTP ACK messages
     83 #define DEBUG_ENTER_EXIT        0x00000800  ///<  Display entry and exit messages
     84 
     85 #define MAX_PACKETS             8           ///<  Maximum number of packets in the window
     86 
     87 #define TFTP_PORT_POLL_DELAY  ( 2 * 1000 )  ///<  Delay in milliseconds for attempts to open the TFTP port
     88 #define CLIENT_POLL_DELAY     50            ///<  Delay in milliseconds between client polls
     89 
     90 #define TPL_TFTP_SERVER        TPL_CALLBACK ///<  TPL for routine synchronization
     91 
     92 /**
     93   Verify new TPL value
     94 
     95   This macro which is enabled when debug is enabled verifies that
     96   the new TPL value is >= the current TPL value.
     97 **/
     98 #ifdef VERIFY_TPL
     99 #undef VERIFY_TPL
    100 #endif  //  VERIFY_TPL
    101 
    102 #if !defined(MDEPKG_NDEBUG)
    103 
    104 #define VERIFY_TPL(tpl)                           \
    105 {                                                 \
    106   EFI_TPL PreviousTpl;                            \
    107                                                   \
    108   PreviousTpl = gBS->RaiseTPL ( TPL_HIGH_LEVEL ); \
    109   gBS->RestoreTPL ( PreviousTpl );                \
    110   if ( PreviousTpl > tpl ) {                      \
    111     DEBUG (( DEBUG_ERROR, "Current TPL: %d, New TPL: %d\r\n", PreviousTpl, tpl ));  \
    112     ASSERT ( PreviousTpl <= tpl );                \
    113   }                                               \
    114 }
    115 
    116 #else   //  MDEPKG_NDEBUG
    117 
    118 #define VERIFY_TPL(tpl)
    119 
    120 #endif  //  MDEPKG_NDEBUG
    121 
    122 #define TFTP_SERVER_SIGNATURE       SIGNATURE_32('T','F','T','P') ///<  TSDT_TFTP_SERVER memory signature
    123 
    124 //
    125 //  See: http://www.rfc-editor.org/rfc/pdfrfc/rfc1350.txt.pdf
    126 //
    127 //  TFTP Operations
    128 //
    129 
    130 #define TFTP_OP_READ_REQUEST      1     ///<  Read request, zero terminated file name, zero terminated mode
    131 #define TFTP_OP_WRITE_REQUEST     2     ///<  Write request, zero terminated file name, zero terminated mode
    132 #define TFTP_OP_DATA              3     ///<  Data block, end-of-file indicated by short block
    133 #define TFTP_OP_ACK               4     ///<  ACK block number
    134 #define TFTP_OP_ERROR             5     ///<  Error number and explaination
    135 #define TFTP_OP_OACK              6     ///<  ACK the options
    136 
    137 #define TFTP_MAX_BLOCK_SIZE       4096  ///<  Maximum block size
    138 
    139 #define TFTP_ERROR_SEE_MSG          0   ///<  See the error message
    140 #define TFTP_ERROR_NOT_FOUND        1   ///<  File not found
    141 #define TFTP_ERROR_ACCESS_VIOLATION 2   ///<  Access violation
    142 #define TFTP_ERROR_DISK_FULL        3   ///<  Disk full
    143 #define TFTP_ERROR_ILLEGAL_OP       4   ///<  Illegal operation
    144 #define TFTP_ERROR_UNKNOWN_XFER_ID  5   ///<  Unknown transfer ID
    145 #define TFTP_ERROR_FILE_EXISTS      6   ///<  File already exists
    146 #define TFTP_ERROR_NO_SUCH_USER     7   ///<  No such user
    147 
    148 //------------------------------------------------------------------------------
    149 //  Data Types
    150 //------------------------------------------------------------------------------
    151 
    152 /**
    153   Packet structure
    154 **/
    155 typedef struct _TFTP_PACKET TFTP_PACKET;
    156 typedef struct _TFTP_PACKET {
    157   TFTP_PACKET * pNext;          ///<  Next packet in list
    158   UINT64    TxTime;             ///<  Time the transmit was performed
    159   ssize_t   TxBytes;            ///<  Bytes in the TX buffer
    160   UINT32    RetryCount;         ///<  Number of transmissions
    161   UINT16    BlockNumber;        ///<  Block number of this packet
    162   UINT8     TxBuffer[ 2 + 2 + TFTP_MAX_BLOCK_SIZE ];  ///<  Transmit buffer
    163 } GCC_TFTP_PACKET;
    164 
    165 /**
    166   Port control structure
    167 **/
    168 typedef struct _TSDT_CONNECTION_CONTEXT TSDT_CONNECTION_CONTEXT;
    169 typedef struct _TSDT_CONNECTION_CONTEXT {
    170   //
    171   //  Remote connection management
    172   //
    173   TSDT_CONNECTION_CONTEXT * pNext;    ///<  Next context in the connection list
    174   struct sockaddr_in6 RemoteAddress;  ///<  Remote address
    175   int SocketFd;                       ///<  Socket file descriptor
    176 
    177   //
    178   //  File management parameters
    179   //
    180   FILE * File;                  ///<  NULL while file is closed
    181   UINT64 LengthInBytes;         ///<  Size of the file
    182   UINT64 BytesRemaining;        ///<  Number of bytes remaining to be sent
    183   UINT64 BytesToSend;           ///<  Number of bytes to send
    184   UINT64 ValidBytes;            ///<  Number of valid bytes in the buffer
    185   BOOLEAN bEofSent;             ///<  End of file sent
    186   UINT8 * pFill;                ///<  Next portion of the buffer to fill
    187   UINT8 * pBuffer;              ///<  Pointer into the file data
    188   UINT8 * pEnd;                 ///<  End of the file data
    189   UINT8 FileData[ 2 * MAX_PACKETS * TFTP_MAX_BLOCK_SIZE ];  ///<  File data to send
    190   UINT64 TimeStart;             ///<  Start of file transfer
    191 
    192   //
    193   //  TFTP management parameters
    194   //
    195   UINT16 BlockNumber;           ///<  Next block to be transmitted
    196   UINT32 BlockSize;             ///<  Negotiated block size
    197 
    198   //
    199   //  Window management
    200   //
    201   UINT32 AckCount;              ///<  Number of ACKs to receive before increasing the window
    202   UINT32 PacketsInWindow;       ///<  Number of packets in the window
    203   UINT32 Threshold;             ///<  Size of window when ACK count becomes logrithmic
    204   UINT32 WindowSize;            ///<  Size of the transmit window
    205   UINT64 MaxTimeout;            ///<  Maximum number of seconds to wait before retransmission
    206   UINT64 Rtt2x;                 ///<  Twice the average round trip time in nanoseconds
    207 
    208   //
    209   //  Buffer management
    210   //
    211   TFTP_PACKET * pFreeList;      ///<  List of free packets
    212   TFTP_PACKET * pTxHead;        ///<  First packet in the list of packets for transmission
    213   TFTP_PACKET * pTxTail;        ///<  Last packet in the list of packets for transmission
    214   TFTP_PACKET ErrorPacket;      ///<  Error packet
    215   TFTP_PACKET Tx[ MAX_PACKETS ];///<  Transmit packets
    216 }GCC_TSDT_CONNECTION_CONTEXT;
    217 
    218 /**
    219   TFTP server control structure
    220 **/
    221 typedef struct {
    222   UINTN Signature;              ///<  Structure identification
    223 
    224   //
    225   //  Image attributes
    226   //
    227   EFI_HANDLE ImageHandle;       ///<  Image handle
    228 
    229   //
    230   //  Performance management
    231   //
    232   UINT64 ClockFrequency;        ///<  Frequency of the clock
    233   UINT64 Time1;                 ///<  Clock value after rollover
    234   UINT64 Time2;                 ///<  Clock value before rollover
    235   UINT64 RxTime;                ///<  Time when the packet was recevied
    236 
    237   //
    238   //  TFTP port management
    239   //
    240   EFI_EVENT TimerEvent;         ///<  Timer to open TFTP port
    241   int Udpv4Index;               ///<  Entry for UDPv4
    242   int Udpv6Index;               ///<  Entry for UDPv6
    243   int Entries;                  ///<  Number of TFTP ports
    244   struct pollfd TftpPort [ 2 ]; ///<  Poll descriptor for the TFTP ports (UDP4, UDP6)
    245 
    246   //
    247   //  Request management
    248   //
    249   union {
    250     struct sockaddr_in v4;      ///<  UDP4 address
    251     struct sockaddr_in6 v6;     ///<  UDP6 address
    252   } RemoteAddress;              ///<  Remote address
    253   ssize_t RxBytes;              ///<  Receive data length in bytes
    254   UINT8 RxBuffer[ 2 + 2 + TFTP_MAX_BLOCK_SIZE ];  ///<  Receive buffer
    255 
    256   //
    257   //  Client port management
    258   //
    259   TSDT_CONNECTION_CONTEXT * pContextList; ///<  List of connection context structures
    260 } TSDT_TFTP_SERVER;
    261 
    262 //#define SERVER_FROM_SERVICE(a) CR(a, TSDT_TFTP_SERVER, ServiceBinding, TFTP_SERVER_SIGNATURE) ///< Locate DT_LAYER from service binding
    263 
    264 extern TSDT_TFTP_SERVER mTftpServer;
    265 
    266 //------------------------------------------------------------------------------
    267 // Support routines
    268 //------------------------------------------------------------------------------
    269 
    270 /**
    271   Queue data packets for transmission
    272 
    273   @param [in] pContext    Connection context structure address
    274 
    275   @retval TRUE if a read error occurred
    276 
    277 **/
    278 BOOLEAN
    279 PacketFill (
    280   IN TSDT_CONNECTION_CONTEXT * pContext
    281   );
    282 
    283 /**
    284   Free the packet
    285 
    286   @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure
    287   @param [in] pPacket     Address of a ::TFTP_PACKET structure
    288 
    289 **/
    290 VOID
    291 PacketFree(
    292   IN TSDT_CONNECTION_CONTEXT * pContext,
    293   IN TFTP_PACKET * pPacket
    294   );
    295 
    296 /**
    297   Get a packet for transmission
    298 
    299   @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure
    300 
    301   @retval Address of a ::TFTP_PACKET structure
    302 
    303 **/
    304 TFTP_PACKET *
    305 PacketGet (
    306   IN TSDT_CONNECTION_CONTEXT * pContext
    307   );
    308 
    309 /**
    310   Queue the packet for transmission
    311 
    312   @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure
    313   @param [in] pPacket     Address of a ::TFTP_PACKET structure
    314 
    315   @retval TRUE if a transmission error has occurred
    316 
    317 **/
    318 BOOLEAN
    319 PacketQueue (
    320   IN TSDT_CONNECTION_CONTEXT * pContext,
    321   IN TFTP_PACKET * pPacket
    322   );
    323 
    324 /**
    325   Transmit the packet
    326 
    327   @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure
    328   @param [in] pPacket     Address of a ::TFTP_PACKET structure
    329 
    330   @retval EFI_SUCCESS   Message processed successfully
    331 
    332 **/
    333 EFI_STATUS
    334 PacketTx (
    335   IN TSDT_CONNECTION_CONTEXT * pContext,
    336   IN TFTP_PACKET * pPacket
    337   );
    338 
    339 /**
    340   Build and send an error packet
    341 
    342   @param [in] pContext    The context structure address.
    343   @param [in] Error       Error number for the packet
    344   @param [in] pError      Zero terminated error string address
    345 
    346   @retval EFI_SUCCESS     Message processed successfully
    347 
    348 **/
    349 EFI_STATUS
    350 SendError (
    351   IN TSDT_CONNECTION_CONTEXT * pContext,
    352   IN UINT16 Error,
    353   IN UINT8 * pError
    354   );
    355 
    356 /**
    357   Process the TFTP request
    358 
    359   @param [in] pOption   Address of the first zero terminated option string
    360   @param [in] pValue    Address to receive the value
    361 
    362   @retval EFI_SUCCESS   Option translated into a value
    363 
    364 **/
    365 EFI_STATUS
    366 TftpOptionValue (
    367   IN UINT8 * pOption,
    368   IN INT32 * pValue
    369   );
    370 
    371 /**
    372   Process the TFTP request
    373 
    374   @param [in] pTftpServer The TFTP server control structure address.
    375   @param [in] pContext    Connection context structure address
    376   @param [in] SocketFd    Socket file descriptor
    377 
    378 **/
    379 VOID
    380 TftpProcessRequest (
    381   IN TSDT_TFTP_SERVER * pTftpServer,
    382   IN TSDT_CONNECTION_CONTEXT * pContext,
    383   IN int SocketFd
    384   );
    385 
    386 /**
    387   Process the read request
    388 
    389   @param [in] pTftpServer Address of the ::TSDT_TFTP_SERVER structure
    390   @param [in] pContext    Connection context structure address
    391   @param [in] SocketFd    Socket file descriptor
    392 
    393   @retval TRUE if the context should be closed
    394 
    395 **/
    396 BOOLEAN
    397 TftpRead (
    398   IN TSDT_TFTP_SERVER * pTftpServer,
    399   IN TSDT_CONNECTION_CONTEXT * pContext,
    400   IN int SocketFd
    401   );
    402 
    403 /**
    404   Update the window due to the ACK
    405 
    406   @param [in] pTftpServer Address of the ::TSDT_TFTP_SERVER structure
    407   @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure
    408   @param [in] pPacket     Address of a ::TFTP_PACKET structure
    409 
    410 **/
    411 VOID
    412 WindowAck (
    413   IN TSDT_TFTP_SERVER * pTftpServer,
    414   IN TSDT_CONNECTION_CONTEXT * pContext,
    415   IN TFTP_PACKET * pPacket
    416   );
    417 
    418 /**
    419   A timeout has occurred, close the window
    420 
    421   @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure
    422 
    423 **/
    424 VOID
    425 WindowTimeout (
    426   IN TSDT_CONNECTION_CONTEXT * pContext
    427   );
    428 
    429 //------------------------------------------------------------------------------
    430 
    431 #endif  //  _TFTP_SERVER_H_
    432