Merged socket development branch:
[mirror_edk2.git] / AppPkg / Applications / Sockets / TftpServer / TftpServer.h
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_