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 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 *
18 * Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the
21 * distribution.
22 *
23 * Neither the name of Texas Instruments Incorporated nor the names of
24 * its contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 *
39 * \par
40 */
41 #include "types.h"
42 #include "iblloc.h"
43 #include "net.h"
44 #include "netif.h"
45 #include "timer.h"
46 #include "stream.h"
47 #include <string.h>
48 #include "net_osal.h"
51 /**********************************************************************
52 *************************** LOCAL Structures *************************
53 **********************************************************************/
55 /**
56 * @brief
57 * The structure describes the TFTP State
58 *
59 * @details
60 * The TFTP client can be in one of the following states which are
61 * described in this structure.
62 */
63 typedef enum TFTP_STATE
64 {
65 /**
66 * @brief This is the initial state of the TFTP client during startup
67 * In this state the TFTP client has sent out the READ Request and has
68 * not yet received a data packet in acknowledgment.
69 */
70 READ_REQUEST = 0x1,
72 /**
73 * @brief This is the data receive state of the TFTP client in which
74 * the TFTP client is receiving data packets from the TFTP server.
75 */
76 DATA_RECEIVE
77 }TFTP_STATE;
79 /**
80 * @brief
81 * The structure describes the TFTP Master Control Block.
82 *
83 * @details
84 * The TFTP Master control block stores information used by the
85 * TFTP module.
86 */
87 typedef struct TFTP_MCB
88 {
89 /**
90 * @brief This describes the state of the TFTP client.
91 */
92 TFTP_STATE state;
94 /**
95 * @brief This is the IP Address of the server from where the file
96 * is downloaded.
97 */
98 IPN server_ip;
100 /**
101 * @brief This is the TFTP socket which is used to communicate
102 * with the UDP module.
103 */
104 Int32 sock;
106 /**
107 * @brief This is the TFTP Timer handle which is used to handle
108 * retransmissions of the READ REQUEST.
109 */
110 Int32 timer;
112 /**
113 * @brief This is the name of the file which is being downloaded.
114 * File Names are typically exchanged through the BOOTP protocol
115 * where the max file name length is 64.
116 */
117 Uint8 filename[64];
119 /**
120 * @brief This is the block number we expect.
121 */
122 Uint16 block_num;
124 /**
125 * @brief This is a generic buffer used by the TFTP module,
126 */
127 Uint8 buffer[TFTP_DATA_SIZE + TFTPHEADER_SIZE];
129 /**
130 * @brief Number of retransmission done.
131 */
132 Uint32 num_retransmits;
133 }TFTP_MCB;
135 /**********************************************************************
136 *************************** GLOBAL Variables *************************
137 **********************************************************************/
139 /**
140 * @brief This is the global master control block for the TFTP
141 * module and keeps track of all the information regarding TFTP.
142 */
143 TFTP_MCB tftpmcb;
145 /**********************************************************************
146 **************************** TFTP Functions **************************
147 **********************************************************************/
149 /**
150 * @b Description
151 * @n
152 * The function cleans up the TFTP Client. This can be called
153 * on an ERROR or SUCCESSFUL exit.
154 *
155 * @retval
156 * Not Applicable.
157 */
158 static void tftp_cleanup (void)
159 {
160 /* Close any open timers. */
161 timer_delete (tftpmcb.timer);
162 tftpmcb.timer = -1;
164 /* Close the UDP Sockets. */
165 udp_sock_close (tftpmcb.sock);
167 /* Close the STREAM module */
168 stream_close ();
169 return;
170 }
172 /**
173 * @b Description
174 * @n
175 * The function creates the TFTP read request and populates it
176 * in the internal TFTP buffer.
177 *
178 * @retval
179 * Size of the TFTP Read Request.
180 */
181 static Int32 tftp_create_read_req (Uint8* filename)
182 {
183 Uint16* ptr_op;
184 Int32 index = 0;
186 /* Create the Read Request: Populate the Request op type */
187 ptr_op = (Uint16 *)&tftpmcb.buffer[0];
188 *ptr_op = htons(TFTP_OPCODE_RRQ);
190 /* Copy the file name */
191 index = 0;
192 while (filename[index] != 0)
193 {
194 tftpmcb.buffer[index + 2] = filename[index];
195 index++;
196 }
198 /* Null Terminate the file name. */
199 tftpmcb.buffer[index + 2] = 0;
200 index = index + 3;
202 /* Copy the transfer mode. */
203 tftpmcb.buffer[index++] = (Uint8)'o';
204 tftpmcb.buffer[index++] = (Uint8)'c';
205 tftpmcb.buffer[index++] = (Uint8)'t';
206 tftpmcb.buffer[index++] = (Uint8)'e';
207 tftpmcb.buffer[index++] = (Uint8)'t';
208 tftpmcb.buffer[index++] = (Uint8)0;
210 /* Return the size of the read request */
211 return index;
212 }
214 /**
215 * @b Description
216 * @n
217 * The function is used to send an ACK back to TFTP Server.
218 *
219 * @retval
220 * Not Applicable
221 */
222 static void tftp_send_ack(void)
223 {
224 TFTPHDR* ptr_tftphdr;
226 /* Initialize the data buffer. */
227 netMemset ((void *)&tftpmcb.buffer[0], 0, TFTP_DATA_SIZE + TFTPHEADER_SIZE);
229 /* Create an ACK packet which is to be sent out. Get the pointer to the
230 * TFTP Header. */
231 ptr_tftphdr = (TFTPHDR *)&tftpmcb.buffer[0];
232 ptr_tftphdr->opcode = htons (TFTP_OPCODE_ACK);
233 ptr_tftphdr->block = htons (tftpmcb.block_num);
235 /* The packet has been populated; send it to the server; this transfer is now done
236 * over the data socket. */
237 udp_sock_send (tftpmcb.sock, (Uint8 *)ptr_tftphdr, TFTPHEADER_SIZE);
239 /* Increment the block number. */
240 tftpmcb.block_num++;
241 return;
242 }
244 /**
245 * @b Description
246 * @n
247 * The function is the timer expiration for TFTP.
248 *
249 * @retval
250 * Not Applicable
251 */
252 static void tftp_timer_expiry (void)
253 {
254 Int32 len;
256 /* Determine the state of the TFTP. */
257 if (tftpmcb.state == READ_REQUEST)
258 {
259 /* We were sending out READ Request and have not received a response
260 * Increment the number of retransmissions which have been done. */
261 tftpmcb.num_retransmits++;
263 /* Check if we have exceeded the max allowed? */
264 if (tftpmcb.num_retransmits > MAX_TFTP_RETRANSMITS)
265 {
266 /* FATAL Error: We need to close the TFTP Client and signal Error to the NET Boot Module. */
267 mprintf ("Error: TFTP READ REQ Retransmissions have exceeded\n");
268 tftp_cleanup ();
269 net_set_error();
270 return;
271 }
273 /* Create the TFTP Read Request */
274 len = tftp_create_read_req (&tftpmcb.filename[0]);
276 /* Send out the READ Request again. */
277 udp_sock_send (tftpmcb.sock, (Uint8 *)&tftpmcb.buffer[0], len);
278 }
279 else
280 {
281 /* We were receiving data from the TFTP Server and there was a timeout. This can
282 * happen only if we have not received any data from the TFTP server. */
283 mprintf ("Error: TFTP server is down; no packet received.\n");
284 tftp_cleanup();
285 net_set_error();
286 return;
287 }
288 return;
289 }
291 /**
292 * @b Description
293 * @n
294 * This is a call back function registered with the UDP module to
295 * be invoked when a TFTP packet is received.
296 *
297 * @param[in] sock
298 * This is the socket handle on which packet was received.
299 * @param[in] ptr_data
300 * This is the pointer to the TFTP data payload.
301 * @param[in] num_bytes
302 * This is the number of bytes of TFTP data received.
303 *
304 * @retval
305 * Success - 0
306 * @retval
307 * Error - <0
308 */
309 static Int32 tftp_receive (Int32 sock, Uint8* ptr_data, Int32 num_bytes)
310 {
311 TFTPHDR* ptr_tftphdr;
312 UDPHDR* ptr_udphdr;
313 Uint16 src_port;
314 SOCKET socket;
316 /* Get the pointer to the TFTP Header. */
317 ptr_tftphdr = (TFTPHDR *)ptr_data;
319 /* Process the received packet depending on the type of packet received */
320 switch (ntohs(ptr_tftphdr->opcode))
321 {
322 case TFTP_OPCODE_DATA:
323 {
324 /* Is this the first data packet we have received? */
325 if (tftpmcb.state == READ_REQUEST)
326 {
327 /* YES. In this case the socket on which the request was sent has completed
328 * its job. Lets shut it down and open another one for the data transfers. */
329 udp_sock_close (sock);
331 /* We need to get the source port from where the data was received.
332 * This information is present in the UDP layer. This is required to
333 * open the data socket. */
334 ptr_udphdr = (UDPHDR *)(ptr_data - sizeof(UDPHDR));
335 src_port = ntohs(ptr_udphdr->SrcPort);
337 /* Populate the socket structure and register this with the UDP module. */
338 socket.local_port = 1234;
339 socket.remote_port = src_port;
340 socket.remote_address = tftpmcb.server_ip;
341 socket.app_fn = tftp_receive;
343 /* Move to the DATA State. */
344 tftpmcb.state = DATA_RECEIVE;
345 tftpmcb.num_retransmits = 0;
347 /* Close the timer. */
348 timer_delete (tftpmcb.timer);
349 tftpmcb.timer = -1;
351 /* Open the TFTP data socket. */
352 tftpmcb.sock = udp_sock_open (&socket);
353 if (tftpmcb.sock < 0)
354 {
355 /* Error: Data Socket open failed. */
356 mprintf ("Error: TFTP Data Socket Open Failed\n");
357 tftp_cleanup();
358 net_set_error();
359 return -1;
360 }
361 }
363 /* We are in the DATA State: Start the TFTP Server Keep Alive Timer. This timer
364 * keeps track of the TFTP Server and ensures it does not die behind us. This will
365 * help detect that error. */
366 timer_delete (tftpmcb.timer);
367 tftpmcb.timer = timer_add (TFTP_SERVER_TIMEOUT, tftp_timer_expiry);
368 if (tftpmcb.timer < 0)
369 {
370 /* Timer creation failed. */
371 mprintf ("Error: TFTP Timer creation failed\n");
372 tftp_cleanup();
373 net_set_error();
374 return -1;
375 }
377 /* Received a data block. Ensure that the block number matches what we expect! */
378 if (ntohs(ptr_tftphdr->block) != tftpmcb.block_num)
379 {
380 /* There is a block number mismatch. This could occur if the ACK we sent was lost.
381 * Increment the number of retransmissions. */
382 tftpmcb.num_retransmits++;
383 if (tftpmcb.num_retransmits > MAX_TFTP_RETRANSMITS)
384 {
385 /* OK; we resent the ACK multiple times & the server still kept sending the
386 * same packet back. We just give up now. */
387 mprintf ("Error: TFTP ACK Retransmits Exceeded\n");
388 tftp_cleanup();
389 net_set_error();
390 return -1;
391 }
393 /* We need to send out the ACK for the previous 'block' */
394 tftpmcb.block_num = tftpmcb.block_num - 1;
396 /* Send the ACK out again. */
397 tftp_send_ack ();
399 /* We dont need to process this packet since we had already picked it up. */
400 return 0;
401 }
403 /* The packet looks good. Reset the number of retransmissions. */
404 tftpmcb.num_retransmits = 0;
406 /* Pass the received data packet to the STREAM Module.
407 * We need to skip the TFTP Header. */
408 if (stream_write ((ptr_data + TFTPHEADER_SIZE), (num_bytes - TFTPHEADER_SIZE)) == 0)
409 {
410 /* Packet has been copied successfully into the STREAM Buffer. */
411 tftp_send_ack();
412 }
413 else
414 {
415 /* Packet could not be copied; let the server retransmit the packet
416 * because we did not send the ACK. */
417 }
419 /* Determine if the TFTP file transfer is complete or not?
420 * If the received number of bytes is less than the TFTP Data Size this
421 * indicates that the transfer is successfully completed. */
422 if (num_bytes < (TFTP_DATA_SIZE + TFTPHEADER_SIZE))
423 {
424 /* Successfully downloaded the file */
425 tftp_cleanup();
426 }
427 break;
428 }
429 default:
430 {
431 /* Control comes here for ERROR, ACK and WRQ which are all indicate
432 * failure. ERROR packet is the only expected failure which is mentioned
433 * in the RFC. All other packets are violation of the RFC. Both these
434 * cases are handled similarly. */
435 mprintf ("Error: TFTP Error Packet Received\n");
436 tftp_cleanup();
437 net_set_error();
439 /* Return Error. */
440 return -1;
441 }
442 }
443 return 0;
444 }
446 /**
447 * @b Description
448 * @n
449 * The function gets a file from the TFTP Server. The function
450 * simply initiates the transfer. Successful completion of this
451 * API does not gurantee that the file was downloaded.
452 *
453 * @param[in] server_ip
454 * TFTP Server IP address from where the file is downloaded.
455 * @param[in] filename
456 * Name of the file to be downloaded.
457 *
458 * @retval
459 * Success - 0
460 * @retval
461 * Error - <0
462 */
463 Int32 tftp_get_file (IPN server_ip, Int8* filename)
464 {
465 SOCKET socket;
466 Int32 index = 0;
468 /* Basic Validations: Ensure the parameters passed are correct. */
469 if ((server_ip == 0) || (filename == NULL))
470 {
471 /* Error: Invalid parameters passed. Stop the network boot module. */
472 net_set_error();
473 return -1;
474 }
476 /* Open the stream module. */
477 if (stream_open (TFTP_DATA_SIZE) < 0)
478 {
479 /* Error: Unable to open the stream device. */
480 net_set_error();
481 return -1;
482 }
484 /* Initialize the TFTP MCB at this stage... */
485 netMemset ((void *)&tftpmcb, 0, sizeof(TFTP_MCB));
487 /* Populate the socket structure and register this with the UDP module. */
488 socket.local_port = 1234;
489 socket.remote_port = TFTP_SERVER_PORT;
490 socket.remote_address = server_ip;
491 socket.app_fn = tftp_receive;
493 /* Open the TFTP Control socket. */
494 tftpmcb.sock = udp_sock_open (&socket);
495 if (tftpmcb.sock < 0)
496 {
497 /* ERROR: UDP Socket could not be opened. */
498 stream_close();
499 net_set_error();
500 return -1;
501 }
503 /* Remember the parameters passed to the TFTP. */
504 tftpmcb.server_ip = server_ip;
506 /* Copy the file name over... */
507 while (filename[index] != 0)
508 {
509 tftpmcb.filename[index] = filename[index];
510 index++;
511 }
513 /* Initialize the block number expected. */
514 tftpmcb.block_num = 1;
516 /* Create the TFTP Read Request. */
517 index = tftp_create_read_req ((Uint8 *)filename);
519 /* Initialize the TFTP Client state */
520 tftpmcb.state = READ_REQUEST;
522 /* Initialize the TFTP Timer. */
523 tftpmcb.timer = timer_add (TFTP_TIMEOUT, tftp_timer_expiry);
524 if (tftpmcb.timer < 0)
525 {
526 /* Error: TFTP Timer Creation Failed. TFTP is not operational. */
527 mprintf ("Error: TFTP Timer Creation Failed\n");
528 tftp_cleanup ();
529 net_set_error();
530 return -1;
531 }
533 /* The packet has been populated; send it to the server. */
534 udp_sock_send (tftpmcb.sock, (Uint8 *)&tftpmcb.buffer[0], index);
536 /* Send out the TFTP Read request. */
537 return 0;
538 }