1 /**
2 * @file tftp.c
3 *
4 * @brief
5 * The file implements the NET Module TFTP functionality.
6 *
7 * \par
8 * NOTE:
9 * (C) Copyright 2008, Texas Instruments, Inc.
10 *
11 * \par
12 */
13 #include "types.h"
14 #include "iblloc.h"
15 #include "net.h"
16 #include "netif.h"
17 #include "timer.h"
18 #include "stream.h"
19 #include <string.h>
20 #include "net_osal.h"
23 /**********************************************************************
24 *************************** LOCAL Structures *************************
25 **********************************************************************/
27 /**
28 * @brief
29 * The structure describes the TFTP State
30 *
31 * @details
32 * The TFTP client can be in one of the following states which are
33 * described in this structure.
34 */
35 typedef enum TFTP_STATE
36 {
37 /**
38 * @brief This is the initial state of the TFTP client during startup
39 * In this state the TFTP client has sent out the READ Request and has
40 * not yet received a data packet in acknowledgment.
41 */
42 READ_REQUEST = 0x1,
44 /**
45 * @brief This is the data receive state of the TFTP client in which
46 * the TFTP client is receiving data packets from the TFTP server.
47 */
48 DATA_RECEIVE
49 }TFTP_STATE;
51 /**
52 * @brief
53 * The structure describes the TFTP Master Control Block.
54 *
55 * @details
56 * The TFTP Master control block stores information used by the
57 * TFTP module.
58 */
59 typedef struct TFTP_MCB
60 {
61 /**
62 * @brief This describes the state of the TFTP client.
63 */
64 TFTP_STATE state;
66 /**
67 * @brief This is the IP Address of the server from where the file
68 * is downloaded.
69 */
70 IPN server_ip;
72 /**
73 * @brief This is the TFTP socket which is used to communicate
74 * with the UDP module.
75 */
76 Int32 sock;
78 /**
79 * @brief This is the TFTP Timer handle which is used to handle
80 * retransmissions of the READ REQUEST.
81 */
82 Int32 timer;
84 /**
85 * @brief This is the name of the file which is being downloaded.
86 * File Names are typically exchanged through the BOOTP protocol
87 * where the max file name length is 64.
88 */
89 Uint8 filename[64];
91 /**
92 * @brief This is the block number we expect.
93 */
94 Uint16 block_num;
96 /**
97 * @brief This is a generic buffer used by the TFTP module,
98 */
99 Uint8 buffer[TFTP_DATA_SIZE + TFTPHEADER_SIZE];
101 /**
102 * @brief Number of retransmission done.
103 */
104 Uint32 num_retransmits;
105 }TFTP_MCB;
107 /**********************************************************************
108 *************************** GLOBAL Variables *************************
109 **********************************************************************/
111 /**
112 * @brief This is the global master control block for the TFTP
113 * module and keeps track of all the information regarding TFTP.
114 */
115 TFTP_MCB tftpmcb;
117 /**********************************************************************
118 **************************** TFTP Functions **************************
119 **********************************************************************/
121 /**
122 * @b Description
123 * @n
124 * The function cleans up the TFTP Client. This can be called
125 * on an ERROR or SUCCESSFUL exit.
126 *
127 * @retval
128 * Not Applicable.
129 */
130 static void tftp_cleanup (void)
131 {
132 /* Close any open timers. */
133 timer_delete (tftpmcb.timer);
134 tftpmcb.timer = -1;
136 /* Close the UDP Sockets. */
137 udp_sock_close (tftpmcb.sock);
139 /* Close the STREAM module */
140 stream_close ();
141 return;
142 }
144 /**
145 * @b Description
146 * @n
147 * The function creates the TFTP read request and populates it
148 * in the internal TFTP buffer.
149 *
150 * @retval
151 * Size of the TFTP Read Request.
152 */
153 static Int32 tftp_create_read_req (Uint8* filename)
154 {
155 Uint16* ptr_op;
156 Int32 index = 0;
158 /* Create the Read Request: Populate the Request op type */
159 ptr_op = (Uint16 *)&tftpmcb.buffer[0];
160 *ptr_op = htons(TFTP_OPCODE_RRQ);
162 /* Copy the file name */
163 index = 0;
164 while (filename[index] != 0)
165 {
166 tftpmcb.buffer[index + 2] = filename[index];
167 index++;
168 }
170 /* Null Terminate the file name. */
171 tftpmcb.buffer[index + 2] = 0;
172 index = index + 3;
174 /* Copy the transfer mode. */
175 tftpmcb.buffer[index++] = (Uint8)'o';
176 tftpmcb.buffer[index++] = (Uint8)'c';
177 tftpmcb.buffer[index++] = (Uint8)'t';
178 tftpmcb.buffer[index++] = (Uint8)'e';
179 tftpmcb.buffer[index++] = (Uint8)'t';
180 tftpmcb.buffer[index++] = (Uint8)0;
182 /* Return the size of the read request */
183 return index;
184 }
186 /**
187 * @b Description
188 * @n
189 * The function is used to send an ACK back to TFTP Server.
190 *
191 * @retval
192 * Not Applicable
193 */
194 static void tftp_send_ack(void)
195 {
196 TFTPHDR* ptr_tftphdr;
198 /* Initialize the data buffer. */
199 netMemset ((void *)&tftpmcb.buffer[0], 0, TFTP_DATA_SIZE + TFTPHEADER_SIZE);
201 /* Create an ACK packet which is to be sent out. Get the pointer to the
202 * TFTP Header. */
203 ptr_tftphdr = (TFTPHDR *)&tftpmcb.buffer[0];
204 ptr_tftphdr->opcode = htons (TFTP_OPCODE_ACK);
205 ptr_tftphdr->block = htons (tftpmcb.block_num);
207 /* The packet has been populated; send it to the server; this transfer is now done
208 * over the data socket. */
209 udp_sock_send (tftpmcb.sock, (Uint8 *)ptr_tftphdr, TFTPHEADER_SIZE);
211 /* Increment the block number. */
212 tftpmcb.block_num++;
213 return;
214 }
216 /**
217 * @b Description
218 * @n
219 * The function is the timer expiration for TFTP.
220 *
221 * @retval
222 * Not Applicable
223 */
224 static void tftp_timer_expiry (void)
225 {
226 Int32 len;
228 /* Determine the state of the TFTP. */
229 if (tftpmcb.state == READ_REQUEST)
230 {
231 /* We were sending out READ Request and have not received a response
232 * Increment the number of retransmissions which have been done. */
233 tftpmcb.num_retransmits++;
235 /* Check if we have exceeded the max allowed? */
236 if (tftpmcb.num_retransmits > MAX_TFTP_RETRANSMITS)
237 {
238 /* FATAL Error: We need to close the TFTP Client and signal Error to the NET Boot Module. */
239 mprintf ("Error: TFTP READ REQ Retransmissions have exceeded\n");
240 tftp_cleanup ();
241 net_set_error();
242 return;
243 }
245 /* Create the TFTP Read Request */
246 len = tftp_create_read_req (&tftpmcb.filename[0]);
248 /* Send out the READ Request again. */
249 udp_sock_send (tftpmcb.sock, (Uint8 *)&tftpmcb.buffer[0], len);
250 }
251 else
252 {
253 /* We were receiving data from the TFTP Server and there was a timeout. This can
254 * happen only if we have not received any data from the TFTP server. */
255 mprintf ("Error: TFTP server is down; no packet received.\n");
256 tftp_cleanup();
257 net_set_error();
258 return;
259 }
260 return;
261 }
263 /**
264 * @b Description
265 * @n
266 * This is a call back function registered with the UDP module to
267 * be invoked when a TFTP packet is received.
268 *
269 * @param[in] sock
270 * This is the socket handle on which packet was received.
271 * @param[in] ptr_data
272 * This is the pointer to the TFTP data payload.
273 * @param[in] num_bytes
274 * This is the number of bytes of TFTP data received.
275 *
276 * @retval
277 * Success - 0
278 * @retval
279 * Error - <0
280 */
281 static Int32 tftp_receive (Int32 sock, Uint8* ptr_data, Int32 num_bytes)
282 {
283 TFTPHDR* ptr_tftphdr;
284 UDPHDR* ptr_udphdr;
285 Uint16 src_port;
286 SOCKET socket;
288 /* Get the pointer to the TFTP Header. */
289 ptr_tftphdr = (TFTPHDR *)ptr_data;
291 /* Process the received packet depending on the type of packet received */
292 switch (ntohs(ptr_tftphdr->opcode))
293 {
294 case TFTP_OPCODE_DATA:
295 {
296 /* Is this the first data packet we have received? */
297 if (tftpmcb.state == READ_REQUEST)
298 {
299 /* YES. In this case the socket on which the request was sent has completed
300 * its job. Lets shut it down and open another one for the data transfers. */
301 udp_sock_close (sock);
303 /* We need to get the source port from where the data was received.
304 * This information is present in the UDP layer. This is required to
305 * open the data socket. */
306 ptr_udphdr = (UDPHDR *)(ptr_data - sizeof(UDPHDR));
307 src_port = ntohs(ptr_udphdr->SrcPort);
309 /* Populate the socket structure and register this with the UDP module. */
310 socket.local_port = 1234;
311 socket.remote_port = src_port;
312 socket.remote_address = tftpmcb.server_ip;
313 socket.app_fn = tftp_receive;
315 /* Move to the DATA State. */
316 tftpmcb.state = DATA_RECEIVE;
317 tftpmcb.num_retransmits = 0;
319 /* Close the timer. */
320 timer_delete (tftpmcb.timer);
321 tftpmcb.timer = -1;
323 /* Open the TFTP data socket. */
324 tftpmcb.sock = udp_sock_open (&socket);
325 if (tftpmcb.sock < 0)
326 {
327 /* Error: Data Socket open failed. */
328 mprintf ("Error: TFTP Data Socket Open Failed\n");
329 tftp_cleanup();
330 net_set_error();
331 return -1;
332 }
333 }
335 /* We are in the DATA State: Start the TFTP Server Keep Alive Timer. This timer
336 * keeps track of the TFTP Server and ensures it does not die behind us. This will
337 * help detect that error. */
338 timer_delete (tftpmcb.timer);
339 tftpmcb.timer = timer_add (TFTP_SERVER_TIMEOUT, tftp_timer_expiry);
340 if (tftpmcb.timer < 0)
341 {
342 /* Timer creation failed. */
343 mprintf ("Error: TFTP Timer creation failed\n");
344 tftp_cleanup();
345 net_set_error();
346 return -1;
347 }
349 /* Received a data block. Ensure that the block number matches what we expect! */
350 if (ntohs(ptr_tftphdr->block) != tftpmcb.block_num)
351 {
352 /* There is a block number mismatch. This could occur if the ACK we sent was lost.
353 * Increment the number of retransmissions. */
354 tftpmcb.num_retransmits++;
355 if (tftpmcb.num_retransmits > MAX_TFTP_RETRANSMITS)
356 {
357 /* OK; we resent the ACK multiple times & the server still kept sending the
358 * same packet back. We just give up now. */
359 mprintf ("Error: TFTP ACK Retransmits Exceeded\n");
360 tftp_cleanup();
361 net_set_error();
362 return -1;
363 }
365 /* We need to send out the ACK for the previous 'block' */
366 tftpmcb.block_num = tftpmcb.block_num - 1;
368 /* Send the ACK out again. */
369 tftp_send_ack ();
371 /* We dont need to process this packet since we had already picked it up. */
372 return 0;
373 }
375 /* The packet looks good. Reset the number of retransmissions. */
376 tftpmcb.num_retransmits = 0;
378 /* Pass the received data packet to the STREAM Module.
379 * We need to skip the TFTP Header. */
380 if (stream_write ((ptr_data + TFTPHEADER_SIZE), (num_bytes - TFTPHEADER_SIZE)) == 0)
381 {
382 /* Packet has been copied successfully into the STREAM Buffer. */
383 tftp_send_ack();
384 }
385 else
386 {
387 /* Packet could not be copied; let the server retransmit the packet
388 * because we did not send the ACK. */
389 }
391 /* Determine if the TFTP file transfer is complete or not?
392 * If the received number of bytes is less than the TFTP Data Size this
393 * indicates that the transfer is successfully completed. */
394 if (num_bytes < (TFTP_DATA_SIZE + TFTPHEADER_SIZE))
395 {
396 /* Successfully downloaded the file */
397 tftp_cleanup();
398 }
399 break;
400 }
401 default:
402 {
403 /* Control comes here for ERROR, ACK and WRQ which are all indicate
404 * failure. ERROR packet is the only expected failure which is mentioned
405 * in the RFC. All other packets are violation of the RFC. Both these
406 * cases are handled similarly. */
407 mprintf ("Error: TFTP Error Packet Received\n");
408 tftp_cleanup();
409 net_set_error();
411 /* Return Error. */
412 return -1;
413 }
414 }
415 return 0;
416 }
418 /**
419 * @b Description
420 * @n
421 * The function gets a file from the TFTP Server. The function
422 * simply initiates the transfer. Successful completion of this
423 * API does not gurantee that the file was downloaded.
424 *
425 * @param[in] server_ip
426 * TFTP Server IP address from where the file is downloaded.
427 * @param[in] filename
428 * Name of the file to be downloaded.
429 *
430 * @retval
431 * Success - 0
432 * @retval
433 * Error - <0
434 */
435 Int32 tftp_get_file (IPN server_ip, Int8* filename)
436 {
437 SOCKET socket;
438 Int32 index = 0;
440 /* Basic Validations: Ensure the parameters passed are correct. */
441 if ((server_ip == 0) || (filename == NULL))
442 {
443 /* Error: Invalid parameters passed. Stop the network boot module. */
444 net_set_error();
445 return -1;
446 }
448 /* Open the stream module. */
449 if (stream_open (TFTP_DATA_SIZE) < 0)
450 {
451 /* Error: Unable to open the stream device. */
452 net_set_error();
453 return -1;
454 }
456 /* Initialize the TFTP MCB at this stage... */
457 netMemset ((void *)&tftpmcb, 0, sizeof(TFTP_MCB));
459 /* Populate the socket structure and register this with the UDP module. */
460 socket.local_port = 1234;
461 socket.remote_port = TFTP_SERVER_PORT;
462 socket.remote_address = server_ip;
463 socket.app_fn = tftp_receive;
465 /* Open the TFTP Control socket. */
466 tftpmcb.sock = udp_sock_open (&socket);
467 if (tftpmcb.sock < 0)
468 {
469 /* ERROR: UDP Socket could not be opened. */
470 stream_close();
471 net_set_error();
472 return -1;
473 }
475 /* Remember the parameters passed to the TFTP. */
476 tftpmcb.server_ip = server_ip;
478 /* Copy the file name over... */
479 while (filename[index] != 0)
480 {
481 tftpmcb.filename[index] = filename[index];
482 index++;
483 }
485 /* Initialize the block number expected. */
486 tftpmcb.block_num = 1;
488 /* Create the TFTP Read Request. */
489 index = tftp_create_read_req ((Uint8 *)filename);
491 /* Initialize the TFTP Client state */
492 tftpmcb.state = READ_REQUEST;
494 /* Initialize the TFTP Timer. */
495 tftpmcb.timer = timer_add (TFTP_TIMEOUT, tftp_timer_expiry);
496 if (tftpmcb.timer < 0)
497 {
498 /* Error: TFTP Timer Creation Failed. TFTP is not operational. */
499 mprintf ("Error: TFTP Timer Creation Failed\n");
500 tftp_cleanup ();
501 net_set_error();
502 return -1;
503 }
505 /* The packet has been populated; send it to the server. */
506 udp_sock_send (tftpmcb.sock, (Uint8 *)&tftpmcb.buffer[0], index);
508 /* Send out the TFTP Read request. */
509 return 0;
510 }