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