• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  * Description: implementation for tftp client
15  * Author: none
16  * Create: 2020
17  */
18 
19 
20 #include "lwip/opt.h"
21 
22 #if LWIP_TFTP /* don't build if not configured for use in lwipopts.h */
23 
24 #include "lwip/tcpip.h"
25 #include "lwip/netif.h"
26 #include "lwip/mem.h"
27 #include "lwip/err.h"
28 #include "lwip/inet.h"
29 #include "netif/etharp.h"
30 #include "lwip/ip_addr.h"
31 #include "lwip/sockets.h"
32 #include "lwip/udp.h"
33 #include "lwip/ip_addr.h"
34 #include "lwip/netif.h"
35 #include "lwip/def.h"
36 #include "lwip/tftpc.h"
37 #include "fcntl.h"
38 #include <string.h>
39 #include <stdbool.h>
40 #include <unistd.h>
41 
42 #include <sys/stat.h>
43 
44 /* Function Declarations */
45 #ifdef LOSCFG_NET_LWIP_SACK_TFTP
46 static u32_t lwip_tftp_create_bind_socket(s32_t *pi_socketid);
47 
48 static s32_t lwip_tftp_make_tftp_packet(u16_t us_opcode, const s8_t *sz_filename,
49                                         u32_t ul_mode, tftpc_packet_s *pst_packet);
50 
51 u32_t lwip_tftp_recv_from_server(s32_t i_socknum,
52                                  u32_t *pul_size,
53                                  tftpc_packet_s *pst_recvbuf,
54                                  u32_t *pul_ignorepkt,
55                                  struct sockaddr_in *pst_serveraddr,
56                                  tftpc_packet_s *pst_sendbuf);
57 
58 u32_t lwip_tftp_send_to_server(s32_t i_socknum, u32_t ul_size,
59                                tftpc_packet_s *pst_sendbuf,
60                                struct sockaddr_in *pst_serveraddr);
61 
62 u32_t lwip_tftp_validate_data_pkt(s32_t i_socknum,
63                                   u32_t *pul_size,
64                                   tftpc_packet_s *pst_recvbuf,
65                                   u16_t us_currblk, u32_t *pul_resendpkt,
66                                   struct sockaddr_in  *pst_serveraddr);
67 
68 u32_t lwip_tftp_inner_put_file(s32_t i_socknum, tftpc_packet_s *pst_sendbuf,
69                                u32_t ulLength, u16_t us_currblk,
70                                struct sockaddr_in *pst_serveraddr);
71 
72 static void lwip_tftp_send_error(s32_t i_socknum, u32_t ul_error, const char *sz_errmsg,
73                                  struct sockaddr_in *pst_serveraddr, tftpc_packet_s *pst_sendbuf);
74 
75 
76 /* Create and bind a UDP socket. */
77 static u32_t
lwip_tftp_create_bind_socket(s32_t * pi_socketid)78 lwip_tftp_create_bind_socket(s32_t *pi_socketid)
79 {
80   int retval;
81   struct sockaddr_in st_client_addr;
82   u32_t ul_temp_clientip;
83   u32_t set_non_block_socket = 1;
84 
85   /* create a socket */
86   *pi_socketid = lwip_socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
87   if (*pi_socketid == -1) {
88     LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_create_bind_socket : lwip_socket create socket failed\n"));
89     return TFTPC_SOCKET_FAILURE;
90   }
91 
92   /* Make the socket as NON-BLOCKING. */
93   retval = lwip_ioctl(*pi_socketid, (long)FIONBIO, &set_non_block_socket);
94   if (retval != 0) {
95     (void)lwip_close(*pi_socketid);
96     *pi_socketid = TFTP_NULL_INT32;
97     return TFTPC_IOCTLSOCKET_FAILURE;
98   }
99 
100   ul_temp_clientip = INADDR_ANY;
101 
102   /* specify a local address for this socket */
103   (void)memset_s(&st_client_addr, sizeof(st_client_addr), 0, sizeof(st_client_addr));
104   st_client_addr.sin_family = AF_INET;
105   st_client_addr.sin_port = 0;
106   st_client_addr.sin_addr.s_addr = htonl(ul_temp_clientip);
107 
108   retval = lwip_bind(*pi_socketid, (struct sockaddr *)&st_client_addr, sizeof(st_client_addr));
109   if (retval != 0) {
110     (void)lwip_close(*pi_socketid);
111     *pi_socketid = TFTP_NULL_INT32;
112     return TFTPC_BIND_FAILURE;
113   }
114 
115   return ERR_OK;
116 }
117 
118 /*
119  * Function to create TFTP packet.
120  * us_opcode - indiacting the nature of the operation
121  * sz_filename -filename on which the operation needs to done
122  * ul_mode -mode in which the operation needs to done
123  * pst_packet - packet generated
124  * Returns packet address on success
125  */
126 static s32_t
lwip_tftp_make_tftp_packet(u16_t us_opcode,const s8_t * sz_filename,u32_t ul_mode,tftpc_packet_s * pst_packet)127 lwip_tftp_make_tftp_packet(u16_t us_opcode, const s8_t *sz_filename, u32_t ul_mode, tftpc_packet_s *pst_packet)
128 {
129   s8_t *pc_cp = NULL;
130 
131   pst_packet->us_opcode = htons(us_opcode);
132   pc_cp = pst_packet->u.uc_name_mode;
133 
134   /*
135    * Request packet format is:
136    * | Opcode |  Filename  |   0  |    Mode    |   0  |
137    */
138   (void)strncpy_s((char *)pc_cp, TFTP_MAX_PATH_LENGTH, (char *)sz_filename, (TFTP_MAX_PATH_LENGTH - 1));
139   pc_cp[(TFTP_MAX_PATH_LENGTH - 1)] = '\0';
140 
141   pc_cp += (strlen((char *)sz_filename) + 1);
142   if (ul_mode == TRANSFER_MODE_BINARY) {
143     (void)strncpy_s((char *)pc_cp, TFTP_MAX_MODE_SIZE, "octet", (TFTP_MAX_MODE_SIZE - 1));
144     pc_cp[(TFTP_MAX_MODE_SIZE - 1)] = '\0';
145   } else if (ul_mode == TRANSFER_MODE_ASCII) {
146     (void)strncpy_s((char *)pc_cp, TFTP_MAX_MODE_SIZE, "netascii", (TFTP_MAX_MODE_SIZE - 1));
147     pc_cp[(TFTP_MAX_MODE_SIZE - 1)] = '\0';
148   }
149 
150   pc_cp += (strlen((char *)pc_cp) + 1);
151 
152   return (pc_cp - (s8_t *)pst_packet);
153 }
154 
155 /*
156  * Function to recv a packet from server
157  * i_socknum - Socket Number
158  * pst_serveraddr - Server address
159  * pul_ignorepkt - Ignore packet flag
160  * pst_recvbuf - received packet
161  * pul_size - Size of the packet
162  */
163 u32_t
lwip_tftp_recv_from_server(s32_t i_socknum,u32_t * pul_size,tftpc_packet_s * pst_recvbuf,u32_t * pul_ignorepkt,struct sockaddr_in * pst_serveraddr,tftpc_packet_s * pst_sendbuf)164 lwip_tftp_recv_from_server(s32_t i_socknum, u32_t *pul_size,
165                            tftpc_packet_s *pst_recvbuf, u32_t *pul_ignorepkt,
166                            struct sockaddr_in *pst_serveraddr, tftpc_packet_s *pst_sendbuf)
167 {
168   u32_t ulerror;
169   socklen_t sl_fromaddrlen;
170   struct sockaddr_in st_fromaddr;
171   fd_set st_readfds;
172   struct timeval st_timeout;
173   u16_t us_opcode; /* Opcode value */
174   s32_t iret;
175 
176   sl_fromaddrlen = sizeof(st_fromaddr);
177   st_timeout.tv_sec = TFTPC_TIMEOUT_PERIOD;
178   st_timeout.tv_usec = 0;
179   if ((pul_size == NULL) || (pst_recvbuf == NULL) || (pst_serveraddr == NULL) || (pst_sendbuf == NULL)) {
180     return ERR_ARG;
181   }
182   /* wait for DATA packet */
183   FD_ZERO(&st_readfds);
184   FD_SET(i_socknum, &st_readfds);
185 
186   iret = lwip_select((s32_t)(i_socknum + 1), &st_readfds, 0, 0, &st_timeout);
187   if (iret == -1) {
188     return TFTPC_SELECT_ERROR;
189   } else if (iret == 0) {
190     return TFTPC_TIMEOUT_ERROR; /* Select timeout occured */
191   }
192 
193   if (!FD_ISSET(i_socknum, &st_readfds)) {
194     return TFTPC_TIMEOUT_ERROR; /* FD not set */
195   }
196 
197   /* receive a packet from server */
198   iret = lwip_recvfrom(i_socknum, (s8_t *)pst_recvbuf, TFTP_PKTSIZE, 0,
199                        (struct sockaddr *)&st_fromaddr, &sl_fromaddrlen);
200   if (iret <= 0) {
201     return TFTPC_RECVFROM_ERROR;
202   }
203 
204   /* If received packet size < minimum packet size */
205   if (iret < TFTPC_FOUR) {
206     /* Send Error packet to server */
207     lwip_tftp_send_error(i_socknum,
208                          TFTPC_PROTOCOL_PROTO_ERROR,
209                          "Packet size < min size",
210                          pst_serveraddr, pst_sendbuf);
211 
212     return TFTPC_PKT_SIZE_ERROR;
213   }
214 
215   /* convert network opcode to host format after receive. */
216   us_opcode = ntohs(pst_recvbuf->us_opcode);
217   /* if this packet is ERROR packet */
218   if (us_opcode == TFTPC_OP_ERROR) {
219     ulerror = ntohs(pst_recvbuf->u.sttftp_err.us_errnum);
220 
221     /*
222      * If the error is according to RFC,then convert to lwip error codes.
223      * Constant values are used in the cases as these error codes are as per
224      * the RFC, these are constant values returned by many standard TFTP
225      * serevrs
226      */
227     switch (ulerror) {
228       case TFTPC_PROTOCOL_USER_DEFINED:
229         ulerror = TFTPC_ERROR_NOT_DEFINED;
230         break;
231       case TFTPC_PROTOCOL_FILE_NOT_FOUND:
232         ulerror = TFTPC_FILE_NOT_FOUND;
233         break;
234       case TFTPC_PROTOCOL_ACCESS_ERROR:
235         ulerror = TFTPC_ACCESS_ERROR;
236         break;
237       case TFTPC_PROTOCOL_DISK_FULL:
238         ulerror = TFTPC_DISK_FULL;
239         break;
240       case TFTPC_PROTOCOL_PROTO_ERROR:
241         ulerror = TFTPC_PROTO_ERROR;
242         break;
243       case TFTPC_PROTOCOL_UNKNOWN_TRANSFER_ID:
244         ulerror = TFTPC_UNKNOWN_TRANSFER_ID;
245         break;
246       case TFTPC_PROTOCOL_FILE_EXISTS:
247         ulerror = TFTPC_FILE_EXISTS;
248         break;
249       case TFTPC_PROTOCOL_CANNOT_RESOLVE_HOSTNAME:
250         ulerror = TFTPC_CANNOT_RESOLVE_HOSTNAME;
251         break;
252       default:
253         ulerror = TFTPC_ERROR_NOT_DEFINED;
254         break;
255     }
256 
257     /* If length of error msg > 100 chars */
258     pst_recvbuf->u.sttftp_err.uc_errmesg[TFTP_MAXERRSTRSIZE - 1] = '\0';
259 
260     LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_recv_from_server : ERROR pkt received: %s\n",
261                              pst_recvbuf->u.sttftp_err.uc_errmesg));
262 
263     /* Now we get error block, so return. */
264     return ulerror;
265   }
266 
267   /* Store the size of received block */
268   *pul_size = (u32_t)iret;
269 
270   /*
271    * If received packet is first block of data(for get operation) or if
272    * received packet is acknowledgement for write request (put operation)
273    * store the received port number
274    */
275   if (((us_opcode == TFTPC_OP_DATA) && (ntohs(pst_recvbuf->u.sttftp_data.us_blknum) == 1)) ||
276       ((us_opcode == TFTPC_OP_ACK) && (ntohs(pst_recvbuf->u.us_blknum) == 0))) {
277     /* If received packet from correct server */
278     if (st_fromaddr.sin_addr.s_addr == pst_serveraddr->sin_addr.s_addr) {
279       /* set the server port to received port */
280       pst_serveraddr->sin_port = st_fromaddr.sin_port;
281     } else {
282       /* Received packet form wrong server. */
283       LWIP_DEBUGF(TFTP_DEBUG,
284                   ("lwip_tftp_recv_from_server : Received 1st packet from wrong Server or unknown server\n"));
285 
286       /* Set ignore packet flag */
287       *pul_ignorepkt = 1;
288     }
289   } else {
290     /* If not first packet, check if the received packet is from correct server and from correct port */
291     if ((st_fromaddr.sin_addr.s_addr != pst_serveraddr->sin_addr.s_addr) ||
292         (pst_serveraddr->sin_port != st_fromaddr.sin_port)) {
293       /* Received packet form wrong server or wrong port.Ignore packet. */
294       LWIP_DEBUGF(TFTP_DEBUG,
295                   ("lwip_tftp_recv_from_server : Received a packet from wrong Server or unknown server\n"));
296 
297       /* Set ignore packet flag */
298       *pul_ignorepkt = 1;
299     }
300   }
301 
302   return ERR_OK;
303 }
304 
305 /*
306  * Function to send a packet to server
307  * i_socknum: Socket Number
308  * ul_size: Size of the packet
309  * pst_sendbuf: Packet to send
310  * pst_serveraddr: Server address
311  */
312 u32_t
lwip_tftp_send_to_server(s32_t i_socknum,u32_t ul_size,tftpc_packet_s * pst_sendbuf,struct sockaddr_in * pst_serveraddr)313 lwip_tftp_send_to_server(s32_t i_socknum,
314                          u32_t ul_size,
315                          tftpc_packet_s *pst_sendbuf,
316                          struct sockaddr_in *pst_serveraddr)
317 {
318   s32_t iret;
319   if ((pst_sendbuf == NULL) || (pst_serveraddr == NULL)) {
320     return ERR_ARG;
321   }
322   /* Send packet to server */
323   iret = lwip_sendto(i_socknum, (s8_t *)pst_sendbuf,
324                      (size_t)ul_size, 0,
325                      (struct sockaddr *)pst_serveraddr,
326                      sizeof(struct sockaddr_in));
327   /* Size of data sent not equal to size of packet */
328   if ((iret == TFTP_NULL_INT32) || ((u32_t)iret != ul_size)) {
329     return TFTPC_SENDTO_ERROR;
330   }
331 
332   return ERR_OK;
333 }
334 
335 /*
336  * lwip_tftp_validate_data_pkt
337  * Get the data block from the received packet
338  * @param Input i_socknum Socket Number
339  *              pul_size: Size of received packet,
340  *              pst_recvbuf - received packet
341  *              us_currblk - Current block number
342  * @param Output pul_resendpkt - Resend packet flag
343  * @return VOS_OK on success.else error code
344  */
345 u32_t
lwip_tftp_validate_data_pkt(s32_t i_socknum,u32_t * pul_size,tftpc_packet_s * pst_recvbuf,u16_t us_currblk,u32_t * pul_resendpkt,struct sockaddr_in * pst_serveraddr)346 lwip_tftp_validate_data_pkt(s32_t i_socknum,
347                             u32_t *pul_size,
348                             tftpc_packet_s *pst_recvbuf,
349                             u16_t us_currblk,
350                             u32_t *pul_resendpkt,
351                             struct sockaddr_in *pst_serveraddr)
352 {
353   fd_set st_readfds;
354   struct timeval st_timeout;
355   struct sockaddr_in st_fromaddr;
356   socklen_t ul_fromaddrlen;
357   s32_t ierror;
358   u16_t usblknum;
359   u32_t ul_loopcnt = 0;
360   if ((pul_size == NULL) || (pst_recvbuf == NULL) ||
361       (pul_resendpkt == NULL) || (pst_serveraddr == NULL)) {
362     return ERR_ARG;
363   }
364   s32_t irecvlen = (s32_t)*pul_size;
365   ul_fromaddrlen = sizeof(st_fromaddr);
366 
367   /* Initialize from address to the server address at first */
368   if (memcpy_s((void *)&st_fromaddr, sizeof(struct sockaddr_in), (void *)pst_serveraddr, sizeof(st_fromaddr)) != EOK) {
369     LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_validate_data_pkt : memcpy_s error\n"));
370     return TFTPC_MEMCPY_FAILURE;
371   }
372 
373   /* Get Block Number */
374   usblknum = ntohs(pst_recvbuf->u.sttftp_data.us_blknum);
375   /* Now data blocks are not in sync. */
376   if (usblknum != us_currblk) {
377     /* Set timeout value */
378     st_timeout.tv_sec = 1;
379     st_timeout.tv_usec = 0;
380 
381     /* Reset any stored packets. */
382     FD_ZERO(&st_readfds);
383     FD_SET(i_socknum, &st_readfds);
384 
385     ierror = lwip_select((s32_t)(i_socknum + 1),
386                          &st_readfds, 0, 0, &st_timeout);
387 
388     /* Loop to get the last data packet from the receive buffer */
389     while ((ierror != TFTP_NULL_INT32) && (ierror != 0)) {
390       ul_loopcnt++;
391 
392       /*
393        * MAX file size in TFTP is 32 MB.
394        * Reason for keeping 75 here , is ((75*512=38400bytes)/1024) =  37MB. So the recv/Send
395        * Loop can receive the complete MAX message from the network.
396        */
397       if (ul_loopcnt > TFTPC_MAX_WAIT_IN_LOOP) {
398         LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_validate_data_pkt : unexpected packets are received repeatedly\n"));
399         *pul_size = TFTP_NULL_UINT32;
400         return TFTPC_PKT_SIZE_ERROR;
401       }
402 
403       FD_ZERO(&st_readfds);
404       FD_SET(i_socknum, &st_readfds);
405 
406       irecvlen = lwip_recvfrom(i_socknum,
407                                (s8_t *)pst_recvbuf,
408                                TFTP_PKTSIZE, 0,
409                                (struct sockaddr *)&st_fromaddr,
410                                &ul_fromaddrlen);
411       if (irecvlen == -1) {
412         *pul_size = TFTP_NULL_UINT32;
413 
414         /* return from the function, recvfrom operation failed */
415         return TFTPC_RECVFROM_ERROR;
416       }
417 
418       st_timeout.tv_sec = 1;
419       st_timeout.tv_usec = 0;
420       ierror = lwip_select((s32_t)(i_socknum + 1), &st_readfds, 0, 0, &st_timeout);
421     }
422 
423     /* If received packet size < minimum packet size */
424     if (irecvlen < TFTPC_FOUR) {
425       return TFTPC_PKT_SIZE_ERROR;
426     }
427 
428     /*
429      * Check if the received packet is from correct server and from
430      * correct port
431      */
432     if ((st_fromaddr.sin_addr.s_addr != pst_serveraddr->sin_addr.s_addr) ||
433         (pst_serveraddr->sin_port != st_fromaddr.sin_port)) {
434       /* resend ack packet */
435       *pul_resendpkt = 1;
436       LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_validate_data_pkt : Received pkt from unknown server\n"));
437       return ERR_OK;
438     }
439 
440     /* if this packet is not DATA packet */
441     if (TFTPC_OP_DATA != ntohs(pst_recvbuf->us_opcode)) {
442       LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_validate_data_pkt : Received pkt not a DATA pkt\n"));
443 
444      /*
445       * return from the function, incorrect packet received,
446       * expected packet is data packet
447       */
448       return TFTPC_PROTO_ERROR;
449     }
450 
451     usblknum = ntohs(pst_recvbuf->u.sttftp_data.us_blknum);
452     /*
453      * if we now have the earlier data packet, then the host probably
454      * never got our acknowledge packet, now we will send it again.
455      */
456     if (usblknum == (us_currblk - 1)) {
457       /* resend ack packet */
458       *pul_resendpkt = 1;
459       LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_validate_data_pkt : Received previous DATA pkt\n"));
460 
461       return ERR_OK;
462     }
463 
464     /* If the block of data received is not current block or also previous block, then it is abnormal case. */
465     if (usblknum != us_currblk) {
466       LWIP_DEBUGF(TFTP_DEBUG,
467                   ("lwip_tftp_validate_data_pkt : Received DATA pkt no. %"S32_F" instead of pkt no.%"S32_F"\n",
468                    usblknum, us_currblk));
469 
470       return TFTPC_SYNC_FAILURE;
471     }
472   }
473 
474   *pul_size = (u32_t)irecvlen;
475   return ERR_OK;
476 }
477 
478 /*
479  * Send an error packet to the server
480  * i_socknum : Socket Number
481  * ul_error: Error code
482  * sz_errmsg - Error message
483  * pst_serveraddr - Server address
484  */
485 static void
lwip_tftp_send_error(s32_t i_socknum,u32_t ul_error,const char * sz_errmsg,struct sockaddr_in * pst_serveraddr,tftpc_packet_s * pst_sendbuf)486 lwip_tftp_send_error(s32_t i_socknum, u32_t ul_error, const char *sz_errmsg,
487                      struct sockaddr_in *pst_serveraddr, tftpc_packet_s *pst_sendbuf)
488 {
489   u16_t us_opcode = TFTPC_OP_ERROR;
490 
491   (void)memset_s((void *)pst_sendbuf, sizeof(tftpc_packet_s), 0, sizeof(tftpc_packet_s));
492 
493   /* Set up the send buffer */
494   pst_sendbuf->us_opcode = htons(us_opcode);
495   pst_sendbuf->u.sttftp_err.us_errnum = htons((u16_t)ul_error);
496 
497   if (strncpy_s((char *)(pst_sendbuf->u.sttftp_err.uc_errmesg), TFTP_MAXERRSTRSIZE,
498                 (char *)sz_errmsg, (TFTP_MAXERRSTRSIZE - 1)) != EOK) {
499     LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_send_error : strncpy_s error\n"));
500     return;
501   }
502   pst_sendbuf->u.sttftp_err.uc_errmesg[(TFTP_MAXERRSTRSIZE - 1)] = '\0';
503 
504   /* Send to server */
505   if (lwip_tftp_send_to_server(i_socknum,
506                                sizeof(tftpc_packet_s),
507                                pst_sendbuf,
508                                pst_serveraddr) != ERR_OK) {
509     LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_send_to_server error."));
510     return;
511   }
512 }
513 
514 /*
515  * INTEFACE to get a file using filename
516  * ul_hostaddr - IP address of Host
517  * sz_srcfilename - Source file
518  * sz_destdirpath - Destination file path
519  */
520 u32_t
lwip_tftp_get_file_by_filename(u32_t ul_hostaddr,u16_t us_tftpservport,u8_t uc_tftptransmode,s8_t * sz_srcfilename,s8_t * sz_destdirpath)521 lwip_tftp_get_file_by_filename(u32_t ul_hostaddr,
522                                u16_t us_tftpservport,
523                                u8_t uc_tftptransmode,
524                                s8_t *sz_srcfilename,
525                                s8_t *sz_destdirpath)
526 {
527   s32_t i_socknum = TFTP_NULL_INT32;
528   u32_t ul_srcstrlen;
529   u32_t ul_deststrlen;
530   u32_t ul_size;
531   u32_t ul_recvsize = TFTP_NULL_UINT32;
532   s32_t i_errcode;
533   u32_t ul_errcode;
534   u16_t us_readreq;
535   u16_t us_tempservport;
536   s8_t *psz_tempdestname = NULL;
537   s8_t *sz_tempsrcname = NULL;
538   u32_t ul_currblk = 1;
539   u32_t ul_resendpkt = 0; /* Resend the previous packet */
540   u32_t ul_ignorepkt = 0; /* Ignore received packet */
541   u32_t ul_totaltime = 0;
542   u32_t is_localfileopened = false;
543 
544   tftpc_packet_s *pst_sendbuf = NULL;
545   tftpc_packet_s *pst_recvbuf = NULL;
546   struct sockaddr_in st_serveraddr;
547   struct stat sb;
548   u32_t is_direxist = 0;
549   s32_t fp = -1;
550 
551   /* Validate the parameters */
552   if ((sz_srcfilename == NULL) || (sz_destdirpath == NULL)) {
553     return TFTPC_INVALID_PARAVALUE;
554   }
555 
556   if ((uc_tftptransmode != TRANSFER_MODE_BINARY) && (uc_tftptransmode != TRANSFER_MODE_ASCII)) {
557     return TFTPC_INVALID_PARAVALUE;
558   }
559 
560   /* check IP address not within ( 1.0.0.0 - 126.255.255.255 ) and ( 128.0.0.0 - 223.255.255.255 ) range. */
561   if (!(((ul_hostaddr >= TFTPC_IP_ADDR_MIN) && (ul_hostaddr <= TFTPC_IP_ADDR_EX_RESV)) ||
562       ((ul_hostaddr >= TFTPC_IP_ADDR_CLASS_B) && (ul_hostaddr <= TFTPC_IP_ADDR_EX_CLASS_DE)))) {
563     return TFTPC_IP_NOT_WITHIN_RANGE;
564   }
565 
566   /* Check validity of source filename */
567   ul_srcstrlen = strlen((char *)sz_srcfilename);
568   if ((ul_srcstrlen == 0) || (ul_srcstrlen >= TFTP_MAX_PATH_LENGTH)) {
569     return TFTPC_SRC_FILENAME_LENGTH_ERROR;
570   }
571 
572   /* Check validity of destination path */
573   ul_deststrlen = strlen((char *)sz_destdirpath);
574   if ((ul_deststrlen >= TFTP_MAX_PATH_LENGTH) || (ul_deststrlen == 0)) {
575     return TFTPC_DEST_PATH_LENGTH_ERROR;
576   }
577 
578   pst_sendbuf = (tftpc_packet_s *)mem_malloc(sizeof(tftpc_packet_s));
579   if (pst_sendbuf == NULL) {
580     return TFTPC_MEMALLOC_ERROR;
581   }
582 
583   pst_recvbuf = (tftpc_packet_s *)mem_malloc(sizeof(tftpc_packet_s));
584   if (pst_recvbuf == NULL) {
585     mem_free(pst_sendbuf);
586     return TFTPC_MEMALLOC_ERROR;
587   }
588 
589   psz_tempdestname = (s8_t *)mem_malloc(TFTP_MAX_PATH_LENGTH);
590   if (psz_tempdestname == NULL) {
591     mem_free(pst_sendbuf);
592     mem_free(pst_recvbuf);
593     return TFTPC_MEMALLOC_ERROR;
594   }
595 
596   /* First time initialize the buffers */
597   (void)memset_s((void *)pst_sendbuf, sizeof(tftpc_packet_s), 0, sizeof(tftpc_packet_s));
598   (void)memset_s((void *)pst_recvbuf, sizeof(tftpc_packet_s), 0, sizeof(tftpc_packet_s));
599 
600   /* If given src filename is a relative path extrac the file name from the path */
601   if ((strchr((char *)sz_srcfilename, '/') != 0) || (strchr((char *)sz_srcfilename, '\\') != 0)) {
602     /* Move to the end of the src file path */
603     sz_tempsrcname = sz_srcfilename + (ul_srcstrlen - 1);
604 
605     while (((*(sz_tempsrcname - 1) != '/') &&
606             (*(sz_tempsrcname - 1) != '\\')) &&
607            (sz_tempsrcname != sz_srcfilename)) {
608       sz_tempsrcname--;
609     }
610 
611     /* Get length of the extracted src filename */
612     ul_srcstrlen = strlen((char *)sz_tempsrcname);
613   } else {
614     /* If not a relative src path use the given src filename */
615     sz_tempsrcname = sz_srcfilename;
616   }
617 
618   (void)memset_s(psz_tempdestname, TFTP_MAX_PATH_LENGTH, 0, TFTP_MAX_PATH_LENGTH);
619   if (strncpy_s((char *)psz_tempdestname, TFTP_MAX_PATH_LENGTH,
620                 (char *)sz_destdirpath, TFTP_MAX_PATH_LENGTH - 1) != EOK) {
621     ul_errcode = TFTPC_MEMCPY_FAILURE;
622     goto err_handler;
623   }
624   psz_tempdestname[TFTP_MAX_PATH_LENGTH - 1] = '\0';
625 
626   if ((stat((char *)psz_tempdestname, &sb) == 0) && (S_ISDIR(sb.st_mode))) {
627     is_direxist = 1;
628   }
629 
630   if (is_direxist == 1) {
631     /* The filename is not present concat source filename and try */
632     if ((ul_deststrlen + ul_srcstrlen) >= TFTP_MAX_PATH_LENGTH) {
633       /* If concatenating src filename exceeds 256 bytes */
634       ul_errcode = TFTPC_DEST_PATH_LENGTH_ERROR;
635       goto err_handler;
636     }
637 
638     /* Check if / present at end of string */
639     if ((psz_tempdestname[ul_deststrlen - 1] != '/') &&
640         (psz_tempdestname[ul_deststrlen - 1] != '\\')) {
641       if ((ul_deststrlen + ul_srcstrlen + 1) >= TFTP_MAX_PATH_LENGTH) {
642         /* If concatenating src filename exceeds 256 bytes */
643         ul_errcode = TFTPC_DEST_PATH_LENGTH_ERROR;
644         goto err_handler;
645       }
646 
647       /* If not present concat / to the path */
648       if (strncat_s((char *)psz_tempdestname, (TFTP_MAX_PATH_LENGTH - strlen((char *)psz_tempdestname)),
649                     "/", TFTP_MAX_PATH_LENGTH - strlen((char *)psz_tempdestname) - 1) != EOK) {
650         ul_errcode = TFTPC_ERROR_NOT_DEFINED;
651         goto err_handler;
652       }
653     }
654 
655     /* Concatenate src filename to destination path */
656     if (strncat_s((char *)psz_tempdestname, (TFTP_MAX_PATH_LENGTH - strlen((char *)psz_tempdestname)),
657                   (char *)sz_tempsrcname, TFTP_MAX_PATH_LENGTH - strlen((char *)psz_tempdestname) - 1) != EOK) {
658       ul_errcode = TFTPC_ERROR_NOT_DEFINED;
659       goto err_handler;
660     }
661   }
662 
663   ul_errcode = lwip_tftp_create_bind_socket(&i_socknum);
664   if (ul_errcode != ERR_OK) {
665     goto err_handler;
666   }
667 
668   if (us_tftpservport == 0) {
669     us_tftpservport = TFTPC_SERVER_PORT;
670   }
671 
672   us_tempservport = us_tftpservport;
673 
674   /* set server IP address */
675   (void)memset_s(&st_serveraddr, sizeof(st_serveraddr), 0, sizeof(st_serveraddr));
676   st_serveraddr.sin_family = AF_INET;
677   st_serveraddr.sin_port = htons(us_tempservport);
678   st_serveraddr.sin_addr.s_addr = htonl(ul_hostaddr);
679 
680   /* Make a request packet - TFTPC_OP_RRQ */
681   ul_size = (u32_t)lwip_tftp_make_tftp_packet(TFTPC_OP_RRQ, sz_srcfilename,
682                                               (u32_t)uc_tftptransmode,
683                                               pst_sendbuf);
684   ul_errcode = lwip_tftp_send_to_server(i_socknum, ul_size,
685                                         pst_sendbuf, &st_serveraddr);
686   if (ul_errcode != ERR_OK) {
687     /* send to server failed */
688     (void)lwip_close(i_socknum);
689     goto err_handler;
690   }
691 
692   for (;;) {
693     if (ul_ignorepkt > 0) {
694       ul_ignorepkt = 0;
695     }
696 
697     ul_errcode = lwip_tftp_recv_from_server(i_socknum, &ul_recvsize, pst_recvbuf,
698                                             &ul_ignorepkt, &st_serveraddr, pst_sendbuf);
699     /* If select timeout occured */
700     if (ul_errcode == TFTPC_TIMEOUT_ERROR) {
701       ul_totaltime++;
702       if (ul_totaltime < TFTPC_MAX_SEND_REQ_ATTEMPTS) {
703         /* Max attempts not reached. Resend packet */
704         ul_errcode = lwip_tftp_send_to_server(i_socknum, ul_size,
705                                               pst_sendbuf, &st_serveraddr);
706         if (ul_errcode != ERR_OK) {
707           (void)lwip_close(i_socknum);
708           if (is_localfileopened == true) {
709             close(fp);
710           }
711           goto err_handler;
712         }
713 
714         continue;
715       } else {
716         /* return from the function, max attempts limit reached */
717         (void)lwip_close(i_socknum);
718         if (is_localfileopened == true) {
719           close(fp);
720         }
721         ul_errcode = TFTPC_TIMEOUT_ERROR;
722         goto err_handler;
723       }
724     } else if (ul_errcode != ERR_OK) {
725       (void)lwip_close(i_socknum);
726       if (is_localfileopened == true) {
727         close(fp);
728       }
729       goto err_handler;
730     }
731 
732     /* Now we have receive block from different server. */
733     if (ul_ignorepkt > 0) {
734       /* Continue without processing this block. */
735       continue;
736     }
737 
738     /* if this packet is unkonwn or incorrect packet */
739     if (ntohs(pst_recvbuf->us_opcode) != TFTPC_OP_DATA) {
740       /* Send error packet to server */
741       lwip_tftp_send_error(i_socknum,
742                            TFTPC_PROTOCOL_PROTO_ERROR,
743                            "Protocol error.",
744                            &st_serveraddr, pst_sendbuf);
745 
746       (void)lwip_close(i_socknum);
747       if (is_localfileopened == true) {
748         close(fp);
749       }
750 
751       LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_get_file_by_filename : Received pkt not DATA pkt\n"));
752 
753       ul_errcode = TFTPC_PROTO_ERROR;
754       goto err_handler;
755     }
756 
757     /* Now the number of tries will be reset. */
758     ul_totaltime = 0;
759 
760     /* Validate received  DATA packet. */
761     ul_errcode = lwip_tftp_validate_data_pkt(i_socknum, &ul_recvsize,
762                                              pst_recvbuf, (u16_t)ul_currblk,
763                                              &ul_resendpkt,
764                                              &st_serveraddr);
765     if (ul_errcode != ERR_OK) {
766       /* Send Error packet to server */
767       if (ul_errcode != TFTPC_RECVFROM_ERROR) {
768         lwip_tftp_send_error(i_socknum,
769                              TFTPC_PROTOCOL_PROTO_ERROR,
770                              "Received unexpected packet",
771                              &st_serveraddr, pst_sendbuf);
772       }
773 
774       (void)lwip_close(i_socknum);
775       if (is_localfileopened == true) {
776         close(fp);
777       }
778 
779       goto err_handler;
780     }
781 
782     /* Received previous data block again. Resend last packet */
783     if (ul_resendpkt > 0) {
784       /* Now set ul_resendpkt to 0 to send the last packet. */
785       ul_resendpkt = 0;
786       ul_errcode = lwip_tftp_send_to_server(i_socknum, ul_size,
787                                             pst_sendbuf, &st_serveraddr);
788       if (ul_errcode != ERR_OK) {
789         (void)lwip_close(i_socknum);
790         if (is_localfileopened == true) {
791           close(fp);
792         }
793 
794         goto err_handler;
795       }
796 
797       /* Continue in loop to send last packet again. */
798       continue;
799     }
800 
801     /* Get the size of the data block received */
802     ul_recvsize -= TFTP_HDRSIZE;
803 
804     /* Check if the size of the received data block > max size */
805     if (ul_recvsize > TFTP_BLKSIZE) {
806       /* Send Error packet to server */
807       lwip_tftp_send_error(i_socknum,
808                            TFTPC_PROTOCOL_PROTO_ERROR,
809                            "Packet size > max size",
810                            &st_serveraddr, pst_sendbuf);
811 
812       (void)lwip_close(i_socknum);
813       if (is_localfileopened == true) {
814         close(fp);
815       }
816 
817       LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_get_file_by_filename : Packet size > max size\n"));
818 
819       ul_errcode = TFTPC_PKT_SIZE_ERROR;
820       goto err_handler;
821     }
822 
823     us_readreq = (u16_t)TFTPC_OP_ACK;
824     pst_sendbuf->us_opcode = htons(us_readreq);
825     pst_sendbuf->u.us_blknum = htons((u16_t)ul_currblk);
826     ul_size = TFTP_HDRSIZE;
827 
828     if (is_localfileopened == false) {
829       fp = open((char *)psz_tempdestname, (O_WRONLY | O_CREAT | O_TRUNC), DEFFILEMODE);
830       if (fp == TFTP_NULL_INT32) {
831         ul_errcode = TFTPC_FILECREATE_ERROR;
832         goto err_handler;
833       }
834       is_localfileopened = true;
835     }
836 
837     if (ul_recvsize != TFTP_BLKSIZE) {
838       (void)lwip_tftp_send_to_server(i_socknum, ul_size, pst_sendbuf, &st_serveraddr);
839 
840       if (ul_recvsize == 0) {
841         /* Now free allocated resourdes and return, data block receiving is already completed */
842         (void)lwip_close(i_socknum);
843         close(fp);
844         ul_errcode = ERR_OK;
845         goto err_handler;
846       }
847       /* Write the last packet to the file */
848       i_errcode = write(fp, (void *)pst_recvbuf->u.sttftp_data.uc_databuf, (size_t)ul_recvsize);
849       if (ul_recvsize != (u32_t)i_errcode) {
850         /* Write to file failed. */
851         lwip_tftp_send_error(i_socknum,
852                              TFTPC_PROTOCOL_USER_DEFINED,
853                              "Write to file failed",
854                              &st_serveraddr, pst_sendbuf);
855 
856         (void)lwip_close(i_socknum);
857         close(fp);
858 
859         /* return from the function, file write failed */
860         ul_errcode = TFTPC_FILEWRITE_ERROR;
861         goto err_handler;
862       }
863 
864       /* Now free allocated resourdes and return, data block receiving is already completed */
865       (void)lwip_close(i_socknum);
866       close(fp);
867       ul_errcode = ERR_OK;
868       goto err_handler;
869     }
870 
871     ul_errcode = lwip_tftp_send_to_server(i_socknum, ul_size,
872                                           pst_sendbuf, &st_serveraddr);
873     if (ul_errcode != ERR_OK) {
874       (void)lwip_close(i_socknum);
875       close(fp);
876       goto err_handler;
877     }
878 
879     i_errcode = write(fp, (void *)pst_recvbuf->u.sttftp_data.uc_databuf, (size_t)ul_recvsize);
880     if (ul_recvsize != (u32_t)i_errcode) {
881       /* Write to file failed. */
882       lwip_tftp_send_error(i_socknum,
883                            TFTPC_PROTOCOL_USER_DEFINED,
884                            "Write to file failed",
885                            &st_serveraddr, pst_sendbuf);
886 
887       (void)lwip_close(i_socknum);
888       close(fp);
889 
890       /* return from the function, file write failed */
891       ul_errcode = TFTPC_FILEWRITE_ERROR;
892       goto err_handler;
893     }
894 
895     /* form the ACK packet for the DATA packet received */
896     /* Go to the next packet no. */
897     ul_currblk++;
898 
899     /* if the file is too big, exit */
900     if (ul_currblk > TFTP_MAX_BLK_NUM) {
901       /* Send error packet to server */
902       lwip_tftp_send_error(i_socknum,
903                            TFTPC_PROTOCOL_USER_DEFINED,
904                            "File is too big.",
905                            &st_serveraddr, pst_sendbuf);
906 
907       (void)lwip_close(i_socknum);
908       close(fp);
909       LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_get_file_by_filename : Data block number exceeded max value\n"));
910 
911       ul_errcode = TFTPC_FILE_TOO_BIG;
912       goto err_handler;
913     }
914   }
915 
916 err_handler:
917   mem_free(pst_sendbuf);
918   mem_free(pst_recvbuf);
919   mem_free(psz_tempdestname);
920   fp = -1;
921   return ul_errcode;
922 }
923 
924 
925 /*
926  * INTERFACE Function to put a file using filename
927  * ul_hostaddr: IP address of Host
928  * sz_srcfilename: Source file
929  * sz_destdirpath: Destination file path
930  */
931 u32_t
lwip_tftp_put_file_by_filename(u32_t ul_hostaddr,u16_t us_tftpservport,u8_t uc_tftptransmode,s8_t * sz_srcfilename,s8_t * sz_destdirpath)932 lwip_tftp_put_file_by_filename(u32_t ul_hostaddr, u16_t us_tftpservport, u8_t uc_tftptransmode,
933                                s8_t *sz_srcfilename, s8_t *sz_destdirpath)
934 {
935   u32_t ul_srcstrlen;
936   u32_t ul_deststrlen;
937   s32_t i_socknum = TFTP_NULL_INT32;
938   s32_t i_errcode;
939   u32_t ul_errcode;
940   u16_t us_tempservport;
941   tftpc_packet_s *pst_sendbuf = NULL;
942   u16_t us_readreq;
943   u32_t ul_size;
944   s8_t *puc_buffer = 0;
945   s8_t *sz_tempdestname = NULL;
946 
947   /* Initialize the block number */
948   u16_t us_currblk = 0;
949   struct sockaddr_in st_serveraddr;
950   struct stat buffer;
951   s32_t fp = -1;
952 
953   /* Validate parameters */
954   if ((sz_srcfilename == NULL) || (sz_destdirpath == NULL)) {
955     return TFTPC_INVALID_PARAVALUE;
956   }
957 
958   if ((uc_tftptransmode != TRANSFER_MODE_BINARY) && (uc_tftptransmode != TRANSFER_MODE_ASCII)) {
959     return TFTPC_INVALID_PARAVALUE;
960   }
961 
962   /* check IP address not within ( 1.0.0.0 - 126.255.255.255 ) and ( 128.0.0.0 - 223.255.255.255 ) range. */
963   if (!(((ul_hostaddr >= TFTPC_IP_ADDR_MIN) && (ul_hostaddr <= TFTPC_IP_ADDR_EX_RESV)) ||
964       ((ul_hostaddr >= TFTPC_IP_ADDR_CLASS_B) && (ul_hostaddr <= TFTPC_IP_ADDR_EX_CLASS_DE)))) {
965     return TFTPC_IP_NOT_WITHIN_RANGE;
966   }
967 
968   /* If Src filename is empty or exceeded max length */
969   ul_srcstrlen = strlen((char *)sz_srcfilename);
970   if ((ul_srcstrlen == 0) || (ul_srcstrlen >= TFTP_MAX_PATH_LENGTH)) {
971     return TFTPC_SRC_FILENAME_LENGTH_ERROR;
972   }
973 
974   /* Check if source file exists */
975   if (stat((char *)sz_srcfilename, &buffer) != 0) {
976     return TFTPC_FILE_NOT_EXIST;
977   }
978 
979   /* Check if the file is too big */
980   if (buffer.st_size >= (off_t)(TFTP_MAX_BLK_NUM * TFTP_BLKSIZE)) {
981     return TFTPC_FILE_TOO_BIG;
982   }
983 
984   /* Check validity of destination path */
985   ul_deststrlen = strlen((char *)sz_destdirpath);
986   /* If dest path length exceeded max value */
987   if (ul_deststrlen >= TFTP_MAX_PATH_LENGTH) {
988     return TFTPC_DEST_PATH_LENGTH_ERROR;
989   }
990 
991   pst_sendbuf = (tftpc_packet_s *)mem_malloc(sizeof(tftpc_packet_s));
992   if (pst_sendbuf == NULL) {
993     return TFTPC_MEMALLOC_ERROR;
994   }
995 
996   /* First time intialize the buffer */
997   (void)memset_s((void *)pst_sendbuf, sizeof(tftpc_packet_s), 0, sizeof(tftpc_packet_s));
998 
999   /*
1000    * The destination path can only be one of the following:
1001    * 1. Only filename
1002    * 2. Relative path WITH filename
1003    * 3. Empty string
1004    */
1005   if (ul_deststrlen != 0) {
1006     /* If not empty string use the Destination path name */
1007     sz_tempdestname = sz_destdirpath;
1008   } else {
1009     /*
1010      * If destination directory is empty string use source filename
1011      * If given src filename is a relative path extract the file name
1012      * from the path
1013      */
1014     if ((strchr((char *)sz_srcfilename, '/') != 0) ||
1015         (strchr((char *)sz_srcfilename, '\\') != 0)) {
1016       /* Move to the end of the src file path */
1017       sz_tempdestname = sz_srcfilename + (ul_srcstrlen - 1);
1018 
1019       while (((*(sz_tempdestname - 1) != '/') && (*(sz_tempdestname - 1) != '\\')) &&
1020              (sz_tempdestname != sz_srcfilename)) {
1021         sz_tempdestname--;
1022       }
1023     } else {
1024       /* If not a relative src path use the given src filename */
1025       sz_tempdestname = sz_srcfilename;
1026     }
1027   }
1028 
1029   /* Create a socket and bind it to an available port number */
1030   ul_errcode = lwip_tftp_create_bind_socket(&i_socknum);
1031   if (ul_errcode != ERR_OK) {
1032     /* Create and Bind socket failed */
1033     goto err_handler;
1034   }
1035 
1036   if (us_tftpservport == 0) {
1037     us_tftpservport = TFTPC_SERVER_PORT;
1038   }
1039 
1040   us_tempservport = us_tftpservport;
1041 
1042   /* set server internet address */
1043   (void)memset_s(&st_serveraddr, sizeof(st_serveraddr), 0, sizeof(st_serveraddr));
1044   st_serveraddr.sin_family = AF_INET;
1045   st_serveraddr.sin_port = htons(us_tempservport);
1046   st_serveraddr.sin_addr.s_addr = htonl(ul_hostaddr);
1047 
1048   /* Make request packet - TFTPC_OP_WRQ */
1049   ul_size = (u32_t)lwip_tftp_make_tftp_packet(TFTPC_OP_WRQ,
1050                                               sz_tempdestname,
1051                                               uc_tftptransmode,
1052                                               pst_sendbuf);
1053 
1054   ul_errcode = lwip_tftp_send_to_server(i_socknum, ul_size,
1055                                         pst_sendbuf, &st_serveraddr);
1056   if (ul_errcode != ERR_OK) {
1057     /* Send to server error */
1058     (void)lwip_close(i_socknum);
1059 
1060     goto err_handler;
1061   }
1062 
1063   /* Send the request packet */
1064   ul_errcode = lwip_tftp_inner_put_file(i_socknum, pst_sendbuf, ul_size,
1065                                         us_currblk, &st_serveraddr);
1066   if (ul_errcode != ERR_OK) {
1067     /* Send request packet failed */
1068     (void)lwip_close(i_socknum);
1069 
1070     LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_put_file_by_filename : Failed to send request packet\n"));
1071 
1072     goto err_handler;
1073   }
1074 
1075   /* Create buffer block size */
1076   puc_buffer = mem_malloc(TFTP_BLKSIZE);
1077   if (puc_buffer == NULL) {
1078     /* Memory allocation failed */
1079     lwip_tftp_send_error(i_socknum,
1080                          TFTPC_PROTOCOL_USER_DEFINED,
1081                          "Memory allocation failed.",
1082                          &st_serveraddr, pst_sendbuf);
1083 
1084     (void)lwip_close(i_socknum);
1085     ul_errcode = TFTPC_MEMALLOC_ERROR;
1086     goto err_handler;
1087   }
1088 
1089   (void)memset_s((void *)puc_buffer, TFTP_BLKSIZE, 0, TFTP_BLKSIZE);
1090 
1091   fp = open((char *)sz_srcfilename, O_RDONLY);
1092   if (fp == TFTP_NULL_INT32) {
1093     /* If file could not be opened send error to server */
1094     lwip_tftp_send_error(i_socknum,
1095                          TFTPC_PROTOCOL_USER_DEFINED,
1096                          "File open error.",
1097                          &st_serveraddr, pst_sendbuf);
1098 
1099     (void)lwip_close(i_socknum);
1100     close(fp);
1101     mem_free(puc_buffer);
1102 
1103     ul_errcode = TFTPC_FILEOPEN_ERROR;
1104     goto err_handler;
1105   }
1106 
1107   i_errcode = read(fp, puc_buffer, TFTP_BLKSIZE);
1108   if (i_errcode < 0) {
1109     /* If failed to read from file */
1110     lwip_tftp_send_error(i_socknum,
1111                          TFTPC_PROTOCOL_USER_DEFINED,
1112                          "File read error.",
1113                          &st_serveraddr, pst_sendbuf);
1114 
1115     (void)lwip_close(i_socknum);
1116     close(fp);
1117     mem_free(puc_buffer);
1118 
1119     ul_errcode = TFTPC_FILEREAD_ERROR;
1120     goto err_handler;
1121   }
1122 
1123   /*
1124    * Read from source file and send to server
1125    * To send empty packet to server when file is a 0 byte file
1126    */
1127   do {
1128     if (((u32_t)us_currblk + 1) > TFTP_MAX_BLK_NUM) {
1129       lwip_tftp_send_error(i_socknum,
1130                            TFTPC_PROTOCOL_USER_DEFINED,
1131                            "File is too big.",
1132                            &st_serveraddr, pst_sendbuf);
1133 
1134       (void)lwip_close(i_socknum);
1135       close(fp);
1136       mem_free(puc_buffer);
1137       LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_put_file_by_filename : Data block number exceeded max value\n"));
1138 
1139       ul_errcode = TFTPC_FILE_TOO_BIG;
1140       goto err_handler;
1141     }
1142 
1143     /* Increment block number */
1144     us_currblk++;
1145 
1146     ul_size = (u32_t)i_errcode + TFTP_HDRSIZE;
1147 
1148     /* Form the DATA packet */
1149     us_readreq = (u16_t)TFTPC_OP_DATA;
1150     pst_sendbuf->us_opcode = htons(us_readreq);
1151     pst_sendbuf->u.sttftp_data.us_blknum = htons(us_currblk);
1152     if (memcpy_s((void *)pst_sendbuf->u.sttftp_data.uc_databuf, TFTP_BLKSIZE,
1153                  (void *)puc_buffer, (u32_t)i_errcode) != EOK) {
1154       (void)lwip_close(i_socknum);
1155       close(fp);
1156       mem_free(puc_buffer);
1157       goto err_handler;
1158     }
1159 
1160     ul_errcode = lwip_tftp_send_to_server(i_socknum, ul_size,
1161                                           pst_sendbuf, &st_serveraddr);
1162     if ((ul_errcode != ERR_OK) || (memset_s((void *)puc_buffer, TFTP_BLKSIZE, 0, TFTP_BLKSIZE) != EOK)) {
1163       (void)lwip_close(i_socknum);
1164       close(fp);
1165       mem_free(puc_buffer);
1166       goto err_handler;
1167     }
1168 
1169     /* Read a block from the file to buffer */
1170     i_errcode = read(fp, puc_buffer, TFTP_BLKSIZE);
1171     if (i_errcode < 0) {
1172       /* If failed to read from file */
1173       lwip_tftp_send_error(i_socknum, TFTPC_PROTOCOL_USER_DEFINED, "File read error.",
1174                            &st_serveraddr, pst_sendbuf);
1175 
1176       (void)lwip_close(i_socknum);
1177       close(fp);
1178       mem_free(puc_buffer);
1179       ul_errcode = TFTPC_FILEREAD_ERROR;
1180       goto err_handler;
1181     }
1182 
1183     /* Send the request packet */
1184     ul_errcode = lwip_tftp_inner_put_file(i_socknum, pst_sendbuf, ul_size,
1185                                           us_currblk, &st_serveraddr);
1186     if (ul_errcode != ERR_OK) {
1187       /* Sending buffer contents failed */
1188       (void)lwip_close(i_socknum);
1189       close(fp);
1190       mem_free(puc_buffer);
1191       LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_put_file_by_filename : Sending file to server failed\n"));
1192       goto err_handler;
1193     }
1194   } while (ul_size == (TFTP_BLKSIZE + TFTP_HDRSIZE));
1195 
1196   /* Transfer of data is finished */
1197   (void)lwip_close(i_socknum);
1198   close(fp);
1199   mem_free(puc_buffer);
1200 
1201   ul_errcode = ERR_OK;
1202 err_handler:
1203   mem_free(pst_sendbuf);
1204   fp = -1;
1205   return ul_errcode;
1206 }
1207 
1208 /*
1209  * Put file function
1210  * i_socknum: Socket ID
1211  * pst_sendbuf: Packet to send to server
1212  * ul_sendsize: Packet length
1213  * us_currblk: Current block number
1214  * pst_serveraddr: Server address
1215  */
1216 u32_t
lwip_tftp_inner_put_file(s32_t i_socknum,tftpc_packet_s * pst_sendbuf,u32_t ul_sendsize,u16_t us_currblk,struct sockaddr_in * pst_serveraddr)1217 lwip_tftp_inner_put_file(s32_t i_socknum,
1218                          tftpc_packet_s *pst_sendbuf,
1219                          u32_t ul_sendsize,
1220                          u16_t us_currblk,
1221                          struct sockaddr_in *pst_serveraddr)
1222 {
1223   u32_t ul_pktsize;
1224   u32_t ul_error;
1225   s32_t i_error;
1226   int i_recvlen = 0;
1227   socklen_t i_fromaddrlen;
1228   u32_t ul_totaltime = 0;
1229   fd_set st_readfds;
1230   struct sockaddr_in st_fromaddr;
1231   struct timeval st_timeout;
1232   tftpc_packet_s *pst_recvbuf = NULL;
1233   u32_t ul_ignorepkt = 0;
1234   u16_t us_blknum;
1235   u32_t ul_loopcnt = 0;
1236   if ((pst_sendbuf == NULL) || (pst_serveraddr == NULL)) {
1237     return ERR_ARG;
1238   }
1239   i_fromaddrlen = sizeof(st_fromaddr);
1240 
1241   pst_recvbuf = (tftpc_packet_s *)mem_malloc(sizeof(tftpc_packet_s));
1242   if (pst_recvbuf == NULL) {
1243     return TFTPC_MEMALLOC_ERROR;
1244   }
1245 
1246   /* First time intialize the buffer */
1247   (void)memset_s((void *)pst_recvbuf, sizeof(tftpc_packet_s), 0, sizeof(tftpc_packet_s));
1248 
1249   /* Initialize from address to the server address at first */
1250   if (memcpy_s((void *)&st_fromaddr, sizeof(struct sockaddr_in),
1251                (void *)pst_serveraddr, sizeof(st_fromaddr)) != EOK) {
1252     ul_error = TFTPC_MEMCPY_FAILURE;
1253     goto err_handler;
1254   }
1255 
1256   for (;;) {
1257     ul_error = lwip_tftp_recv_from_server(i_socknum, &ul_pktsize,
1258                                           pst_recvbuf, &ul_ignorepkt,
1259                                           pst_serveraddr, pst_sendbuf);
1260     /* If select timeout occured */
1261     if (ul_error == TFTPC_TIMEOUT_ERROR) {
1262       ul_totaltime++;
1263       if (ul_totaltime < TFTPC_MAX_SEND_REQ_ATTEMPTS) {
1264         /* Max attempts not reached. Resend packet */
1265         ul_error = lwip_tftp_send_to_server(i_socknum, ul_sendsize,
1266                                             pst_sendbuf, pst_serveraddr);
1267         if (ul_error != ERR_OK) {
1268           goto err_handler;
1269         }
1270 
1271         continue;
1272       } else {
1273         /* return from the function, max attempts limit reached */
1274         ul_error = TFTPC_TIMEOUT_ERROR;
1275         goto err_handler;
1276       }
1277     } else if (ul_error != ERR_OK) {
1278       /* return from the function, RecvFromServer failed */
1279       goto err_handler;
1280     }
1281 
1282     /* If Received packet from another server */
1283     if (ul_ignorepkt > 0) {
1284       /* The packet that is received is to be ignored. So continue without processing it. */
1285       ul_ignorepkt = 0;
1286       continue;
1287     }
1288 
1289     /* if this packet is unknown or incorrect packet */
1290     if (ntohs(pst_recvbuf->us_opcode) != TFTPC_OP_ACK) {
1291       lwip_tftp_send_error(i_socknum,
1292                            TFTPC_PROTOCOL_PROTO_ERROR,
1293                            "Protocol error.",
1294                            pst_serveraddr, pst_sendbuf);
1295 
1296       LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_inner_put_file : Received pkt not Ack pkt\n"));
1297 
1298       ul_error = TFTPC_PROTO_ERROR;
1299       goto err_handler;
1300     }
1301 
1302     ul_totaltime = 0;
1303 
1304     /* if the packet is acknowledge packet */
1305     us_blknum = ntohs(pst_recvbuf->u.us_blknum);
1306     i_recvlen = (int)ul_pktsize;
1307 
1308     /* If not correct block no. */
1309     if (us_blknum != us_currblk) {
1310       /* we are not in sync now */
1311       /* reset any collected packets. */
1312       st_timeout.tv_sec = 1;
1313       st_timeout.tv_usec = 0;
1314 
1315       FD_ZERO(&st_readfds);
1316       FD_SET(i_socknum, &st_readfds);
1317 
1318       /*
1319        * Need to take care of timeout scenario in Select call.
1320        * Since the socket used is blocking, if select timeout occurs,
1321        * the following recvfrom will block indefinitely.
1322        */
1323       i_error = lwip_select((s32_t)(i_socknum + 1), &st_readfds, 0, 0, &st_timeout);
1324 
1325        /* Loop to get the last data packet from the receive buffer */
1326       while ((i_error != -1) && (i_error != 0)) {
1327         ul_loopcnt++;
1328 
1329         /*
1330          * MAX file size in TFTP is 32 MB.
1331          * Reason for keeping 75 here , is ((75*512=38400bytes)/1024) =  37MB. So the recv/Snd
1332          * Loop can receive the complete MAX message from the network.
1333          */
1334         if (ul_loopcnt > TFTPC_MAX_WAIT_IN_LOOP) {
1335           LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_inner_put_file : unexpected packets are received repeatedly\n"));
1336           ul_error = TFTPC_PKT_SIZE_ERROR;
1337           goto err_handler;
1338         }
1339 
1340         FD_ZERO(&st_readfds);
1341         FD_SET(i_socknum, &st_readfds);
1342         i_recvlen = lwip_recvfrom(i_socknum,
1343                                   (s8_t *)pst_recvbuf,
1344                                   TFTP_PKTSIZE, 0,
1345                                   (struct sockaddr *)&st_fromaddr,
1346                                   &i_fromaddrlen);
1347         if (TFTP_NULL_INT32 == i_recvlen) {
1348           ul_error = TFTPC_RECVFROM_ERROR;
1349           goto err_handler;
1350         }
1351 
1352         st_timeout.tv_sec = 1;
1353         st_timeout.tv_usec = 0;
1354         i_error = lwip_select((s32_t)(i_socknum + 1),
1355                               &st_readfds, 0, 0, &st_timeout);
1356       }
1357 
1358       /*
1359        * If a new packet is not received then donot change the byte order
1360        * as it has already been done
1361        */
1362       /* If received packet size < minimum packet size */
1363       if (i_recvlen < TFTPC_FOUR) {
1364         lwip_tftp_send_error(i_socknum,
1365                              TFTPC_PROTOCOL_PROTO_ERROR,
1366                              "Packet size < min packet size",
1367                              pst_serveraddr, pst_sendbuf);
1368 
1369         LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_inner_put_file : Received pkt not Ack pkt\n"));
1370 
1371         ul_error = TFTPC_PKT_SIZE_ERROR;
1372         goto err_handler;
1373       }
1374 
1375       /* Check if the received packet is from correct server and from correct port */
1376       if ((st_fromaddr.sin_addr.s_addr != pst_serveraddr->sin_addr.s_addr) ||
1377           (pst_serveraddr->sin_port != st_fromaddr.sin_port)) {
1378         /* This ACK packet is invalid. Just ignore it. */
1379         LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_inner_put_file : Received pkt from unknown server\n"));
1380         continue;
1381       }
1382 
1383       /* if this packet is not ACK packet */
1384       if (TFTPC_OP_ACK != ntohs(pst_recvbuf->us_opcode)) {
1385         lwip_tftp_send_error(i_socknum,
1386                              TFTPC_PROTOCOL_PROTO_ERROR,
1387                              "Protocol error.",
1388                              pst_serveraddr, pst_sendbuf);
1389 
1390         LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_inner_put_file : Received pkt not Ack pkt\n"));
1391 
1392         ul_error = TFTPC_PROTO_ERROR;
1393         goto err_handler;
1394       }
1395 
1396       us_blknum = ntohs(pst_recvbuf->u.us_blknum);
1397       /*
1398        * In this case we have received a duplicate ACK for data block.
1399        * (ACK for this data block was aready received earlier)
1400        * In this case we have usRecvBlkNum == (usNextBlkNum - 1).
1401        * This could mean that:
1402        * (i) last data packet that was sent was not received at server side
1403        * (ii) Acknowledgement of peer side is delayed.
1404        *
1405        * In this case, this duplicate ACK will be ignored and return to the
1406        * state machine to initiate a receive of this data packet.
1407        */
1408       if ((us_currblk - 1) == us_blknum) {
1409         /* This ACK packet is invalid. Just ignore it. */
1410         continue;
1411       }
1412       /*
1413        * Now check the block number with current block
1414        * If it is not the previous block and the current block,
1415        * then it is an unexpected packet.
1416        */
1417       if (us_blknum != us_currblk) {
1418         lwip_tftp_send_error(i_socknum,
1419                              TFTPC_PROTOCOL_PROTO_ERROR,
1420                              "Received unexpected packet",
1421                              pst_serveraddr, pst_sendbuf);
1422 
1423         LWIP_DEBUGF(TFTP_DEBUG,
1424                     ("lwip_tftp_inner_put_file : Received DATA pkt no. %"S32_F"instead of pkt no. %"S32_F"\n",
1425                      us_blknum, us_currblk));
1426 
1427         ul_error = TFTPC_SYNC_FAILURE;
1428         goto err_handler;
1429       }
1430     }
1431 
1432     ul_error = ERR_OK;
1433     goto err_handler;
1434   }
1435 
1436 err_handler:
1437   mem_free(pst_recvbuf);
1438   return ul_error;
1439 }
1440 
1441 /*
1442  * INTEFACE to get a file using filename
1443  * ul_hostaddr - IP address of Host
1444  * sz_srcfilename - Source file
1445  * sz_destmemaddr - The target memory address in the client
1446  *
1447  * Example :
1448  * ul_hostaddr = ntohl(inet_addr ("192.168.1.3"));
1449  * lwip_tftp_get_file_by_filename_to_rawmem(ul_hostaddr, "/ramfs/vs_server.bin", memaddr, &filelen);
1450  */
1451 u32_t
lwip_tftp_get_file_by_filename_to_rawmem(u32_t ul_hostaddr,u16_t us_tftpservport,u8_t uc_tftptransmode,const s8_t * sz_srcfilename,s8_t * sz_destmemaddr,u32_t * ul_flelength)1452 lwip_tftp_get_file_by_filename_to_rawmem(u32_t ul_hostaddr,
1453                                          u16_t us_tftpservport,
1454                                          u8_t uc_tftptransmode,
1455                                          const s8_t *sz_srcfilename,
1456                                          s8_t *sz_destmemaddr,
1457                                          u32_t *ul_flelength)
1458 {
1459   s32_t i_socknum = TFTP_NULL_INT32;
1460   u32_t ul_srcstrlen;
1461   u32_t ul_size;
1462   u32_t ul_recvsize = TFTP_NULL_UINT32;
1463   u32_t ul_errcode;
1464   u16_t us_readreq;
1465   u16_t us_tempservport;
1466   u32_t ul_currblk = 1;
1467   u32_t ul_resendpkt = 0; /* Resend the previous packet */
1468   u32_t ul_ignorepkt = 0; /* Ignore received packet */
1469   u32_t ul_totaltime = 0;
1470 
1471   tftpc_packet_s *pst_sendbuf = NULL;
1472   tftpc_packet_s *pst_recvbuf = NULL;
1473   struct sockaddr_in st_serveraddr;
1474   u32_t ul_memoffset = 0;
1475 
1476   /* Validate the parameters */
1477   if ((sz_srcfilename == NULL) || (sz_destmemaddr == NULL) || (*ul_flelength == 0)) {
1478     return TFTPC_INVALID_PARAVALUE;
1479   }
1480 
1481   if ((uc_tftptransmode != TRANSFER_MODE_BINARY) && (uc_tftptransmode != TRANSFER_MODE_ASCII)) {
1482     return TFTPC_INVALID_PARAVALUE;
1483   }
1484 
1485   /* check IP address not within ( 1.0.0.0 - 126.255.255.255 ) and ( 128.0.0.0 - 223.255.255.255 ) range. */
1486   if (!(((ul_hostaddr >= TFTPC_IP_ADDR_MIN) && (ul_hostaddr <= TFTPC_IP_ADDR_EX_RESV)) ||
1487       ((ul_hostaddr >= TFTPC_IP_ADDR_CLASS_B) && (ul_hostaddr <= TFTPC_IP_ADDR_EX_CLASS_DE)))) {
1488     return TFTPC_IP_NOT_WITHIN_RANGE;
1489   }
1490 
1491   /* Check validity of source filename */
1492   ul_srcstrlen = strlen((const char *)sz_srcfilename);
1493   if ((ul_srcstrlen == 0) || (ul_srcstrlen >= TFTP_MAX_PATH_LENGTH)) {
1494     return TFTPC_SRC_FILENAME_LENGTH_ERROR;
1495   }
1496 
1497   pst_sendbuf = (tftpc_packet_s *)mem_malloc(sizeof(tftpc_packet_s));
1498   if (pst_sendbuf == NULL) {
1499     return TFTPC_MEMALLOC_ERROR;
1500   }
1501 
1502   pst_recvbuf = (tftpc_packet_s *)mem_malloc(sizeof(tftpc_packet_s));
1503   if (pst_recvbuf == NULL) {
1504     mem_free(pst_sendbuf);
1505     return TFTPC_MEMALLOC_ERROR;
1506   }
1507 
1508   /* First time initialize the buffers */
1509   (void)memset_s((void *)pst_sendbuf, sizeof(tftpc_packet_s), 0, sizeof(tftpc_packet_s));
1510   (void)memset_s((void *)pst_recvbuf, sizeof(tftpc_packet_s), 0, sizeof(tftpc_packet_s));
1511 
1512   ul_errcode = lwip_tftp_create_bind_socket(&i_socknum);
1513   if (ul_errcode != ERR_OK) {
1514     goto err_handler;
1515   }
1516 
1517   if (us_tftpservport == 0) {
1518     us_tftpservport = TFTPC_SERVER_PORT;
1519   }
1520 
1521   us_tempservport = us_tftpservport;
1522 
1523   /* set server IP address */
1524   (void)memset_s(&st_serveraddr, sizeof(st_serveraddr), 0, sizeof(st_serveraddr));
1525   st_serveraddr.sin_family = AF_INET;
1526   st_serveraddr.sin_port = htons(us_tempservport);
1527   st_serveraddr.sin_addr.s_addr = htonl(ul_hostaddr);
1528 
1529   /* Make a request packet - TFTPC_OP_RRQ */
1530   ul_size = (u32_t)lwip_tftp_make_tftp_packet(TFTPC_OP_RRQ, sz_srcfilename, (u32_t)uc_tftptransmode, pst_sendbuf);
1531   ul_errcode = lwip_tftp_send_to_server(i_socknum, ul_size, pst_sendbuf, &st_serveraddr);
1532   if (ul_errcode != ERR_OK) {
1533     /* send to server failed */
1534     (void)lwip_close(i_socknum);
1535     goto err_handler;
1536   }
1537 
1538   for (;;) {
1539     if (ul_ignorepkt > 0) {
1540       ul_ignorepkt = 0;
1541     }
1542 
1543     ul_errcode = lwip_tftp_recv_from_server(i_socknum, &ul_recvsize, pst_recvbuf, &ul_ignorepkt,
1544                                             &st_serveraddr, pst_sendbuf);
1545     /* If select timeout occured */
1546     if (ul_errcode == TFTPC_TIMEOUT_ERROR) {
1547       ul_totaltime++;
1548       if (ul_totaltime < TFTPC_MAX_SEND_REQ_ATTEMPTS) {
1549         /* Max attempts not reached. Resend packet */
1550         ul_errcode = lwip_tftp_send_to_server(i_socknum, ul_size,
1551                                               pst_sendbuf, &st_serveraddr);
1552         if (ul_errcode != ERR_OK) {
1553           (void)lwip_close(i_socknum);
1554           goto err_handler;
1555         }
1556 
1557         continue;
1558       } else {
1559         /* return from the function, max attempts limit reached */
1560         (void)lwip_close(i_socknum);
1561         ul_errcode = TFTPC_TIMEOUT_ERROR;
1562         goto err_handler;
1563       }
1564     } else if (ul_errcode != ERR_OK) {
1565       (void)lwip_close(i_socknum);
1566       goto err_handler;
1567     }
1568 
1569     /* Now we have receive block from different server. */
1570     if (ul_ignorepkt > 0) {
1571       /* Continue without processing this block. */
1572       continue;
1573     }
1574 
1575     /* if this packet is unkonwn or incorrect packet */
1576     if (ntohs(pst_recvbuf->us_opcode) != TFTPC_OP_DATA) {
1577       /* Send error packet to server */
1578       lwip_tftp_send_error(i_socknum,
1579                            TFTPC_PROTOCOL_PROTO_ERROR,
1580                            "Protocol error.",
1581                            &st_serveraddr, pst_sendbuf);
1582 
1583       (void)lwip_close(i_socknum);
1584 
1585       LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_get_file_by_filename : Received pkt not DATA pkt\n"));
1586 
1587       ul_errcode = TFTPC_PROTO_ERROR;
1588       goto err_handler;
1589     }
1590 
1591     /* Now the number of tries will be reset. */
1592     ul_totaltime = 0;
1593 
1594     /* Validate received  DATA packet. */
1595     ul_errcode = lwip_tftp_validate_data_pkt(i_socknum, &ul_recvsize,
1596                                              pst_recvbuf, (u16_t)ul_currblk,
1597                                              &ul_resendpkt,
1598                                              &st_serveraddr);
1599     if (ul_errcode != ERR_OK) {
1600       /* Send Error packet to server */
1601       if (ul_errcode != TFTPC_RECVFROM_ERROR) {
1602         lwip_tftp_send_error(i_socknum,
1603                              TFTPC_PROTOCOL_PROTO_ERROR,
1604                              "Received unexpected packet",
1605                              &st_serveraddr, pst_sendbuf);
1606       }
1607 
1608       (void)lwip_close(i_socknum);
1609 
1610       goto err_handler;
1611     }
1612 
1613     /* Received previous data block again. Resend last packet */
1614     if (ul_resendpkt > 0) {
1615       /* Now set ul_resendpkt to 0 to send the last packet. */
1616       ul_resendpkt = 0;
1617       ul_errcode = lwip_tftp_send_to_server(i_socknum, ul_size,
1618                                             pst_sendbuf, &st_serveraddr);
1619       if (ul_errcode != ERR_OK) {
1620         (void)lwip_close(i_socknum);
1621 
1622         goto err_handler;
1623       }
1624 
1625       /* Continue in loop to send last packet again. */
1626       continue;
1627     }
1628 
1629     /* Get the size of the data block received */
1630     ul_recvsize -= TFTP_HDRSIZE;
1631 
1632     /* Check if the size of the received data block > max size */
1633     if (ul_recvsize > TFTP_BLKSIZE) {
1634       /* Send Error packet to server */
1635       lwip_tftp_send_error(i_socknum,
1636                            TFTPC_PROTOCOL_PROTO_ERROR,
1637                            "Packet size > max size",
1638                            &st_serveraddr, pst_sendbuf);
1639 
1640       (void)lwip_close(i_socknum);
1641 
1642       LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_get_file_by_filename : Packet size > max size\n"));
1643 
1644       ul_errcode = TFTPC_PKT_SIZE_ERROR;
1645       goto err_handler;
1646     }
1647 
1648     us_readreq = (u16_t)TFTPC_OP_ACK;
1649     pst_sendbuf->us_opcode = htons(us_readreq);
1650     pst_sendbuf->u.us_blknum = htons((u16_t)ul_currblk);
1651     ul_size = TFTP_HDRSIZE;
1652 
1653     if (ul_recvsize != TFTP_BLKSIZE) {
1654       (void)lwip_tftp_send_to_server(i_socknum, ul_size,
1655                                      pst_sendbuf, &st_serveraddr);
1656 
1657       /* If the received packet has only header and do not have payload, the return failure */
1658       if (ul_recvsize != 0) {
1659         /* memcopy filed */
1660         if (*ul_flelength < (ul_memoffset + ul_recvsize)) {
1661           ul_errcode = TFTPC_MEMCPY_FAILURE;
1662           (void)lwip_close(i_socknum);
1663           *ul_flelength = ul_memoffset;
1664           goto err_handler;
1665         }
1666         /* copy the last packet to the memory */
1667         if (memcpy_s(sz_destmemaddr + ul_memoffset, TFTP_MAX_BLK_NUM * TFTP_BLKSIZE,
1668                      (void *)pst_recvbuf->u.sttftp_data.uc_databuf, (size_t)ul_recvsize) != EOK) {
1669           ul_errcode = TFTPC_MEMCPY_FAILURE;
1670           (void)lwip_close(i_socknum);
1671           *ul_flelength = ul_memoffset;
1672           goto err_handler;
1673         }
1674         ul_memoffset += ul_recvsize;
1675       }
1676 
1677       /* Now free allocated resourdes and return, data block receiving is already completed */
1678       (void)lwip_close(i_socknum);
1679       ul_errcode = ERR_OK;
1680       *ul_flelength = ul_memoffset;
1681       goto err_handler;
1682     }
1683 
1684     ul_errcode = lwip_tftp_send_to_server(i_socknum, ul_size,
1685                                           pst_sendbuf, &st_serveraddr);
1686     if (ul_errcode != ERR_OK) {
1687       (void)lwip_close(i_socknum);
1688       goto err_handler;
1689     }
1690 
1691     /* memcopy filed */
1692     if (*ul_flelength < (ul_recvsize * ul_currblk)) {
1693       ul_errcode = TFTPC_MEMCPY_FAILURE;
1694       (void)lwip_close(i_socknum);
1695       *ul_flelength = ul_memoffset;
1696       goto err_handler;
1697     }
1698     if (memcpy_s(sz_destmemaddr + ul_memoffset, TFTP_MAX_BLK_NUM * TFTP_BLKSIZE,
1699                  (void *)pst_recvbuf->u.sttftp_data.uc_databuf, (size_t)ul_recvsize) != EOK) {
1700       ul_errcode = TFTPC_MEMCPY_FAILURE;
1701       (void)lwip_close(i_socknum);
1702       *ul_flelength = ul_memoffset;
1703       goto err_handler;
1704     }
1705 
1706     ul_memoffset += ul_recvsize;
1707     /* form the ACK packet for the DATA packet received */
1708     /* Go to the next packet no. */
1709     ul_currblk++;
1710     /* if the file is too big, exit */
1711     if (ul_currblk > TFTP_MAX_BLK_NUM) {
1712       /* Send error packet to server */
1713       lwip_tftp_send_error(i_socknum,
1714                            TFTPC_PROTOCOL_USER_DEFINED,
1715                            "File is too big.",
1716                            &st_serveraddr, pst_sendbuf);
1717 
1718       (void)lwip_close(i_socknum);
1719 
1720       LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_get_file_by_filename : Data block number exceeded max value\n"));
1721 
1722       ul_errcode = TFTPC_FILE_TOO_BIG;
1723       goto err_handler;
1724     }
1725   }
1726 
1727 err_handler:
1728   mem_free(pst_sendbuf);
1729   mem_free(pst_recvbuf);
1730   return ul_errcode;
1731 }
1732 #endif
1733 
1734 #endif /* LWIP_TFTP */
1735