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