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