10d163575Sopenharmony_ci/*
20d163575Sopenharmony_ci * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
30d163575Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
40d163575Sopenharmony_ci *
50d163575Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification,
60d163575Sopenharmony_ci * are permitted provided that the following conditions are met:
70d163575Sopenharmony_ci *
80d163575Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of
90d163575Sopenharmony_ci *    conditions and the following disclaimer.
100d163575Sopenharmony_ci *
110d163575Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list
120d163575Sopenharmony_ci *    of conditions and the following disclaimer in the documentation and/or other materials
130d163575Sopenharmony_ci *    provided with the distribution.
140d163575Sopenharmony_ci *
150d163575Sopenharmony_ci * 3. Neither the name of the copyright holder nor the names of its contributors may be used
160d163575Sopenharmony_ci *    to endorse or promote products derived from this software without specific prior written
170d163575Sopenharmony_ci *    permission.
180d163575Sopenharmony_ci *
190d163575Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
200d163575Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
210d163575Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
220d163575Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
230d163575Sopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
240d163575Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
250d163575Sopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
260d163575Sopenharmony_ci * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
270d163575Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
280d163575Sopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
290d163575Sopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
300d163575Sopenharmony_ci */
310d163575Sopenharmony_ci
320d163575Sopenharmony_ci/* TFTP Client utility */
330d163575Sopenharmony_ci
340d163575Sopenharmony_ci#include "tftpc.h"
350d163575Sopenharmony_ci
360d163575Sopenharmony_ci#if LWIP_TFTP /* don't build if not configured for use in lwipopts.h */
370d163575Sopenharmony_ci
380d163575Sopenharmony_ci#include <fcntl.h>
390d163575Sopenharmony_ci#include <string.h>
400d163575Sopenharmony_ci#include <unistd.h>
410d163575Sopenharmony_ci#include <sys/socket.h>
420d163575Sopenharmony_ci#include <arpa/inet.h>
430d163575Sopenharmony_ci#include <netinet/in.h>
440d163575Sopenharmony_ci#include <sys/stat.h>
450d163575Sopenharmony_ci#include <sys/select.h>
460d163575Sopenharmony_ci#include <sys/ioctl.h>
470d163575Sopenharmony_ci#include <sys/types.h>
480d163575Sopenharmony_ci#include <assert.h>
490d163575Sopenharmony_ci#include <stdio.h>
500d163575Sopenharmony_ci#include <stdlib.h>
510d163575Sopenharmony_ci#include <securec.h>
520d163575Sopenharmony_ci
530d163575Sopenharmony_ci/* Function Declarations */
540d163575Sopenharmony_ci#ifdef LOSCFG_NET_LWIP_SACK_TFTP
550d163575Sopenharmony_cistatic u32_t lwip_tftp_create_bind_socket(s32_t *piSocketID);
560d163575Sopenharmony_ci
570d163575Sopenharmony_cistatic s32_t lwip_tftp_make_tftp_packet(u16_t usOpcode, s8_t *szFileName,
580d163575Sopenharmony_ci                                        u32_t ulMode, TFTPC_PACKET_S *pstPacket);
590d163575Sopenharmony_ci
600d163575Sopenharmony_cistatic u32_t lwip_tftp_recv_from_server(s32_t iSockNum,
610d163575Sopenharmony_ci                                 u32_t *pulSize,
620d163575Sopenharmony_ci                                 TFTPC_PACKET_S *pstRecvBuf,
630d163575Sopenharmony_ci                                 u32_t *pulIgnorePkt,
640d163575Sopenharmony_ci                                 struct sockaddr_in *pstServerAddr,
650d163575Sopenharmony_ci                                 TFTPC_PACKET_S *pstSendBuf);
660d163575Sopenharmony_ci
670d163575Sopenharmony_cistatic u32_t lwip_tftp_send_to_server(s32_t iSockNum, u32_t ulSize,
680d163575Sopenharmony_ci                               TFTPC_PACKET_S *pstSendBuf,
690d163575Sopenharmony_ci                               struct sockaddr_in *pstServerAddr);
700d163575Sopenharmony_ci
710d163575Sopenharmony_cistatic u32_t lwip_tftp_validate_data_pkt(s32_t iSockNum,
720d163575Sopenharmony_ci                                  u32_t *pulSize,
730d163575Sopenharmony_ci                                  TFTPC_PACKET_S *pstRecvBuf,
740d163575Sopenharmony_ci                                  u16_t usCurrBlk, u32_t *pulResendPkt,
750d163575Sopenharmony_ci                                  struct sockaddr_in *pstServerAddr);
760d163575Sopenharmony_ci
770d163575Sopenharmony_cistatic u32_t lwip_tftp_inner_put_file(s32_t iSockNum, TFTPC_PACKET_S *pstSendBuf,
780d163575Sopenharmony_ci                               u32_t ulSendSize, u16_t usCurrBlk,
790d163575Sopenharmony_ci                               struct sockaddr_in *pstServerAddr);
800d163575Sopenharmony_ci
810d163575Sopenharmony_cistatic void lwip_tftp_send_error(s32_t iSockNum, u32_t ulError, const char *szErrMsg,
820d163575Sopenharmony_ci                                 struct sockaddr_in *pstServerAddr, TFTPC_PACKET_S *pstSendBuf);
830d163575Sopenharmony_ci
840d163575Sopenharmony_ci
850d163575Sopenharmony_ci/* Create and bind a UDP socket. */
860d163575Sopenharmony_ciu32_t lwip_tftp_create_bind_socket(s32_t *piSocketID)
870d163575Sopenharmony_ci{
880d163575Sopenharmony_ci    int retval;
890d163575Sopenharmony_ci    struct sockaddr_in stClientAddr;
900d163575Sopenharmony_ci    u32_t ulTempClientIp;
910d163575Sopenharmony_ci    u32_t set_non_block_socket = 1;
920d163575Sopenharmony_ci
930d163575Sopenharmony_ci    /* create a socket */
940d163575Sopenharmony_ci    *piSocketID = lwip_socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
950d163575Sopenharmony_ci    if (*piSocketID == -1) {
960d163575Sopenharmony_ci        LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_create_bind_socket : lwip_socket create socket failed\n"));
970d163575Sopenharmony_ci        return TFTPC_SOCKET_FAILURE;
980d163575Sopenharmony_ci    }
990d163575Sopenharmony_ci
1000d163575Sopenharmony_ci    /* Make the socket as NON-BLOCKING. */
1010d163575Sopenharmony_ci    retval = lwip_ioctl(*piSocketID, (long)FIONBIO, &set_non_block_socket);
1020d163575Sopenharmony_ci    if (retval != 0) {
1030d163575Sopenharmony_ci        (void)lwip_close(*piSocketID);
1040d163575Sopenharmony_ci        *piSocketID = TFTP_NULL_INT32;
1050d163575Sopenharmony_ci        return TFTPC_IOCTLSOCKET_FAILURE;
1060d163575Sopenharmony_ci    }
1070d163575Sopenharmony_ci
1080d163575Sopenharmony_ci    ulTempClientIp = INADDR_ANY;
1090d163575Sopenharmony_ci
1100d163575Sopenharmony_ci    /* specify a local address for this socket */
1110d163575Sopenharmony_ci    (void)memset_s(&stClientAddr, sizeof(stClientAddr), 0, sizeof(stClientAddr));
1120d163575Sopenharmony_ci    stClientAddr.sin_family = AF_INET;
1130d163575Sopenharmony_ci    stClientAddr.sin_port = 0;
1140d163575Sopenharmony_ci    stClientAddr.sin_addr.s_addr = htonl(ulTempClientIp);
1150d163575Sopenharmony_ci
1160d163575Sopenharmony_ci    retval = lwip_bind(*piSocketID, (struct sockaddr *)&stClientAddr, sizeof(stClientAddr));
1170d163575Sopenharmony_ci    if (retval != 0) {
1180d163575Sopenharmony_ci        (void)lwip_close(*piSocketID);
1190d163575Sopenharmony_ci        *piSocketID = TFTP_NULL_INT32;
1200d163575Sopenharmony_ci
1210d163575Sopenharmony_ci        return TFTPC_BIND_FAILURE;
1220d163575Sopenharmony_ci    }
1230d163575Sopenharmony_ci
1240d163575Sopenharmony_ci    return ERR_OK;
1250d163575Sopenharmony_ci}
1260d163575Sopenharmony_ci
1270d163575Sopenharmony_ci
1280d163575Sopenharmony_ci/* Function to create TFTP packet.
1290d163575Sopenharmony_ci     usOpcode - indiacting the nature of the operation
1300d163575Sopenharmony_ci     pFileName -filename on which the operation needs to done
1310d163575Sopenharmony_ci     ulMode -mode in which the operation needs to done
1320d163575Sopenharmony_ci     pstPacket - packet generated
1330d163575Sopenharmony_ci     Returns packet address on success
1340d163575Sopenharmony_ci*/
1350d163575Sopenharmony_cistatic s32_t lwip_tftp_make_tftp_packet(u16_t usOpcode, s8_t *szFileName, u32_t ulMode, TFTPC_PACKET_S *pstPacket)
1360d163575Sopenharmony_ci{
1370d163575Sopenharmony_ci    s8_t *pcCp = NULL;
1380d163575Sopenharmony_ci
1390d163575Sopenharmony_ci    pstPacket->usOpcode = htons(usOpcode);
1400d163575Sopenharmony_ci    pcCp = pstPacket->u.ucName_Mode;
1410d163575Sopenharmony_ci
1420d163575Sopenharmony_ci    /* Request packet format is:
1430d163575Sopenharmony_ci            | Opcode |  Filename  |   0  |    Mode    |   0  |
1440d163575Sopenharmony_ci    */
1450d163575Sopenharmony_ci    (void)strncpy_s((char *)pcCp, TFTP_MAX_PATH_LENGTH, (char *)szFileName, (TFTP_MAX_PATH_LENGTH - 1));
1460d163575Sopenharmony_ci    pcCp[(TFTP_MAX_PATH_LENGTH - 1)] = '\0';
1470d163575Sopenharmony_ci
1480d163575Sopenharmony_ci    pcCp += (strlen((char *)szFileName) + 1);
1490d163575Sopenharmony_ci    if (ulMode == TRANSFER_MODE_BINARY) {
1500d163575Sopenharmony_ci        (void)strncpy_s((char *)pcCp, TFTP_MAX_MODE_SIZE, "octet", (TFTP_MAX_MODE_SIZE - 1));
1510d163575Sopenharmony_ci        pcCp[(TFTP_MAX_MODE_SIZE - 1)] = '\0';
1520d163575Sopenharmony_ci    } else if (ulMode == TRANSFER_MODE_ASCII) {
1530d163575Sopenharmony_ci        (void)strncpy_s((char *)pcCp, TFTP_MAX_MODE_SIZE, "netascii", (TFTP_MAX_MODE_SIZE - 1));
1540d163575Sopenharmony_ci        pcCp[(TFTP_MAX_MODE_SIZE - 1)] = '\0';
1550d163575Sopenharmony_ci    }
1560d163575Sopenharmony_ci
1570d163575Sopenharmony_ci    pcCp += (strlen((char *)pcCp) + 1);
1580d163575Sopenharmony_ci
1590d163575Sopenharmony_ci    return (pcCp - (s8_t *)pstPacket);
1600d163575Sopenharmony_ci}
1610d163575Sopenharmony_ci
1620d163575Sopenharmony_ci/* Function to recv a packet from server
1630d163575Sopenharmony_ci  iSockNum - Socket Number
1640d163575Sopenharmony_ci  pstServerAddr - Server address
1650d163575Sopenharmony_ci  pulIgnorePkt - Ignore packet flag
1660d163575Sopenharmony_ci  pstRecvBuf - received packet
1670d163575Sopenharmony_ci  pulSize - Size of the packet
1680d163575Sopenharmony_ci*/
1690d163575Sopenharmony_ciu32_t lwip_tftp_recv_from_server(s32_t iSockNum, u32_t *pulSize, TFTPC_PACKET_S *pstRecvBuf, u32_t *pulIgnorePkt,
1700d163575Sopenharmony_ci                                 struct sockaddr_in *pstServerAddr, TFTPC_PACKET_S *pstSendBuf)
1710d163575Sopenharmony_ci{
1720d163575Sopenharmony_ci    u32_t ulError;
1730d163575Sopenharmony_ci    socklen_t slFromAddrLen;
1740d163575Sopenharmony_ci    struct sockaddr_in stFromAddr;
1750d163575Sopenharmony_ci    fd_set stReadfds;
1760d163575Sopenharmony_ci    struct timeval stTimeout;
1770d163575Sopenharmony_ci    u16_t usOpcode; /* Opcode value */
1780d163575Sopenharmony_ci    s32_t iRet;
1790d163575Sopenharmony_ci
1800d163575Sopenharmony_ci    slFromAddrLen = sizeof(stFromAddr);
1810d163575Sopenharmony_ci    stTimeout.tv_sec = TFTPC_TIMEOUT_PERIOD;
1820d163575Sopenharmony_ci    stTimeout.tv_usec = 0;
1830d163575Sopenharmony_ci
1840d163575Sopenharmony_ci    /* wait for DATA packet */
1850d163575Sopenharmony_ci    FD_ZERO(&stReadfds);
1860d163575Sopenharmony_ci    FD_SET(iSockNum, &stReadfds);
1870d163575Sopenharmony_ci
1880d163575Sopenharmony_ci    iRet = select((s32_t)(iSockNum + 1), &stReadfds, 0, 0, &stTimeout);
1890d163575Sopenharmony_ci    if (iRet == -1) {
1900d163575Sopenharmony_ci        return TFTPC_SELECT_ERROR;
1910d163575Sopenharmony_ci    } else if (iRet == 0) {
1920d163575Sopenharmony_ci        return TFTPC_TIMEOUT_ERROR;         /* Select timeout occurred */
1930d163575Sopenharmony_ci    }
1940d163575Sopenharmony_ci
1950d163575Sopenharmony_ci    if (!FD_ISSET(iSockNum, &stReadfds)) {
1960d163575Sopenharmony_ci        return TFTPC_TIMEOUT_ERROR;         /* FD not set*/
1970d163575Sopenharmony_ci    }
1980d163575Sopenharmony_ci
1990d163575Sopenharmony_ci    /* receive a packet from server */
2000d163575Sopenharmony_ci    iRet = lwip_recvfrom(iSockNum, (s8_t *)pstRecvBuf, TFTP_PKTSIZE, 0,
2010d163575Sopenharmony_ci                         (struct sockaddr *)&stFromAddr, &slFromAddrLen);
2020d163575Sopenharmony_ci    if (iRet <= 0) {
2030d163575Sopenharmony_ci        return TFTPC_RECVFROM_ERROR;
2040d163575Sopenharmony_ci    }
2050d163575Sopenharmony_ci
2060d163575Sopenharmony_ci    /* If received packet size < minimum packet size */
2070d163575Sopenharmony_ci    if (iRet < TFTPC_FOUR) {
2080d163575Sopenharmony_ci        /* Send Error packet to server */
2090d163575Sopenharmony_ci        lwip_tftp_send_error(iSockNum,
2100d163575Sopenharmony_ci                             TFTPC_PROTOCOL_PROTO_ERROR,
2110d163575Sopenharmony_ci                             "Packet size < min size",
2120d163575Sopenharmony_ci                             pstServerAddr, pstSendBuf);
2130d163575Sopenharmony_ci
2140d163575Sopenharmony_ci        return TFTPC_PKT_SIZE_ERROR;
2150d163575Sopenharmony_ci    }
2160d163575Sopenharmony_ci
2170d163575Sopenharmony_ci    /* convert network opcode to host format after receive. */
2180d163575Sopenharmony_ci    usOpcode = ntohs(pstRecvBuf->usOpcode);
2190d163575Sopenharmony_ci    /* if this packet is ERROR packet */
2200d163575Sopenharmony_ci    if (usOpcode == TFTPC_OP_ERROR) {
2210d163575Sopenharmony_ci        ulError = ntohs(pstRecvBuf->u.stTFTP_Err.usErrNum);
2220d163575Sopenharmony_ci
2230d163575Sopenharmony_ci        /*If the error is according to RFC,then convert to lwip error codes.
2240d163575Sopenharmony_ci        Constant values are used in the cases as these error codes are as per
2250d163575Sopenharmony_ci        the RFC, these are constant values returned by many standard TFTP
2260d163575Sopenharmony_ci        serevrs.*/
2270d163575Sopenharmony_ci        switch (ulError) {
2280d163575Sopenharmony_ci            case TFTPC_PROTOCOL_USER_DEFINED:
2290d163575Sopenharmony_ci                ulError = TFTPC_ERROR_NOT_DEFINED;
2300d163575Sopenharmony_ci                break;
2310d163575Sopenharmony_ci            case TFTPC_PROTOCOL_FILE_NOT_FOUND:
2320d163575Sopenharmony_ci                ulError = TFTPC_FILE_NOT_FOUND;
2330d163575Sopenharmony_ci                break;
2340d163575Sopenharmony_ci            case TFTPC_PROTOCOL_ACCESS_ERROR:
2350d163575Sopenharmony_ci                ulError = TFTPC_ACCESS_ERROR;
2360d163575Sopenharmony_ci                break;
2370d163575Sopenharmony_ci            case TFTPC_PROTOCOL_DISK_FULL:
2380d163575Sopenharmony_ci                ulError = TFTPC_DISK_FULL;
2390d163575Sopenharmony_ci                break;
2400d163575Sopenharmony_ci            case TFTPC_PROTOCOL_PROTO_ERROR:
2410d163575Sopenharmony_ci                ulError = TFTPC_PROTO_ERROR;
2420d163575Sopenharmony_ci                break;
2430d163575Sopenharmony_ci            case TFTPC_PROTOCOL_UNKNOWN_TRANSFER_ID:
2440d163575Sopenharmony_ci                ulError = TFTPC_UNKNOWN_TRANSFER_ID;
2450d163575Sopenharmony_ci                break;
2460d163575Sopenharmony_ci            case TFTPC_PROTOCOL_FILE_EXISTS:
2470d163575Sopenharmony_ci                ulError = TFTPC_FILE_EXISTS;
2480d163575Sopenharmony_ci                break;
2490d163575Sopenharmony_ci            case TFTPC_PROTOCOL_CANNOT_RESOLVE_HOSTNAME:
2500d163575Sopenharmony_ci                ulError = TFTPC_CANNOT_RESOLVE_HOSTNAME;
2510d163575Sopenharmony_ci                break;
2520d163575Sopenharmony_ci            default:
2530d163575Sopenharmony_ci                ulError = TFTPC_ERROR_NOT_DEFINED;
2540d163575Sopenharmony_ci                break;
2550d163575Sopenharmony_ci        }
2560d163575Sopenharmony_ci
2570d163575Sopenharmony_ci        /* If length of error msg > 100 chars */
2580d163575Sopenharmony_ci        pstRecvBuf->u.stTFTP_Err.ucErrMesg[TFTP_MAXERRSTRSIZE - 1] = '\0';
2590d163575Sopenharmony_ci
2600d163575Sopenharmony_ci        LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_recv_from_server : ERROR pkt received: %s\n",
2610d163575Sopenharmony_ci            pstRecvBuf->u.stTFTP_Err.ucErrMesg));
2620d163575Sopenharmony_ci
2630d163575Sopenharmony_ci        /* Now we get error block, so return. */
2640d163575Sopenharmony_ci        return ulError;
2650d163575Sopenharmony_ci    }
2660d163575Sopenharmony_ci
2670d163575Sopenharmony_ci    /* Store the size of received block */
2680d163575Sopenharmony_ci    *pulSize = (u32_t)iRet;
2690d163575Sopenharmony_ci
2700d163575Sopenharmony_ci    /* If received packet is first block of data(for get operation) or if
2710d163575Sopenharmony_ci       received packet is acknowledgment for write request (put operation)
2720d163575Sopenharmony_ci       store the received port number */
2730d163575Sopenharmony_ci    if (((usOpcode == TFTPC_OP_DATA) &&
2740d163575Sopenharmony_ci         (ntohs(pstRecvBuf->u.stTFTP_Data.usBlknum) == 1)) ||
2750d163575Sopenharmony_ci        ((usOpcode == TFTPC_OP_ACK) &&
2760d163575Sopenharmony_ci         (ntohs(pstRecvBuf->u.usBlknum) == 0))) {
2770d163575Sopenharmony_ci        /* If received packet from correct server */
2780d163575Sopenharmony_ci        if (stFromAddr.sin_addr.s_addr == pstServerAddr->sin_addr.s_addr) {
2790d163575Sopenharmony_ci            /* set the server port to received port */
2800d163575Sopenharmony_ci            pstServerAddr->sin_port = stFromAddr.sin_port;
2810d163575Sopenharmony_ci        } else {
2820d163575Sopenharmony_ci            /* Received packet form wrong server. */
2830d163575Sopenharmony_ci            LWIP_DEBUGF(TFTP_DEBUG,
2840d163575Sopenharmony_ci                        ("lwip_tftp_recv_from_server : Received 1st packet from wrong Server or unknown server\n"));
2850d163575Sopenharmony_ci
2860d163575Sopenharmony_ci            /* Set ignore packet flag */
2870d163575Sopenharmony_ci            *pulIgnorePkt = 1;
2880d163575Sopenharmony_ci        }
2890d163575Sopenharmony_ci    } else {
2900d163575Sopenharmony_ci        /* If not first packet, check if the received packet is from correct
2910d163575Sopenharmony_ci           server and from correct port */
2920d163575Sopenharmony_ci        if ((stFromAddr.sin_addr.s_addr != pstServerAddr->sin_addr.s_addr) ||
2930d163575Sopenharmony_ci            (pstServerAddr->sin_port != stFromAddr.sin_port)) {
2940d163575Sopenharmony_ci            /* Received packet form wrong server or wrong port.Ignore packet. */
2950d163575Sopenharmony_ci            LWIP_DEBUGF(TFTP_DEBUG,
2960d163575Sopenharmony_ci                        ("lwip_tftp_recv_from_server : Received a packet from wrong Server or unknown server\n"));
2970d163575Sopenharmony_ci
2980d163575Sopenharmony_ci            /* Set ignore packet flag */
2990d163575Sopenharmony_ci            *pulIgnorePkt = 1;
3000d163575Sopenharmony_ci        }
3010d163575Sopenharmony_ci    }
3020d163575Sopenharmony_ci
3030d163575Sopenharmony_ci    return ERR_OK;
3040d163575Sopenharmony_ci}
3050d163575Sopenharmony_ci
3060d163575Sopenharmony_ci/* Function to send a packet to server
3070d163575Sopenharmony_ci    iSockNum: Socket Number
3080d163575Sopenharmony_ci    ulSize: Size of the packet
3090d163575Sopenharmony_ci    pstSendBuf: Packet to send
3100d163575Sopenharmony_ci    pstServerAddr: Server address
3110d163575Sopenharmony_ci*/
3120d163575Sopenharmony_ciu32_t lwip_tftp_send_to_server(s32_t iSockNum,
3130d163575Sopenharmony_ci                               u32_t ulSize,
3140d163575Sopenharmony_ci                               TFTPC_PACKET_S *pstSendBuf,
3150d163575Sopenharmony_ci                               struct sockaddr_in *pstServerAddr)
3160d163575Sopenharmony_ci{
3170d163575Sopenharmony_ci    s32_t iRet;
3180d163575Sopenharmony_ci
3190d163575Sopenharmony_ci    /* Send packet to server */
3200d163575Sopenharmony_ci    iRet = lwip_sendto(iSockNum, (s8_t *)pstSendBuf,
3210d163575Sopenharmony_ci                       (size_t)ulSize, 0,
3220d163575Sopenharmony_ci                       (struct sockaddr *)pstServerAddr,
3230d163575Sopenharmony_ci                       sizeof(struct sockaddr_in));
3240d163575Sopenharmony_ci    /* Size of data sent not equal to size of packet */
3250d163575Sopenharmony_ci    if ((iRet == TFTP_NULL_INT32) || ((u32_t)iRet != ulSize)) {
3260d163575Sopenharmony_ci        return TFTPC_SENDTO_ERROR;
3270d163575Sopenharmony_ci    }
3280d163575Sopenharmony_ci
3290d163575Sopenharmony_ci    return ERR_OK;
3300d163575Sopenharmony_ci}
3310d163575Sopenharmony_ci
3320d163575Sopenharmony_ci/* lwip_tftp_validate_data_pkt
3330d163575Sopenharmony_ci* Get the data block from the received packet
3340d163575Sopenharmony_ci* @param Input iSockNum Socket Number
3350d163575Sopenharmony_ci*                     pulSize: Size of received packet,
3360d163575Sopenharmony_ci                       pstRecvBuf - received packet
3370d163575Sopenharmony_ci                       usCurrBlk - Current block number
3380d163575Sopenharmony_ci * @param Output pulResendPkt - Resend packet flag
3390d163575Sopenharmony_ci * @return VOS_OK on success.else error code*/
3400d163575Sopenharmony_ci
3410d163575Sopenharmony_ciu32_t lwip_tftp_validate_data_pkt(s32_t iSockNum,
3420d163575Sopenharmony_ci                                  u32_t *pulSize,
3430d163575Sopenharmony_ci                                  TFTPC_PACKET_S *pstRecvBuf,
3440d163575Sopenharmony_ci                                  u16_t usCurrBlk,
3450d163575Sopenharmony_ci                                  u32_t *pulResendPkt,
3460d163575Sopenharmony_ci                                  struct sockaddr_in *pstServerAddr)
3470d163575Sopenharmony_ci{
3480d163575Sopenharmony_ci    fd_set stReadfds;
3490d163575Sopenharmony_ci    struct timeval stTimeout;
3500d163575Sopenharmony_ci    struct sockaddr_in stFromAddr;
3510d163575Sopenharmony_ci    socklen_t ulFromAddrLen;
3520d163575Sopenharmony_ci    s32_t iRecvLen = (s32_t)*pulSize;
3530d163575Sopenharmony_ci    s32_t iError;
3540d163575Sopenharmony_ci    u16_t usBlknum;
3550d163575Sopenharmony_ci    u32_t ulLoopCnt = 0;
3560d163575Sopenharmony_ci
3570d163575Sopenharmony_ci    ulFromAddrLen = sizeof(stFromAddr);
3580d163575Sopenharmony_ci
3590d163575Sopenharmony_ci    /* Initialize from address to the server address at first */
3600d163575Sopenharmony_ci    if (memcpy_s((void *)&stFromAddr, sizeof(struct sockaddr_in), (void *)pstServerAddr, sizeof(stFromAddr)) != 0) {
3610d163575Sopenharmony_ci        LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_validate_data_pkt : memcpy_s error\n"));
3620d163575Sopenharmony_ci        return TFTPC_MEMCPY_FAILURE;
3630d163575Sopenharmony_ci    }
3640d163575Sopenharmony_ci
3650d163575Sopenharmony_ci    /* Get Block Number */
3660d163575Sopenharmony_ci    usBlknum = ntohs(pstRecvBuf->u.stTFTP_Data.usBlknum);
3670d163575Sopenharmony_ci    /* Now data blocks are not in sync. */
3680d163575Sopenharmony_ci    if (usBlknum != usCurrBlk) {
3690d163575Sopenharmony_ci        /* Set timeout value */
3700d163575Sopenharmony_ci        stTimeout.tv_sec = 1;
3710d163575Sopenharmony_ci        stTimeout.tv_usec = 0;
3720d163575Sopenharmony_ci
3730d163575Sopenharmony_ci        /* Reset any stored packets. */
3740d163575Sopenharmony_ci        FD_ZERO(&stReadfds);
3750d163575Sopenharmony_ci        FD_SET(iSockNum, &stReadfds);
3760d163575Sopenharmony_ci
3770d163575Sopenharmony_ci        iError = select((s32_t)(iSockNum + 1),
3780d163575Sopenharmony_ci                        &stReadfds, 0, 0, &stTimeout);
3790d163575Sopenharmony_ci
3800d163575Sopenharmony_ci        /* Loop to get the last data packet from the receive buffer */
3810d163575Sopenharmony_ci        while ((iError != TFTP_NULL_INT32) && (iError != 0)) {
3820d163575Sopenharmony_ci            ulLoopCnt++;
3830d163575Sopenharmony_ci
3840d163575Sopenharmony_ci            /* MAX file size in TFTP is 32 MB.
3850d163575Sopenharmony_ci                 Reason for keeping 75 here , is ((75*512=38400bytes)/1024) =  37MB. So the recv/Send
3860d163575Sopenharmony_ci                 Loop can receive the complete MAX message from the network.
3870d163575Sopenharmony_ci            */
3880d163575Sopenharmony_ci            if (ulLoopCnt > TFTPC_MAX_WAIT_IN_LOOP) {
3890d163575Sopenharmony_ci                LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_validate_data_pkt : unexpected packets are received repeatedly\n"));
3900d163575Sopenharmony_ci                *pulSize = TFTP_NULL_UINT32;
3910d163575Sopenharmony_ci                return TFTPC_PKT_SIZE_ERROR;
3920d163575Sopenharmony_ci            }
3930d163575Sopenharmony_ci
3940d163575Sopenharmony_ci            FD_ZERO(&stReadfds);
3950d163575Sopenharmony_ci            FD_SET(iSockNum, &stReadfds);
3960d163575Sopenharmony_ci
3970d163575Sopenharmony_ci            iRecvLen = lwip_recvfrom(iSockNum,
3980d163575Sopenharmony_ci                                     (s8_t *)pstRecvBuf,
3990d163575Sopenharmony_ci                                     TFTP_PKTSIZE, 0,
4000d163575Sopenharmony_ci                                     (struct sockaddr *)&stFromAddr,
4010d163575Sopenharmony_ci                                     &ulFromAddrLen);
4020d163575Sopenharmony_ci            if (iRecvLen == -1) {
4030d163575Sopenharmony_ci                *pulSize = TFTP_NULL_UINT32;
4040d163575Sopenharmony_ci
4050d163575Sopenharmony_ci                /* return from the function, recvfrom operation failed */
4060d163575Sopenharmony_ci                return TFTPC_RECVFROM_ERROR;
4070d163575Sopenharmony_ci            }
4080d163575Sopenharmony_ci
4090d163575Sopenharmony_ci            stTimeout.tv_sec = 1;
4100d163575Sopenharmony_ci            stTimeout.tv_usec = 0;
4110d163575Sopenharmony_ci            iError = select((s32_t)(iSockNum + 1), &stReadfds, 0, 0, &stTimeout);
4120d163575Sopenharmony_ci        }
4130d163575Sopenharmony_ci
4140d163575Sopenharmony_ci        /* If received packet size < minimum packet size */
4150d163575Sopenharmony_ci        if (iRecvLen < TFTPC_FOUR) {
4160d163575Sopenharmony_ci            return TFTPC_PKT_SIZE_ERROR;
4170d163575Sopenharmony_ci        }
4180d163575Sopenharmony_ci
4190d163575Sopenharmony_ci        /* Check if the received packet is from correct server and from
4200d163575Sopenharmony_ci           correct port
4210d163575Sopenharmony_ci           */
4220d163575Sopenharmony_ci        if ((stFromAddr.sin_addr.s_addr != pstServerAddr->sin_addr.s_addr) ||
4230d163575Sopenharmony_ci            (pstServerAddr->sin_port != stFromAddr.sin_port)) {
4240d163575Sopenharmony_ci            /* resend ack packet */
4250d163575Sopenharmony_ci            *pulResendPkt = 1;
4260d163575Sopenharmony_ci            LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_validate_data_pkt : Received pkt from unknown server\n"));
4270d163575Sopenharmony_ci
4280d163575Sopenharmony_ci            return ERR_OK;
4290d163575Sopenharmony_ci        }
4300d163575Sopenharmony_ci
4310d163575Sopenharmony_ci        /* if this packet is not DATA packet */
4320d163575Sopenharmony_ci        if (TFTPC_OP_DATA != ntohs(pstRecvBuf->usOpcode)) {
4330d163575Sopenharmony_ci            LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_validate_data_pkt : Received pkt not a DATA pkt\n"));
4340d163575Sopenharmony_ci
4350d163575Sopenharmony_ci            /* return from the function, incorrect packet received,
4360d163575Sopenharmony_ci               expected packet is data packet */
4370d163575Sopenharmony_ci            return TFTPC_PROTO_ERROR;
4380d163575Sopenharmony_ci        }
4390d163575Sopenharmony_ci
4400d163575Sopenharmony_ci        usBlknum = ntohs(pstRecvBuf->u.stTFTP_Data.usBlknum);
4410d163575Sopenharmony_ci        /* if we now have the earlier data packet, then the host probably
4420d163575Sopenharmony_ci           never got our acknowledge packet, now we will send it again. */
4430d163575Sopenharmony_ci        if (usBlknum == (usCurrBlk - 1)) {
4440d163575Sopenharmony_ci            /* resend ack packet */
4450d163575Sopenharmony_ci            *pulResendPkt = 1;
4460d163575Sopenharmony_ci            LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_validate_data_pkt : Received previous DATA pkt\n"));
4470d163575Sopenharmony_ci
4480d163575Sopenharmony_ci            return ERR_OK;
4490d163575Sopenharmony_ci        }
4500d163575Sopenharmony_ci
4510d163575Sopenharmony_ci        /* If the block of data received is not current block or also
4520d163575Sopenharmony_ci           previous block, then it is abnormal case. */
4530d163575Sopenharmony_ci        if (usBlknum != usCurrBlk) {
4540d163575Sopenharmony_ci            LWIP_DEBUGF(TFTP_DEBUG,
4550d163575Sopenharmony_ci                        ("lwip_tftp_validate_data_pkt : Received DATA pkt no. %"S32_F" instead of pkt no.%"S32_F"\n",
4560d163575Sopenharmony_ci                            usBlknum, usCurrBlk));
4570d163575Sopenharmony_ci
4580d163575Sopenharmony_ci            return TFTPC_SYNC_FAILURE;
4590d163575Sopenharmony_ci        }
4600d163575Sopenharmony_ci    }
4610d163575Sopenharmony_ci
4620d163575Sopenharmony_ci    *pulSize = (u32_t)iRecvLen;
4630d163575Sopenharmony_ci    return ERR_OK;
4640d163575Sopenharmony_ci}
4650d163575Sopenharmony_ci
4660d163575Sopenharmony_ci/* Send an error packet to the server
4670d163575Sopenharmony_ci    iSockNum : Socket Number
4680d163575Sopenharmony_ci    ulError: Error code
4690d163575Sopenharmony_ci    szErrMsg - Error message
4700d163575Sopenharmony_ci    pstServerAddr - Server address
4710d163575Sopenharmony_ci*/
4720d163575Sopenharmony_cistatic void lwip_tftp_send_error(s32_t iSockNum, u32_t ulError, const char *szErrMsg,
4730d163575Sopenharmony_ci                                 struct sockaddr_in *pstServerAddr, TFTPC_PACKET_S *pstSendBuf)
4740d163575Sopenharmony_ci{
4750d163575Sopenharmony_ci    u16_t usOpCode = TFTPC_OP_ERROR;
4760d163575Sopenharmony_ci
4770d163575Sopenharmony_ci    if (memset_s((void *)pstSendBuf, sizeof(TFTPC_PACKET_S), 0, sizeof(TFTPC_PACKET_S)) != 0) {
4780d163575Sopenharmony_ci        LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_send_error : memset_s error\n"));
4790d163575Sopenharmony_ci        return;
4800d163575Sopenharmony_ci    }
4810d163575Sopenharmony_ci
4820d163575Sopenharmony_ci    /* Set up the send buffer */
4830d163575Sopenharmony_ci    pstSendBuf->usOpcode = htons(usOpCode);
4840d163575Sopenharmony_ci    pstSendBuf->u.stTFTP_Err.usErrNum = htons((u16_t)ulError);
4850d163575Sopenharmony_ci
4860d163575Sopenharmony_ci    if (strncpy_s((char *)(pstSendBuf->u.stTFTP_Err.ucErrMesg), TFTP_MAXERRSTRSIZE,
4870d163575Sopenharmony_ci                  (char *)szErrMsg, (TFTP_MAXERRSTRSIZE - 1)) != EOK) {
4880d163575Sopenharmony_ci        LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_send_error : strncpy_s error\n"));
4890d163575Sopenharmony_ci        return;
4900d163575Sopenharmony_ci    }
4910d163575Sopenharmony_ci    pstSendBuf->u.stTFTP_Err.ucErrMesg[(TFTP_MAXERRSTRSIZE - 1)] = '\0';
4920d163575Sopenharmony_ci
4930d163575Sopenharmony_ci    /* Send to server */
4940d163575Sopenharmony_ci    if (lwip_tftp_send_to_server(iSockNum,
4950d163575Sopenharmony_ci                                 sizeof(TFTPC_PACKET_S),
4960d163575Sopenharmony_ci                                 pstSendBuf,
4970d163575Sopenharmony_ci                                 pstServerAddr) != ERR_OK) {
4980d163575Sopenharmony_ci        LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_send_to_server error."));
4990d163575Sopenharmony_ci        return;
5000d163575Sopenharmony_ci    }
5010d163575Sopenharmony_ci}
5020d163575Sopenharmony_ci
5030d163575Sopenharmony_ci/* INTERFACE to get a file using filename
5040d163575Sopenharmony_ci    ulHostAddr - IP address of Host
5050d163575Sopenharmony_ci    szSrcFileName - Source file
5060d163575Sopenharmony_ci    szDestDirPath - Destination file path
5070d163575Sopenharmony_ci*/
5080d163575Sopenharmony_ciu32_t lwip_tftp_get_file_by_filename(u32_t ulHostAddr,
5090d163575Sopenharmony_ci                                     u16_t usTftpServPort,
5100d163575Sopenharmony_ci                                     u8_t ucTftpTransMode,
5110d163575Sopenharmony_ci                                     s8_t *szSrcFileName,
5120d163575Sopenharmony_ci                                     s8_t *szDestDirPath)
5130d163575Sopenharmony_ci{
5140d163575Sopenharmony_ci    s32_t iSockNum = TFTP_NULL_INT32;
5150d163575Sopenharmony_ci    u32_t ulSrcStrLen;
5160d163575Sopenharmony_ci    u32_t ulDestStrLen;
5170d163575Sopenharmony_ci    u32_t ulSize;
5180d163575Sopenharmony_ci    u32_t ulRecvSize = TFTP_NULL_UINT32;
5190d163575Sopenharmony_ci    s32_t iErrCode;
5200d163575Sopenharmony_ci    u32_t ulErrCode;
5210d163575Sopenharmony_ci    u16_t usReadReq;
5220d163575Sopenharmony_ci    u16_t usTempServPort;
5230d163575Sopenharmony_ci    s8_t *pszTempDestName = NULL;
5240d163575Sopenharmony_ci    s8_t *szTempSrcName = NULL;
5250d163575Sopenharmony_ci    u32_t ulCurrBlk = 1;
5260d163575Sopenharmony_ci    u32_t ulResendPkt = 0; /*Resend the previous packet*/
5270d163575Sopenharmony_ci    u32_t ulIgnorePkt = 0; /*Ignore received packet*/
5280d163575Sopenharmony_ci    u32_t ulTotalTime = 0;
5290d163575Sopenharmony_ci    u32_t isLocalFileOpened = false;
5300d163575Sopenharmony_ci
5310d163575Sopenharmony_ci    TFTPC_PACKET_S *pstSendBuf = NULL;
5320d163575Sopenharmony_ci    TFTPC_PACKET_S *pstRecvBuf = NULL;
5330d163575Sopenharmony_ci    struct sockaddr_in stServerAddr;
5340d163575Sopenharmony_ci    struct stat sb;
5350d163575Sopenharmony_ci    u32_t IsDirExist = 0;
5360d163575Sopenharmony_ci    s32_t fp = -1;
5370d163575Sopenharmony_ci
5380d163575Sopenharmony_ci    /*Validate the parameters*/
5390d163575Sopenharmony_ci    if ((szSrcFileName == NULL) || (szDestDirPath == NULL)) {
5400d163575Sopenharmony_ci        return TFTPC_INVALID_PARAVALUE;
5410d163575Sopenharmony_ci    }
5420d163575Sopenharmony_ci
5430d163575Sopenharmony_ci    if ((ucTftpTransMode != TRANSFER_MODE_BINARY) && (ucTftpTransMode != TRANSFER_MODE_ASCII)) {
5440d163575Sopenharmony_ci        return TFTPC_INVALID_PARAVALUE;
5450d163575Sopenharmony_ci    }
5460d163575Sopenharmony_ci
5470d163575Sopenharmony_ci    /*check IP address not within ( 1.0.0.0 - 126.255.255.255 )
5480d163575Sopenharmony_ci    and ( 128.0.0.0 - 223.255.255.255 ) range.*/
5490d163575Sopenharmony_ci    if (!(((ulHostAddr >= TFTPC_IP_ADDR_MIN) &&
5500d163575Sopenharmony_ci           (ulHostAddr <= TFTPC_IP_ADDR_EX_RESV)) ||
5510d163575Sopenharmony_ci          ((ulHostAddr >= TFTPC_IP_ADDR_CLASS_B) &&
5520d163575Sopenharmony_ci           (ulHostAddr <= TFTPC_IP_ADDR_EX_CLASS_DE)))) {
5530d163575Sopenharmony_ci        return TFTPC_IP_NOT_WITHIN_RANGE;
5540d163575Sopenharmony_ci    }
5550d163575Sopenharmony_ci
5560d163575Sopenharmony_ci    /*Check validity of source filename*/
5570d163575Sopenharmony_ci    ulSrcStrLen = strlen((char *)szSrcFileName);
5580d163575Sopenharmony_ci    if ((ulSrcStrLen == 0) || (ulSrcStrLen >= TFTP_MAX_PATH_LENGTH)) {
5590d163575Sopenharmony_ci        return TFTPC_SRC_FILENAME_LENGTH_ERROR;
5600d163575Sopenharmony_ci    }
5610d163575Sopenharmony_ci
5620d163575Sopenharmony_ci    /*Check validity of destination path*/
5630d163575Sopenharmony_ci    ulDestStrLen = strlen((char *)szDestDirPath);
5640d163575Sopenharmony_ci    if ((ulDestStrLen >= TFTP_MAX_PATH_LENGTH) || (ulDestStrLen == 0)) {
5650d163575Sopenharmony_ci        return TFTPC_DEST_PATH_LENGTH_ERROR;
5660d163575Sopenharmony_ci    }
5670d163575Sopenharmony_ci
5680d163575Sopenharmony_ci    pstSendBuf = (TFTPC_PACKET_S *)mem_malloc(sizeof(TFTPC_PACKET_S));
5690d163575Sopenharmony_ci    if (pstSendBuf == NULL) {
5700d163575Sopenharmony_ci        return TFTPC_MEMALLOC_ERROR;
5710d163575Sopenharmony_ci    }
5720d163575Sopenharmony_ci
5730d163575Sopenharmony_ci    pstRecvBuf = (TFTPC_PACKET_S *)mem_malloc(sizeof(TFTPC_PACKET_S));
5740d163575Sopenharmony_ci    if (pstRecvBuf == NULL) {
5750d163575Sopenharmony_ci        mem_free(pstSendBuf);
5760d163575Sopenharmony_ci        return TFTPC_MEMALLOC_ERROR;
5770d163575Sopenharmony_ci    }
5780d163575Sopenharmony_ci
5790d163575Sopenharmony_ci    pszTempDestName = (s8_t *)mem_malloc(TFTP_MAX_PATH_LENGTH);
5800d163575Sopenharmony_ci    if (pszTempDestName == NULL) {
5810d163575Sopenharmony_ci        mem_free(pstSendBuf);
5820d163575Sopenharmony_ci        mem_free(pstRecvBuf);
5830d163575Sopenharmony_ci        return TFTPC_MEMALLOC_ERROR;
5840d163575Sopenharmony_ci    }
5850d163575Sopenharmony_ci
5860d163575Sopenharmony_ci    /* First time initialize the buffers */
5870d163575Sopenharmony_ci    (void)memset_s((void *)pstSendBuf, sizeof(TFTPC_PACKET_S), 0, sizeof(TFTPC_PACKET_S));
5880d163575Sopenharmony_ci    (void)memset_s((void *)pstRecvBuf, sizeof(TFTPC_PACKET_S), 0, sizeof(TFTPC_PACKET_S));
5890d163575Sopenharmony_ci
5900d163575Sopenharmony_ci    /*If given src filename is a relative path extract
5910d163575Sopenharmony_ci    the file name from the path*/
5920d163575Sopenharmony_ci    if ((0 != strchr((char *)szSrcFileName, '/')) || (0 != strchr((char *)szSrcFileName, '\\'))) {
5930d163575Sopenharmony_ci        /*Move to the end of the src file path*/
5940d163575Sopenharmony_ci        szTempSrcName = szSrcFileName + (ulSrcStrLen - 1);
5950d163575Sopenharmony_ci
5960d163575Sopenharmony_ci        while (((*(szTempSrcName - 1) != '/') &&
5970d163575Sopenharmony_ci                (*(szTempSrcName - 1) != '\\')) &&
5980d163575Sopenharmony_ci               (szTempSrcName != szSrcFileName)) {
5990d163575Sopenharmony_ci            szTempSrcName--;
6000d163575Sopenharmony_ci        }
6010d163575Sopenharmony_ci
6020d163575Sopenharmony_ci        /*Get length of the extracted src filename*/
6030d163575Sopenharmony_ci        ulSrcStrLen = strlen((char *)szTempSrcName);
6040d163575Sopenharmony_ci    } else {
6050d163575Sopenharmony_ci        /*If not a relative src path use the given src filename*/
6060d163575Sopenharmony_ci        szTempSrcName = szSrcFileName;
6070d163575Sopenharmony_ci    }
6080d163575Sopenharmony_ci
6090d163575Sopenharmony_ci    (void)memset_s(pszTempDestName, TFTP_MAX_PATH_LENGTH, 0, TFTP_MAX_PATH_LENGTH);
6100d163575Sopenharmony_ci    if (strncpy_s((char *)pszTempDestName, TFTP_MAX_PATH_LENGTH, (char *)szDestDirPath, TFTP_MAX_PATH_LENGTH - 1) !=
6110d163575Sopenharmony_ci        0) {
6120d163575Sopenharmony_ci        ulErrCode = TFTPC_MEMCPY_FAILURE;
6130d163575Sopenharmony_ci        goto err_handler;
6140d163575Sopenharmony_ci    }
6150d163575Sopenharmony_ci    pszTempDestName[TFTP_MAX_PATH_LENGTH - 1] = '\0';
6160d163575Sopenharmony_ci
6170d163575Sopenharmony_ci    if (stat((char *)pszTempDestName, &sb) == 0 && S_ISDIR(sb.st_mode)) {
6180d163575Sopenharmony_ci        IsDirExist = 1;
6190d163575Sopenharmony_ci    }
6200d163575Sopenharmony_ci
6210d163575Sopenharmony_ci    if (IsDirExist == 1) {
6220d163575Sopenharmony_ci        /*The filename is not present concat source filename and try*/
6230d163575Sopenharmony_ci        if ((ulDestStrLen + ulSrcStrLen) >= TFTP_MAX_PATH_LENGTH) {
6240d163575Sopenharmony_ci            /*If concatenating src filename exceeds 256 bytes*/
6250d163575Sopenharmony_ci            ulErrCode = TFTPC_DEST_PATH_LENGTH_ERROR;
6260d163575Sopenharmony_ci            goto err_handler;
6270d163575Sopenharmony_ci        }
6280d163575Sopenharmony_ci
6290d163575Sopenharmony_ci        /*Check if / present at end of string*/
6300d163575Sopenharmony_ci        if ((pszTempDestName[ulDestStrLen - 1] != '/') &&
6310d163575Sopenharmony_ci            (pszTempDestName[ulDestStrLen - 1] != '\\')) {
6320d163575Sopenharmony_ci            if ((ulDestStrLen + ulSrcStrLen + 1) >= TFTP_MAX_PATH_LENGTH) {
6330d163575Sopenharmony_ci                /*If concatenating src filename exceeds 256 bytes*/
6340d163575Sopenharmony_ci                ulErrCode = TFTPC_DEST_PATH_LENGTH_ERROR;
6350d163575Sopenharmony_ci                goto err_handler;
6360d163575Sopenharmony_ci            }
6370d163575Sopenharmony_ci
6380d163575Sopenharmony_ci            /*If not present concat / to the path*/
6390d163575Sopenharmony_ci            if (strncat_s((char *)pszTempDestName, (TFTP_MAX_PATH_LENGTH - strlen((char *)pszTempDestName)),
6400d163575Sopenharmony_ci                          "/", TFTP_MAX_PATH_LENGTH - strlen((char *)pszTempDestName) - 1) != 0) {
6410d163575Sopenharmony_ci                ulErrCode = TFTPC_ERROR_NOT_DEFINED;
6420d163575Sopenharmony_ci                goto err_handler;
6430d163575Sopenharmony_ci            }
6440d163575Sopenharmony_ci        }
6450d163575Sopenharmony_ci
6460d163575Sopenharmony_ci        /*Concatenate src filename to destination path*/
6470d163575Sopenharmony_ci        if (strncat_s((char *)pszTempDestName, (TFTP_MAX_PATH_LENGTH - strlen((char *)pszTempDestName)),
6480d163575Sopenharmony_ci                      (char *)szTempSrcName, TFTP_MAX_PATH_LENGTH - strlen((char *)pszTempDestName) - 1) != 0) {
6490d163575Sopenharmony_ci            ulErrCode = TFTPC_ERROR_NOT_DEFINED;
6500d163575Sopenharmony_ci            goto err_handler;
6510d163575Sopenharmony_ci        }
6520d163575Sopenharmony_ci    }
6530d163575Sopenharmony_ci
6540d163575Sopenharmony_ci    ulErrCode = lwip_tftp_create_bind_socket(&iSockNum);
6550d163575Sopenharmony_ci    if (ulErrCode != ERR_OK) {
6560d163575Sopenharmony_ci        goto err_handler;
6570d163575Sopenharmony_ci    }
6580d163575Sopenharmony_ci
6590d163575Sopenharmony_ci    if (usTftpServPort == 0) {
6600d163575Sopenharmony_ci        usTftpServPort = TFTPC_SERVER_PORT;
6610d163575Sopenharmony_ci    }
6620d163575Sopenharmony_ci
6630d163575Sopenharmony_ci    usTempServPort = usTftpServPort;
6640d163575Sopenharmony_ci
6650d163575Sopenharmony_ci    /* set server IP address */
6660d163575Sopenharmony_ci    (void)memset_s(&stServerAddr, sizeof(stServerAddr), 0, sizeof(stServerAddr));
6670d163575Sopenharmony_ci    stServerAddr.sin_family = AF_INET;
6680d163575Sopenharmony_ci    stServerAddr.sin_port = htons(usTempServPort);
6690d163575Sopenharmony_ci    stServerAddr.sin_addr.s_addr = htonl(ulHostAddr);
6700d163575Sopenharmony_ci
6710d163575Sopenharmony_ci    /* Make a request packet - TFTPC_OP_RRQ */
6720d163575Sopenharmony_ci    ulSize = (u32_t)lwip_tftp_make_tftp_packet(TFTPC_OP_RRQ, szSrcFileName,
6730d163575Sopenharmony_ci                                               (u32_t)ucTftpTransMode,
6740d163575Sopenharmony_ci                                               pstSendBuf);
6750d163575Sopenharmony_ci    ulErrCode = lwip_tftp_send_to_server(iSockNum, ulSize,
6760d163575Sopenharmony_ci                                         pstSendBuf, &stServerAddr);
6770d163575Sopenharmony_ci    if (ulErrCode != ERR_OK) {
6780d163575Sopenharmony_ci        /* send to server failed */
6790d163575Sopenharmony_ci        (void)lwip_close(iSockNum);
6800d163575Sopenharmony_ci        goto err_handler;
6810d163575Sopenharmony_ci    }
6820d163575Sopenharmony_ci
6830d163575Sopenharmony_ci    for (;;) {
6840d163575Sopenharmony_ci        if (ulIgnorePkt > 0) {
6850d163575Sopenharmony_ci            ulIgnorePkt = 0;
6860d163575Sopenharmony_ci        }
6870d163575Sopenharmony_ci
6880d163575Sopenharmony_ci        ulErrCode = lwip_tftp_recv_from_server(iSockNum, &ulRecvSize, pstRecvBuf,
6890d163575Sopenharmony_ci                                               &ulIgnorePkt, &stServerAddr, pstSendBuf);
6900d163575Sopenharmony_ci        /* If select timeout occurred */
6910d163575Sopenharmony_ci        if (ulErrCode == TFTPC_TIMEOUT_ERROR) {
6920d163575Sopenharmony_ci            ulTotalTime++;
6930d163575Sopenharmony_ci            if (ulTotalTime < TFTPC_MAX_SEND_REQ_ATTEMPTS) {
6940d163575Sopenharmony_ci                /* Max attempts not reached. Resend packet */
6950d163575Sopenharmony_ci                ulErrCode = lwip_tftp_send_to_server(iSockNum, ulSize,
6960d163575Sopenharmony_ci                                                     pstSendBuf, &stServerAddr);
6970d163575Sopenharmony_ci                if (ulErrCode != ERR_OK) {
6980d163575Sopenharmony_ci                    (void)lwip_close(iSockNum);
6990d163575Sopenharmony_ci                    if (isLocalFileOpened == true) {
7000d163575Sopenharmony_ci                        close(fp);
7010d163575Sopenharmony_ci                    }
7020d163575Sopenharmony_ci                    goto err_handler;
7030d163575Sopenharmony_ci                }
7040d163575Sopenharmony_ci
7050d163575Sopenharmony_ci                continue;
7060d163575Sopenharmony_ci            } else {
7070d163575Sopenharmony_ci                /* return from the function, max attempts limit reached */
7080d163575Sopenharmony_ci                (void)lwip_close(iSockNum);
7090d163575Sopenharmony_ci                if (isLocalFileOpened == true) {
7100d163575Sopenharmony_ci                    close(fp);
7110d163575Sopenharmony_ci                }
7120d163575Sopenharmony_ci                ulErrCode = TFTPC_TIMEOUT_ERROR;
7130d163575Sopenharmony_ci                goto err_handler;
7140d163575Sopenharmony_ci            }
7150d163575Sopenharmony_ci        } else if (ulErrCode != ERR_OK) {
7160d163575Sopenharmony_ci            (void)lwip_close(iSockNum);
7170d163575Sopenharmony_ci            if (isLocalFileOpened == true) {
7180d163575Sopenharmony_ci                close(fp);
7190d163575Sopenharmony_ci            }
7200d163575Sopenharmony_ci            goto err_handler;
7210d163575Sopenharmony_ci        }
7220d163575Sopenharmony_ci
7230d163575Sopenharmony_ci        /* Now we have receive block from different server. */
7240d163575Sopenharmony_ci        if (ulIgnorePkt > 0) {
7250d163575Sopenharmony_ci            /*Continue without processing this block. */
7260d163575Sopenharmony_ci            continue;
7270d163575Sopenharmony_ci        }
7280d163575Sopenharmony_ci
7290d163575Sopenharmony_ci        /* if this packet is unkonwn or incorrect packet */
7300d163575Sopenharmony_ci        if (ntohs(pstRecvBuf->usOpcode) != TFTPC_OP_DATA) {
7310d163575Sopenharmony_ci            /* Send error packet to server */
7320d163575Sopenharmony_ci            lwip_tftp_send_error(iSockNum,
7330d163575Sopenharmony_ci                                 TFTPC_PROTOCOL_PROTO_ERROR,
7340d163575Sopenharmony_ci                                 "Protocol error.",
7350d163575Sopenharmony_ci                                 &stServerAddr, pstSendBuf);
7360d163575Sopenharmony_ci
7370d163575Sopenharmony_ci            (void)lwip_close(iSockNum);
7380d163575Sopenharmony_ci            if (isLocalFileOpened == true) {
7390d163575Sopenharmony_ci                close(fp);
7400d163575Sopenharmony_ci            }
7410d163575Sopenharmony_ci
7420d163575Sopenharmony_ci            LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_get_file_by_filename : Received pkt not DATA pkt\n"));
7430d163575Sopenharmony_ci
7440d163575Sopenharmony_ci            ulErrCode = TFTPC_PROTO_ERROR;
7450d163575Sopenharmony_ci            goto err_handler;
7460d163575Sopenharmony_ci        }
7470d163575Sopenharmony_ci
7480d163575Sopenharmony_ci        /* Now the number of tries will be reset. */
7490d163575Sopenharmony_ci        ulTotalTime = 0;
7500d163575Sopenharmony_ci
7510d163575Sopenharmony_ci        /* Validate received  DATA packet. */
7520d163575Sopenharmony_ci        ulErrCode = lwip_tftp_validate_data_pkt(iSockNum, &ulRecvSize,
7530d163575Sopenharmony_ci                                                pstRecvBuf, (u16_t)ulCurrBlk,
7540d163575Sopenharmony_ci                                                &ulResendPkt,
7550d163575Sopenharmony_ci                                                &stServerAddr);
7560d163575Sopenharmony_ci        if (ulErrCode != ERR_OK) {
7570d163575Sopenharmony_ci            /* Send Error packet to server */
7580d163575Sopenharmony_ci            if (ulErrCode != TFTPC_RECVFROM_ERROR) {
7590d163575Sopenharmony_ci                lwip_tftp_send_error(iSockNum,
7600d163575Sopenharmony_ci                                     TFTPC_PROTOCOL_PROTO_ERROR,
7610d163575Sopenharmony_ci                                     "Received unexpected packet",
7620d163575Sopenharmony_ci                                     &stServerAddr, pstSendBuf);
7630d163575Sopenharmony_ci            }
7640d163575Sopenharmony_ci
7650d163575Sopenharmony_ci            (void)lwip_close(iSockNum);
7660d163575Sopenharmony_ci            if (isLocalFileOpened == true) {
7670d163575Sopenharmony_ci                close(fp);
7680d163575Sopenharmony_ci            }
7690d163575Sopenharmony_ci
7700d163575Sopenharmony_ci            goto err_handler;
7710d163575Sopenharmony_ci        }
7720d163575Sopenharmony_ci
7730d163575Sopenharmony_ci        /* Received previous data block again. Resend last packet */
7740d163575Sopenharmony_ci        if (ulResendPkt > 0) {
7750d163575Sopenharmony_ci            /* Now set ulResendPkt to 0 to send the last packet. */
7760d163575Sopenharmony_ci            ulResendPkt = 0;
7770d163575Sopenharmony_ci            ulErrCode = lwip_tftp_send_to_server(iSockNum, ulSize,
7780d163575Sopenharmony_ci                                                 pstSendBuf, &stServerAddr);
7790d163575Sopenharmony_ci            if (ulErrCode != ERR_OK) {
7800d163575Sopenharmony_ci                (void)lwip_close(iSockNum);
7810d163575Sopenharmony_ci                if (isLocalFileOpened == true) {
7820d163575Sopenharmony_ci                    close(fp);
7830d163575Sopenharmony_ci                }
7840d163575Sopenharmony_ci
7850d163575Sopenharmony_ci                goto err_handler;
7860d163575Sopenharmony_ci            }
7870d163575Sopenharmony_ci
7880d163575Sopenharmony_ci            /* Continue in loop to send last packet again. */
7890d163575Sopenharmony_ci            continue;
7900d163575Sopenharmony_ci        }
7910d163575Sopenharmony_ci
7920d163575Sopenharmony_ci        /* Get the size of the data block received */
7930d163575Sopenharmony_ci        ulRecvSize -= TFTP_HDRSIZE;
7940d163575Sopenharmony_ci
7950d163575Sopenharmony_ci        /* Check if the size of the received data block > max size */
7960d163575Sopenharmony_ci        if (ulRecvSize > TFTP_BLKSIZE) {
7970d163575Sopenharmony_ci            /* Send Error packet to server */
7980d163575Sopenharmony_ci            lwip_tftp_send_error(iSockNum,
7990d163575Sopenharmony_ci                                 TFTPC_PROTOCOL_PROTO_ERROR,
8000d163575Sopenharmony_ci                                 "Packet size > max size",
8010d163575Sopenharmony_ci                                 &stServerAddr, pstSendBuf);
8020d163575Sopenharmony_ci
8030d163575Sopenharmony_ci            (void)lwip_close(iSockNum);
8040d163575Sopenharmony_ci            if (isLocalFileOpened == true) {
8050d163575Sopenharmony_ci                close(fp);
8060d163575Sopenharmony_ci            }
8070d163575Sopenharmony_ci
8080d163575Sopenharmony_ci            LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_get_file_by_filename : Packet size > max size\n"));
8090d163575Sopenharmony_ci
8100d163575Sopenharmony_ci            ulErrCode = TFTPC_PKT_SIZE_ERROR;
8110d163575Sopenharmony_ci            goto err_handler;
8120d163575Sopenharmony_ci        }
8130d163575Sopenharmony_ci
8140d163575Sopenharmony_ci        usReadReq = (u16_t)TFTPC_OP_ACK;
8150d163575Sopenharmony_ci        pstSendBuf->usOpcode = htons(usReadReq);
8160d163575Sopenharmony_ci        pstSendBuf->u.usBlknum = htons((u16_t)ulCurrBlk);
8170d163575Sopenharmony_ci        ulSize = TFTP_HDRSIZE;
8180d163575Sopenharmony_ci
8190d163575Sopenharmony_ci        if (isLocalFileOpened == false) {
8200d163575Sopenharmony_ci            fp = open((char *)pszTempDestName, (O_WRONLY | O_CREAT | O_TRUNC), DEFFILEMODE);
8210d163575Sopenharmony_ci            if (fp == TFTP_NULL_INT32) {
8220d163575Sopenharmony_ci                ulErrCode = TFTPC_FILECREATE_ERROR;
8230d163575Sopenharmony_ci                (void)lwip_close(iSockNum);
8240d163575Sopenharmony_ci                goto err_handler;
8250d163575Sopenharmony_ci            }
8260d163575Sopenharmony_ci            isLocalFileOpened = true;
8270d163575Sopenharmony_ci        }
8280d163575Sopenharmony_ci
8290d163575Sopenharmony_ci        if (ulRecvSize != TFTP_BLKSIZE) {
8300d163575Sopenharmony_ci            (void)lwip_tftp_send_to_server(iSockNum, ulSize, pstSendBuf, &stServerAddr);
8310d163575Sopenharmony_ci
8320d163575Sopenharmony_ci            /* If the received packet has only header and do not have payload, the return failure */
8330d163575Sopenharmony_ci            if (ulRecvSize != 0) {
8340d163575Sopenharmony_ci                /* Write the last packet to the file */
8350d163575Sopenharmony_ci                iErrCode = write(fp, (void *)pstRecvBuf->u.stTFTP_Data.ucDataBuf, (size_t)ulRecvSize);
8360d163575Sopenharmony_ci                if (ulRecvSize != (u32_t)iErrCode) {
8370d163575Sopenharmony_ci                    /* Write to file failed. */
8380d163575Sopenharmony_ci                    lwip_tftp_send_error(iSockNum,
8390d163575Sopenharmony_ci                                         TFTPC_PROTOCOL_USER_DEFINED,
8400d163575Sopenharmony_ci                                         "Write to file failed",
8410d163575Sopenharmony_ci                                         &stServerAddr, pstSendBuf);
8420d163575Sopenharmony_ci
8430d163575Sopenharmony_ci                    (void)lwip_close(iSockNum);
8440d163575Sopenharmony_ci                    close(fp);
8450d163575Sopenharmony_ci
8460d163575Sopenharmony_ci                    /* return from the function, file write failed */
8470d163575Sopenharmony_ci                    ulErrCode = TFTPC_FILEWRITE_ERROR;
8480d163575Sopenharmony_ci                    goto err_handler;
8490d163575Sopenharmony_ci                }
8500d163575Sopenharmony_ci            }
8510d163575Sopenharmony_ci
8520d163575Sopenharmony_ci            /* Now free allocated resourdes and return,
8530d163575Sopenharmony_ci              data block receiving is already completed */
8540d163575Sopenharmony_ci            (void)lwip_close(iSockNum);
8550d163575Sopenharmony_ci            close(fp);
8560d163575Sopenharmony_ci            ulErrCode = ERR_OK;
8570d163575Sopenharmony_ci            goto err_handler;
8580d163575Sopenharmony_ci        }
8590d163575Sopenharmony_ci
8600d163575Sopenharmony_ci        ulErrCode = lwip_tftp_send_to_server(iSockNum, ulSize,
8610d163575Sopenharmony_ci                                             pstSendBuf, &stServerAddr);
8620d163575Sopenharmony_ci        if (ulErrCode != ERR_OK) {
8630d163575Sopenharmony_ci            (void)lwip_close(iSockNum);
8640d163575Sopenharmony_ci            close(fp);
8650d163575Sopenharmony_ci            goto err_handler;
8660d163575Sopenharmony_ci        }
8670d163575Sopenharmony_ci
8680d163575Sopenharmony_ci        iErrCode = write(fp, (void *)pstRecvBuf->u.stTFTP_Data.ucDataBuf, (size_t)ulRecvSize);
8690d163575Sopenharmony_ci        if (ulRecvSize != (u32_t)iErrCode) {
8700d163575Sopenharmony_ci            /* Write to file failed. */
8710d163575Sopenharmony_ci            lwip_tftp_send_error(iSockNum,
8720d163575Sopenharmony_ci                                 TFTPC_PROTOCOL_USER_DEFINED,
8730d163575Sopenharmony_ci                                 "Write to file failed",
8740d163575Sopenharmony_ci                                 &stServerAddr, pstSendBuf);
8750d163575Sopenharmony_ci
8760d163575Sopenharmony_ci            (void)lwip_close(iSockNum);
8770d163575Sopenharmony_ci            close(fp);
8780d163575Sopenharmony_ci
8790d163575Sopenharmony_ci            /* return from the function, file write failed */
8800d163575Sopenharmony_ci            ulErrCode = TFTPC_FILEWRITE_ERROR;
8810d163575Sopenharmony_ci            goto err_handler;
8820d163575Sopenharmony_ci        }
8830d163575Sopenharmony_ci
8840d163575Sopenharmony_ci        /* form the ACK packet for the DATA packet received */
8850d163575Sopenharmony_ci        /* Go to the next packet no. */
8860d163575Sopenharmony_ci        ulCurrBlk++;
8870d163575Sopenharmony_ci
8880d163575Sopenharmony_ci        /* if the file is too big, exit */
8890d163575Sopenharmony_ci        if (ulCurrBlk > TFTP_MAX_BLK_NUM) {
8900d163575Sopenharmony_ci            /* Send error packet to server */
8910d163575Sopenharmony_ci            lwip_tftp_send_error(iSockNum,
8920d163575Sopenharmony_ci                                 TFTPC_PROTOCOL_USER_DEFINED,
8930d163575Sopenharmony_ci                                 "File is too big.",
8940d163575Sopenharmony_ci                                 &stServerAddr, pstSendBuf);
8950d163575Sopenharmony_ci
8960d163575Sopenharmony_ci            (void)lwip_close(iSockNum);
8970d163575Sopenharmony_ci            close(fp);
8980d163575Sopenharmony_ci            LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_get_file_by_filename : Data block number exceeded max value\n"));
8990d163575Sopenharmony_ci
9000d163575Sopenharmony_ci            ulErrCode = TFTPC_FILE_TOO_BIG;
9010d163575Sopenharmony_ci            goto err_handler;
9020d163575Sopenharmony_ci        }
9030d163575Sopenharmony_ci    }
9040d163575Sopenharmony_ci
9050d163575Sopenharmony_cierr_handler:
9060d163575Sopenharmony_ci    mem_free(pstSendBuf);
9070d163575Sopenharmony_ci    mem_free(pstRecvBuf);
9080d163575Sopenharmony_ci    mem_free(pszTempDestName);
9090d163575Sopenharmony_ci    return ulErrCode;
9100d163575Sopenharmony_ci}
9110d163575Sopenharmony_ci
9120d163575Sopenharmony_ci
9130d163575Sopenharmony_ci/* INTERFACE Function to put a file using filename
9140d163575Sopenharmony_ci  ulHostAddr: IP address of Host
9150d163575Sopenharmony_ci  szSrcFileName: Source file
9160d163575Sopenharmony_ci  szDestDirPath: Destination file path
9170d163575Sopenharmony_ci*/
9180d163575Sopenharmony_ciu32_t lwip_tftp_put_file_by_filename(u32_t ulHostAddr, u16_t usTftpServPort, u8_t ucTftpTransMode,
9190d163575Sopenharmony_ci                                     s8_t *szSrcFileName, s8_t *szDestDirPath)
9200d163575Sopenharmony_ci{
9210d163575Sopenharmony_ci    u32_t ulSrcStrLen;
9220d163575Sopenharmony_ci    u32_t ulDestStrLen;
9230d163575Sopenharmony_ci    s32_t iSockNum = TFTP_NULL_INT32;
9240d163575Sopenharmony_ci    s32_t iErrCode;
9250d163575Sopenharmony_ci    u32_t ulErrCode;
9260d163575Sopenharmony_ci    u16_t usTempServPort;
9270d163575Sopenharmony_ci    TFTPC_PACKET_S *pstSendBuf = NULL;
9280d163575Sopenharmony_ci    u16_t usReadReq;
9290d163575Sopenharmony_ci    u32_t ulSize;
9300d163575Sopenharmony_ci    s8_t *pucBuffer = 0;
9310d163575Sopenharmony_ci    s8_t *szTempDestName = NULL;
9320d163575Sopenharmony_ci
9330d163575Sopenharmony_ci    /*Initialize the block number*/
9340d163575Sopenharmony_ci    u16_t usCurrBlk = 0;
9350d163575Sopenharmony_ci    struct sockaddr_in stServerAddr;
9360d163575Sopenharmony_ci    struct stat buffer;
9370d163575Sopenharmony_ci    s32_t fp = -1;
9380d163575Sopenharmony_ci
9390d163575Sopenharmony_ci    /* Validate parameters */
9400d163575Sopenharmony_ci    if ((szSrcFileName == NULL) || (szDestDirPath == NULL)) {
9410d163575Sopenharmony_ci        return TFTPC_INVALID_PARAVALUE;
9420d163575Sopenharmony_ci    }
9430d163575Sopenharmony_ci
9440d163575Sopenharmony_ci    if ((ucTftpTransMode != TRANSFER_MODE_BINARY) && (ucTftpTransMode != TRANSFER_MODE_ASCII)) {
9450d163575Sopenharmony_ci        return TFTPC_INVALID_PARAVALUE;
9460d163575Sopenharmony_ci    }
9470d163575Sopenharmony_ci
9480d163575Sopenharmony_ci    /*check IP address not within ( 1.0.0.0 - 126.255.255.255 )
9490d163575Sopenharmony_ci      and ( 128.0.0.0 - 223.255.255.255 ) range.*/
9500d163575Sopenharmony_ci    if (!(((ulHostAddr >= TFTPC_IP_ADDR_MIN) &&
9510d163575Sopenharmony_ci           (ulHostAddr <= TFTPC_IP_ADDR_EX_RESV)) ||
9520d163575Sopenharmony_ci          ((ulHostAddr >= TFTPC_IP_ADDR_CLASS_B) &&
9530d163575Sopenharmony_ci           (ulHostAddr <= TFTPC_IP_ADDR_EX_CLASS_DE)))) {
9540d163575Sopenharmony_ci        return TFTPC_IP_NOT_WITHIN_RANGE;
9550d163575Sopenharmony_ci    }
9560d163575Sopenharmony_ci
9570d163575Sopenharmony_ci    /* If Src filename is empty or exceeded max length */
9580d163575Sopenharmony_ci    ulSrcStrLen = strlen((char *)szSrcFileName);
9590d163575Sopenharmony_ci    if ((ulSrcStrLen == 0) || (ulSrcStrLen >= TFTP_MAX_PATH_LENGTH)) {
9600d163575Sopenharmony_ci        return TFTPC_SRC_FILENAME_LENGTH_ERROR;
9610d163575Sopenharmony_ci    }
9620d163575Sopenharmony_ci
9630d163575Sopenharmony_ci    /* Check if source file exists */
9640d163575Sopenharmony_ci    if (stat((char *)szSrcFileName, &buffer) != 0) {
9650d163575Sopenharmony_ci        return TFTPC_FILE_NOT_EXIST;
9660d163575Sopenharmony_ci    }
9670d163575Sopenharmony_ci
9680d163575Sopenharmony_ci    /* Check if the file is too big */
9690d163575Sopenharmony_ci    if (buffer.st_size >= (off_t)(TFTP_MAX_BLK_NUM * TFTP_BLKSIZE)) {
9700d163575Sopenharmony_ci        return TFTPC_FILE_TOO_BIG;
9710d163575Sopenharmony_ci    }
9720d163575Sopenharmony_ci
9730d163575Sopenharmony_ci    /* Check validity of destination path */
9740d163575Sopenharmony_ci    ulDestStrLen = strlen((char *)szDestDirPath);
9750d163575Sopenharmony_ci    /* If dest path length exceeded max value */
9760d163575Sopenharmony_ci    if (ulDestStrLen >= TFTP_MAX_PATH_LENGTH) {
9770d163575Sopenharmony_ci        return TFTPC_DEST_PATH_LENGTH_ERROR;
9780d163575Sopenharmony_ci    }
9790d163575Sopenharmony_ci
9800d163575Sopenharmony_ci    pstSendBuf = (TFTPC_PACKET_S *)mem_malloc(sizeof(TFTPC_PACKET_S));
9810d163575Sopenharmony_ci    if (pstSendBuf == NULL) {
9820d163575Sopenharmony_ci        return TFTPC_MEMALLOC_ERROR;
9830d163575Sopenharmony_ci    }
9840d163575Sopenharmony_ci
9850d163575Sopenharmony_ci    /* First time initialize the buffer */
9860d163575Sopenharmony_ci    (void)memset_s((void *)pstSendBuf, sizeof(TFTPC_PACKET_S), 0, sizeof(TFTPC_PACKET_S));
9870d163575Sopenharmony_ci
9880d163575Sopenharmony_ci    /* The destination path can only be one of the following:
9890d163575Sopenharmony_ci    1. Only filename
9900d163575Sopenharmony_ci    2. Relative path WITH filename
9910d163575Sopenharmony_ci    3. Empty string
9920d163575Sopenharmony_ci    */
9930d163575Sopenharmony_ci    if (ulDestStrLen != 0) {
9940d163575Sopenharmony_ci        /* If not empty string use the Destination path name */
9950d163575Sopenharmony_ci        szTempDestName = szDestDirPath;
9960d163575Sopenharmony_ci    } else {
9970d163575Sopenharmony_ci        /* If destination directory is empty string use source filename
9980d163575Sopenharmony_ci        If given src filename is a relative path extract the file name
9990d163575Sopenharmony_ci        from the path */
10000d163575Sopenharmony_ci        if ((strchr((char *)szSrcFileName, '/') != 0) ||
10010d163575Sopenharmony_ci            (strchr((char *)szSrcFileName, '\\') != 0)) {
10020d163575Sopenharmony_ci            /* Move to the end of the src file path */
10030d163575Sopenharmony_ci            szTempDestName = szSrcFileName + (ulSrcStrLen - 1);
10040d163575Sopenharmony_ci
10050d163575Sopenharmony_ci            while (((*(szTempDestName - 1) != '/') && (*(szTempDestName - 1) != '\\')) &&
10060d163575Sopenharmony_ci                   (szTempDestName != szSrcFileName)) {
10070d163575Sopenharmony_ci                szTempDestName--;
10080d163575Sopenharmony_ci            }
10090d163575Sopenharmony_ci        } else {
10100d163575Sopenharmony_ci            /* If not a relative src path use the given src filename */
10110d163575Sopenharmony_ci            szTempDestName = szSrcFileName;
10120d163575Sopenharmony_ci        }
10130d163575Sopenharmony_ci    }
10140d163575Sopenharmony_ci
10150d163575Sopenharmony_ci    /* Create a socket and bind it to an available port number */
10160d163575Sopenharmony_ci    ulErrCode = lwip_tftp_create_bind_socket(&iSockNum);
10170d163575Sopenharmony_ci    if (ulErrCode != EOK) {
10180d163575Sopenharmony_ci        /* Create and Bind socket failed */
10190d163575Sopenharmony_ci        goto err_handler;
10200d163575Sopenharmony_ci    }
10210d163575Sopenharmony_ci
10220d163575Sopenharmony_ci    if (usTftpServPort == 0) {
10230d163575Sopenharmony_ci        usTftpServPort = TFTPC_SERVER_PORT;
10240d163575Sopenharmony_ci    }
10250d163575Sopenharmony_ci
10260d163575Sopenharmony_ci    usTempServPort = usTftpServPort;
10270d163575Sopenharmony_ci
10280d163575Sopenharmony_ci    /* set server internet address */
10290d163575Sopenharmony_ci    (void)memset_s(&stServerAddr, sizeof(stServerAddr), 0, sizeof(stServerAddr));
10300d163575Sopenharmony_ci    stServerAddr.sin_family = AF_INET;
10310d163575Sopenharmony_ci    stServerAddr.sin_port = htons(usTempServPort);
10320d163575Sopenharmony_ci    stServerAddr.sin_addr.s_addr = htonl(ulHostAddr);
10330d163575Sopenharmony_ci
10340d163575Sopenharmony_ci    /* Make request packet - TFTPC_OP_WRQ */
10350d163575Sopenharmony_ci    ulSize = (u32_t)lwip_tftp_make_tftp_packet(TFTPC_OP_WRQ,
10360d163575Sopenharmony_ci                                               szTempDestName,
10370d163575Sopenharmony_ci                                               ucTftpTransMode,
10380d163575Sopenharmony_ci                                               pstSendBuf);
10390d163575Sopenharmony_ci
10400d163575Sopenharmony_ci    ulErrCode = lwip_tftp_send_to_server(iSockNum, ulSize,
10410d163575Sopenharmony_ci                                         pstSendBuf, &stServerAddr);
10420d163575Sopenharmony_ci    if (ulErrCode != ERR_OK) {
10430d163575Sopenharmony_ci        /* Send to server error */
10440d163575Sopenharmony_ci        (void)lwip_close(iSockNum);
10450d163575Sopenharmony_ci
10460d163575Sopenharmony_ci        goto err_handler;
10470d163575Sopenharmony_ci    }
10480d163575Sopenharmony_ci
10490d163575Sopenharmony_ci    /* Send the request packet */
10500d163575Sopenharmony_ci    ulErrCode = lwip_tftp_inner_put_file(iSockNum, pstSendBuf, ulSize,
10510d163575Sopenharmony_ci                                         usCurrBlk, &stServerAddr);
10520d163575Sopenharmony_ci    if (ulErrCode != ERR_OK) {
10530d163575Sopenharmony_ci        /* Send request packet failed */
10540d163575Sopenharmony_ci        (void)lwip_close(iSockNum);
10550d163575Sopenharmony_ci
10560d163575Sopenharmony_ci        LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_put_file_by_filename : Failed to send request packet\n"));
10570d163575Sopenharmony_ci
10580d163575Sopenharmony_ci        goto err_handler;
10590d163575Sopenharmony_ci    }
10600d163575Sopenharmony_ci
10610d163575Sopenharmony_ci    /* Create buffer block size */
10620d163575Sopenharmony_ci    pucBuffer = mem_malloc(TFTP_BLKSIZE);
10630d163575Sopenharmony_ci    if (pucBuffer == NULL) {
10640d163575Sopenharmony_ci        /* Memory allocation failed */
10650d163575Sopenharmony_ci        lwip_tftp_send_error(iSockNum,
10660d163575Sopenharmony_ci                             TFTPC_PROTOCOL_USER_DEFINED,
10670d163575Sopenharmony_ci                             "Memory allocation failed.",
10680d163575Sopenharmony_ci                             &stServerAddr, pstSendBuf);
10690d163575Sopenharmony_ci
10700d163575Sopenharmony_ci        (void)lwip_close(iSockNum);
10710d163575Sopenharmony_ci        ulErrCode = TFTPC_MEMALLOC_ERROR;
10720d163575Sopenharmony_ci        goto err_handler;
10730d163575Sopenharmony_ci    }
10740d163575Sopenharmony_ci
10750d163575Sopenharmony_ci    (void)memset_s((void *)pucBuffer, TFTP_BLKSIZE, 0, TFTP_BLKSIZE);
10760d163575Sopenharmony_ci
10770d163575Sopenharmony_ci    fp = open((char *)szSrcFileName, O_RDONLY);
10780d163575Sopenharmony_ci    if (TFTP_NULL_INT32 == fp) {
10790d163575Sopenharmony_ci        /* If file could not be opened send error to server */
10800d163575Sopenharmony_ci        lwip_tftp_send_error(iSockNum,
10810d163575Sopenharmony_ci                             TFTPC_PROTOCOL_USER_DEFINED,
10820d163575Sopenharmony_ci                             "File open error.",
10830d163575Sopenharmony_ci                             &stServerAddr, pstSendBuf);
10840d163575Sopenharmony_ci
10850d163575Sopenharmony_ci        (void)lwip_close(iSockNum);
10860d163575Sopenharmony_ci        mem_free(pucBuffer);
10870d163575Sopenharmony_ci
10880d163575Sopenharmony_ci        ulErrCode = TFTPC_FILEOPEN_ERROR;
10890d163575Sopenharmony_ci        goto err_handler;
10900d163575Sopenharmony_ci    }
10910d163575Sopenharmony_ci
10920d163575Sopenharmony_ci    iErrCode = read(fp, pucBuffer, TFTP_BLKSIZE);
10930d163575Sopenharmony_ci    if (iErrCode < 0) {
10940d163575Sopenharmony_ci        /* If failed to read from file */
10950d163575Sopenharmony_ci        lwip_tftp_send_error(iSockNum,
10960d163575Sopenharmony_ci                             TFTPC_PROTOCOL_USER_DEFINED,
10970d163575Sopenharmony_ci                             "File read error.",
10980d163575Sopenharmony_ci                             &stServerAddr, pstSendBuf);
10990d163575Sopenharmony_ci
11000d163575Sopenharmony_ci        (void)lwip_close(iSockNum);
11010d163575Sopenharmony_ci        close(fp);
11020d163575Sopenharmony_ci        mem_free(pucBuffer);
11030d163575Sopenharmony_ci
11040d163575Sopenharmony_ci        ulErrCode = TFTPC_FILEREAD_ERROR;
11050d163575Sopenharmony_ci        goto err_handler;
11060d163575Sopenharmony_ci    }
11070d163575Sopenharmony_ci
11080d163575Sopenharmony_ci    /* Read from source file and send to server */
11090d163575Sopenharmony_ci    /* To send empty packet to server when file is a 0 byte file */
11100d163575Sopenharmony_ci    do {
11110d163575Sopenharmony_ci        if (((u32_t)usCurrBlk + 1) > TFTP_MAX_BLK_NUM) {
11120d163575Sopenharmony_ci            lwip_tftp_send_error(iSockNum,
11130d163575Sopenharmony_ci                                 TFTPC_PROTOCOL_USER_DEFINED,
11140d163575Sopenharmony_ci                                 "File is too big.",
11150d163575Sopenharmony_ci                                 &stServerAddr, pstSendBuf);
11160d163575Sopenharmony_ci
11170d163575Sopenharmony_ci            (void)lwip_close(iSockNum);
11180d163575Sopenharmony_ci            close(fp);
11190d163575Sopenharmony_ci            mem_free(pucBuffer);
11200d163575Sopenharmony_ci            LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_put_file_by_filename : Data block number exceeded max value\n"));
11210d163575Sopenharmony_ci
11220d163575Sopenharmony_ci            ulErrCode = TFTPC_FILE_TOO_BIG;
11230d163575Sopenharmony_ci            goto err_handler;
11240d163575Sopenharmony_ci        }
11250d163575Sopenharmony_ci
11260d163575Sopenharmony_ci        /* Increment block number */
11270d163575Sopenharmony_ci        usCurrBlk++;
11280d163575Sopenharmony_ci
11290d163575Sopenharmony_ci        ulSize = (u32_t)iErrCode + TFTP_HDRSIZE;
11300d163575Sopenharmony_ci
11310d163575Sopenharmony_ci        /* Form the DATA packet */
11320d163575Sopenharmony_ci        usReadReq = (u16_t)TFTPC_OP_DATA;
11330d163575Sopenharmony_ci        pstSendBuf->usOpcode = htons(usReadReq);
11340d163575Sopenharmony_ci        pstSendBuf->u.stTFTP_Data.usBlknum = htons(usCurrBlk);
11350d163575Sopenharmony_ci        if (memcpy_s((void *)pstSendBuf->u.stTFTP_Data.ucDataBuf, TFTP_BLKSIZE,
11360d163575Sopenharmony_ci                     (void *)pucBuffer, (u32_t)iErrCode) != EOK) {
11370d163575Sopenharmony_ci            (void)lwip_close(iSockNum);
11380d163575Sopenharmony_ci            close(fp);
11390d163575Sopenharmony_ci            mem_free(pucBuffer);
11400d163575Sopenharmony_ci            goto err_handler;
11410d163575Sopenharmony_ci        }
11420d163575Sopenharmony_ci
11430d163575Sopenharmony_ci        ulErrCode = lwip_tftp_send_to_server(iSockNum, ulSize,
11440d163575Sopenharmony_ci                                             pstSendBuf, &stServerAddr);
11450d163575Sopenharmony_ci        if ((ulErrCode != ERR_OK) || (memset_s((void *)pucBuffer, TFTP_BLKSIZE, 0, TFTP_BLKSIZE) != 0)) {
11460d163575Sopenharmony_ci            (void)lwip_close(iSockNum);
11470d163575Sopenharmony_ci            close(fp);
11480d163575Sopenharmony_ci            mem_free(pucBuffer);
11490d163575Sopenharmony_ci            goto err_handler;
11500d163575Sopenharmony_ci        }
11510d163575Sopenharmony_ci
11520d163575Sopenharmony_ci        /* Read a block from the file to buffer */
11530d163575Sopenharmony_ci        iErrCode = read(fp, pucBuffer, TFTP_BLKSIZE);
11540d163575Sopenharmony_ci        if (iErrCode < 0) {
11550d163575Sopenharmony_ci            /*If failed to read from file*/
11560d163575Sopenharmony_ci            lwip_tftp_send_error(iSockNum, TFTPC_PROTOCOL_USER_DEFINED, "File read error.",
11570d163575Sopenharmony_ci                                 &stServerAddr, pstSendBuf);
11580d163575Sopenharmony_ci
11590d163575Sopenharmony_ci            (void)lwip_close(iSockNum);
11600d163575Sopenharmony_ci            close(fp);
11610d163575Sopenharmony_ci            mem_free(pucBuffer);
11620d163575Sopenharmony_ci            ulErrCode = TFTPC_FILEREAD_ERROR;
11630d163575Sopenharmony_ci            goto err_handler;
11640d163575Sopenharmony_ci        }
11650d163575Sopenharmony_ci
11660d163575Sopenharmony_ci        /* Send the request packet */
11670d163575Sopenharmony_ci        ulErrCode = lwip_tftp_inner_put_file(iSockNum, pstSendBuf, ulSize,
11680d163575Sopenharmony_ci                                             usCurrBlk, &stServerAddr);
11690d163575Sopenharmony_ci        if (ulErrCode != ERR_OK) {
11700d163575Sopenharmony_ci            /* Sending buffer contents failed */
11710d163575Sopenharmony_ci            (void)lwip_close(iSockNum);
11720d163575Sopenharmony_ci            close(fp);
11730d163575Sopenharmony_ci            mem_free(pucBuffer);
11740d163575Sopenharmony_ci            LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_put_file_by_filename : Sending file to server failed\n"));
11750d163575Sopenharmony_ci            goto err_handler;
11760d163575Sopenharmony_ci        }
11770d163575Sopenharmony_ci    } while (ulSize == (TFTP_BLKSIZE + TFTP_HDRSIZE));
11780d163575Sopenharmony_ci
11790d163575Sopenharmony_ci    /* Transfer of data is finished */
11800d163575Sopenharmony_ci    (void)lwip_close(iSockNum);
11810d163575Sopenharmony_ci    close(fp);
11820d163575Sopenharmony_ci    mem_free(pucBuffer);
11830d163575Sopenharmony_ci
11840d163575Sopenharmony_ci    ulErrCode = ERR_OK;
11850d163575Sopenharmony_cierr_handler:
11860d163575Sopenharmony_ci    mem_free(pstSendBuf);
11870d163575Sopenharmony_ci    return ulErrCode;
11880d163575Sopenharmony_ci}
11890d163575Sopenharmony_ci
11900d163575Sopenharmony_ci/* Put file function
11910d163575Sopenharmony_ci    iSockNum: Socket ID
11920d163575Sopenharmony_ci    pstSendBuf: Packet to send to server
11930d163575Sopenharmony_ci    ulSendSize: Packet length
11940d163575Sopenharmony_ci    usCurrBlk: Current block number
11950d163575Sopenharmony_ci    pstServerAddr: Server address
11960d163575Sopenharmony_ci*/
11970d163575Sopenharmony_ciu32_t lwip_tftp_inner_put_file(s32_t iSockNum,
11980d163575Sopenharmony_ci                               TFTPC_PACKET_S *pstSendBuf,
11990d163575Sopenharmony_ci                               u32_t ulSendSize,
12000d163575Sopenharmony_ci                               u16_t usCurrBlk,
12010d163575Sopenharmony_ci                               struct sockaddr_in *pstServerAddr)
12020d163575Sopenharmony_ci{
12030d163575Sopenharmony_ci    u32_t ulPktSize;
12040d163575Sopenharmony_ci    u32_t ulError;
12050d163575Sopenharmony_ci    s32_t iError;
12060d163575Sopenharmony_ci    int iRecvLen = 0;
12070d163575Sopenharmony_ci    socklen_t iFromAddrLen;
12080d163575Sopenharmony_ci    u32_t ulTotalTime = 0;
12090d163575Sopenharmony_ci    fd_set stReadfds;
12100d163575Sopenharmony_ci    struct sockaddr_in stFromAddr;
12110d163575Sopenharmony_ci    struct timeval stTimeout;
12120d163575Sopenharmony_ci    TFTPC_PACKET_S *pstRecvBuf = NULL;
12130d163575Sopenharmony_ci    u32_t ulIgnorePkt = 0;
12140d163575Sopenharmony_ci    u16_t usBlknum;
12150d163575Sopenharmony_ci    u32_t ulLoopCnt = 0;
12160d163575Sopenharmony_ci
12170d163575Sopenharmony_ci    iFromAddrLen = sizeof(stFromAddr);
12180d163575Sopenharmony_ci
12190d163575Sopenharmony_ci    pstRecvBuf = (TFTPC_PACKET_S *)mem_malloc(sizeof(TFTPC_PACKET_S));
12200d163575Sopenharmony_ci    if (pstRecvBuf == NULL) {
12210d163575Sopenharmony_ci        return TFTPC_MEMALLOC_ERROR;
12220d163575Sopenharmony_ci    }
12230d163575Sopenharmony_ci
12240d163575Sopenharmony_ci    /* First time initialize the buffer */
12250d163575Sopenharmony_ci    (void)memset_s((void *)pstRecvBuf, sizeof(TFTPC_PACKET_S), 0, sizeof(TFTPC_PACKET_S));
12260d163575Sopenharmony_ci
12270d163575Sopenharmony_ci    /* Initialize from address to the server address at first */
12280d163575Sopenharmony_ci    if (memcpy_s((void *)&stFromAddr, sizeof(struct sockaddr_in),
12290d163575Sopenharmony_ci                 (void *)pstServerAddr, sizeof(stFromAddr)) != EOK) {
12300d163575Sopenharmony_ci        ulError = TFTPC_MEMCPY_FAILURE;
12310d163575Sopenharmony_ci        goto err_handler;
12320d163575Sopenharmony_ci    }
12330d163575Sopenharmony_ci
12340d163575Sopenharmony_ci    for (;;) {
12350d163575Sopenharmony_ci        ulError = lwip_tftp_recv_from_server(iSockNum, &ulPktSize,
12360d163575Sopenharmony_ci                                             pstRecvBuf, &ulIgnorePkt,
12370d163575Sopenharmony_ci                                             pstServerAddr, pstSendBuf);
12380d163575Sopenharmony_ci        /* If select timeout occurred */
12390d163575Sopenharmony_ci        if (ulError == TFTPC_TIMEOUT_ERROR) {
12400d163575Sopenharmony_ci            ulTotalTime++;
12410d163575Sopenharmony_ci            if (ulTotalTime < TFTPC_MAX_SEND_REQ_ATTEMPTS) {
12420d163575Sopenharmony_ci                /*Max attempts not reached. Resend packet*/
12430d163575Sopenharmony_ci                ulError = lwip_tftp_send_to_server(iSockNum, ulSendSize,
12440d163575Sopenharmony_ci                                                   pstSendBuf, pstServerAddr);
12450d163575Sopenharmony_ci                if (ulError != ERR_OK) {
12460d163575Sopenharmony_ci                    goto err_handler;
12470d163575Sopenharmony_ci                }
12480d163575Sopenharmony_ci
12490d163575Sopenharmony_ci                continue;
12500d163575Sopenharmony_ci            } else {
12510d163575Sopenharmony_ci                /* return from the function, max attempts limit reached */
12520d163575Sopenharmony_ci                ulError = TFTPC_TIMEOUT_ERROR;
12530d163575Sopenharmony_ci                goto err_handler;
12540d163575Sopenharmony_ci            }
12550d163575Sopenharmony_ci        } else if (ulError != ERR_OK) {
12560d163575Sopenharmony_ci            /* return from the function, RecvFromServer failed */
12570d163575Sopenharmony_ci            goto err_handler;
12580d163575Sopenharmony_ci        }
12590d163575Sopenharmony_ci
12600d163575Sopenharmony_ci        /* If Received packet from another server */
12610d163575Sopenharmony_ci        if (ulIgnorePkt > 0) {
12620d163575Sopenharmony_ci            /* The packet that is received is to be ignored.
12630d163575Sopenharmony_ci               So continue without processing it. */
12640d163575Sopenharmony_ci            ulIgnorePkt = 0;
12650d163575Sopenharmony_ci            continue;
12660d163575Sopenharmony_ci        }
12670d163575Sopenharmony_ci
12680d163575Sopenharmony_ci        /* if this packet is unknown or incorrect packet */
12690d163575Sopenharmony_ci        if (TFTPC_OP_ACK != ntohs(pstRecvBuf->usOpcode)) {
12700d163575Sopenharmony_ci            lwip_tftp_send_error(iSockNum,
12710d163575Sopenharmony_ci                                 TFTPC_PROTOCOL_PROTO_ERROR,
12720d163575Sopenharmony_ci                                 "Protocol error.",
12730d163575Sopenharmony_ci                                 pstServerAddr, pstSendBuf);
12740d163575Sopenharmony_ci
12750d163575Sopenharmony_ci            LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_inner_put_file : Received pkt not Ack pkt\n"));
12760d163575Sopenharmony_ci
12770d163575Sopenharmony_ci            ulError = TFTPC_PROTO_ERROR;
12780d163575Sopenharmony_ci            goto err_handler;
12790d163575Sopenharmony_ci        }
12800d163575Sopenharmony_ci
12810d163575Sopenharmony_ci        ulTotalTime = 0;
12820d163575Sopenharmony_ci
12830d163575Sopenharmony_ci        /* if the packet is acknowledge packet */
12840d163575Sopenharmony_ci        usBlknum = ntohs(pstRecvBuf->u.usBlknum);
12850d163575Sopenharmony_ci        iRecvLen = (int)ulPktSize;
12860d163575Sopenharmony_ci
12870d163575Sopenharmony_ci        /* If not correct block no. */
12880d163575Sopenharmony_ci        if (usBlknum != usCurrBlk) {
12890d163575Sopenharmony_ci            /* we are not in sync now */
12900d163575Sopenharmony_ci            /* reset any collected packets. */
12910d163575Sopenharmony_ci            stTimeout.tv_sec = 1;
12920d163575Sopenharmony_ci            stTimeout.tv_usec = 0;
12930d163575Sopenharmony_ci
12940d163575Sopenharmony_ci            FD_ZERO(&stReadfds);
12950d163575Sopenharmony_ci            FD_SET(iSockNum, &stReadfds);
12960d163575Sopenharmony_ci
12970d163575Sopenharmony_ci            /*
12980d163575Sopenharmony_ci            Need to take care of timeout scenario in Select call.
12990d163575Sopenharmony_ci            Since the socket used is blocking, if select timeout occurs,
13000d163575Sopenharmony_ci            the following recvfrom will block indefinitely.
13010d163575Sopenharmony_ci            */
13020d163575Sopenharmony_ci            iError = select((s32_t)(iSockNum + 1), &stReadfds, 0, 0, &stTimeout);
13030d163575Sopenharmony_ci
13040d163575Sopenharmony_ci            /* Loop to get the last data packet from the receive buffer */
13050d163575Sopenharmony_ci            while ((iError != -1) && (iError != 0)) {
13060d163575Sopenharmony_ci                ulLoopCnt++;
13070d163575Sopenharmony_ci
13080d163575Sopenharmony_ci                /* MAX file size in TFTP is 32 MB.
13090d163575Sopenharmony_ci                     Reason for keeping 75 here , is ((75*512=38400bytes)/1024) =  37MB. So the recv/Snd
13100d163575Sopenharmony_ci                     Loop can receive the complete MAX message from the network.
13110d163575Sopenharmony_ci                */
13120d163575Sopenharmony_ci                if (ulLoopCnt > TFTPC_MAX_WAIT_IN_LOOP) {
13130d163575Sopenharmony_ci                    LWIP_DEBUGF(TFTP_DEBUG,
13140d163575Sopenharmony_ci                                ("lwip_tftp_inner_put_file : unexpected packets are received repeatedly\n"));
13150d163575Sopenharmony_ci                    ulError = TFTPC_PKT_SIZE_ERROR;
13160d163575Sopenharmony_ci                    goto err_handler;
13170d163575Sopenharmony_ci                }
13180d163575Sopenharmony_ci
13190d163575Sopenharmony_ci                FD_ZERO(&stReadfds);
13200d163575Sopenharmony_ci                FD_SET(iSockNum, &stReadfds);
13210d163575Sopenharmony_ci                iRecvLen = lwip_recvfrom(iSockNum,
13220d163575Sopenharmony_ci                                         (s8_t *)pstRecvBuf,
13230d163575Sopenharmony_ci                                         TFTP_PKTSIZE, 0,
13240d163575Sopenharmony_ci                                         (struct sockaddr *)&stFromAddr,
13250d163575Sopenharmony_ci                                         &iFromAddrLen);
13260d163575Sopenharmony_ci                if (TFTP_NULL_INT32 == iRecvLen) {
13270d163575Sopenharmony_ci                    ulError = TFTPC_RECVFROM_ERROR;
13280d163575Sopenharmony_ci                    goto err_handler;
13290d163575Sopenharmony_ci                }
13300d163575Sopenharmony_ci
13310d163575Sopenharmony_ci                stTimeout.tv_sec = 1;
13320d163575Sopenharmony_ci                stTimeout.tv_usec = 0;
13330d163575Sopenharmony_ci                iError = select((s32_t)(iSockNum + 1),
13340d163575Sopenharmony_ci                                &stReadfds, 0, 0, &stTimeout);
13350d163575Sopenharmony_ci            }
13360d163575Sopenharmony_ci
13370d163575Sopenharmony_ci            /* If a new packet is not received then donot change the byte order
13380d163575Sopenharmony_ci             * as it has already been done
13390d163575Sopenharmony_ci             */
13400d163575Sopenharmony_ci            /* If received packet size < minimum packet size */
13410d163575Sopenharmony_ci            if (iRecvLen < TFTPC_FOUR) {
13420d163575Sopenharmony_ci                lwip_tftp_send_error(iSockNum,
13430d163575Sopenharmony_ci                                     TFTPC_PROTOCOL_PROTO_ERROR,
13440d163575Sopenharmony_ci                                     "Packet size < min packet size",
13450d163575Sopenharmony_ci                                     pstServerAddr, pstSendBuf);
13460d163575Sopenharmony_ci
13470d163575Sopenharmony_ci                LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_inner_put_file : Received pkt not Ack pkt\n"));
13480d163575Sopenharmony_ci
13490d163575Sopenharmony_ci                ulError = TFTPC_PKT_SIZE_ERROR;
13500d163575Sopenharmony_ci                goto err_handler;
13510d163575Sopenharmony_ci            }
13520d163575Sopenharmony_ci
13530d163575Sopenharmony_ci            /* Check if the received packet is from correct server and from
13540d163575Sopenharmony_ci               correct port
13550d163575Sopenharmony_ci               */
13560d163575Sopenharmony_ci            if ((stFromAddr.sin_addr.s_addr != pstServerAddr->sin_addr.s_addr) ||
13570d163575Sopenharmony_ci                (pstServerAddr->sin_port != stFromAddr.sin_port)) {
13580d163575Sopenharmony_ci                /* This ACK packet is invalid. Just ignore it. */
13590d163575Sopenharmony_ci                LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_inner_put_file : Received pkt from unknown server\n"));
13600d163575Sopenharmony_ci                continue;
13610d163575Sopenharmony_ci            }
13620d163575Sopenharmony_ci
13630d163575Sopenharmony_ci            /* if this packet is not ACK packet */
13640d163575Sopenharmony_ci            if (TFTPC_OP_ACK != ntohs(pstRecvBuf->usOpcode)) {
13650d163575Sopenharmony_ci                lwip_tftp_send_error(iSockNum,
13660d163575Sopenharmony_ci                                     TFTPC_PROTOCOL_PROTO_ERROR,
13670d163575Sopenharmony_ci                                     "Protocol error.",
13680d163575Sopenharmony_ci                                     pstServerAddr, pstSendBuf);
13690d163575Sopenharmony_ci
13700d163575Sopenharmony_ci                LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_inner_put_file : Received pkt not Ack pkt\n"));
13710d163575Sopenharmony_ci
13720d163575Sopenharmony_ci                ulError = TFTPC_PROTO_ERROR;
13730d163575Sopenharmony_ci                goto err_handler;
13740d163575Sopenharmony_ci            }
13750d163575Sopenharmony_ci
13760d163575Sopenharmony_ci            usBlknum = ntohs(pstRecvBuf->u.usBlknum);
13770d163575Sopenharmony_ci            /*
13780d163575Sopenharmony_ci            * In this case we have received a duplicate ACK for data block.
13790d163575Sopenharmony_ci            * (ACK for this data block was aready received earlier)
13800d163575Sopenharmony_ci            * In this case we have usRecvBlkNum == (usNextBlkNum - 1).
13810d163575Sopenharmony_ci            * This could mean that:
13820d163575Sopenharmony_ci            * (i) last data packet that was sent was not received at server side
13830d163575Sopenharmony_ci            * (ii) Acknowledgement of peer side is delayed.
13840d163575Sopenharmony_ci            *
13850d163575Sopenharmony_ci            * In this case, this duplicate ACK will be ignored and return to the
13860d163575Sopenharmony_ci            * state machine to initiate a receive of this data packet.
13870d163575Sopenharmony_ci            */
13880d163575Sopenharmony_ci            if ((usCurrBlk - 1) == usBlknum) {
13890d163575Sopenharmony_ci                /* This ACK packet is invalid. Just ignore it. */
13900d163575Sopenharmony_ci                continue;
13910d163575Sopenharmony_ci            }
13920d163575Sopenharmony_ci
13930d163575Sopenharmony_ci            /* Now check the block number with current block.
13940d163575Sopenharmony_ci            * If it is not the previous block and the current block,
13950d163575Sopenharmony_ci            * then it is an unexpected packet.
13960d163575Sopenharmony_ci            */
13970d163575Sopenharmony_ci            if (usBlknum != usCurrBlk) {
13980d163575Sopenharmony_ci                lwip_tftp_send_error(iSockNum,
13990d163575Sopenharmony_ci                                     TFTPC_PROTOCOL_PROTO_ERROR,
14000d163575Sopenharmony_ci                                     "Received unexpected packet",
14010d163575Sopenharmony_ci                                     pstServerAddr, pstSendBuf);
14020d163575Sopenharmony_ci
14030d163575Sopenharmony_ci                LWIP_DEBUGF(TFTP_DEBUG,
14040d163575Sopenharmony_ci                            ("lwip_tftp_inner_put_file : Received DATA pkt no. %"S32_F"instead of pkt no. %"S32_F"\n",
14050d163575Sopenharmony_ci                                usBlknum, usCurrBlk));
14060d163575Sopenharmony_ci
14070d163575Sopenharmony_ci                ulError = TFTPC_SYNC_FAILURE;
14080d163575Sopenharmony_ci                goto err_handler;
14090d163575Sopenharmony_ci            }
14100d163575Sopenharmony_ci        }
14110d163575Sopenharmony_ci
14120d163575Sopenharmony_ci        ulError = ERR_OK;
14130d163575Sopenharmony_ci        goto err_handler;
14140d163575Sopenharmony_ci    }
14150d163575Sopenharmony_ci
14160d163575Sopenharmony_cierr_handler:
14170d163575Sopenharmony_ci    mem_free(pstRecvBuf);
14180d163575Sopenharmony_ci    return ulError;
14190d163575Sopenharmony_ci}
14200d163575Sopenharmony_ci
14210d163575Sopenharmony_ci#ifdef TFTP_TO_RAWMEM
14220d163575Sopenharmony_ci/* INTERFACE to get a file using filename
14230d163575Sopenharmony_ci    ulHostAddr - IP address of Host
14240d163575Sopenharmony_ci    szSrcFileName - Source file
14250d163575Sopenharmony_ci    szDestMemAddr - The target memory address in the client
14260d163575Sopenharmony_ci
14270d163575Sopenharmony_ci    Example :
14280d163575Sopenharmony_ci    ulHostAddr = ntohl(inet_addr ("192.168.1.3"));
14290d163575Sopenharmony_ci    lwip_tftp_get_file_by_filename_to_rawmem(ulHostAddr, "/ramfs/vs_server.bin", memaddr, &filelen);
14300d163575Sopenharmony_ci*/
14310d163575Sopenharmony_ciu32_t lwip_tftp_get_file_by_filename_to_rawmem(u32_t ulHostAddr,
14320d163575Sopenharmony_ci                                               u16_t usTftpServPort,
14330d163575Sopenharmony_ci                                               u8_t ucTftpTransMode,
14340d163575Sopenharmony_ci                                               s8_t *szSrcFileName,
14350d163575Sopenharmony_ci                                               s8_t *szDestMemAddr,
14360d163575Sopenharmony_ci                                               u32_t *ulFileLength)
14370d163575Sopenharmony_ci{
14380d163575Sopenharmony_ci    s32_t iSockNum = TFTP_NULL_INT32;
14390d163575Sopenharmony_ci    u32_t ulSrcStrLen;
14400d163575Sopenharmony_ci    u32_t ulSize;
14410d163575Sopenharmony_ci    u32_t ulRecvSize = TFTP_NULL_UINT32;
14420d163575Sopenharmony_ci    u32_t ulErrCode;
14430d163575Sopenharmony_ci    u16_t usReadReq;
14440d163575Sopenharmony_ci    u16_t usTempServPort;
14450d163575Sopenharmony_ci    u32_t ulCurrBlk = 1;
14460d163575Sopenharmony_ci    u32_t ulResendPkt = 0; /* Resend the previous packet */
14470d163575Sopenharmony_ci    u32_t ulIgnorePkt = 0; /* Ignore received packet */
14480d163575Sopenharmony_ci    u32_t ulTotalTime = 0;
14490d163575Sopenharmony_ci
14500d163575Sopenharmony_ci    TFTPC_PACKET_S *pstSendBuf = NULL;
14510d163575Sopenharmony_ci    TFTPC_PACKET_S *pstRecvBuf = NULL;
14520d163575Sopenharmony_ci    struct sockaddr_in stServerAddr;
14530d163575Sopenharmony_ci    u32_t ulMemOffset = 0;
14540d163575Sopenharmony_ci
14550d163575Sopenharmony_ci    /* Validate the parameters */
14560d163575Sopenharmony_ci    if ((szSrcFileName == NULL) || (szDestMemAddr == NULL) || (*ulFileLength == 0)) {
14570d163575Sopenharmony_ci        return TFTPC_INVALID_PARAVALUE;
14580d163575Sopenharmony_ci    }
14590d163575Sopenharmony_ci
14600d163575Sopenharmony_ci    if ((ucTftpTransMode != TRANSFER_MODE_BINARY) && (ucTftpTransMode != TRANSFER_MODE_ASCII)) {
14610d163575Sopenharmony_ci        return TFTPC_INVALID_PARAVALUE;
14620d163575Sopenharmony_ci    }
14630d163575Sopenharmony_ci
14640d163575Sopenharmony_ci    /* check IP address not within ( 1.0.0.0 - 126.255.255.255 )
14650d163575Sopenharmony_ci     and ( 128.0.0.0 - 223.255.255.255 ) range. */
14660d163575Sopenharmony_ci    if (!(((ulHostAddr >= TFTPC_IP_ADDR_MIN) &&
14670d163575Sopenharmony_ci           (ulHostAddr <= TFTPC_IP_ADDR_EX_RESV)) ||
14680d163575Sopenharmony_ci          ((ulHostAddr >= TFTPC_IP_ADDR_CLASS_B) &&
14690d163575Sopenharmony_ci           (ulHostAddr <= TFTPC_IP_ADDR_EX_CLASS_DE)))) {
14700d163575Sopenharmony_ci        return TFTPC_IP_NOT_WITHIN_RANGE;
14710d163575Sopenharmony_ci    }
14720d163575Sopenharmony_ci
14730d163575Sopenharmony_ci    /*Check validity of source filename*/
14740d163575Sopenharmony_ci    ulSrcStrLen = strlen(szSrcFileName);
14750d163575Sopenharmony_ci    if ((ulSrcStrLen == 0) || (ulSrcStrLen >= TFTP_MAX_PATH_LENGTH)) {
14760d163575Sopenharmony_ci        return TFTPC_SRC_FILENAME_LENGTH_ERROR;
14770d163575Sopenharmony_ci    }
14780d163575Sopenharmony_ci
14790d163575Sopenharmony_ci    pstSendBuf = (TFTPC_PACKET_S *)mem_malloc(sizeof(TFTPC_PACKET_S));
14800d163575Sopenharmony_ci    if (pstSendBuf == NULL) {
14810d163575Sopenharmony_ci        return TFTPC_MEMALLOC_ERROR;
14820d163575Sopenharmony_ci    }
14830d163575Sopenharmony_ci
14840d163575Sopenharmony_ci    pstRecvBuf = (TFTPC_PACKET_S *)mem_malloc(sizeof(TFTPC_PACKET_S));
14850d163575Sopenharmony_ci    if (pstRecvBuf == NULL) {
14860d163575Sopenharmony_ci        mem_free(pstSendBuf);
14870d163575Sopenharmony_ci        return TFTPC_MEMALLOC_ERROR;
14880d163575Sopenharmony_ci    }
14890d163575Sopenharmony_ci
14900d163575Sopenharmony_ci    /* First time initialize the buffers */
14910d163575Sopenharmony_ci    (void)memset_s((void *)pstSendBuf, sizeof(TFTPC_PACKET_S), 0, sizeof(TFTPC_PACKET_S));
14920d163575Sopenharmony_ci    (void)memset_s((void *)pstRecvBuf, sizeof(TFTPC_PACKET_S), 0, sizeof(TFTPC_PACKET_S));
14930d163575Sopenharmony_ci
14940d163575Sopenharmony_ci    ulErrCode = lwip_tftp_create_bind_socket(&iSockNum);
14950d163575Sopenharmony_ci    if (ulErrCode != EOK) {
14960d163575Sopenharmony_ci        goto err_handler;
14970d163575Sopenharmony_ci    }
14980d163575Sopenharmony_ci
14990d163575Sopenharmony_ci    if (usTftpServPort == 0) {
15000d163575Sopenharmony_ci        usTftpServPort = TFTPC_SERVER_PORT;
15010d163575Sopenharmony_ci    }
15020d163575Sopenharmony_ci
15030d163575Sopenharmony_ci    usTempServPort = usTftpServPort;
15040d163575Sopenharmony_ci
15050d163575Sopenharmony_ci    /* set server IP address */
15060d163575Sopenharmony_ci    (void)memset_s(&stServerAddr, sizeof(stServerAddr), 0, sizeof(stServerAddr));
15070d163575Sopenharmony_ci    stServerAddr.sin_family = AF_INET;
15080d163575Sopenharmony_ci    stServerAddr.sin_port = htons(usTempServPort);
15090d163575Sopenharmony_ci    stServerAddr.sin_addr.s_addr = htonl(ulHostAddr);
15100d163575Sopenharmony_ci
15110d163575Sopenharmony_ci    /* Make a request packet - TFTPC_OP_RRQ */
15120d163575Sopenharmony_ci    ulSize = (u32_t)lwip_tftp_make_tftp_packet(TFTPC_OP_RRQ, szSrcFileName, (u32_t)ucTftpTransMode, pstSendBuf);
15130d163575Sopenharmony_ci    ulErrCode = lwip_tftp_send_to_server(iSockNum, ulSize, pstSendBuf, &stServerAddr);
15140d163575Sopenharmony_ci    if (ulErrCode != ERR_OK) {
15150d163575Sopenharmony_ci        /* send to server failed */
15160d163575Sopenharmony_ci        (void)lwip_close(iSockNum);
15170d163575Sopenharmony_ci        goto err_handler;
15180d163575Sopenharmony_ci    }
15190d163575Sopenharmony_ci
15200d163575Sopenharmony_ci    for (;;) {
15210d163575Sopenharmony_ci        if (ulIgnorePkt > 0) {
15220d163575Sopenharmony_ci            ulIgnorePkt = 0;
15230d163575Sopenharmony_ci        }
15240d163575Sopenharmony_ci
15250d163575Sopenharmony_ci        ulErrCode = lwip_tftp_recv_from_server(iSockNum, &ulRecvSize, pstRecvBuf, &ulIgnorePkt,
15260d163575Sopenharmony_ci                                               &stServerAddr, pstSendBuf);
15270d163575Sopenharmony_ci        /* If select timeout occurred */
15280d163575Sopenharmony_ci        if (ulErrCode == TFTPC_TIMEOUT_ERROR) {
15290d163575Sopenharmony_ci            ulTotalTime++;
15300d163575Sopenharmony_ci            if (ulTotalTime < TFTPC_MAX_SEND_REQ_ATTEMPTS) {
15310d163575Sopenharmony_ci                /* Max attempts not reached. Resend packet */
15320d163575Sopenharmony_ci                ulErrCode = lwip_tftp_send_to_server(iSockNum, ulSize,
15330d163575Sopenharmony_ci                                                     pstSendBuf, &stServerAddr);
15340d163575Sopenharmony_ci                if (ulErrCode != ERR_OK) {
15350d163575Sopenharmony_ci                    (void)lwip_close(iSockNum);
15360d163575Sopenharmony_ci                    goto err_handler;
15370d163575Sopenharmony_ci                }
15380d163575Sopenharmony_ci
15390d163575Sopenharmony_ci                continue;
15400d163575Sopenharmony_ci            } else {
15410d163575Sopenharmony_ci                /* return from the function, max attempts limit reached */
15420d163575Sopenharmony_ci                (void)lwip_close(iSockNum);
15430d163575Sopenharmony_ci                ulErrCode = TFTPC_TIMEOUT_ERROR;
15440d163575Sopenharmony_ci                goto err_handler;
15450d163575Sopenharmony_ci            }
15460d163575Sopenharmony_ci        } else if (ulErrCode != ERR_OK) {
15470d163575Sopenharmony_ci            (void)lwip_close(iSockNum);
15480d163575Sopenharmony_ci            goto err_handler;
15490d163575Sopenharmony_ci        }
15500d163575Sopenharmony_ci
15510d163575Sopenharmony_ci        /* Now we have receive block from different server. */
15520d163575Sopenharmony_ci        if (ulIgnorePkt > 0) {
15530d163575Sopenharmony_ci            /*Continue without processing this block. */
15540d163575Sopenharmony_ci            continue;
15550d163575Sopenharmony_ci        }
15560d163575Sopenharmony_ci
15570d163575Sopenharmony_ci        /* if this packet is unkonwn or incorrect packet */
15580d163575Sopenharmony_ci        if (ntohs(pstRecvBuf->usOpcode) != TFTPC_OP_DATA) {
15590d163575Sopenharmony_ci            /* Send error packet to server */
15600d163575Sopenharmony_ci            lwip_tftp_send_error(iSockNum,
15610d163575Sopenharmony_ci                                 TFTPC_PROTOCOL_PROTO_ERROR,
15620d163575Sopenharmony_ci                                 "Protocol error.",
15630d163575Sopenharmony_ci                                 &stServerAddr, pstSendBuf);
15640d163575Sopenharmony_ci
15650d163575Sopenharmony_ci            (void)lwip_close(iSockNum);
15660d163575Sopenharmony_ci
15670d163575Sopenharmony_ci            LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_get_file_by_filename : Received pkt not DATA pkt\n"));
15680d163575Sopenharmony_ci
15690d163575Sopenharmony_ci            ulErrCode = TFTPC_PROTO_ERROR;
15700d163575Sopenharmony_ci            goto err_handler;
15710d163575Sopenharmony_ci        }
15720d163575Sopenharmony_ci
15730d163575Sopenharmony_ci        /* Now the number of tries will be reset. */
15740d163575Sopenharmony_ci        ulTotalTime = 0;
15750d163575Sopenharmony_ci
15760d163575Sopenharmony_ci        /* Validate received  DATA packet. */
15770d163575Sopenharmony_ci        ulErrCode = lwip_tftp_validate_data_pkt(iSockNum, &ulRecvSize,
15780d163575Sopenharmony_ci                                                pstRecvBuf, (u16_t)ulCurrBlk,
15790d163575Sopenharmony_ci                                                &ulResendPkt,
15800d163575Sopenharmony_ci                                                &stServerAddr);
15810d163575Sopenharmony_ci        if (ulErrCode != ERR_OK) {
15820d163575Sopenharmony_ci            /* Send Error packet to server */
15830d163575Sopenharmony_ci            if (ulErrCode != TFTPC_RECVFROM_ERROR) {
15840d163575Sopenharmony_ci                lwip_tftp_send_error(iSockNum,
15850d163575Sopenharmony_ci                                     TFTPC_PROTOCOL_PROTO_ERROR,
15860d163575Sopenharmony_ci                                     "Received unexpected packet",
15870d163575Sopenharmony_ci                                     &stServerAddr, pstSendBuf);
15880d163575Sopenharmony_ci            }
15890d163575Sopenharmony_ci
15900d163575Sopenharmony_ci            (void)lwip_close(iSockNum);
15910d163575Sopenharmony_ci
15920d163575Sopenharmony_ci            goto err_handler;
15930d163575Sopenharmony_ci        }
15940d163575Sopenharmony_ci
15950d163575Sopenharmony_ci        /* Received previous data block again. Resend last packet */
15960d163575Sopenharmony_ci        if (ulResendPkt > 0) {
15970d163575Sopenharmony_ci            /* Now set ulResendPkt to 0 to send the last packet. */
15980d163575Sopenharmony_ci            ulResendPkt = 0;
15990d163575Sopenharmony_ci            ulErrCode = lwip_tftp_send_to_server(iSockNum, ulSize,
16000d163575Sopenharmony_ci                                                 pstSendBuf, &stServerAddr);
16010d163575Sopenharmony_ci            if (ulErrCode != ERR_OK) {
16020d163575Sopenharmony_ci                (void)lwip_close(iSockNum);
16030d163575Sopenharmony_ci
16040d163575Sopenharmony_ci                goto err_handler;
16050d163575Sopenharmony_ci            }
16060d163575Sopenharmony_ci
16070d163575Sopenharmony_ci            /* Continue in loop to send last packet again. */
16080d163575Sopenharmony_ci            continue;
16090d163575Sopenharmony_ci        }
16100d163575Sopenharmony_ci
16110d163575Sopenharmony_ci        /* Get the size of the data block received */
16120d163575Sopenharmony_ci        ulRecvSize -= TFTP_HDRSIZE;
16130d163575Sopenharmony_ci
16140d163575Sopenharmony_ci        /* Check if the size of the received data block > max size */
16150d163575Sopenharmony_ci        if (ulRecvSize > TFTP_BLKSIZE) {
16160d163575Sopenharmony_ci            /* Send Error packet to server */
16170d163575Sopenharmony_ci            lwip_tftp_send_error(iSockNum,
16180d163575Sopenharmony_ci                                 TFTPC_PROTOCOL_PROTO_ERROR,
16190d163575Sopenharmony_ci                                 "Packet size > max size",
16200d163575Sopenharmony_ci                                 &stServerAddr, pstSendBuf);
16210d163575Sopenharmony_ci
16220d163575Sopenharmony_ci            (void)lwip_close(iSockNum);
16230d163575Sopenharmony_ci
16240d163575Sopenharmony_ci            LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_get_file_by_filename : Packet size > max size\n"));
16250d163575Sopenharmony_ci
16260d163575Sopenharmony_ci            ulErrCode = TFTPC_PKT_SIZE_ERROR;
16270d163575Sopenharmony_ci            goto err_handler;
16280d163575Sopenharmony_ci        }
16290d163575Sopenharmony_ci
16300d163575Sopenharmony_ci        usReadReq = (u16_t)TFTPC_OP_ACK;
16310d163575Sopenharmony_ci        pstSendBuf->usOpcode = htons(usReadReq);
16320d163575Sopenharmony_ci        pstSendBuf->u.usBlknum = htons((u16_t)ulCurrBlk);
16330d163575Sopenharmony_ci        ulSize = TFTP_HDRSIZE;
16340d163575Sopenharmony_ci
16350d163575Sopenharmony_ci        if (ulRecvSize != TFTP_BLKSIZE) {
16360d163575Sopenharmony_ci            (void)lwip_tftp_send_to_server(iSockNum, ulSize,
16370d163575Sopenharmony_ci                                           pstSendBuf, &stServerAddr);
16380d163575Sopenharmony_ci
16390d163575Sopenharmony_ci            /* If the received packet has only header and do not have payload, the return failure */
16400d163575Sopenharmony_ci            if (ulRecvSize != 0) {
16410d163575Sopenharmony_ci                /* memcopy filed */
16420d163575Sopenharmony_ci                if (*ulFileLength < (ulMemOffset + ulRecvSize)) {
16430d163575Sopenharmony_ci                    ulErrCode = TFTPC_MEMCPY_FAILURE;
16440d163575Sopenharmony_ci                    (void)lwip_close(iSockNum);
16450d163575Sopenharmony_ci                    *ulFileLength = ulMemOffset;
16460d163575Sopenharmony_ci                    goto err_handler;
16470d163575Sopenharmony_ci                }
16480d163575Sopenharmony_ci                /* copy the last packet to the memory */
16490d163575Sopenharmony_ci                if (memcpy_s(szDestMemAddr + ulMemOffset, TFTP_MAX_BLK_NUM * TFTP_BLKSIZE,
16500d163575Sopenharmony_ci                             (void *)pstRecvBuf->u.stTFTP_Data.ucDataBuf, (size_t)ulRecvSize) != EOK) {
16510d163575Sopenharmony_ci                    ulErrCode = TFTPC_MEMCPY_FAILURE;
16520d163575Sopenharmony_ci                    (void)lwip_close(iSockNum);
16530d163575Sopenharmony_ci                    *ulFileLength = ulMemOffset;
16540d163575Sopenharmony_ci                    goto err_handler;
16550d163575Sopenharmony_ci                }
16560d163575Sopenharmony_ci                ulMemOffset += ulRecvSize;
16570d163575Sopenharmony_ci            }
16580d163575Sopenharmony_ci
16590d163575Sopenharmony_ci            /* Now free allocated resourdes and return,
16600d163575Sopenharmony_ci              data block receiving is already completed */
16610d163575Sopenharmony_ci            (void)lwip_close(iSockNum);
16620d163575Sopenharmony_ci            ulErrCode = ERR_OK;
16630d163575Sopenharmony_ci            *ulFileLength = ulMemOffset;
16640d163575Sopenharmony_ci            goto err_handler;
16650d163575Sopenharmony_ci        }
16660d163575Sopenharmony_ci
16670d163575Sopenharmony_ci        ulErrCode = lwip_tftp_send_to_server(iSockNum, ulSize,
16680d163575Sopenharmony_ci                                             pstSendBuf, &stServerAddr);
16690d163575Sopenharmony_ci        if (ulErrCode != ERR_OK) {
16700d163575Sopenharmony_ci            (void)lwip_close(iSockNum);
16710d163575Sopenharmony_ci            goto err_handler;
16720d163575Sopenharmony_ci        }
16730d163575Sopenharmony_ci
16740d163575Sopenharmony_ci        /* memcopy filed */
16750d163575Sopenharmony_ci        if (*ulFileLength < ulRecvSize * ulCurrBlk) {
16760d163575Sopenharmony_ci            ulErrCode = TFTPC_MEMCPY_FAILURE;
16770d163575Sopenharmony_ci            (void)lwip_close(iSockNum);
16780d163575Sopenharmony_ci            *ulFileLength = ulMemOffset;
16790d163575Sopenharmony_ci            goto err_handler;
16800d163575Sopenharmony_ci        }
16810d163575Sopenharmony_ci        if (memcpy_s(szDestMemAddr + ulMemOffset, TFTP_MAX_BLK_NUM * TFTP_BLKSIZE,
16820d163575Sopenharmony_ci                     (void *)pstRecvBuf->u.stTFTP_Data.ucDataBuf, (size_t)ulRecvSize) != EOK) {
16830d163575Sopenharmony_ci            ulErrCode = TFTPC_MEMCPY_FAILURE;
16840d163575Sopenharmony_ci            (void)lwip_close(iSockNum);
16850d163575Sopenharmony_ci            *ulFileLength = ulMemOffset;
16860d163575Sopenharmony_ci            goto err_handler;
16870d163575Sopenharmony_ci        }
16880d163575Sopenharmony_ci
16890d163575Sopenharmony_ci        ulMemOffset += ulRecvSize;
16900d163575Sopenharmony_ci        /* form the ACK packet for the DATA packet received */
16910d163575Sopenharmony_ci        /* Go to the next packet no. */
16920d163575Sopenharmony_ci        ulCurrBlk++;
16930d163575Sopenharmony_ci        /* if the file is too big, exit */
16940d163575Sopenharmony_ci        if (ulCurrBlk > TFTP_MAX_BLK_NUM) {
16950d163575Sopenharmony_ci            /* Send error packet to server */
16960d163575Sopenharmony_ci            lwip_tftp_send_error(iSockNum,
16970d163575Sopenharmony_ci                                 TFTPC_PROTOCOL_USER_DEFINED,
16980d163575Sopenharmony_ci                                 "File is too big.",
16990d163575Sopenharmony_ci                                 &stServerAddr, pstSendBuf);
17000d163575Sopenharmony_ci
17010d163575Sopenharmony_ci            (void)lwip_close(iSockNum);
17020d163575Sopenharmony_ci
17030d163575Sopenharmony_ci            LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_get_file_by_filename : Data block number exceeded max value\n"));
17040d163575Sopenharmony_ci
17050d163575Sopenharmony_ci            ulErrCode = TFTPC_FILE_TOO_BIG;
17060d163575Sopenharmony_ci            goto err_handler;
17070d163575Sopenharmony_ci        }
17080d163575Sopenharmony_ci    }
17090d163575Sopenharmony_ci
17100d163575Sopenharmony_cierr_handler:
17110d163575Sopenharmony_ci    mem_free(pstSendBuf);
17120d163575Sopenharmony_ci    mem_free(pstRecvBuf);
17130d163575Sopenharmony_ci    return ulErrCode;
17140d163575Sopenharmony_ci}
17150d163575Sopenharmony_ci#endif
17160d163575Sopenharmony_ci
17170d163575Sopenharmony_ci#endif /* LOSCFG_NET_LWIP_SACK_TFTP */
17180d163575Sopenharmony_ci#endif /* LWIP_TFTP */
1719