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