From 4f55f678c154c0e832ed825f80cc8789dc5d0f26 Mon Sep 17 00:00:00 2001 From: c00546070 Date: Tue, 22 Sep 2020 18:38:46 +0800 Subject: [PATCH] Description: add dhcps and tftpc Reviewed-by: jianghan --- net/lwip-2.1/Makefile | 2 +- net/lwip-2.1/enhancement/include/dhcps_fix.h | 102 - .../include/{ => lwip}/api_shell.h | 8 +- .../enhancement/include/{ => lwip}/dhcps.h | 10 - .../include/{api_shell_fix.h => lwip/fixme.h} | 141 +- net/lwip-2.1/enhancement/include/lwip/tftpc.h | 310 +++ net/lwip-2.1/enhancement/src/api_shell.c | 9 +- net/lwip-2.1/enhancement/src/dhcps.c | 983 ++++++++++ .../src/{api_shell_fix.c => fixme.c} | 137 +- net/lwip-2.1/enhancement/src/tftpc.c | 1726 +++++++++++++++++ net/lwip-2.1/porting/include/lwip/dhcp.h | 19 + net/lwip-2.1/porting/include/lwip/lwipopts.h | 4 + net/lwip-2.1/porting/include/lwip/netif.h | 15 +- net/lwip-2.1/porting/include/lwip/netifapi.h | 1 + net/lwip-2.1/porting/src/driverif.c | 78 +- net/lwip-2.1/porting/src/fixme.c | 46 - net/lwip-2.1/porting/src/sockets.c | 14 +- net/lwip-2.1/porting/src/sys_arch.c | 25 +- 18 files changed, 3225 insertions(+), 405 deletions(-) delete mode 100755 net/lwip-2.1/enhancement/include/dhcps_fix.h rename net/lwip-2.1/enhancement/include/{ => lwip}/api_shell.h (96%) rename net/lwip-2.1/enhancement/include/{ => lwip}/dhcps.h (80%) rename net/lwip-2.1/enhancement/include/{api_shell_fix.h => lwip/fixme.h} (66%) create mode 100644 net/lwip-2.1/enhancement/include/lwip/tftpc.h create mode 100644 net/lwip-2.1/enhancement/src/dhcps.c rename net/lwip-2.1/enhancement/src/{api_shell_fix.c => fixme.c} (82%) create mode 100644 net/lwip-2.1/enhancement/src/tftpc.c delete mode 100755 net/lwip-2.1/porting/src/fixme.c diff --git a/net/lwip-2.1/Makefile b/net/lwip-2.1/Makefile index 7ce79fcc..5194ad9e 100755 --- a/net/lwip-2.1/Makefile +++ b/net/lwip-2.1/Makefile @@ -44,7 +44,7 @@ LOCAL_FLAGS += $(LOCAL_INCLUDE) LOCAL_SRCS := $(wildcard porting/src/*.c $(LWIPNOAPPSFILES)) LOCAL_SRCS += $(wildcard enhancement/src/*.c) -LOCAL_SRCS += $(wildcard $(LWIPDIR)/core/ipv4/dhcps.c) +LOCAL_SRCS := $(filter-out $(LWIPDIR)/core/ipv4/dhcp.c, $(LOCAL_SRCS)) LOCAL_SRCS := $(filter-out $(LWIPDIR)/core/ipv4/etharp.c, $(LOCAL_SRCS)) LOCAL_SRCS := $(filter-out $(LWIPDIR)/api/sockets.c, $(LOCAL_SRCS)) diff --git a/net/lwip-2.1/enhancement/include/dhcps_fix.h b/net/lwip-2.1/enhancement/include/dhcps_fix.h deleted file mode 100755 index 616eab7e..00000000 --- a/net/lwip-2.1/enhancement/include/dhcps_fix.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. - * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be used - * to endorse or promote products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef LITEOS_A_DHCPS_FIXME_H -#define LITEOS_A_DHCPS_FIXME_H - -#include "lwip/opt.h" - -#if (LWIP_DHCP) && (LWIP_DHCPS) - -#define LWIP_STATIC static - - -/* Option handling: options are parsed in dhcp_parse_reply - * and saved in an array where other functions can load them from. - * This might be moved into the struct dhcp (not necessarily since - * lwIP is single-threaded and the array is only used while in recv - * callback). */ -enum dhcp_option_idx { - DHCP_OPTION_IDX_OVERLOAD = 0, - DHCP_OPTION_IDX_MSG_TYPE, - DHCP_OPTION_IDX_SERVER_ID, - DHCP_OPTION_IDX_LEASE_TIME, - DHCP_OPTION_IDX_T1, - DHCP_OPTION_IDX_T2, - DHCP_OPTION_IDX_SUBNET_MASK, - DHCP_OPTION_IDX_ROUTER, -#if LWIP_DHCP_PROVIDE_DNS_SERVERS - DHCP_OPTION_IDX_DNS_SERVER, - DHCP_OPTION_IDX_DNS_SERVER_LAST = DHCP_OPTION_IDX_DNS_SERVER + LWIP_DHCP_PROVIDE_DNS_SERVERS - 1, -#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */ -#if LWIP_DHCP_GET_NTP_SRV - DHCP_OPTION_IDX_NTP_SERVER, - DHCP_OPTION_IDX_NTP_SERVER_LAST = DHCP_OPTION_IDX_NTP_SERVER + LWIP_DHCP_MAX_NTP_SERVERS - 1, -#endif /* LWIP_DHCP_GET_NTP_SRV */ - DHCP_OPTION_IDX_REQUESTED_IP, - DHCP_OPTION_IDX_MAX -}; - -#define DHCP_OPTION_ROUTER_SIZE 4 -#define DHCP_OPTION_SUBNET_MASK_SIZE 4 -#define DHCP_OPTION_LEASE_TIME_SIZE 4 -#define DHCP_OPTION_SERVER_ID_LEN 4 -#define DHCP_OPTION_T1_LEN 4 -#define DHCP_OPTION_T2_LEN 4 - -#define DHCP_CLIENT_PORT 68 -#define DHCP_SERVER_PORT 67 - -#define DHCP_BROADCAST_FLAG 0x8000 -#define DHCP_MAX_MSG_LEN_MIN_REQUIRED 576 - -struct dyn_lease_addr { - u8_t cli_hwaddr[DHCP_CHADDR_LEN]; - u32_t flags; - u32_t leasetime; - u32_t proposed_leasetime; - ip4_addr_t cli_addr; -}; - -struct dhcps { - struct udp_pcb *pcb; - struct dyn_lease_addr leasearr[LWIP_DHCPS_MAX_LEASE]; - u8_t pcb_allocated; - u8_t lease_num; - struct netif *netif; - ip4_addr_t start_addr; - ip4_addr_t end_addr; -}; - - -#endif // (LWIP_DHCP) && (LWIP_DHCPS) - -#endif // LITEOS_A_DHCPS_FIXME_H diff --git a/net/lwip-2.1/enhancement/include/api_shell.h b/net/lwip-2.1/enhancement/include/lwip/api_shell.h similarity index 96% rename from net/lwip-2.1/enhancement/include/api_shell.h rename to net/lwip-2.1/enhancement/include/lwip/api_shell.h index ae6918a0..4575c6e6 100755 --- a/net/lwip-2.1/enhancement/include/api_shell.h +++ b/net/lwip-2.1/enhancement/include/lwip/api_shell.h @@ -29,8 +29,8 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef LWIP_API_SHELL_H -#define LWIP_API_SHELL_H +#ifndef LWIP_HDR_API_SHELL_H +#define LWIP_HDR_API_SHELL_H #include "arch/cc.h" #include "lwip/opt.h" @@ -58,6 +58,4 @@ void netstat_internal(void *ctx); } #endif - -#endif - +#endif /* LWIP_HDR_API_SHELL_H */ diff --git a/net/lwip-2.1/enhancement/include/dhcps.h b/net/lwip-2.1/enhancement/include/lwip/dhcps.h similarity index 80% rename from net/lwip-2.1/enhancement/include/dhcps.h rename to net/lwip-2.1/enhancement/include/lwip/dhcps.h index 0a3adf4b..261938ee 100755 --- a/net/lwip-2.1/enhancement/include/dhcps.h +++ b/net/lwip-2.1/enhancement/include/lwip/dhcps.h @@ -63,16 +63,6 @@ extern "C" { err_t dhcps_start(struct netif *netif, const char *start_ip, u16_t ip_num); void dhcps_stop(struct netif *netif); -void dhcp_common_option(struct dhcp_msg *msg_out, u8_t option_type, u8_t option_len, u16_t *options_out_len); -void dhcp_common_option_byte(struct dhcp_msg *msg_out, u8_t value, u16_t *options_out_len); -void dhcp_common_option_short(struct dhcp_msg *msg_out, u16_t value, u16_t *options_out_len); -void dhcp_common_option_long(struct dhcp_msg *msg_out, u32_t value, u16_t *options_out_len); -void dhcp_common_option_trailer(struct dhcp_msg *msg_out, u16_t *options_out_len); -#if LWIP_DHCP_BOOTP_FILE -err_t dhcps_parse_options(struct pbuf *p, char *boot_file_name); -#else -err_t dhcps_parse_options(struct pbuf *p); -#endif #if defined (__cplusplus) && __cplusplus } diff --git a/net/lwip-2.1/enhancement/include/api_shell_fix.h b/net/lwip-2.1/enhancement/include/lwip/fixme.h similarity index 66% rename from net/lwip-2.1/enhancement/include/api_shell_fix.h rename to net/lwip-2.1/enhancement/include/lwip/fixme.h index 198d81db..38bfbd19 100755 --- a/net/lwip-2.1/enhancement/include/api_shell_fix.h +++ b/net/lwip-2.1/enhancement/include/lwip/fixme.h @@ -29,17 +29,12 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef LITEOS_A_FIXME_H -#define LITEOS_A_FIXME_H - -#define LWIP_ENABLE_LOS_SHELL_CMD 1 -#define LWIP_ENABLE_IP_CONFLICT_SIGNAL 0 -#define PF_PKT_SUPPORT 1 -#define NETCONN_PKT_RAW 0x80 +#ifndef LWIP_HDR_FIXME_H +#define LWIP_HDR_FIXME_H #include "lwip/opt.h" - -#if LWIP_ENABLE_LOS_SHELL_CMD +#include "netif/etharp.h" +#include "lwip/netif.h" #define link_rx_drop cachehit #define link_tx_drop cachehit @@ -51,78 +46,37 @@ #define ip_rx_bytes cachehit #define ip_tx_bytes cachehit -#define LWIP_STATIC static -#define SYS_ARCH_ERROR SYS_ARCH_TIMEOUT +#define DUP_ARP_DETECT_TIME 2000 /* 2 seconds period */ +#define SOF_BINDNONUNICAST 0x0800U /* socket has bind to a non unicast */ +#define NETCONN_PKT_RAW 0x80 +#define SYS_ARCH_ERROR SYS_ARCH_TIMEOUT -#include "netif/etharp.h" -#include "lwip/netif.h" - -#define LWIP_SHELL_CMD_PING_RETRY_TIMES 4 +#define LWIP_ENABLE_LOS_SHELL_CMD LOSCFG_SHELL +#define LWIP_SHELL_CMD_PING_RETRY_TIMES 4 #define LWIP_SHELL_CMD_PING_TIMEOUT 2000 +#define LWIP_MAX_UDP_RAW_SEND_SIZE 65332 +#define LWIP_EXT_POLL_SUPPORT LWIP_SOCKET_POLL -#define TRANSFER_MODE_BINARY 1 - -u32_t lwip_tftp_get_file_by_filename(u32_t ulHostAddr, - u16_t usTftpServPort, - u8_t ucTftpTransMode, - s8_t *szSrcFileName, - s8_t *szDestDirPath); - -u32_t lwip_tftp_put_file_by_filename(u32_t ulHostAddr, - u16_t usTftpServPort, - u8_t cTftpTransMode, - s8_t *szSrcFileName, - s8_t *szDestDirPath); - - -#define ip_addr_set_val(dest, src) do { IP_SET_TYPE_VAL(*dest, IP_GET_TYPE(src)); if(IP_IS_V6_VAL(*(src))) { \ - ip6_addr_set(ip_2_ip6(dest), ip_2_ip6(src)); } else { \ - ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); }} while (0) +#define ip_addr_set_val(dest, src) do { \ + IP_SET_TYPE_VAL(*dest, IP_GET_TYPE(src)); \ + if(IP_IS_V6_VAL(*(src))) { \ + ip6_addr_set(ip_2_ip6(dest), ip_2_ip6(src)); \ + } else { \ + ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); \ + } \ + } while (0) #define ip_addr_ismulticast_val(ipaddr) ((IP_IS_V6_VAL(*ipaddr)) ? \ - ip6_addr_ismulticast(ip_2_ip6(ipaddr)) : \ - ip4_addr_ismulticast(ip_2_ip4(ipaddr))) - + ip6_addr_ismulticast(ip_2_ip6(ipaddr)) : \ + ip4_addr_ismulticast(ip_2_ip4(ipaddr))) #define ip_addr_isbroadcast_val(ipaddr, netif) ((IP_IS_V6_VAL(*ipaddr)) ? \ - 0 : \ - ip4_addr_isbroadcast(ip_2_ip4(ipaddr), netif)) + 0 : \ + ip4_addr_isbroadcast(ip_2_ip4(ipaddr), netif)) #define ip_addr_netcmp_val(addr1, addr2, mask) ((IP_IS_V6_VAL(*(addr1)) && IP_IS_V6_VAL(*(addr2))) ? \ - 0 : \ - ip4_addr_netcmp(ip_2_ip4(addr1), ip_2_ip4(addr2), mask)) - -#if LWIP_DHCP - -/* - * Close DHCP and set static network. - * - * @param netif a pre-allocated netif structure - * - * @return ERR_OK, or ERR_VAL if failed. - */ -err_t netif_dhcp_off(struct netif *netif); - -#endif /* LWIP_DHCP */ - -#include "lwip/prot/dhcp.h" - -err_t netif_do_rmv_ipv6_addr(struct netif *netif, void *arguments); - -err_t netif_set_mtu(struct netif *netif, u16_t netif_mtu); - -err_t netif_set_hwaddr(struct netif *netif, const unsigned char *hw_addr, int hw_len); - -struct netif *netifapi_netif_find_by_name(const char *name); - -/* 2 seconds period */ -#define DUP_ARP_DETECT_TIME 2000 - -err_t etharp_update_arp_entry(struct netif *netif, const ip4_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags); - -err_t etharp_delete_arp_entry(struct netif *netif, ip4_addr_t *ipaddr); - -#define LWIP_MAX_UDP_RAW_SEND_SIZE 65332 + 0 : \ + ip4_addr_netcmp(ip_2_ip4(addr1), ip_2_ip4(addr2), mask)) #define ip6_addr_isnone_val(ip6addr) (((ip6addr).addr[0] == 0xffffffffUL) && \ ((ip6addr).addr[1] == 0xffffffffUL) && \ @@ -131,20 +85,7 @@ err_t etharp_delete_arp_entry(struct netif *netif, ip4_addr_t *ipaddr); #define ip6_addr_isnone(ip6addr) (((ip6addr) == NULL) || ip6_addr_isnone_val(*(ip6addr))) - -err_t lwip_dns_setserver(u8_t numdns, ip_addr_t *dnsserver); - -err_t lwip_dns_getserver(u8_t numdns, ip_addr_t *dnsserver); - -#define ipaddr_ntoa_unsafe(addr) ((IP_IS_V6_VAL(*addr)) ? ip6addr_ntoa(ip_2_ip6(addr)) : ip4addr_ntoa(ip_2_ip4(addr))) - -#define SOF_BINDNONUNICAST 0x0800U /* socket has bind to a non unicast */ - -#if PF_PKT_SUPPORT -extern struct raw_pcb *pkt_raw_pcbs; -#endif - -extern struct raw_pcb *raw_pcbs; +#define ipaddr_ntoa_unsafe(addr) ((IP_IS_V6_VAL(*addr)) ? ip6addr_ntoa(ip_2_ip6(addr)) : ip4addr_ntoa(ip_2_ip4(addr))) #ifdef ip6_addr_cmp #undef ip6_addr_cmp @@ -152,10 +93,30 @@ extern struct raw_pcb *raw_pcbs; ((addr1)->addr[1] == (addr2)->addr[1]) && \ ((addr1)->addr[2] == (addr2)->addr[2]) && \ ((addr1)->addr[3] == (addr2)->addr[3])) -#endif //ip6_addr_cmp +#endif -#define LWIP_EXT_POLL_SUPPORT LWIP_SOCKET_POLL +err_t netif_dhcp_off(struct netif *netif); -#endif //LWIP_ENABLE_LOS_SHELL_CMD +err_t netif_do_rmv_ipv6_addr(struct netif *netif, void *arguments); -#endif //LITEOS_A_FIXME_H +err_t netif_set_mtu(struct netif *netif, u16_t netif_mtu); + +err_t netif_set_hwaddr(struct netif *netif, const unsigned char *hw_addr, int hw_len); + +err_t etharp_update_arp_entry(struct netif *netif, const ip4_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags); + +err_t etharp_delete_arp_entry(struct netif *netif, ip4_addr_t *ipaddr); + +err_t lwip_dns_setserver(u8_t numdns, ip_addr_t *dnsserver); + +err_t lwip_dns_getserver(u8_t numdns, ip_addr_t *dnsserver); + +#if PF_PKT_SUPPORT +extern struct raw_pcb *pkt_raw_pcbs; +#endif + +#if LWIP_RAW +extern struct raw_pcb *raw_pcbs; +#endif + +#endif /* LWIP_HDR_FIXME_H */ diff --git a/net/lwip-2.1/enhancement/include/lwip/tftpc.h b/net/lwip-2.1/enhancement/include/lwip/tftpc.h new file mode 100644 index 00000000..49ff2930 --- /dev/null +++ b/net/lwip-2.1/enhancement/include/lwip/tftpc.h @@ -0,0 +1,310 @@ +/* + * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LWIP_HDR_TFTPC_H +#define LWIP_HDR_TFTPC_H + +#include "lwip/opt.h" +#include "lwip/sockets.h" + +#if LWIP_TFTP /* don't build if not configured for use in lwipopts.h */ + +#if defined (__cplusplus) && __cplusplus +extern "C" { +#endif + +#define TFTP_NULL_UINT32 ((u32_t)0xffffffffUL) + +#define TFTP_NULL_INT32 -1 + +/** @cond liteos +* @defgroup TFTP_Interfaces +* @ingroup Enums +* * This section contains the TFTP enums. +*/ +/** +* +* This Enum is used to specify the transfer mode of the file to be handled by TFTP client. +*/ +typedef enum tagTFTPC_TransferMode { + TRANSFER_MODE_ASCII = 0, /**< Indicates that the mode of transfer is ASCII. */ + TRANSFER_MODE_BINARY, /**< Indicates that the mode of transfer is Binary */ + TRANSFER_MODE_BUTT /**< Indicates invalid transfer mode.*/ +} TFTPC_TRANSFER_MODE_E; + +/** +* This Enum is used to specify the transfer mode to be handled by TFTP client +* This Enum indicates the TFTP client transfer mode of the file + +*/ +typedef enum tagTFTPC_ErrCode { + TFTPC_SOCKET_FAILURE = 1, /**< Error while creating UDP socket. */ + TFTPC_BIND_FAILURE = 2, /**< Error while binding to the UDP socket. */ + TFTPC_SELECT_ERROR = 3, /**< Error returned by select() system call. */ + TFTPC_RECVFROM_ERROR = 4, /**< Error while receiving data from the peer. */ + TFTPC_SENDTO_ERROR = 5, /**< Error while sending data to the peer. */ + TFTPC_FILE_NOT_FOUND = 6, /**< Requested file is not found. */ + + /**< This is the error sent by the server when host name cannot be resolved. */ + TFTPC_CANNOT_RESOLVE_HOSTNAME = 7, + TFTPC_INVALID_PARAVALUE = 8, /**< Input parameters passed to TFTP interfaces are invalid. */ + + /**< Error detected in TFTP packet or the error received from the TFTP server. */ + TFTPC_PROTO_ERROR = 9, + /**< Error during packet synchronization while sending or unexpected packet is received. */ + TFTPC_SYNC_FAILURE = 10, + /**< File size limit crossed, Max block can be 0xFFFF, each block containing 512 bytes. */ + TFTPC_FILE_TOO_BIG = 11, + TFTPC_SRC_FILENAME_LENGTH_ERROR = 12, /**< File name length greater than 256. */ + TFTPC_IP_NOT_WITHIN_RANGE = 13, /**< Host name IP is not valid. */ + TFTPC_ACCESS_ERROR = 14, /**< TFTP server returned file access error. */ + + /**< TFTP server returned error signifying that the DISK is full to write. */ + TFTPC_DISK_FULL = 15, + TFTPC_FILE_EXISTS = 16, /**< TFTP server returned error signifying that the file exists. */ + + /**< tftp_put_file_by_filename returned error signifying that the source file name do not exist. */ + TFTPC_FILE_NOT_EXIST = 17, + TFTPC_MEMALLOC_ERROR = 18, /**< Memory allocation failed in TFTP client. */ + TFTPC_FILEOPEN_ERROR = 19, /**< File open failed. */ + TFTPC_FILEREAD_ERROR = 20, /**< File read error. */ + TFTPC_FILECREATE_ERROR = 21, /**< File create error. */ + TFTPC_FILEWRITE_ERROR = 22, /**< File write error. */ + TFTPC_TIMEOUT_ERROR = 23, /**< Max time expired while waiting for file to be received. */ + + /**< Error when the received packet is less than 4 bytes (error length) or greater than 512 bytes. */ + TFTPC_PKT_SIZE_ERROR = 24, + TFTPC_ERROR_NOT_DEFINED = 25, /**< Returned by TFTP server for protocol user error. */ + TFTPC_DEST_PATH_LENGTH_ERROR = 26, /**< If the destination file path length is greater than 256. */ + TFTPC_UNKNOWN_TRANSFER_ID = 27, /**< Returned by TFTP server for undefined transfer ID. */ + + /**< IOCTL function failed at TFTP client while setting the socket to non-block. */ + TFTPC_IOCTLSOCKET_FAILURE = 28, + TFTPC_MEMCPY_FAILURE = 29 /**< TFTP memcpy failure. */ +} TFTPC_ERR_CODE_E; + +typedef enum tagTFTPC_OpCode { + TFTPC_OP_RRQ = 1, /* read request */ + TFTPC_OP_WRQ, /* write request */ + TFTPC_OP_DATA, /* data packet */ + TFTPC_OP_ACK, /* acknowledgement */ + TFTPC_OP_ERROR, /* error code */ + TFTPC_OP_OPT /* option code */ +} TFTPC_OPCODE_E; + +typedef enum tagTFTPC_PROTOCOL_ErrCode { + TFTPC_PROTOCOL_USER_DEFINED = 0, + TFTPC_PROTOCOL_FILE_NOT_FOUND, + TFTPC_PROTOCOL_ACCESS_ERROR, + TFTPC_PROTOCOL_DISK_FULL, + TFTPC_PROTOCOL_PROTO_ERROR, + TFTPC_PROTOCOL_UNKNOWN_TRANSFER_ID, + TFTPC_PROTOCOL_FILE_EXISTS, + TFTPC_PROTOCOL_CANNOT_RESOLVE_HOSTNAME +} TFTPC_PROT_ERRCODE_E; + + +#ifndef TFTPC_MAX_SEND_REQ_ATTEMPTS +#define TFTPC_MAX_SEND_REQ_ATTEMPTS 5 /* tftp max attempts */ +#endif + +#ifndef TFTPC_TIMEOUT_PERIOD +#define TFTPC_TIMEOUT_PERIOD 5 /* tftp timeout period,unit :s */ +#endif + +#define TFTPC_SERVER_PORT 69 /* tftp server well known port no. */ + +/* MAX file size in TFTP is 32 MB. + Reason for keeping 75 here , is ((75*512=38400bytes)/1024) = 37MB. So the recv/Send Loop can + receive the complete MAX message from the network +*/ +#define TFTPC_MAX_WAIT_IN_LOOP 75 + +#define TFTP_BLKSIZE 512 /* data block size (IEN-133) */ +#define TFTP_HDRSIZE 4 /* TFTP header size */ +#define TFTP_PKTSIZE (TFTP_BLKSIZE + TFTP_HDRSIZE) /* Packet size */ +#define TFTP_MAX_MODE_SIZE 9 /* max size of mode string */ +#define TFTP_MAXERRSTRSIZE 100 /* max size of error message string */ +#define TFTP_MAX_PATH_LENGTH 256 /* Max path or filename length */ +#define TFTP_MAX_BLK_NUM (0xFFFFL) /* MAximum block number */ + +/* IP address not including reserved IPs(0 and 127) and multicast addresses(Class D) */ +#define TFTPC_IP_ADDR_MIN 0x01000000 +#define TFTPC_IP_ADDR_EX_RESV 0x7effffff +#define TFTPC_IP_ADDR_CLASS_B 0x80000000 +#define TFTPC_IP_ADDR_EX_CLASS_DE 0xdfffffff + +#define TFTPC_FOUR 4 /* minimum packet size */ + +/****************************************************************************/ +/* Structure definitions */ +/****************************************************************************/ +/* Tftp data packet */ +typedef struct tagTFTPC_DATA { + u16_t usBlknum; /* block number */ + u8_t ucDataBuf[TFTP_BLKSIZE]; /* Actual data */ +} TFTPC_DATA_S; + + +/* TFTP error packet */ +typedef struct tagTFTPC_ERROR { + u16_t usErrNum; /* error number */ + u8_t ucErrMesg[TFTP_MAXERRSTRSIZE]; /* error message */ +} TFTPC_ERROR_S; + + +/* TFTP packet format */ +typedef struct tagTFTPC_PACKET { + u16_t usOpcode; /* Opcode value */ + union { + /* it contains mode and filename */ + s8_t ucName_Mode[TFTP_MAX_PATH_LENGTH + TFTP_MAX_MODE_SIZE]; + u16_t usBlknum; /* Block Number */ + TFTPC_DATA_S stTFTP_Data; /* Data Packet */ + TFTPC_ERROR_S stTFTP_Err; /* Error Packet */ + } u; +} TFTPC_PACKET_S; + + +/** @defgroup TFTP_Interfaces +* This section contains the TFTP Interfaces +*/ +/* +Func Name: lwip_tftp_get_file_by_filename +*/ +/** +* @ingroup TFTP_Interfaces +* @brief +* This API gets the source file from the server. It then stores the received file in the destination path +* on the client system. +* +* @param[in] ulHostAddr IP address of Host. This is the TFTP server IP. [NA] +* @param[in] usTftpServPort TFTP server port. If the value is passed as 0 then the default TFTP +* PORT 69 is used. [NA] +* @param[in] ucTftpTransMode File transfer mode, either TRANSFER_MODE_BINARY or TRANSFER_MODE_ASCII. [NA] +* @param[in] szSrcFileName Source file in the tftp server. [NA] +* @param[in] szDestDirPath Destination file path in the in the client. [NA] +* @param[out] [N/A] +* +* @return +* ERR_OK: On success \n +* TFTPC_ERR_CODE_E: On failure +* +* @note +* \n +* The behavior of this API is such that if the destination file already exists, it will be overwritten. +*/ +u32_t lwip_tftp_get_file_by_filename(u32_t ulHostAddr, + u16_t usTftpServPort, + u8_t ucTftpTransMode, + s8_t *szSrcFileName, + s8_t *szDestDirPath); + + +/* @defgroup TFTP_Interfaces +* This section contains the TFTP Interfaces +*/ +/* +Func Name: lwip_tftp_put_file_by_filename +*/ +/** +* @ingroup TFTP_Interfaces + +* @brief +* This API reads the contents of the source file on the client system and sends it to the server and +* server then receives the data and stores it in the specified destination path. +* +* @param[in] ulHostAddr Indicates the IP address of Host. This is the TFTP server IP. +* @param[in] usTftpServPort Indicates the TFTP server port. If the value is passed as 0 then the default TFTP +* PORT 69 is used. +* @param[in] ucTftpTransMode Indicates the file transfer mode, either TRANSFER_MODE_BINARY or TRANSFER_MODE_ASCII. +* @param[in] szSrcFileName Indicates the source file in the client. +* @param[in] szDestDirPath Indicates the destination file path on the tftp server. +* +* @return +* ERR_OK: On success \n +* TFTPC_ERR_CODE_E: On failure +* +*/ +u32_t lwip_tftp_put_file_by_filename(u32_t ulHostAddr, + u16_t usTftpServPort, + u8_t cTftpTransMode, + s8_t *szSrcFileName, + s8_t *szDestDirPath); + +#ifdef TFTP_TO_RAWMEM +/* @defgroup TFTP_Interfaces +* This section contains the TFTP Interfaces +*/ +/* +Func Name: lwip_tftp_get_file_by_filename_to_rawmem +*/ +/** +* @ingroup TFTP_Interfaces + +* @brief +* This API gets the source file from the server. It then stores the received file in the target memory +* on the client system. +* +* @param[in] ulHostAddr Indicates the IP address of the Host. This is the TFTP server IP. +* @param[in] usTftpServPort Indicates the TFTP server port. If the value is passed as 0 then the default TFTP +* PORT 69 is used. +* @param[in] ucTftpTransMode Indicates the File transfer mode, either TRANSFER_MODE_BINARY or TRANSFER_MODE_ASCII. +* @param[in] szSrcFileName Indicates the Source file in the TFTP server. +* @param[in] szDestMemAddr Indicates the target memory address in the client. +* @param[in/out] ulFileLength Indicates the target memory address can cache the size of the content, + and The real size of the Source file. +* +* @return +* ERR_OK: On success \n +* TFTPC_ERR_CODE_E: On failure +* @note + +* 1.You must define TFTP_TO_RAWMEM when using this API. \n +* 2.The behavior of this API is such that if the destination file already exists, it will be overwritten. +* @endcond +*/ + +u32_t lwip_tftp_get_file_by_filename_to_rawmem(u32_t ulHostAddr, + u16_t usTftpServPort, + u8_t ucTftpTransMode, + s8_t *szSrcFileName, + s8_t *szDestMemAddr, + u32_t *ulFileLength); +#endif + +#if defined (__cplusplus) && __cplusplus +} +#endif + +#endif /* LWIP_TFTP */ + +#endif /* LWIP_HDR_TFTPC_H */ diff --git a/net/lwip-2.1/enhancement/src/api_shell.c b/net/lwip-2.1/enhancement/src/api_shell.c index 26a3e11d..24df1b48 100755 --- a/net/lwip-2.1/enhancement/src/api_shell.c +++ b/net/lwip-2.1/enhancement/src/api_shell.c @@ -33,7 +33,7 @@ #define icmp6_hdr netinet_icmp6_hdr #include #undef icmp6_hdr -#include "api_shell_fix.h" +#include "lwip/fixme.h" #include "lwip/opt.h" #if LWIP_ENABLE_LOS_SHELL_CMD @@ -62,7 +62,8 @@ #include #include -#include "api_shell.h" +#include "lwip/api_shell.h" +#include "lwip/tftpc.h" #include "lwip/dns.h" #include "lwip/netdb.h" @@ -78,7 +79,7 @@ #include "shell.h" #endif -#define netif_find netifapi_netif_find_by_name +#define LWIP_STATIC static #if LWIP_ARP extern sys_sem_t ip_conflict_detect; @@ -3163,8 +3164,10 @@ void netstat_internal(void *ctx) int recvQlen = 0; int sendQlen = 0; u_int proto; +#if PF_PKT_SUPPORT u8_t netif_name[IFNAMSIZ]; struct netif *netif = NULL; +#endif if (ndata == NULL) { return; diff --git a/net/lwip-2.1/enhancement/src/dhcps.c b/net/lwip-2.1/enhancement/src/dhcps.c new file mode 100644 index 00000000..0d386468 --- /dev/null +++ b/net/lwip-2.1/enhancement/src/dhcps.c @@ -0,0 +1,983 @@ +/* + * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * Dynamic Host Configuration Protocol Server + * + */ + +#include "../core/ipv4/dhcp.c" /* for enum dhcp_option_idx/dhcp_option_xx/dhcp_parse_reply etc. */ + +#include "lwip/opt.h" + +#if (LWIP_DHCP) && (LWIP_DHCPS) /* don't build if not configured for use in lwipopts.h */ +#include + +#include "lwip/stats.h" +#include "lwip/mem.h" +#include "lwip/udp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/def.h" +#include "lwip/prot/dhcp.h" +#include "lwip/dhcp.h" +#include "lwip/dhcps.h" +#include "lwip/sys.h" +#include "netif/etharp.h" + +#define DHCPS_ADDRESS_FREE 0x0 +#define DHCPS_ADDRESS_OFFERRED 0x1 +#define DHCPS_ADDRESS_BOUND 0x2 +#define DHCPS_ADDRESS_DECLINED 0x3 + +#define LWIP_STATIC static +#define DHCP_OPTION_ROUTER_SIZE 4 +#define DHCP_OPTION_SUBNET_MASK_SIZE 4 +#define DHCP_OPTION_LEASE_TIME_SIZE 4 +#define DHCP_OPTION_SERVER_ID_LEN 4 +#define DHCP_OPTION_T1_LEN 4 +#define DHCP_OPTION_T2_LEN 4 + +#define DHCP_CLIENT_PORT 68 +#define DHCP_SERVER_PORT 67 + +#define DHCP_BROADCAST_FLAG 0x8000 + +struct dyn_lease_addr { + u8_t cli_hwaddr[DHCP_CHADDR_LEN]; + u32_t flags; + u32_t leasetime; + u32_t proposed_leasetime; + ip4_addr_t cli_addr; +}; + +struct dhcps { + struct dhcp dhcp; + struct udp_pcb *pcb; + struct dyn_lease_addr leasearr[LWIP_DHCPS_MAX_LEASE]; + u8_t pcb_allocated; + u8_t lease_num; + struct netif *netif; + ip4_addr_t start_addr; + ip4_addr_t end_addr; +}; + +#define dhcps_option_given(dhcps, idx) dhcp_option_given(&(dhcps)->dhcp, idx) +#define dhcps_got_option(dhcps, idx) dhcp_got_option(&(dhcps)->dhcp, idx) +#define dhcps_clear_option(dhcps, idx) dhcp_clear_option(&(dhcps)->dhcp, idx) +#define dhcps_clear_all_options(dhcps) dhcp_clear_all_options(&(dhcps)->dhcp) +#define dhcps_get_option_value(dhcps, idx) dhcp_get_option_value(&(dhcps)->dhcp, idx) +#define dhcps_set_option_value(dhcps, idx, val) dhcp_set_option_value(&(dhcps)->dhcp, idx, val) + +#define netif_get_dhcps(netif) ((struct dhcps*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCPS)) +#define netif_set_dhcps(netif, dhcps) netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCPS, dhcps) + +LWIP_STATIC void dhcp_common_option(struct dhcp_msg *msg_out, u8_t option_type, u8_t option_len, u16_t *options_out_len); +LWIP_STATIC void dhcp_common_option_byte(struct dhcp_msg *msg_out, u8_t value, u16_t *options_out_len); +LWIP_STATIC void dhcp_common_option_long(struct dhcp_msg *msg_out, u32_t value, u16_t *options_out_len); +LWIP_STATIC void dhcp_common_option_trailer(struct dhcp_msg *msg_out, u16_t options_out_len, struct pbuf *p_out); +LWIP_STATIC err_t dhcps_parse_options(struct pbuf *p, struct dhcps *dhcps); + +LWIP_STATIC struct pbuf *dhcps_create_base_msg(struct dhcp_msg *client_msg); +LWIP_STATIC void remove_stale_entries(struct dhcps *dhcps); +LWIP_STATIC void add_client_entry(struct dhcps *dhcps, unsigned int idx, struct dhcp_msg *client_msg); +LWIP_STATIC int find_free_slot(struct dhcps *dhcps); +LWIP_STATIC struct dyn_lease_addr *find_client_lease(struct dhcps *dhcps, struct dhcp_msg *client_msg); +LWIP_STATIC ip4_addr_t validate_discover(struct dhcps *dhcps, struct dhcp_msg *client_msg, + struct dyn_lease_addr **client_lease); +LWIP_STATIC void handle_discover(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg, + struct dyn_lease_addr *client_lease); +LWIP_STATIC ip4_addr_t validate_request_message(struct netif *netif, struct dhcp_msg *client_msg, + struct dyn_lease_addr *client_lease, ip4_addr_t serverid); +LWIP_STATIC void handle_request(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg, + struct dyn_lease_addr *client_lease, ip4_addr_t serverid); +LWIP_STATIC void handle_decline(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg, + struct dyn_lease_addr *client_lease); +LWIP_STATIC void handle_inform(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg); +LWIP_STATIC void handle_client_messages(struct netif *netif, struct dhcps *dhcps, + struct dhcp_msg *client_msg, ip4_addr_t serverid, u8_t msg_type); +LWIP_STATIC void dhcps_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *ip_addr, u16_t port); + +LWIP_STATIC struct pbuf *dhcps_create_base_msg(struct dhcp_msg *client_msg) +{ + struct pbuf *srvr_msg_pbuf = NULL; + struct dhcp_msg *srvr_msg = NULL; + + srvr_msg_pbuf = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM); + if (srvr_msg_pbuf == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("dhcps_create_base_msg(): could not allocate pbuf\n")); + return NULL; + } + + LWIP_ASSERT("dhcps_create_base_msg: check that first pbuf can hold struct dhcp_msg", + (srvr_msg_pbuf->len >= sizeof(struct dhcp_msg))); +#if DRIVER_STATUS_CHECK + srvr_msg_pbuf->flags |= PBUF_FLAG_DHCP_BUF; +#endif + + srvr_msg = (struct dhcp_msg *)srvr_msg_pbuf->payload; + srvr_msg->op = DHCP_BOOTREPLY; + srvr_msg->htype = client_msg->htype; + srvr_msg->hlen = client_msg->hlen; + srvr_msg->hops = 0; + srvr_msg->xid = client_msg->xid; + srvr_msg->secs = 0; + srvr_msg->flags = client_msg->flags; + ip4_addr_set_zero(&srvr_msg->ciaddr); + ip4_addr_set_zero(&srvr_msg->yiaddr); + ip4_addr_set_zero(&srvr_msg->siaddr); + ip4_addr_copy(srvr_msg->giaddr, client_msg->giaddr); + if (memcpy_s(srvr_msg->chaddr, sizeof(srvr_msg->chaddr), client_msg->chaddr, DHCP_CHADDR_LEN) != EOK) { + (void)pbuf_free(srvr_msg_pbuf); + return NULL; + } + (void)memset_s(srvr_msg->sname, sizeof(srvr_msg->sname), 0, DHCP_SNAME_LEN); + (void)memset_s(srvr_msg->file, sizeof(srvr_msg->file), 0, DHCP_FILE_LEN); + srvr_msg->cookie = PP_HTONL(DHCP_MAGIC_COOKIE); + + return srvr_msg_pbuf; +} + +LWIP_STATIC void remove_stale_entries(struct dhcps *dhcps) +{ + int i = 0; + u32_t curr_time = sys_now(); + + for (i = 0; i < dhcps->lease_num; i++) { + /* Slot should not be free or have infinite lease time */ + if ((dhcps->leasearr[i].flags != DHCPS_ADDRESS_FREE) && (dhcps->leasearr[i].leasetime != (u32_t)~0)) { + if (dhcps->leasearr[i].leasetime < curr_time) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("remove_stale_entries: Removing Client Entry at Index = %"U32_F"\n", i)); + (void)memset_s(&(dhcps->leasearr[i]), sizeof(struct dyn_lease_addr), 0, sizeof(struct dyn_lease_addr)); + dhcps->leasearr[i].flags = DHCPS_ADDRESS_FREE; + } + } + } +} + +LWIP_STATIC void add_client_entry(struct dhcps *dhcps, unsigned int idx, struct dhcp_msg *client_msg) +{ + u32_t client_lease_time = (u32_t)(LWIP_DHCPS_LEASE_TIME); + + if ((dhcps_option_given(dhcps, DHCP_OPTION_IDX_LEASE_TIME)) +#if (LWIP_DHCPS_LEASE_TIME != ~0) + && (dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_LEASE_TIME) < LWIP_DHCPS_LEASE_TIME) +#endif + ) { + client_lease_time = (u32_t)dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_LEASE_TIME); + } + + (void)memset_s(&(dhcps->leasearr[idx]), sizeof(struct dyn_lease_addr), 0, sizeof(struct dyn_lease_addr)); + if (memcpy_s(dhcps->leasearr[idx].cli_hwaddr, DHCP_CHADDR_LEN, + client_msg->chaddr, sizeof(client_msg->chaddr)) != EOK) { + return; + } + /* This is called only during offer message, so adding offer time. + This is later updated to lease time when request message is handled */ + dhcps->leasearr[idx].leasetime = sys_now() + (LWIP_DHCPS_OFFER_TIME * 1000); + dhcps->leasearr[idx].cli_addr.addr = dhcps->start_addr.addr + idx; + dhcps->leasearr[idx].flags = DHCPS_ADDRESS_OFFERRED; + dhcps->leasearr[idx].proposed_leasetime = client_lease_time; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("add_client_entry: Adding Client Entry at Index = %"U32_F"\n", idx)); +} + +LWIP_STATIC int find_free_slot(struct dhcps *dhcps) +{ + int i; + for (i = 0; i < dhcps->lease_num; i++) { + if ((dhcps->leasearr[i].flags == DHCPS_ADDRESS_FREE) && + (htonl(dhcps->start_addr.addr + (u32_t)i) != ip_2_ip4(&dhcps->netif->ip_addr)->addr)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("find_free_slot: Found Free Slot at Index = %"U32_F"\n", i)); + return i; + } + } + + return -1; +} + +LWIP_STATIC struct dyn_lease_addr *find_client_lease(struct dhcps *dhcps, struct dhcp_msg *client_msg) +{ + int i; + for (i = 0; i < dhcps->lease_num; i++) { + if (dhcps->leasearr[i].flags != DHCPS_ADDRESS_FREE) { + if (memcmp(dhcps->leasearr[i].cli_hwaddr, client_msg->chaddr, client_msg->hlen) == 0) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("find_client_lease: Found Client Lease at Index = %"U32_F"\n", i)); + return &(dhcps->leasearr[i]); + } + } + } + + return NULL; +} + +LWIP_STATIC ip4_addr_t validate_discover(struct dhcps *dhcps, struct dhcp_msg *client_msg, + struct dyn_lease_addr **client_lease) +{ + ip4_addr_t client_ip; + int idx = -1; + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("validate_discover: Validating Discover Message\n")); + + client_ip.addr = 0; + if (*client_lease == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("validate_discover: Existing Client Lease not Found\n")); + if (dhcps_option_given(dhcps, DHCP_OPTION_IDX_REQUESTED_IP)) { + client_ip.addr = (u32_t)dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_REQUESTED_IP); +#ifdef LWIP_DEV_DEBUG + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("validate_discover function: Requested IP from client = %"U32_F"\n", client_ip.addr)); +#endif + + if ((client_ip.addr >= dhcps->start_addr.addr) && (client_ip.addr <= dhcps->end_addr.addr)) { + idx = (int)(client_ip.addr - dhcps->start_addr.addr); + if ((dhcps->leasearr[idx].flags != DHCPS_ADDRESS_FREE) || + (ntohl(client_ip.addr) == ip_2_ip4(&dhcps->netif->ip_addr)->addr)) { + /* Requested IP is not available */ +#ifdef LWIP_DEV_DEBUG + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("validate_discover function: Requested IP from client = %"U32_F" Not available \n", client_ip.addr)); +#endif + idx = -1; + } + } + } + + if (idx == -1) { + idx = find_free_slot(dhcps); + if (idx == -1) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("validate_discover function: No Free Slot available for Storing addresses\n")); + client_ip.addr = 0; + return client_ip; + } + client_ip.addr = dhcps->start_addr.addr + (u32_t)idx; +#ifdef LWIP_DEV_DEBUG + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("validate_discover function: New IP = %"U32_F" is being assigned\n", client_ip.addr)); +#endif + } + + add_client_entry(dhcps, (unsigned int)idx, client_msg); + (*client_lease) = &(dhcps->leasearr[idx]); + } else { + client_ip.addr = (*client_lease)->cli_addr.addr; +#ifdef LWIP_DEV_DEBUG + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("validate_discover: Existing Client Lease Found. Existing IP =%"U32_F"\n", client_ip.addr)); +#endif + + if ((dhcps_option_given(dhcps, DHCP_OPTION_IDX_LEASE_TIME)) +#if (~0 != LWIP_DHCPS_LEASE_TIME) + && (dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_LEASE_TIME) < LWIP_DHCPS_LEASE_TIME) +#endif + ) { + /* Assign the newly requested time or else use the existing lease time as-is */ + (*client_lease)->proposed_leasetime = (u32_t)dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_LEASE_TIME); + } + } + + return client_ip; +} + +void dhcp_common_option(struct dhcp_msg *msg_out, u8_t option_type, u8_t option_len, u16_t *options_out_len) +{ + *options_out_len = dhcp_option(*options_out_len, msg_out->options, option_type, option_len); +} + +void dhcp_common_option_byte(struct dhcp_msg *msg_out, u8_t value, u16_t *options_out_len) +{ + *options_out_len = dhcp_option_byte(*options_out_len, msg_out->options, value); +} + +void dhcp_common_option_long(struct dhcp_msg *msg_out, u32_t value, u16_t *options_out_len) +{ + *options_out_len = dhcp_option_long(*options_out_len, msg_out->options, value); +} + +void dhcp_common_option_trailer(struct dhcp_msg *msg_out, u16_t options_out_len, struct pbuf *p_out) +{ + dhcp_option_trailer(options_out_len, msg_out->options, p_out); +} + +LWIP_STATIC void handle_discover(struct netif *netif, struct dhcps *dhcps, + struct dhcp_msg *client_msg, struct dyn_lease_addr *client_lease) +{ +#if !LWIP_DHCPS_DISCOVER_BROADCAST + ip_addr_t client_ipaddr; +#endif + + ip4_addr_t client_ip; + ip_addr_t dst_addr; + struct pbuf *out_msg = NULL; + struct dhcp_msg *srvr_msg = NULL; + u16_t options_len = 0; +#if !LWIP_DHCPS_DISCOVER_BROADCAST +#if ETHARP_SUPPORT_STATIC_ENTRIES + struct eth_addr ethaddr; +#endif +#endif + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_discover: Processing Discover Message\n")); + + client_ip = validate_discover(dhcps, client_msg, &client_lease); + if (client_ip.addr == 0) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("handle_discover: Returning as unable to get a proper address for client\n")); + return; + } + + out_msg = dhcps_create_base_msg(client_msg); + if (out_msg == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("handle_discover function: Memory allocation for base message failed\n")); + return; + } + + srvr_msg = (struct dhcp_msg *)out_msg->payload; + // no need check msg pointer from payload here + srvr_msg->yiaddr.addr = htonl(client_ip.addr); + + dhcp_common_option(srvr_msg, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, &options_len); + dhcp_common_option_byte(srvr_msg, DHCP_OFFER, &options_len); + + /* hilink need this router option */ + dhcp_common_option(srvr_msg, DHCP_OPTION_ROUTER, DHCP_OPTION_ROUTER_SIZE, &options_len); + dhcp_common_option_long(srvr_msg, ntohl(ip_2_ip4(&netif->ip_addr)->addr), &options_len); + + /* netif already holds the Server ID in network order. so, no need to convert it again */ + dhcp_common_option(srvr_msg, DHCP_OPTION_SERVER_ID, DHCP_OPTION_SERVER_ID_LEN, &options_len); + dhcp_common_option_long(srvr_msg, ntohl(ip_2_ip4(&netif->ip_addr)->addr), &options_len); + + dhcp_common_option(srvr_msg, DHCP_OPTION_LEASE_TIME, DHCP_OPTION_LEASE_TIME_SIZE, &options_len); + dhcp_common_option_long(srvr_msg, client_lease->proposed_leasetime, &options_len); + + dhcp_common_option(srvr_msg, DHCP_OPTION_T1, DHCP_OPTION_T1_LEN, &options_len); + dhcp_common_option_long(srvr_msg, (client_lease->proposed_leasetime / 2), &options_len); + + dhcp_common_option(srvr_msg, DHCP_OPTION_T2, DHCP_OPTION_T2_LEN, &options_len); + /* calculate safe periods for lease (proposed_leasetime * 0.875 -> 87.5%) */ + dhcp_common_option_long(srvr_msg, ((client_lease->proposed_leasetime * 7) / 8), &options_len); + + /* No need to convert netmask into network order as it is already stored in network order */ + dhcp_common_option(srvr_msg, DHCP_OPTION_SUBNET_MASK, DHCP_OPTION_SUBNET_MASK_SIZE, &options_len); + dhcp_common_option_long(srvr_msg, ntohl(ip4_addr_get_u32(ip_2_ip4(&netif->netmask))), &options_len); + + dhcp_common_option_trailer(srvr_msg, options_len, out_msg); + + if (client_msg->ciaddr.addr != 0) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_discover: sendto(OFFER, ciaddr, DHCP_CLIENT_PORT)\n")); + ip_addr_set_ip4_u32_val(dst_addr, (u32_t)(client_msg->ciaddr.addr)); + (void)udp_sendto_if_src(dhcps->pcb, out_msg, &dst_addr, DHCP_CLIENT_PORT, netif, &(netif->ip_addr)); + } +#if !LWIP_DHCPS_DISCOVER_BROADCAST + else if (ntohs(client_msg->flags) & DHCP_BROADCAST_FLAG) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("handle_discover: sendto(OFFER, IP_ADDR_BROADCAST, DHCP_CLIENT_PORT)\n")); + (void)udp_sendto_if_src(dhcps->pcb, out_msg, IP_ADDR_BROADCAST, DHCP_CLIENT_PORT, netif, &(netif->ip_addr)); + } else { + client_ip.addr = htonl(client_ip.addr); + +#if ETHARP_SUPPORT_STATIC_ENTRIES + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_discover: Updating ARP Static Entry for unicast reply\n")); + if (memcpy_s(ethaddr.addr, ETHARP_HWADDR_LEN, client_msg->chaddr, client_msg->hlen) != EOK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("memcpy_s failed\n")); + (void)pbuf_free(out_msg); + return; + } + if (etharp_add_static_entry(&client_ip, ðaddr) != ERR_OK) { + (void)pbuf_free(out_msg); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_discover: Adding static entry to arp cache failed\n")); + return; + } +#endif + + /* Need to check and add an arp entry to make this pass through smoothly */ + ip_addr_copy_from_ip4(client_ipaddr, client_ip); + (void)udp_sendto_if_src(dhcps->pcb, out_msg, &client_ipaddr, DHCP_CLIENT_PORT, netif, &(netif->ip_addr)); +#if ETHARP_SUPPORT_STATIC_ENTRIES + /* We just added the entry above and checked for it's success too. so, the below function call cannot fail */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("handle_discover: Removing ARP Static Entry added for unicast reply\n")); + (void)etharp_remove_static_entry(&client_ip); +#endif + } +#else + else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("handle_discover: sendto(OFFER, IP_ADDR_BROADCAST, DHCP_CLIENT_PORT)\n")); + (void)udp_sendto_if_src(dhcps->pcb, out_msg, IP_ADDR_BROADCAST, DHCP_CLIENT_PORT, netif, &(netif->ip_addr)); + } +#endif + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_discover: deleting()ing\n")); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_discover: Sending Reply has been successful\n")); + + (void)pbuf_free(out_msg); + return; +} + +LWIP_STATIC ip4_addr_t validate_request_message(struct netif *netif, struct dhcp_msg *client_msg, + struct dyn_lease_addr *client_lease, ip4_addr_t serverid) +{ + struct dhcps *dhcps = netif_get_dhcps(netif); + ip4_addr_t requested_ip; + requested_ip.addr = 0; + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("validate_request_message: Processing Request Message\n")); + + if ((client_lease != NULL) && (client_lease->flags == DHCPS_ADDRESS_OFFERRED)) { + /* Now, we are in selecting state */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("validate_request_message: In Selecting State\n")); + + if ((serverid.addr == 0) || (client_msg->ciaddr.addr != 0) || + (!dhcps_option_given(dhcps, DHCP_OPTION_IDX_REQUESTED_IP))) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("Server ID or ciaddr or requested ip option is not present\n")); + return requested_ip; + } + + if (serverid.addr != ip_2_ip4(&netif->ip_addr)->addr) { + /* This message is not meant for us. The client intends to talk to some other server */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("validate_request_message: Server id doesn't match with ours. Message not for us\n")); + requested_ip.addr = 1; + return requested_ip; + } + + requested_ip.addr = (u32_t)dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_REQUESTED_IP); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("validate_request_message: In Init-Reboot, Renew or Rebinding State\n")); + + /* Now, we can be either in Init-reboot state or renew state or rebinding state */ + if (dhcps_option_given(dhcps, DHCP_OPTION_IDX_REQUESTED_IP)) { + /* Requested IP option is filled in. Indicates we are mostly in Init-Reboot State */ + if (client_lease == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("validate_request_message: No Configuration found corresponding to request message\n")); + requested_ip.addr = 1; + return requested_ip; + } + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("validate_request_message: Requested IP Option is present. So, considering as Init-Reboot State\n")); + + if (client_msg->ciaddr.addr != 0) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("validate_request_message: Error: ciaddr is filled in the Init-Reboot state. \n")); + return requested_ip; + } + + requested_ip.addr = (u32_t)dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_REQUESTED_IP); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("validate_request_message: \ + Requested IP Option is not present. So, considering as Renewing or Rebinding State\n")); + + if (client_msg->ciaddr.addr == 0) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("validate_request_message: Error: ciaddr is not filled in the Renewing or Rebinding state. \n")); + return requested_ip; + } + + requested_ip.addr = ntohl(client_msg->ciaddr.addr); + } + } + + /* requested_ip is in host order and DHCP Server IP is in network order, + so converting the former to network order for check */ + if (htonl(requested_ip.addr) == ip_2_ip4(&netif->ip_addr)->addr) { + /* This requested_ip is the dhcp server is using, it is invalid */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("validate_request_message: Requested IP addr is invalid\n")); + requested_ip.addr = 1; + } + + return requested_ip; +} + +LWIP_STATIC void handle_request(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg, + struct dyn_lease_addr *client_lease, ip4_addr_t serverid) +{ + ip4_addr_t requested_ip; + struct pbuf *out_msg = NULL; + struct dhcp_msg *srvr_msg = NULL; + u16_t options_len = 0; + ip_addr_t dst_addr; + ip_addr_t ip_send; +#if ETHARP_SUPPORT_STATIC_ENTRIES + struct eth_addr ethaddr; +#endif + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_request: Processing Request Message\n")); + + requested_ip = validate_request_message(netif, client_msg, client_lease, serverid); + if (requested_ip.addr == 1) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("handle_request: Validation of request message failed. Dropping the packet.\n")); + return; + } + + out_msg = dhcps_create_base_msg(client_msg); + if (out_msg == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_request: Creating base message failed\n")); + return; + } + + srvr_msg = (struct dhcp_msg *)out_msg->payload; + dhcp_common_option(srvr_msg, DHCP_OPTION_SERVER_ID, DHCP_OPTION_SERVER_ID_LEN, &options_len); + dhcp_common_option_long(srvr_msg, ntohl(ip_2_ip4(&netif->ip_addr)->addr), &options_len); + + /* hilink need this router option */ + dhcp_common_option(srvr_msg, DHCP_OPTION_ROUTER, DHCP_OPTION_ROUTER_SIZE, &options_len); + dhcp_common_option_long(srvr_msg, ntohl(ip_2_ip4(&netif->ip_addr)->addr), &options_len); + + if ((client_lease != NULL) && (client_lease->cli_addr.addr == requested_ip.addr)) { + if (client_lease->proposed_leasetime != (u32_t)(~0)) { + if (client_lease->flags == DHCPS_ADDRESS_OFFERRED) { + client_lease->leasetime = sys_now() + (client_lease->proposed_leasetime * 1000); + } else { + client_lease->leasetime += (client_lease->proposed_leasetime * 1000); + } + } else { + client_lease->leasetime = client_lease->proposed_leasetime; + } + + client_lease->flags = DHCPS_ADDRESS_BOUND; + srvr_msg->yiaddr.addr = htonl(client_lease->cli_addr.addr); + + dhcp_common_option(srvr_msg, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, &options_len); + dhcp_common_option_byte(srvr_msg, DHCP_ACK, &options_len); + + dhcp_common_option(srvr_msg, DHCP_OPTION_LEASE_TIME, DHCP_OPTION_LEASE_TIME_SIZE, &options_len); + dhcp_common_option_long(srvr_msg, client_lease->proposed_leasetime, &options_len); + + dhcp_common_option(srvr_msg, DHCP_OPTION_T1, DHCP_OPTION_T1_LEN, &options_len); + dhcp_common_option_long(srvr_msg, (client_lease->proposed_leasetime / 2), &options_len); + + dhcp_common_option(srvr_msg, DHCP_OPTION_T2, DHCP_OPTION_T2_LEN, &options_len); + /* calculate safe periods for lease (proposed_leasetime * 0.875 -> 87.5%) */ + dhcp_common_option_long(srvr_msg, ((client_lease->proposed_leasetime * 7) / 8), &options_len); + + dhcp_common_option(srvr_msg, DHCP_OPTION_SUBNET_MASK, DHCP_OPTION_SUBNET_MASK_SIZE, &options_len); + dhcp_common_option_long(srvr_msg, ntohl(ip_2_ip4(&netif->netmask)->addr), &options_len); + +#ifdef LWIP_DEV_DEBUG + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("handle_request: Send ACK. to=%"U32_F" lease time=%"U32_F"\n", + requested_ip.addr, client_lease->proposed_leasetime)); +#endif + } else { + dhcp_common_option(srvr_msg, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, &options_len); + dhcp_common_option_byte(srvr_msg, DHCP_NAK, &options_len); + + /* Just set this here, so that the NAK message is brcasted. + The correct flags has already been added in the respose message during base message creation */ + client_msg->flags |= htons(DHCP_BROADCAST_FLAG); + client_msg->ciaddr.addr = 0; /* This is done so that NAK Gets brcasted */ +#ifdef LWIP_DEV_DEBUG + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("handle_request: Send NAK. Requested from=%"U32_F"\n", requested_ip.addr)); +#endif + } + + requested_ip.addr = htonl(requested_ip.addr); + dhcp_common_option_trailer(srvr_msg, options_len, out_msg); + + if (client_msg->ciaddr.addr != 0) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_request: sendto(ACK, ciaddr, DHCP_CLIENT_PORT)\n")); + ip_addr_set_ip4_u32_val(dst_addr, (u32_t)(client_msg->ciaddr.addr)); + (void)udp_sendto_if_src(dhcps->pcb, out_msg, &dst_addr, DHCP_CLIENT_PORT, netif, &(netif->ip_addr)); + } else if (ntohs(client_msg->flags) & DHCP_BROADCAST_FLAG) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_request: sending reply using brdcast \n")); + (void)udp_sendto_if_src(dhcps->pcb, out_msg, IP_ADDR_BROADCAST, DHCP_CLIENT_PORT, netif, &(netif->ip_addr)); + } else { +#if ETHARP_SUPPORT_STATIC_ENTRIES + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_request: Updating ARP Static Entry for unicast reply\n")); + if (memcpy_s(ethaddr.addr, ETHARP_HWADDR_LEN, client_msg->chaddr, client_msg->hlen) != EOK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_request: Copy chaddr failed\n")); + (void)pbuf_free(out_msg); + return; + } + if (ERR_OK != etharp_add_static_entry(&requested_ip, ðaddr)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_request: Adding static entry to arp cache failed\n")); + (void)pbuf_free(out_msg); + return; + } +#endif + /* Need to check and add an arp entry to make this pass through smoothly */ +#ifdef LWIP_DEV_DEBUG + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("handle_request: sending reply using unicast Client IP =%"U32_F"\n", requested_ip.addr)); +#endif + ip_send.u_addr.ip4.addr = requested_ip.addr; + ip_send.type = IPADDR_TYPE_V4; + (void)udp_sendto_if_src(dhcps->pcb, out_msg, &ip_send, DHCP_CLIENT_PORT, netif, &(netif->ip_addr)); + +#if ETHARP_SUPPORT_STATIC_ENTRIES + /* We just added the entry above and checked for it's success too. so, the below function call cannot fail */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("handle_request: Removing ARP Static Entry added for unicast reply\n")); + (void)etharp_remove_static_entry(&requested_ip); +#endif + } + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_request: deleting\n")); + + (void)pbuf_free(out_msg); + return; +} + +LWIP_STATIC void handle_decline(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg, + struct dyn_lease_addr *client_lease) +{ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_decline: Processing Decline Message\n")); + + if ((client_lease != NULL) && (dhcps_option_given(dhcps, DHCP_OPTION_IDX_REQUESTED_IP)) && + (client_msg->ciaddr.addr == 0)) { + if (client_lease->cli_addr.addr == (u32_t)dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_REQUESTED_IP)) { +#ifdef LWIP_DEV_DEBUG + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("handle_decline: Marking Client Entry as declined. Client IP =%"U32_F"\n", + client_lease->cli_addr.addr)); +#endif + (void)memset_s(client_lease->cli_hwaddr, sizeof(client_lease->cli_hwaddr), 0, DHCP_CHADDR_LEN); + client_lease->proposed_leasetime = 0; + client_lease->leasetime = sys_now() + (LWIP_DHCPS_DECLINE_TIME * 1000); + client_lease->flags = DHCPS_ADDRESS_DECLINED; + } + } +} + +LWIP_STATIC void handle_inform(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg) +{ + struct pbuf *out_msg = NULL; + struct dhcp_msg *srvr_msg = NULL; + u16_t options_len = 0; + ip_addr_t dst_addr; + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_inform: Processing Inform Message\n")); + + if (client_msg->ciaddr.addr == 0) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_inform: ciaddr is empty. Can't send back a response\n")); + return; + } + + out_msg = dhcps_create_base_msg(client_msg); + if (out_msg == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_inform: Creating base message failed\n")); + return; + } + + srvr_msg = (struct dhcp_msg *)out_msg->payload; + dhcp_common_option(srvr_msg, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, &options_len); + dhcp_common_option_byte(srvr_msg, DHCP_ACK, &options_len); + + dhcp_common_option_trailer(srvr_msg, options_len, out_msg); + +#ifdef LWIP_DEV_DEBUG + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("handle_inform: Send ACK to Client. Client is=%"U32_F"\n", client_msg->ciaddr.addr)); +#endif + ip_addr_set_ip4_u32_val(dst_addr, client_msg->ciaddr.addr); + (void)udp_sendto_if_src(dhcps->pcb, out_msg, &dst_addr, DHCP_CLIENT_PORT, netif, &(netif->ip_addr)); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_inform: deleting pbuf\n")); + (void)pbuf_free(out_msg); + + return; +} + +LWIP_STATIC void handle_client_messages(struct netif *netif, struct dhcps *dhcps, + struct dhcp_msg *client_msg, ip4_addr_t serverid, u8_t msg_type) +{ + struct dyn_lease_addr *client_lease = NULL; + + client_lease = find_client_lease(dhcps, client_msg); + switch (msg_type) { + case DHCP_DISCOVER: + handle_discover(netif, dhcps, client_msg, client_lease); + break; + case DHCP_REQUEST: + handle_request(netif, dhcps, client_msg, client_lease, serverid); + break; + case DHCP_DECLINE: + handle_decline(netif, dhcps, client_msg, client_lease); + break; + case DHCP_RELEASE: + if ((client_lease != NULL) && (client_lease->cli_addr.addr == ntohl(client_msg->ciaddr.addr))) { +#ifdef LWIP_DEV_DEBUG + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP Release: Client IPAdd =%"U32_F"\n", client_msg->ciaddr.addr)); +#endif + (void)memset_s(client_lease, sizeof(struct dyn_lease_addr), 0, sizeof(struct dyn_lease_addr)); + client_lease->flags = DHCPS_ADDRESS_FREE; + } + break; + case DHCP_INFORM: + handle_inform(netif, dhcps, client_msg); + break; + default: + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("DHCP Server. Invalid message type received %d\n", msg_type)); + } +} + +err_t dhcps_parse_options(struct pbuf *p, struct dhcps *dhcps) +{ + return dhcp_parse_reply(p, &dhcps->dhcp); +} + +LWIP_STATIC void dhcps_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *ip_addr, u16_t port) +{ + struct netif *netif = (struct netif *)arg; + struct dhcps *dhcps = netif_get_dhcps(netif); + struct dhcp_msg *client_msg = (struct dhcp_msg *)p->payload; + u8_t msg_type; + ip4_addr_t serverid; + ip4_addr_t addr; + + if (client_msg == NULL) { + return; + } + addr.addr = ip_addr->u_addr.ip4.addr; + serverid.addr = 0; +#ifdef LWIP_DEV_DEBUG + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("dhcps_recv(pbuf = %p) from DHCP Client %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p, + ip4_addr1_16(&addr), ip4_addr2_16(&addr), ip4_addr3_16(&addr), ip4_addr4_16(&addr), port)); +#endif + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len)); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len)); + /* prevent warnings about unused arguments */ + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(addr); + LWIP_UNUSED_ARG(port); + + dhcps_clear_all_options(dhcps); + + /* Check and remove old entries on each call to dhcp_recv. This way, we don't need to maintain timers */ + remove_stale_entries(dhcps); + + if (p->len < DHCP_OPTIONS_OFS) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("DHCP client message or pbuf too short. pbuf len =%"U16_F" DHCP MIN Reply Len = %"U32_F"\n", + p->len, DHCP_MIN_REPLY_LEN)); + goto free_pbuf_and_return; + } + + if (client_msg->op != DHCP_BOOTREQUEST) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("Not a DHCP reply message, Type %"U16_F"\n", (u16_t)client_msg->op)); + goto free_pbuf_and_return; + } + + if (client_msg->cookie != PP_HTONL(DHCP_MAGIC_COOKIE)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("DHCP Server. Cookie Value is incorrect. %"U32_F"\n", (u32_t)client_msg->cookie)); + goto free_pbuf_and_return; + } + + if (client_msg->hlen != ETHARP_HWADDR_LEN) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("DHCP Server. Invalid hardware address length %"U16_F"\n", (u16_t)client_msg->hlen)); + goto free_pbuf_and_return; + } + + if (dhcps_parse_options(p, dhcps) != ERR_OK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("Parsing of Options failed in DHCP Client Message\n")); + goto free_pbuf_and_return; + } + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("Searching DHCP_OPTION_MESSAGE_TYPE\n")); + /* obtain pointer to DHCP message type */ + if (!dhcps_option_given(dhcps, DHCP_OPTION_IDX_MSG_TYPE)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("DHCP_OPTION_MESSAGE_TYPE option not found\n")); + goto free_pbuf_and_return; + } + + /* read DHCP message type */ + msg_type = (u8_t)dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_MSG_TYPE); + + if (dhcps_option_given(dhcps, DHCP_OPTION_IDX_SERVER_ID)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("DHCP_OPTION_SERVER_ID option found\n")); + /* Parse options would have changed it to host order. But, we have our IP stored in netif in network order */ + serverid.addr = htonl((u32_t)dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_SERVER_ID)); + } + + if ((serverid.addr != 0) && ((msg_type == DHCP_DISCOVER) || (msg_type == DHCP_INFORM))) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("Serverid present in DHCP_DISCOVER and DHCP_INFORM messages\n")); + goto free_pbuf_and_return; + } + + if ((!ip4_addr_cmp(&serverid, ip_2_ip4(&netif->ip_addr))) && + ((msg_type == DHCP_DECLINE) || (msg_type == DHCP_RELEASE))) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("Serverid not present in DHCP_RELEASE and DHCP_DECLINE messages\n")); + goto free_pbuf_and_return; + } + + handle_client_messages(netif, dhcps, client_msg, serverid, msg_type); + +free_pbuf_and_return: + (void)pbuf_free(p); +} + +err_t dhcps_start(struct netif *netif, const char *start_ip, u16_t ip_num) +{ + struct dhcps *dhcps = NULL; + ip4_addr_t address_in_hton; + int err; + + LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG); + dhcps = netif_get_dhcps(netif); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("dhcps_start(netif=%p) %s\n", (void *)netif, netif_get_name(netif))); + + if (netif->mtu < DHCP_MAX_MSG_LEN_MIN_REQUIRED) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("MTU =%"U16_F",DHCP Msg Len Required =%"U32_F"\n", netif->mtu, DHCP_MAX_MSG_LEN_MIN_REQUIRED)); + return ERR_MEM; + } + + if (dhcps != NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcps_start(): DHCP Server is already started\n")); + return ERR_MEM; + } + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcps_start(): starting new DHCP Server\n")); + dhcps = (struct dhcps *)mem_malloc(sizeof(struct dhcps)); + if (dhcps == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcps_start(): could not allocate dhcp\n")); + return ERR_MEM; + } + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcps_start(): allocated dhcp")); + + (void)memset_s(dhcps, sizeof(struct dhcps), 0, sizeof(struct dhcps)); + + dhcps->pcb = udp_new(); + if (dhcps->pcb == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate pcb\n")); + mem_free((void *)dhcps); + return ERR_MEM; + } + +#if LWIP_SO_BINDTODEVICE + /* bind dhcp udp_pcb to specific netif, this could make dhcp server start on multiple netif */ + dhcps->pcb->ifindex = netif->ifindex; +#endif + if ((start_ip == NULL) || (ip_num == 0)) { + /* use default ip lease configuration. */ + dhcps->start_addr.addr = ntohl(ip_2_ip4(&netif->ip_addr)->addr & ip_2_ip4(&netif->netmask)->addr) + 1; + dhcps->end_addr.addr = ntohl(ip_2_ip4(&netif->ip_addr)->addr | (~ip_2_ip4(&netif->netmask)->addr)) - 1; + dhcps->lease_num = (u8_t)(dhcps->end_addr.addr - dhcps->start_addr.addr + 1); + if (dhcps->lease_num > LWIP_DHCPS_MAX_LEASE) { + dhcps->lease_num = LWIP_DHCPS_MAX_LEASE; + dhcps->end_addr.addr = dhcps->start_addr.addr + LWIP_DHCPS_MAX_LEASE - 1; + } + } else { + dhcps->start_addr.addr = ntohl(ipaddr_addr(start_ip)); + dhcps->end_addr.addr = (u32_t)(dhcps->start_addr.addr + + (u32_t)(LWIP_MIN(ip_num - 1, LWIP_DHCPS_MAX_LEASE - 1))); + + ip4_addr_set_hton(&address_in_hton, &dhcps->start_addr); + + if (!ip4_addr_netcmp((&address_in_hton), ip_2_ip4(&netif->ip_addr), ip_2_ip4(&netif->netmask)) || + ip4_addr_isbroadcast((&address_in_hton), netif)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): %s in not a valid ip lease\n", start_ip)); + udp_remove(dhcps->pcb); + mem_free((void *)dhcps); + return ERR_ARG; + } + + ip4_addr_set_hton(&address_in_hton, &dhcps->end_addr); + + if (!ip4_addr_netcmp((&address_in_hton), ip_2_ip4(&netif->ip_addr), ip_2_ip4(&netif->netmask)) || + ip4_addr_isbroadcast((&address_in_hton), netif)) { + dhcps->end_addr.addr = ntohl(ip_2_ip4(&netif->ip_addr)->addr | (~ip_2_ip4(&netif->netmask)->addr)) - 1; + } + dhcps->lease_num = (u8_t)(dhcps->end_addr.addr - dhcps->start_addr.addr + 1); + } + + dhcps->netif = netif; + dhcps->pcb->so_options |= SOF_BROADCAST; + err = udp_bind(dhcps->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT); + if (err != ERR_OK) { + udp_remove(dhcps->pcb); + mem_free((void *)dhcps); + return ERR_MEM; + } + + err = udp_connect(dhcps->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT); + if (err != ERR_OK) { + udp_remove(dhcps->pcb); + mem_free((void *)dhcps); + return ERR_MEM; + } + udp_recv(dhcps->pcb, dhcps_recv, netif); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcps_start(): starting DHCPS Successfully\n")); +#ifdef LWIP_DEV_DEBUG + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("dhcps_start(): DHCPS Conf:: netif addr = %"U32_F" dhcps start addr%"U32_F" dhcp end addr%"U32_F"\n", + ip_2_ip4(&netif->ip_addr)->addr, dhcps->start_addr.addr, dhcps->end_addr.addr)); +#endif + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("dhcps_start(): DHCPS Lease Conf:: Lease Time = %"U32_F" Offer Time = %"U32_F"\n", + LWIP_DHCPS_LEASE_TIME, LWIP_DHCPS_OFFER_TIME)); + netif_set_dhcps(netif, dhcps); + return ERR_OK; +} + +void dhcps_stop(struct netif *netif) +{ + LWIP_ERROR("dhcps_stop: netif != NULL", (netif != NULL), return); + struct dhcps *dhcps = netif_get_dhcps(netif); + if (dhcps != NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcps_stop(): Stopping DHCP Server\n")); + if (dhcps->pcb != NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcps_stop(): Removing UDP PCB\n")); + udp_remove(dhcps->pcb); + dhcps->pcb = NULL; + } + + mem_free(dhcps); + netif_set_dhcps(netif, NULL); + } +} + +#endif + diff --git a/net/lwip-2.1/enhancement/src/api_shell_fix.c b/net/lwip-2.1/enhancement/src/fixme.c similarity index 82% rename from net/lwip-2.1/enhancement/src/api_shell_fix.c rename to net/lwip-2.1/enhancement/src/fixme.c index 56ab3e5f..6143567d 100755 --- a/net/lwip-2.1/enhancement/src/api_shell_fix.c +++ b/net/lwip-2.1/enhancement/src/fixme.c @@ -29,46 +29,26 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "api_shell_fix.h" - -#include +#include "lwip/fixme.h" #include #include #include #include -#include #include -#include "securec.h" - #define NETIFAPI_VAR_REF(name) API_VAR_REF(name) #define NETIFAPI_VAR_DECLARE(name) API_VAR_DECLARE(struct netifapi_msg, name) #define NETIFAPI_VAR_ALLOC(name) API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, name, ERR_MEM) #define NETIFAPI_VAR_FREE(name) API_VAR_FREE(MEMP_NETIFAPI_MSG, name) - -/** - * - * - * ################# FOR API_SHELL ONLY ################# - * - * - * - */ - - -#if LWIP_ENABLE_LOS_SHELL_CMD - #if LWIP_DHCP #include /* * Close DHCP and set static network. - * * @param netif a pre-allocated netif structure - * * @return ERR_OK, or ERR_VAL if failed. */ err_t netif_dhcp_off(struct netif *netif) @@ -85,32 +65,48 @@ err_t netif_dhcp_off(struct netif *netif) old_gateway = netif->gw; if (netif_dhcp_data(netif)) { - (void) dhcp_release(netif); - (void) dhcp_stop(netif); - (void) dhcp_cleanup(netif); + (void)dhcp_release(netif); + (void)dhcp_stop(netif); + (void)dhcp_cleanup(netif); LWIP_DEBUGF(NETIF_DEBUG, ("DHCP is close;set static IP\n")); } ip_addr_set_val(&netif->ip_addr, &old_ipaddr); ip_addr_set_val(&netif->netmask, &old_netmask); ip_addr_set_val(&netif->gw, &old_gateway); - (void) netif_set_up(netif); + (void)netif_set_up(netif); return ERR_OK; } +err_t dhcp_is_bound(struct netif *netif) +{ + struct dhcp *dhcp = NULL; + + LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG); + + dhcp = netif_dhcp_data(netif); + LWIP_ERROR("netif->dhcp != NULL", (dhcp != NULL), return ERR_ARG); + + if (dhcp->state == DHCP_STATE_BOUND) { + return ERR_OK; + } else { + return ERR_INPROGRESS; + } +} + #endif /* LWIP_DHCP */ #if LWIP_DHCPS -#include "dhcps.h" +#include "lwip/dhcps.h" -static err_t netifapi_do_dhcps_start (struct tcpip_api_call_data *m) +static err_t netifapi_do_dhcps_start(struct tcpip_api_call_data *m) { /* cast through void* to silence alignment warnings. * We know it works because the structs have been instantiated as struct netifapi_msg */ err_t ret; - struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; + struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m; ret = dhcps_start(msg->netif, msg->msg.dhcp_start_params.start_ip, msg->msg.dhcp_start_params.ip_num); return ret; } @@ -124,8 +120,8 @@ err_t netifapi_dhcps_start(struct netif *netif, char *start_ip, u16_t ip_num) NETIFAPI_VAR_ALLOC(msg); NETIFAPI_VAR_REF(msg).netif = netif; - NETIFAPI_VAR_REF(msg).msg.dhcp_start_params.start_ip = start_ip ; - NETIFAPI_VAR_REF(msg).msg.dhcp_start_params.ip_num = ip_num ; + NETIFAPI_VAR_REF(msg).msg.dhcp_start_params.start_ip = start_ip; + NETIFAPI_VAR_REF(msg).msg.dhcp_start_params.ip_num = ip_num; err = tcpip_api_call(netifapi_do_dhcps_start, &API_VAR_REF(msg).call); @@ -216,19 +212,19 @@ static struct netif *netif_find_by_name(const char *name) return NULL; } - if (strcmp("lo", name) == 0) { - LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); - return netif_find(name); - } - NETIF_FOREACH(netif) { + if (strcmp("lo", name) == 0 && (netif->name[0] == 'l' && netif->name[1] == 'o')) { + LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_name: found lo\n")); + return netif; + } + if (strcmp(netif->full_name, name) == 0) { - LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); + LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_name: found %s\n", name)); return netif; } } - LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1])); + LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_name: didn't find %s\n", name)); return NULL; } @@ -294,7 +290,7 @@ err_t netif_set_mtu(struct netif *netif, u16_t netif_mtu) #endif /* LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES */ LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif: MTU of interface %s is changed to %d\n", - netif_get_name(netif), netif->mtu)); + netif_get_name(netif), netif->mtu)); return ERR_OK; } @@ -322,31 +318,35 @@ err_t netif_set_hwaddr(struct netif *netif, const unsigned char *hw_addr, int hw LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: HW address of interface %s set to %02X:%02X:%02X:%02X:%02X:%02X\n", - netif_get_name(netif), - netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2], - netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5])); + netif_get_name(netif), + netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2], + netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5])); return ERR_OK; } err_t etharp_update_arp_entry(struct netif *netif, const ip4_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags) { + // FIXME return 0; } err_t etharp_delete_arp_entry(struct netif *netif, ip4_addr_t *ipaddr) { + // FIXME return 0; } err_t lwip_dns_setserver(u8_t numdns, ip_addr_t *dnsserver) { + // FIXME return 0; } err_t lwip_dns_getserver(u8_t numdns, ip_addr_t *dnsserver) { + // FIXME return 0; } @@ -354,57 +354,42 @@ err_t lwip_dns_getserver(u8_t numdns, ip_addr_t *dnsserver) struct raw_pcb *pkt_raw_pcbs; #endif -struct raw_pcb *raw_pcbs; +#if LWIP_RAW +struct raw_pcb *raw_pcbs; /* already defined in raw.c, but is static */ +#endif - -/******************************************************************/ #if LWIP_ENABLE_IP_CONFLICT_SIGNAL u32_t is_ip_conflict_signal = 0; sys_sem_t ip_conflict_detect; #endif - u32_t is_dup_detect_initialized = 0; sys_sem_t dup_addr_detect; +#if LWIP_SNTP + +#include + int lwip_sntp_start(int server_num, char **sntp_server, struct timeval *time) { + // FIXME return 0; } -u32_t lwip_tftp_get_file_by_filename(u32_t ulHostAddr, - u16_t usTftpServPort, - u8_t ucTftpTransMode, - s8_t *szSrcFileName, - s8_t *szDestDirPath) -{ - return 0; -} - -u32_t lwip_tftp_put_file_by_filename(u32_t ulHostAddr, - u16_t usTftpServPort, - u8_t cTftpTransMode, - s8_t *szSrcFileName, - s8_t *szDestDirPath) -{ - return 0; -} - +#endif const char *const tcp_state_str[] = { - "CLOSED", - "LISTEN", - "SYN_SENT", - "SYN_RCVD", - "ESTABLISHED", - "FIN_WAIT_1", - "FIN_WAIT_2", - "CLOSE_WAIT", - "CLOSING", - "LAST_ACK", - "TIME_WAIT" + "CLOSED", + "LISTEN", + "SYN_SENT", + "SYN_RCVD", + "ESTABLISHED", + "FIN_WAIT_1", + "FIN_WAIT_2", + "CLOSE_WAIT", + "CLOSING", + "LAST_ACK", + "TIME_WAIT" }; volatile int tcpip_init_finish = 1; // needed by api_shell.c - -#endif diff --git a/net/lwip-2.1/enhancement/src/tftpc.c b/net/lwip-2.1/enhancement/src/tftpc.c new file mode 100644 index 00000000..16c14928 --- /dev/null +++ b/net/lwip-2.1/enhancement/src/tftpc.c @@ -0,0 +1,1726 @@ +/* + * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* TFTP Client utility */ + +#include "lwip/opt.h" + +#if LWIP_TFTP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/tcpip.h" +#include "lwip/netif.h" +#include "lwip/mem.h" +#include "lwip/err.h" +#include "lwip/inet.h" +#include "netif/etharp.h" +#include "lwip/ip_addr.h" +#include "lwip/sockets.h" +#include "lwip/udp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/def.h" +#include "lwip/tftpc.h" +#include "fcntl.h" +#include +#include + +#include + + +/* Function Declarations */ +#ifdef LOSCFG_NET_LWIP_SACK_TFTP +static u32_t lwip_tftp_create_bind_socket(s32_t *piSocketID); + +static s32_t lwip_tftp_make_tftp_packet(u16_t usOpcode, s8_t *szFileName, + u32_t ulMode, TFTPC_PACKET_S *pstPacket); + +static u32_t lwip_tftp_recv_from_server(s32_t iSockNum, + u32_t *pulSize, + TFTPC_PACKET_S *pstRecvBuf, + u32_t *pulIgnorePkt, + struct sockaddr_in *pstServerAddr, + TFTPC_PACKET_S *pstSendBuf); + +static u32_t lwip_tftp_send_to_server(s32_t iSockNum, u32_t ulSize, + TFTPC_PACKET_S *pstSendBuf, + struct sockaddr_in *pstServerAddr); + +static u32_t lwip_tftp_validate_data_pkt(s32_t iSockNum, + u32_t *pulSize, + TFTPC_PACKET_S *pstRecvBuf, + u16_t usCurrBlk, u32_t *pulResendPkt, + struct sockaddr_in *pstServerAddr); + +static u32_t lwip_tftp_inner_put_file(s32_t iSockNum, TFTPC_PACKET_S *pstSendBuf, + u32_t ulSendSize, u16_t usCurrBlk, + struct sockaddr_in *pstServerAddr); + +static void lwip_tftp_send_error(s32_t iSockNum, u32_t ulError, const char *szErrMsg, + struct sockaddr_in *pstServerAddr, TFTPC_PACKET_S *pstSendBuf); + + +/* Create and bind a UDP socket. */ +u32_t lwip_tftp_create_bind_socket(s32_t *piSocketID) +{ + int retval; + struct sockaddr_in stClientAddr; + u32_t ulTempClientIp; + u32_t set_non_block_socket = 1; + + /* create a socket */ + *piSocketID = lwip_socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (*piSocketID == -1) { + LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_create_bind_socket : lwip_socket create socket failed\n")); + return TFTPC_SOCKET_FAILURE; + } + + /* Make the socket as NON-BLOCKING. */ + retval = lwip_ioctl(*piSocketID, (long)FIONBIO, &set_non_block_socket); + if (retval != 0) { + (void)lwip_close(*piSocketID); + *piSocketID = TFTP_NULL_INT32; + return TFTPC_IOCTLSOCKET_FAILURE; + } + + ulTempClientIp = INADDR_ANY; + + /* specify a local address for this socket */ + (void)memset_s(&stClientAddr, sizeof(stClientAddr), 0, sizeof(stClientAddr)); + stClientAddr.sin_family = AF_INET; + stClientAddr.sin_port = 0; + stClientAddr.sin_addr.s_addr = htonl(ulTempClientIp); + + retval = lwip_bind(*piSocketID, (struct sockaddr *)&stClientAddr, sizeof(stClientAddr)); + if (retval != 0) { + (void)lwip_close(*piSocketID); + *piSocketID = TFTP_NULL_INT32; + + return TFTPC_BIND_FAILURE; + } + + return ERR_OK; +} + + +/* Function to create TFTP packet. + usOpcode - indiacting the nature of the operation + pFileName -filename on which the operation needs to done + ulMode -mode in which the operation needs to done + pstPacket - packet generated + Returns packet address on success +*/ +static s32_t lwip_tftp_make_tftp_packet(u16_t usOpcode, s8_t *szFileName, u32_t ulMode, TFTPC_PACKET_S *pstPacket) +{ + s8_t *pcCp = NULL; + + pstPacket->usOpcode = htons(usOpcode); + pcCp = pstPacket->u.ucName_Mode; + + /* Request packet format is: + | Opcode | Filename | 0 | Mode | 0 | + */ + (void)strncpy_s((char *)pcCp, TFTP_MAX_PATH_LENGTH, (char *)szFileName, (TFTP_MAX_PATH_LENGTH - 1)); + pcCp[(TFTP_MAX_PATH_LENGTH - 1)] = '\0'; + + pcCp += (strlen((char *)szFileName) + 1); + if (ulMode == TRANSFER_MODE_BINARY) { + (void)strncpy_s((char *)pcCp, TFTP_MAX_MODE_SIZE, "octet", (TFTP_MAX_MODE_SIZE - 1)); + pcCp[(TFTP_MAX_MODE_SIZE - 1)] = '\0'; + } else if (ulMode == TRANSFER_MODE_ASCII) { + (void)strncpy_s((char *)pcCp, TFTP_MAX_MODE_SIZE, "netascii", (TFTP_MAX_MODE_SIZE - 1)); + pcCp[(TFTP_MAX_MODE_SIZE - 1)] = '\0'; + } + + pcCp += (strlen((char *)pcCp) + 1); + + return (pcCp - (s8_t *)pstPacket); +} + +/* Function to recv a packet from server + iSockNum - Socket Number + pstServerAddr - Server address + pulIgnorePkt - Ignore packet flag + pstRecvBuf - received packet + pulSize - Size of the packet +*/ +u32_t lwip_tftp_recv_from_server(s32_t iSockNum, u32_t *pulSize, TFTPC_PACKET_S *pstRecvBuf, u32_t *pulIgnorePkt, + struct sockaddr_in *pstServerAddr, TFTPC_PACKET_S *pstSendBuf) +{ + u32_t ulError; + socklen_t slFromAddrLen; + struct sockaddr_in stFromAddr; + fd_set stReadfds; + struct timeval stTimeout; + u16_t usOpcode; /* Opcode value */ + s32_t iRet; + + slFromAddrLen = sizeof(stFromAddr); + stTimeout.tv_sec = TFTPC_TIMEOUT_PERIOD; + stTimeout.tv_usec = 0; + + /* wait for DATA packet */ + FD_ZERO(&stReadfds); + FD_SET(iSockNum, &stReadfds); + + iRet = select((s32_t)(iSockNum + 1), &stReadfds, 0, 0, &stTimeout); + if (iRet == -1) { + return TFTPC_SELECT_ERROR; + } else if (iRet == 0) { + return TFTPC_TIMEOUT_ERROR; /* Select timeout occured */ + } + + if (!FD_ISSET(iSockNum, &stReadfds)) { + return TFTPC_TIMEOUT_ERROR; /* FD not set*/ + } + + /* receive a packet from server */ + iRet = lwip_recvfrom(iSockNum, (s8_t *)pstRecvBuf, TFTP_PKTSIZE, 0, + (struct sockaddr *)&stFromAddr, &slFromAddrLen); + if (iRet <= 0) { + return TFTPC_RECVFROM_ERROR; + } + + /* If received packet size < minimum packet size */ + if (iRet < TFTPC_FOUR) { + /* Send Error packet to server */ + lwip_tftp_send_error(iSockNum, + TFTPC_PROTOCOL_PROTO_ERROR, + "Packet size < min size", + pstServerAddr, pstSendBuf); + + return TFTPC_PKT_SIZE_ERROR; + } + + /* convert network opcode to host format after receive. */ + usOpcode = ntohs(pstRecvBuf->usOpcode); + /* if this packet is ERROR packet */ + if (usOpcode == TFTPC_OP_ERROR) { + ulError = ntohs (pstRecvBuf->u.stTFTP_Err.usErrNum); + + /*If the error is according to RFC,then convert to lwip error codes. + Constant values are used in the cases as these error codes are as per + the RFC, these are constant values returned by many standard TFTP + serevrs.*/ + switch (ulError) { + case TFTPC_PROTOCOL_USER_DEFINED: + ulError = TFTPC_ERROR_NOT_DEFINED; + break; + case TFTPC_PROTOCOL_FILE_NOT_FOUND: + ulError = TFTPC_FILE_NOT_FOUND; + break; + case TFTPC_PROTOCOL_ACCESS_ERROR: + ulError = TFTPC_ACCESS_ERROR; + break; + case TFTPC_PROTOCOL_DISK_FULL: + ulError = TFTPC_DISK_FULL; + break; + case TFTPC_PROTOCOL_PROTO_ERROR: + ulError = TFTPC_PROTO_ERROR; + break; + case TFTPC_PROTOCOL_UNKNOWN_TRANSFER_ID: + ulError = TFTPC_UNKNOWN_TRANSFER_ID; + break; + case TFTPC_PROTOCOL_FILE_EXISTS: + ulError = TFTPC_FILE_EXISTS; + break; + case TFTPC_PROTOCOL_CANNOT_RESOLVE_HOSTNAME: + ulError = TFTPC_CANNOT_RESOLVE_HOSTNAME; + break; + default: + ulError = TFTPC_ERROR_NOT_DEFINED; + break; + } + + /* If length of error msg > 100 chars */ + pstRecvBuf->u.stTFTP_Err.ucErrMesg[TFTP_MAXERRSTRSIZE - 1] = '\0'; + + LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_recv_from_server : ERROR pkt received: %s\n", + pstRecvBuf->u.stTFTP_Err.ucErrMesg)); + + /* Now we get error block, so return. */ + return ulError; + } + + /* Store the size of received block */ + *pulSize = (u32_t)iRet; + + /* If received packet is first block of data(for get operation) or if + received packet is acknowledgement for write request (put operation) + store the received port number */ + if (((usOpcode == TFTPC_OP_DATA) && + (ntohs(pstRecvBuf->u.stTFTP_Data.usBlknum) == 1)) || + ((usOpcode == TFTPC_OP_ACK) && + (ntohs(pstRecvBuf->u.usBlknum) == 0))) { + /* If received packet from correct server */ + if (stFromAddr.sin_addr.s_addr == pstServerAddr->sin_addr.s_addr) { + /* set the server port to received port */ + pstServerAddr->sin_port = stFromAddr.sin_port; + } else { + /* Received packet form wrong server. */ + LWIP_DEBUGF(TFTP_DEBUG, + ("lwip_tftp_recv_from_server : Received 1st packet from wrong Server or unknown server\n")); + + /* Set ignore packet flag */ + *pulIgnorePkt = 1; + } + } else { + /* If not first packet, check if the received packet is from correct + server and from correct port */ + if ((stFromAddr.sin_addr.s_addr != pstServerAddr->sin_addr.s_addr) || + (pstServerAddr->sin_port != stFromAddr.sin_port)) { + /* Received packet form wrong server or wrong port.Ignore packet. */ + LWIP_DEBUGF(TFTP_DEBUG, + ("lwip_tftp_recv_from_server : Received a packet from wrong Server or unknown server\n")); + + /* Set ignore packet flag */ + *pulIgnorePkt = 1; + } + } + + return ERR_OK; +} + +/* Function to send a packet to server + iSockNum: Socket Number + ulSize: Size of the packet + pstSendBuf: Packet to send + pstServerAddr: Server address +*/ +u32_t lwip_tftp_send_to_server(s32_t iSockNum, + u32_t ulSize, + TFTPC_PACKET_S *pstSendBuf, + struct sockaddr_in *pstServerAddr) +{ + s32_t iRet; + + /* Send packet to server */ + iRet = lwip_sendto(iSockNum, (s8_t *)pstSendBuf, + (size_t)ulSize, 0, + (struct sockaddr *)pstServerAddr, + sizeof(struct sockaddr_in)); + /* Size of data sent not equal to size of packet */ + if ((iRet == TFTP_NULL_INT32) || ((u32_t)iRet != ulSize)) { + return TFTPC_SENDTO_ERROR; + } + + return ERR_OK; +} + +/* lwip_tftp_validate_data_pkt +* Get the data block from the received packet +* @param Input iSockNum Socket Number +* pulSize: Size of received packet, + pstRecvBuf - received packet + usCurrBlk - Current block number + * @param Output pulResendPkt - Resend packet flag + * @return VOS_OK on success.else error code*/ + +u32_t lwip_tftp_validate_data_pkt(s32_t iSockNum, + u32_t *pulSize, + TFTPC_PACKET_S *pstRecvBuf, + u16_t usCurrBlk, + u32_t *pulResendPkt, + struct sockaddr_in *pstServerAddr) +{ + fd_set stReadfds; + struct timeval stTimeout; + struct sockaddr_in stFromAddr; + socklen_t ulFromAddrLen; + s32_t iRecvLen = (s32_t)*pulSize; + s32_t iError; + u16_t usBlknum; + u32_t ulLoopCnt = 0; + + ulFromAddrLen = sizeof(stFromAddr); + + /* Initialize from address to the server address at first */ + if (memcpy_s((void *)&stFromAddr, sizeof(struct sockaddr_in), (void *)pstServerAddr, sizeof(stFromAddr)) != 0) { + LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_validate_data_pkt : memcpy_s error\n")); + return TFTPC_MEMCPY_FAILURE; + } + + /* Get Block Number */ + usBlknum = ntohs(pstRecvBuf->u.stTFTP_Data.usBlknum); + /* Now data blocks are not in sync. */ + if (usBlknum != usCurrBlk) { + /* Set timeout value */ + stTimeout.tv_sec = 1; + stTimeout.tv_usec = 0; + + /* Reset any stored packets. */ + FD_ZERO(&stReadfds); + FD_SET(iSockNum, &stReadfds); + + iError = select((s32_t)(iSockNum + 1), + &stReadfds, 0, 0, &stTimeout); + + /* Loop to get the last data packet from the receive buffer */ + while ((iError != TFTP_NULL_INT32) && (iError != 0)) { + ulLoopCnt++; + + /* MAX file size in TFTP is 32 MB. + Reason for keeping 75 here , is ((75*512=38400bytes)/1024) = 37MB. So the recv/Send + Loop can receive the complete MAX message from the network. + */ + if (ulLoopCnt > TFTPC_MAX_WAIT_IN_LOOP) { + LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_validate_data_pkt : unexpected packets are received repeatedly\n")); + *pulSize = TFTP_NULL_UINT32; + return TFTPC_PKT_SIZE_ERROR; + } + + FD_ZERO(&stReadfds); + FD_SET(iSockNum, &stReadfds); + + iRecvLen = lwip_recvfrom(iSockNum, + (s8_t *)pstRecvBuf, + TFTP_PKTSIZE, 0, + (struct sockaddr *)&stFromAddr, + &ulFromAddrLen); + if (iRecvLen == -1) { + *pulSize = TFTP_NULL_UINT32; + + /* return from the function, recvfrom operation failed */ + return TFTPC_RECVFROM_ERROR; + } + + stTimeout.tv_sec = 1; + stTimeout.tv_usec = 0; + iError = select((s32_t)(iSockNum + 1), &stReadfds, 0, 0, &stTimeout); + } + + /* If received packet size < minimum packet size */ + if (iRecvLen < TFTPC_FOUR) { + return TFTPC_PKT_SIZE_ERROR; + } + + /* Check if the received packet is from correct server and from + correct port + */ + if ((stFromAddr.sin_addr.s_addr != pstServerAddr->sin_addr.s_addr) || + (pstServerAddr->sin_port != stFromAddr.sin_port)) { + /* resend ack packet */ + *pulResendPkt = 1; + LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_validate_data_pkt : Received pkt from unknown server\n")); + + return ERR_OK; + } + + /* if this packet is not DATA packet */ + if (TFTPC_OP_DATA != ntohs(pstRecvBuf->usOpcode)) { + LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_validate_data_pkt : Received pkt not a DATA pkt\n")); + + /* return from the function, incorrect packet received, + expected packet is data packet */ + return TFTPC_PROTO_ERROR; + } + + usBlknum = ntohs(pstRecvBuf->u.stTFTP_Data.usBlknum); + /* if we now have the earlier data packet, then the host probably + never got our acknowledge packet, now we will send it again. */ + if (usBlknum == (usCurrBlk - 1)) { + /* resend ack packet */ + *pulResendPkt = 1; + LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_validate_data_pkt : Received previous DATA pkt\n")); + + return ERR_OK; + } + + /* If the block of data received is not current block or also + previous block, then it is abnormal case. */ + if (usBlknum != usCurrBlk) { + LWIP_DEBUGF(TFTP_DEBUG, + ("lwip_tftp_validate_data_pkt : Received DATA pkt no. %"S32_F" instead of pkt no.%"S32_F"\n", + usBlknum, usCurrBlk)); + + return TFTPC_SYNC_FAILURE; + } + } + + *pulSize = (u32_t)iRecvLen; + return ERR_OK; +} + +/* Send an error packet to the server + iSockNum : Socket Number + ulError: Error code + szErrMsg - Error message + pstServerAddr - Server address +*/ +static void lwip_tftp_send_error(s32_t iSockNum, u32_t ulError, const char *szErrMsg, + struct sockaddr_in *pstServerAddr, TFTPC_PACKET_S *pstSendBuf) +{ + u16_t usOpCode = TFTPC_OP_ERROR; + + if (memset_s((void *)pstSendBuf, sizeof(TFTPC_PACKET_S), 0, sizeof(TFTPC_PACKET_S)) != 0) { + LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_send_error : memset_s error\n")); + return; + } + + /* Set up the send buffer */ + pstSendBuf->usOpcode = htons(usOpCode); + pstSendBuf->u.stTFTP_Err.usErrNum = htons((u16_t)ulError); + + if (strncpy_s((char *)(pstSendBuf->u.stTFTP_Err.ucErrMesg), TFTP_MAXERRSTRSIZE, + (char *)szErrMsg, (TFTP_MAXERRSTRSIZE - 1)) != EOK) { + LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_send_error : strncpy_s error\n")); + return; + } + pstSendBuf->u.stTFTP_Err.ucErrMesg[(TFTP_MAXERRSTRSIZE - 1)] = '\0'; + + /* Send to server */ + if (lwip_tftp_send_to_server(iSockNum, + sizeof(TFTPC_PACKET_S), + pstSendBuf, + pstServerAddr) != ERR_OK) { + LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_send_to_server error.")); + return; + } +} + +/* INTEFACE to get a file using filename + ulHostAddr - IP address of Host + szSrcFileName - Source file + szDestDirPath - Destination file path +*/ +u32_t lwip_tftp_get_file_by_filename(u32_t ulHostAddr, + u16_t usTftpServPort, + u8_t ucTftpTransMode, + s8_t *szSrcFileName, + s8_t *szDestDirPath) +{ + s32_t iSockNum = TFTP_NULL_INT32; + u32_t ulSrcStrLen; + u32_t ulDestStrLen; + u32_t ulSize; + u32_t ulRecvSize = TFTP_NULL_UINT32; + s32_t iErrCode; + u32_t ulErrCode; + u16_t usReadReq; + u16_t usTempServPort; + s8_t *pszTempDestName = NULL; + s8_t *szTempSrcName = NULL; + u32_t ulCurrBlk = 1; + u32_t ulResendPkt = 0; /*Resend the previous packet*/ + u32_t ulIgnorePkt = 0; /*Ignore received packet*/ + u32_t ulTotalTime = 0; + u32_t isLocalFileOpened = false; + + TFTPC_PACKET_S *pstSendBuf = NULL; + TFTPC_PACKET_S *pstRecvBuf = NULL; + struct sockaddr_in stServerAddr; + struct stat sb; + u32_t IsDirExist = 0; + s32_t fp = -1; + + /*Validate the parameters*/ + if ((szSrcFileName == NULL) || (szDestDirPath == NULL)) { + return TFTPC_INVALID_PARAVALUE; + } + + if ((ucTftpTransMode != TRANSFER_MODE_BINARY) && (ucTftpTransMode != TRANSFER_MODE_ASCII)) { + return TFTPC_INVALID_PARAVALUE; + } + + /*check IP address not within ( 1.0.0.0 - 126.255.255.255 ) + and ( 128.0.0.0 - 223.255.255.255 ) range.*/ + if (!(((ulHostAddr >= TFTPC_IP_ADDR_MIN) && + (ulHostAddr <= TFTPC_IP_ADDR_EX_RESV)) || + ((ulHostAddr >= TFTPC_IP_ADDR_CLASS_B) && + (ulHostAddr <= TFTPC_IP_ADDR_EX_CLASS_DE)))) { + return TFTPC_IP_NOT_WITHIN_RANGE; + } + + /*Check validity of source filename*/ + ulSrcStrLen = strlen((char *)szSrcFileName); + if ((ulSrcStrLen == 0) || (ulSrcStrLen >= TFTP_MAX_PATH_LENGTH)) { + return TFTPC_SRC_FILENAME_LENGTH_ERROR; + } + + /*Check validity of destination path*/ + ulDestStrLen = strlen((char *)szDestDirPath); + if ((ulDestStrLen >= TFTP_MAX_PATH_LENGTH) || (ulDestStrLen == 0)) { + return TFTPC_DEST_PATH_LENGTH_ERROR; + } + + pstSendBuf = (TFTPC_PACKET_S *)mem_malloc(sizeof(TFTPC_PACKET_S)); + if (pstSendBuf == NULL) { + return TFTPC_MEMALLOC_ERROR; + } + + pstRecvBuf = (TFTPC_PACKET_S *)mem_malloc(sizeof(TFTPC_PACKET_S)); + if (pstRecvBuf == NULL) { + mem_free(pstSendBuf); + return TFTPC_MEMALLOC_ERROR; + } + + pszTempDestName = (s8_t *)mem_malloc(TFTP_MAX_PATH_LENGTH); + if (pszTempDestName == NULL) { + mem_free(pstSendBuf); + mem_free(pstRecvBuf); + return TFTPC_MEMALLOC_ERROR; + } + + /* First time initialize the buffers */ + (void)memset_s((void *)pstSendBuf, sizeof(TFTPC_PACKET_S), 0, sizeof(TFTPC_PACKET_S)); + (void)memset_s((void *)pstRecvBuf, sizeof(TFTPC_PACKET_S), 0, sizeof(TFTPC_PACKET_S)); + + /*If given src filename is a relative path extract + the file name from the path*/ + if ((0 != strchr((char *)szSrcFileName, '/')) || (0 != strchr((char *)szSrcFileName, '\\'))) { + /*Move to the end of the src file path*/ + szTempSrcName = szSrcFileName + (ulSrcStrLen - 1); + + while (((*(szTempSrcName - 1) != '/') && + (*(szTempSrcName - 1) != '\\')) && + (szTempSrcName != szSrcFileName)) { + szTempSrcName--; + } + + /*Get length of the extracted src filename*/ + ulSrcStrLen = strlen((char *)szTempSrcName); + } else { + /*If not a relative src path use the given src filename*/ + szTempSrcName = szSrcFileName; + } + + (void)memset_s(pszTempDestName, TFTP_MAX_PATH_LENGTH, 0, TFTP_MAX_PATH_LENGTH); + if (strncpy_s((char *)pszTempDestName, TFTP_MAX_PATH_LENGTH, (char *)szDestDirPath, TFTP_MAX_PATH_LENGTH - 1) != + 0) { + ulErrCode = TFTPC_MEMCPY_FAILURE; + goto err_handler; + } + pszTempDestName[TFTP_MAX_PATH_LENGTH - 1] = '\0'; + + if (stat((char *)pszTempDestName, &sb) == 0 && S_ISDIR(sb.st_mode)) { + IsDirExist = 1; + } + + if (IsDirExist == 1) { + /*The filename is not present concat source filename and try*/ + if ((ulDestStrLen + ulSrcStrLen) >= TFTP_MAX_PATH_LENGTH) { + /*If concatenating src filename exceeds 256 bytes*/ + ulErrCode = TFTPC_DEST_PATH_LENGTH_ERROR; + goto err_handler; + } + + /*Check if / present at end of string*/ + if ((pszTempDestName[ulDestStrLen - 1] != '/') && + (pszTempDestName[ulDestStrLen - 1] != '\\')) { + if ((ulDestStrLen + ulSrcStrLen + 1) >= TFTP_MAX_PATH_LENGTH) { + /*If concatenating src filename exceeds 256 bytes*/ + ulErrCode = TFTPC_DEST_PATH_LENGTH_ERROR; + goto err_handler; + } + + /*If not present concat / to the path*/ + if (strncat_s((char *)pszTempDestName, (TFTP_MAX_PATH_LENGTH - strlen((char *)pszTempDestName)), + "/", TFTP_MAX_PATH_LENGTH - strlen((char *)pszTempDestName) - 1) != 0) { + ulErrCode = TFTPC_ERROR_NOT_DEFINED; + goto err_handler; + } + } + + /*Concatenate src filename to destination path*/ + if (strncat_s((char *)pszTempDestName, (TFTP_MAX_PATH_LENGTH - strlen((char *)pszTempDestName)), + (char *)szTempSrcName, TFTP_MAX_PATH_LENGTH - strlen((char *)pszTempDestName) - 1) != 0) { + ulErrCode = TFTPC_ERROR_NOT_DEFINED; + goto err_handler; + } + } + + ulErrCode = lwip_tftp_create_bind_socket(&iSockNum); + if (ulErrCode != ERR_OK) { + goto err_handler; + } + + if (usTftpServPort == 0) { + usTftpServPort = TFTPC_SERVER_PORT; + } + + usTempServPort = usTftpServPort; + + /* set server IP address */ + (void)memset_s(&stServerAddr, sizeof(stServerAddr), 0, sizeof(stServerAddr)); + stServerAddr.sin_family = AF_INET; + stServerAddr.sin_port = htons(usTempServPort); + stServerAddr.sin_addr.s_addr = htonl(ulHostAddr); + + /* Make a request packet - TFTPC_OP_RRQ */ + ulSize = (u32_t)lwip_tftp_make_tftp_packet(TFTPC_OP_RRQ, szSrcFileName, + (u32_t)ucTftpTransMode, + pstSendBuf); + ulErrCode = lwip_tftp_send_to_server(iSockNum, ulSize, + pstSendBuf, &stServerAddr); + if (ulErrCode != ERR_OK) { + /* send to server failed */ + (void)lwip_close(iSockNum); + goto err_handler; + } + + for (;;) { + if (ulIgnorePkt > 0) { + ulIgnorePkt = 0; + } + + ulErrCode = lwip_tftp_recv_from_server(iSockNum, &ulRecvSize, pstRecvBuf, + &ulIgnorePkt, &stServerAddr, pstSendBuf); + /* If select timeout occured */ + if (ulErrCode == TFTPC_TIMEOUT_ERROR) { + ulTotalTime++; + if (ulTotalTime < TFTPC_MAX_SEND_REQ_ATTEMPTS) { + /* Max attempts not reached. Resend packet */ + ulErrCode = lwip_tftp_send_to_server(iSockNum, ulSize, + pstSendBuf, &stServerAddr); + if (ulErrCode != ERR_OK) { + (void)lwip_close(iSockNum); + if (isLocalFileOpened == true) { + close(fp); + } + goto err_handler; + } + + continue; + } else { + /* return from the function, max attempts limit reached */ + (void)lwip_close(iSockNum); + if (isLocalFileOpened == true) { + close(fp); + } + ulErrCode = TFTPC_TIMEOUT_ERROR; + goto err_handler; + } + } else if (ulErrCode != ERR_OK) { + (void)lwip_close(iSockNum); + if (isLocalFileOpened == true) { + close(fp); + } + goto err_handler; + } + + /* Now we have receive block from different server. */ + if (ulIgnorePkt > 0) { + /*Continue without processing this block. */ + continue; + } + + /* if this packet is unkonwn or incorrect packet */ + if (ntohs (pstRecvBuf->usOpcode) != TFTPC_OP_DATA) { + /* Send error packet to server */ + lwip_tftp_send_error(iSockNum, + TFTPC_PROTOCOL_PROTO_ERROR, + "Protocol error.", + &stServerAddr, pstSendBuf); + + (void)lwip_close(iSockNum); + if (isLocalFileOpened == true) { + close(fp); + } + + LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_get_file_by_filename : Received pkt not DATA pkt\n")); + + ulErrCode = TFTPC_PROTO_ERROR; + goto err_handler; + } + + /* Now the number of tries will be reset. */ + ulTotalTime = 0; + + /* Validate received DATA packet. */ + ulErrCode = lwip_tftp_validate_data_pkt(iSockNum, &ulRecvSize, + pstRecvBuf, (u16_t)ulCurrBlk, + &ulResendPkt, + &stServerAddr); + if (ulErrCode != ERR_OK) { + /* Send Error packet to server */ + if (ulErrCode != TFTPC_RECVFROM_ERROR) { + lwip_tftp_send_error(iSockNum, + TFTPC_PROTOCOL_PROTO_ERROR, + "Received unexpected packet", + &stServerAddr, pstSendBuf); + } + + (void)lwip_close(iSockNum); + if (isLocalFileOpened == true) { + close(fp); + } + + goto err_handler; + } + + /* Received previous data block again. Resend last packet */ + if (ulResendPkt > 0) { + /* Now set ulResendPkt to 0 to send the last packet. */ + ulResendPkt = 0; + ulErrCode = lwip_tftp_send_to_server(iSockNum, ulSize, + pstSendBuf, &stServerAddr); + if (ulErrCode != ERR_OK) { + (void)lwip_close(iSockNum); + if (isLocalFileOpened == true) { + close(fp); + } + + goto err_handler; + } + + /* Continue in loop to send last packet again. */ + continue; + } + + /* Get the size of the data block received */ + ulRecvSize -= TFTP_HDRSIZE; + + /* Check if the size of the received data block > max size */ + if (ulRecvSize > TFTP_BLKSIZE) { + /* Send Error packet to server */ + lwip_tftp_send_error(iSockNum, + TFTPC_PROTOCOL_PROTO_ERROR, + "Packet size > max size", + &stServerAddr, pstSendBuf); + + (void)lwip_close(iSockNum); + if (isLocalFileOpened == true) { + close(fp); + } + + LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_get_file_by_filename : Packet size > max size\n")); + + ulErrCode = TFTPC_PKT_SIZE_ERROR; + goto err_handler; + } + + usReadReq = (u16_t)TFTPC_OP_ACK; + pstSendBuf->usOpcode = htons(usReadReq); + pstSendBuf->u.usBlknum = htons((u16_t)ulCurrBlk); + ulSize = TFTP_HDRSIZE; + + if (isLocalFileOpened == false) { + fp = open((char *)pszTempDestName, (O_WRONLY | O_CREAT | O_TRUNC), DEFFILEMODE); + if (fp == TFTP_NULL_INT32) { + ulErrCode = TFTPC_FILECREATE_ERROR; + (void)lwip_close(iSockNum); + goto err_handler; + } + isLocalFileOpened = true; + } + + if (ulRecvSize != TFTP_BLKSIZE) { + (void)lwip_tftp_send_to_server(iSockNum, ulSize, pstSendBuf, &stServerAddr); + + /* If the received packet has only header and do not have payload, the return failure */ + if (ulRecvSize != 0) { + /* Write the last packet to the file */ + iErrCode = write(fp, (void *)pstRecvBuf->u.stTFTP_Data.ucDataBuf, (size_t)ulRecvSize); + if (ulRecvSize != (u32_t)iErrCode) { + /* Write to file failed. */ + lwip_tftp_send_error(iSockNum, + TFTPC_PROTOCOL_USER_DEFINED, + "Write to file failed", + &stServerAddr, pstSendBuf); + + (void)lwip_close(iSockNum); + close(fp); + + /* return from the function, file write failed */ + ulErrCode = TFTPC_FILEWRITE_ERROR; + goto err_handler; + } + } + + /* Now free allocated resourdes and return, + data block receiving is already completed */ + (void)lwip_close(iSockNum); + close(fp); + ulErrCode = ERR_OK; + goto err_handler; + } + + ulErrCode = lwip_tftp_send_to_server(iSockNum, ulSize, + pstSendBuf, &stServerAddr); + if (ulErrCode != ERR_OK) { + (void)lwip_close(iSockNum); + close(fp); + goto err_handler; + } + + iErrCode = write(fp, (void *)pstRecvBuf->u.stTFTP_Data.ucDataBuf, (size_t)ulRecvSize); + if (ulRecvSize != (u32_t)iErrCode) { + /* Write to file failed. */ + lwip_tftp_send_error(iSockNum, + TFTPC_PROTOCOL_USER_DEFINED, + "Write to file failed", + &stServerAddr, pstSendBuf); + + (void)lwip_close(iSockNum); + close(fp); + + /* return from the function, file write failed */ + ulErrCode = TFTPC_FILEWRITE_ERROR; + goto err_handler; + } + + /* form the ACK packet for the DATA packet received */ + /* Go to the next packet no. */ + ulCurrBlk++; + + /* if the file is too big, exit */ + if (ulCurrBlk > TFTP_MAX_BLK_NUM) { + /* Send error packet to server */ + lwip_tftp_send_error(iSockNum, + TFTPC_PROTOCOL_USER_DEFINED, + "File is too big.", + &stServerAddr, pstSendBuf); + + (void)lwip_close(iSockNum); + close(fp); + LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_get_file_by_filename : Data block number exceeded max value\n")); + + ulErrCode = TFTPC_FILE_TOO_BIG; + goto err_handler; + } + } + +err_handler: + mem_free(pstSendBuf); + mem_free(pstRecvBuf); + mem_free(pszTempDestName); + return ulErrCode; +} + + +/* INTERFACE Function to put a file using filename + ulHostAddr: IP address of Host + szSrcFileName: Source file + szDestDirPath: Destination file path +*/ +u32_t lwip_tftp_put_file_by_filename(u32_t ulHostAddr, u16_t usTftpServPort, u8_t ucTftpTransMode, + s8_t *szSrcFileName, s8_t *szDestDirPath) +{ + u32_t ulSrcStrLen; + u32_t ulDestStrLen; + s32_t iSockNum = TFTP_NULL_INT32; + s32_t iErrCode; + u32_t ulErrCode; + u16_t usTempServPort; + TFTPC_PACKET_S *pstSendBuf = NULL; + u16_t usReadReq; + u32_t ulSize; + s8_t *pucBuffer = 0; + s8_t *szTempDestName = NULL; + + /*Initialize the block number*/ + u16_t usCurrBlk = 0; + struct sockaddr_in stServerAddr; + struct stat buffer; + s32_t fp = -1; + + /* Validate parameters */ + if ((szSrcFileName == NULL) || (szDestDirPath == NULL)) { + return TFTPC_INVALID_PARAVALUE; + } + + if ((ucTftpTransMode != TRANSFER_MODE_BINARY) && (ucTftpTransMode != TRANSFER_MODE_ASCII)) { + return TFTPC_INVALID_PARAVALUE; + } + + /*check IP address not within ( 1.0.0.0 - 126.255.255.255 ) + and ( 128.0.0.0 - 223.255.255.255 ) range.*/ + if (!(((ulHostAddr >= TFTPC_IP_ADDR_MIN) && + (ulHostAddr <= TFTPC_IP_ADDR_EX_RESV)) || + ((ulHostAddr >= TFTPC_IP_ADDR_CLASS_B) && + (ulHostAddr <= TFTPC_IP_ADDR_EX_CLASS_DE)))) { + return TFTPC_IP_NOT_WITHIN_RANGE; + } + + /* If Src filename is empty or exceeded max length */ + ulSrcStrLen = strlen((char *)szSrcFileName); + if ((ulSrcStrLen == 0) || (ulSrcStrLen >= TFTP_MAX_PATH_LENGTH)) { + return TFTPC_SRC_FILENAME_LENGTH_ERROR; + } + + /* Check if source file exists */ + if (stat((char *)szSrcFileName, &buffer) != 0) { + return TFTPC_FILE_NOT_EXIST; + } + + /* Check if the file is too big */ + if (buffer.st_size >= (off_t)(TFTP_MAX_BLK_NUM * TFTP_BLKSIZE)) { + return TFTPC_FILE_TOO_BIG; + } + + /* Check validity of destination path */ + ulDestStrLen = strlen((char *)szDestDirPath); + /* If dest path length exceeded max value */ + if (ulDestStrLen >= TFTP_MAX_PATH_LENGTH) { + return TFTPC_DEST_PATH_LENGTH_ERROR; + } + + pstSendBuf = (TFTPC_PACKET_S *)mem_malloc(sizeof(TFTPC_PACKET_S)); + if (pstSendBuf == NULL) { + return TFTPC_MEMALLOC_ERROR; + } + + /* First time intialize the buffer */ + (void)memset_s((void *)pstSendBuf, sizeof(TFTPC_PACKET_S), 0, sizeof(TFTPC_PACKET_S)); + + /* The destination path can only be one of the following: + 1. Only filename + 2. Relative path WITH filename + 3. Empty string + */ + if (ulDestStrLen != 0) { + /* If not empty string use the Destination path name */ + szTempDestName = szDestDirPath; + } else { + /* If destination directory is empty string use source filename + If given src filename is a relative path extract the file name + from the path */ + if ((strchr((char *)szSrcFileName, '/') != 0) || + (strchr((char *)szSrcFileName, '\\') != 0)) { + /* Move to the end of the src file path */ + szTempDestName = szSrcFileName + (ulSrcStrLen - 1); + + while (((*(szTempDestName - 1) != '/') && (*(szTempDestName - 1) != '\\')) && + (szTempDestName != szSrcFileName)) { + szTempDestName--; + } + } else { + /* If not a relative src path use the given src filename */ + szTempDestName = szSrcFileName; + } + } + + /* Create a socket and bind it to an available port number */ + ulErrCode = lwip_tftp_create_bind_socket(&iSockNum); + if (ulErrCode != EOK) { + /* Create and Bind socket failed */ + goto err_handler; + } + + if (usTftpServPort == 0) { + usTftpServPort = TFTPC_SERVER_PORT; + } + + usTempServPort = usTftpServPort; + + /* set server internet address */ + (void)memset_s(&stServerAddr, sizeof(stServerAddr), 0, sizeof(stServerAddr)); + stServerAddr.sin_family = AF_INET; + stServerAddr.sin_port = htons(usTempServPort); + stServerAddr.sin_addr.s_addr = htonl(ulHostAddr); + + /* Make request packet - TFTPC_OP_WRQ */ + ulSize = (u32_t)lwip_tftp_make_tftp_packet(TFTPC_OP_WRQ, + szTempDestName, + ucTftpTransMode, + pstSendBuf); + + ulErrCode = lwip_tftp_send_to_server(iSockNum, ulSize, + pstSendBuf, &stServerAddr); + if (ulErrCode != ERR_OK) { + /* Send to server error */ + (void)lwip_close(iSockNum); + + goto err_handler; + } + + /* Send the request packet */ + ulErrCode = lwip_tftp_inner_put_file(iSockNum, pstSendBuf, ulSize, + usCurrBlk, &stServerAddr); + if (ulErrCode != ERR_OK) { + /* Send request packet failed */ + (void)lwip_close(iSockNum); + + LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_put_file_by_filename : Failed to send request packet\n")); + + goto err_handler; + } + + /* Create buffer block size */ + pucBuffer = mem_malloc(TFTP_BLKSIZE); + if (pucBuffer == NULL) { + /* Memory allocation failed */ + lwip_tftp_send_error(iSockNum, + TFTPC_PROTOCOL_USER_DEFINED, + "Memory allocation failed.", + &stServerAddr, pstSendBuf); + + (void)lwip_close(iSockNum); + ulErrCode = TFTPC_MEMALLOC_ERROR; + goto err_handler; + } + + (void)memset_s((void *)pucBuffer, TFTP_BLKSIZE, 0, TFTP_BLKSIZE); + + fp = open((char *)szSrcFileName, O_RDONLY); + if (TFTP_NULL_INT32 == fp) { + /* If file could not be opened send error to server */ + lwip_tftp_send_error(iSockNum, + TFTPC_PROTOCOL_USER_DEFINED, + "File open error.", + &stServerAddr, pstSendBuf); + + (void)lwip_close(iSockNum); + close(fp); + mem_free(pucBuffer); + + ulErrCode = TFTPC_FILEOPEN_ERROR; + goto err_handler; + } + + iErrCode = read(fp, pucBuffer, TFTP_BLKSIZE); + if (iErrCode < 0) { + /* If failed to read from file */ + lwip_tftp_send_error(iSockNum, + TFTPC_PROTOCOL_USER_DEFINED, + "File read error.", + &stServerAddr, pstSendBuf); + + (void)lwip_close(iSockNum); + close(fp); + mem_free(pucBuffer); + + ulErrCode = TFTPC_FILEREAD_ERROR; + goto err_handler; + } + + /* Read from source file and send to server */ + /* To send empty packet to server when file is a 0 byte file */ + do { + if (((u32_t)usCurrBlk + 1) > TFTP_MAX_BLK_NUM) { + lwip_tftp_send_error(iSockNum, + TFTPC_PROTOCOL_USER_DEFINED, + "File is too big.", + &stServerAddr, pstSendBuf); + + (void)lwip_close(iSockNum); + close(fp); + mem_free(pucBuffer); + LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_put_file_by_filename : Data block number exceeded max value\n")); + + ulErrCode = TFTPC_FILE_TOO_BIG; + goto err_handler; + } + + /* Increment block number */ + usCurrBlk++; + + ulSize = (u32_t)iErrCode + TFTP_HDRSIZE; + + /* Form the DATA packet */ + usReadReq = (u16_t)TFTPC_OP_DATA; + pstSendBuf->usOpcode = htons(usReadReq); + pstSendBuf->u.stTFTP_Data.usBlknum = htons(usCurrBlk); + if (memcpy_s((void *)pstSendBuf->u.stTFTP_Data.ucDataBuf, TFTP_BLKSIZE, + (void *)pucBuffer, (u32_t)iErrCode) != EOK) { + (void)lwip_close(iSockNum); + close(fp); + mem_free(pucBuffer); + goto err_handler; + } + + ulErrCode = lwip_tftp_send_to_server(iSockNum, ulSize, + pstSendBuf, &stServerAddr); + if ((ulErrCode != ERR_OK) || (memset_s((void *)pucBuffer, TFTP_BLKSIZE, 0, TFTP_BLKSIZE) != 0)) { + (void)lwip_close(iSockNum); + close(fp); + mem_free(pucBuffer); + goto err_handler; + } + + /* Read a block from the file to buffer */ + iErrCode = read(fp, pucBuffer, TFTP_BLKSIZE); + if (iErrCode < 0) { + /*If failed to read from file*/ + lwip_tftp_send_error(iSockNum, TFTPC_PROTOCOL_USER_DEFINED, "File read error.", + &stServerAddr, pstSendBuf); + + (void)lwip_close(iSockNum); + close(fp); + mem_free(pucBuffer); + ulErrCode = TFTPC_FILEREAD_ERROR; + goto err_handler; + } + + /* Send the request packet */ + ulErrCode = lwip_tftp_inner_put_file(iSockNum, pstSendBuf, ulSize, + usCurrBlk, &stServerAddr); + if (ulErrCode != ERR_OK) { + /* Sending buffer contents failed */ + (void)lwip_close(iSockNum); + close(fp); + mem_free(pucBuffer); + LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_put_file_by_filename : Sending file to server failed\n")); + goto err_handler; + } + } while (ulSize == (TFTP_BLKSIZE + TFTP_HDRSIZE)); + + /* Transfer of data is finished */ + (void)lwip_close(iSockNum); + close(fp); + mem_free(pucBuffer); + + ulErrCode = ERR_OK; +err_handler: + mem_free(pstSendBuf); + return ulErrCode; +} + +/* Put file function + iSockNum: Socket ID + pstSendBuf: Packet to send to server + ulSendSize: Packet length + usCurrBlk: Current block number + pstServerAddr: Server address +*/ +u32_t lwip_tftp_inner_put_file(s32_t iSockNum, + TFTPC_PACKET_S *pstSendBuf, + u32_t ulSendSize, + u16_t usCurrBlk, + struct sockaddr_in *pstServerAddr) +{ + u32_t ulPktSize; + u32_t ulError; + s32_t iError; + int iRecvLen = 0; + socklen_t iFromAddrLen; + u32_t ulTotalTime = 0; + fd_set stReadfds; + struct sockaddr_in stFromAddr; + struct timeval stTimeout; + TFTPC_PACKET_S *pstRecvBuf = NULL; + u32_t ulIgnorePkt = 0; + u16_t usBlknum; + u32_t ulLoopCnt = 0; + + iFromAddrLen = sizeof(stFromAddr); + + pstRecvBuf = (TFTPC_PACKET_S *)mem_malloc(sizeof(TFTPC_PACKET_S)); + if (pstRecvBuf == NULL) { + return TFTPC_MEMALLOC_ERROR; + } + + /* First time intialize the buffer */ + (void)memset_s((void *)pstRecvBuf, sizeof(TFTPC_PACKET_S), 0, sizeof(TFTPC_PACKET_S)); + + /* Initialize from address to the server address at first */ + if (memcpy_s((void *)&stFromAddr, sizeof(struct sockaddr_in), + (void *)pstServerAddr, sizeof(stFromAddr)) != EOK) { + ulError = TFTPC_MEMCPY_FAILURE; + goto err_handler; + } + + for (;;) { + ulError = lwip_tftp_recv_from_server(iSockNum, &ulPktSize, + pstRecvBuf, &ulIgnorePkt, + pstServerAddr, pstSendBuf); + /* If select timeout occured */ + if (ulError == TFTPC_TIMEOUT_ERROR) { + ulTotalTime++; + if (ulTotalTime < TFTPC_MAX_SEND_REQ_ATTEMPTS) { + /*Max attempts not reached. Resend packet*/ + ulError = lwip_tftp_send_to_server(iSockNum, ulSendSize, + pstSendBuf, pstServerAddr); + if (ulError != ERR_OK) { + goto err_handler; + } + + continue; + } else { + /* return from the function, max attempts limit reached */ + ulError = TFTPC_TIMEOUT_ERROR; + goto err_handler; + } + } else if (ulError != ERR_OK) { + /* return from the function, RecvFromServer failed */ + goto err_handler; + } + + /* If Received packet from another server */ + if (ulIgnorePkt > 0) { + /* The packet that is received is to be ignored. + So continue without processing it. */ + ulIgnorePkt = 0; + continue; + } + + /* if this packet is unknown or incorrect packet */ + if (TFTPC_OP_ACK != ntohs(pstRecvBuf->usOpcode)) { + lwip_tftp_send_error(iSockNum, + TFTPC_PROTOCOL_PROTO_ERROR, + "Protocol error.", + pstServerAddr, pstSendBuf); + + LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_inner_put_file : Received pkt not Ack pkt\n")); + + ulError = TFTPC_PROTO_ERROR; + goto err_handler; + } + + ulTotalTime = 0; + + /* if the packet is acknowledge packet */ + usBlknum = ntohs(pstRecvBuf->u.usBlknum); + iRecvLen = (int)ulPktSize; + + /* If not correct block no. */ + if (usBlknum != usCurrBlk) { + /* we are not in sync now */ + /* reset any collected packets. */ + stTimeout.tv_sec = 1; + stTimeout.tv_usec = 0; + + FD_ZERO(&stReadfds); + FD_SET(iSockNum, &stReadfds); + + /* + Need to take care of timeout scenario in Select call. + Since the socket used is blocking, if select timeout occurs, + the following recvfrom will block indefinitely. + */ + iError = select((s32_t)(iSockNum + 1), &stReadfds, 0, 0, &stTimeout); + + /* Loop to get the last data packet from the receive buffer */ + while ((iError != -1) && (iError != 0)) { + ulLoopCnt++; + + /* MAX file size in TFTP is 32 MB. + Reason for keeping 75 here , is ((75*512=38400bytes)/1024) = 37MB. So the recv/Snd + Loop can receive the complete MAX message from the network. + */ + if (ulLoopCnt > TFTPC_MAX_WAIT_IN_LOOP) { + LWIP_DEBUGF(TFTP_DEBUG, + ("lwip_tftp_inner_put_file : unexpected packets are received repeatedly\n")); + ulError = TFTPC_PKT_SIZE_ERROR; + goto err_handler; + } + + FD_ZERO(&stReadfds); + FD_SET(iSockNum, &stReadfds); + iRecvLen = lwip_recvfrom(iSockNum, + (s8_t *)pstRecvBuf, + TFTP_PKTSIZE, 0, + (struct sockaddr *)&stFromAddr, + &iFromAddrLen); + if (TFTP_NULL_INT32 == iRecvLen) { + ulError = TFTPC_RECVFROM_ERROR; + goto err_handler; + } + + stTimeout.tv_sec = 1; + stTimeout.tv_usec = 0; + iError = select((s32_t)(iSockNum + 1), + &stReadfds, 0, 0, &stTimeout); + } + + /* If a new packet is not received then donot change the byte order + * as it has already been done + */ + /* If received packet size < minimum packet size */ + if (iRecvLen < TFTPC_FOUR) { + lwip_tftp_send_error(iSockNum, + TFTPC_PROTOCOL_PROTO_ERROR, + "Packet size < min packet size", + pstServerAddr, pstSendBuf); + + LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_inner_put_file : Received pkt not Ack pkt\n")); + + ulError = TFTPC_PKT_SIZE_ERROR; + goto err_handler; + } + + /* Check if the received packet is from correct server and from + correct port + */ + if ((stFromAddr.sin_addr.s_addr != pstServerAddr->sin_addr.s_addr) || + (pstServerAddr->sin_port != stFromAddr.sin_port)) { + /* This ACK packet is invalid. Just ignore it. */ + LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_inner_put_file : Received pkt from unknown server\n")); + continue; + } + + /* if this packet is not ACK packet */ + if (TFTPC_OP_ACK != ntohs(pstRecvBuf->usOpcode)) { + lwip_tftp_send_error(iSockNum, + TFTPC_PROTOCOL_PROTO_ERROR, + "Protocol error.", + pstServerAddr, pstSendBuf); + + LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_inner_put_file : Received pkt not Ack pkt\n")); + + ulError = TFTPC_PROTO_ERROR; + goto err_handler; + } + + usBlknum = ntohs(pstRecvBuf->u.usBlknum); + /* + * In this case we have received a duplicate ACK for data block. + * (ACK for this data block was aready received earlier) + * In this case we have usRecvBlkNum == (usNextBlkNum - 1). + * This could mean that: + * (i) last data packet that was sent was not received at server side + * (ii) Acknowledgement of peer side is delayed. + * + * In this case, this duplicate ACK will be ignored and return to the + * state machine to initiate a receive of this data packet. + */ + if ((usCurrBlk - 1) == usBlknum) { + /* This ACK packet is invalid. Just ignore it. */ + continue; + } + + /* Now check the block number with current block. + * If it is not the previous block and the current block, + * then it is an unexpected packet. + */ + if (usBlknum != usCurrBlk) { + lwip_tftp_send_error(iSockNum, + TFTPC_PROTOCOL_PROTO_ERROR, + "Received unexpected packet", + pstServerAddr, pstSendBuf); + + LWIP_DEBUGF(TFTP_DEBUG, + ("lwip_tftp_inner_put_file : Received DATA pkt no. %"S32_F"instead of pkt no. %"S32_F"\n", + usBlknum, usCurrBlk)); + + ulError = TFTPC_SYNC_FAILURE; + goto err_handler; + } + } + + ulError = ERR_OK; + goto err_handler; + } + +err_handler: + mem_free(pstRecvBuf); + return ulError; +} + +#ifdef TFTP_TO_RAWMEM +/* INTEFACE to get a file using filename + ulHostAddr - IP address of Host + szSrcFileName - Source file + szDestMemAddr - The target memory address in the client + + Example : + ulHostAddr = ntohl(inet_addr ("192.168.1.3")); + lwip_tftp_get_file_by_filename_to_rawmem(ulHostAddr, "/ramfs/vs_server.bin", memaddr, &filelen); +*/ +u32_t lwip_tftp_get_file_by_filename_to_rawmem(u32_t ulHostAddr, + u16_t usTftpServPort, + u8_t ucTftpTransMode, + s8_t *szSrcFileName, + s8_t *szDestMemAddr, + u32_t *ulFileLength) +{ + s32_t iSockNum = TFTP_NULL_INT32; + u32_t ulSrcStrLen; + u32_t lDestStrLen; + u32_t ulSize; + u32_t ulRecvSize = TFTP_NULL_UINT32; + s32_t iErrCode; + u32_t ulErrCode; + u16_t usReadReq; + u16_t usTempServPort; + u32_t ulCurrBlk = 1; + u32_t ulResendPkt = 0; /* Resend the previous packet */ + u32_t ulIgnorePkt = 0; /* Ignore received packet */ + u32_t ulTotalTime = 0; + + TFTPC_PACKET_S *pstSendBuf = NULL; + TFTPC_PACKET_S *pstRecvBuf = NULL; + struct sockaddr_in stServerAddr; + u32_t ulMemOffset = 0; + + /* Validate the parameters */ + if ((szSrcFileName == NULL) || (szDestMemAddr == NULL) || (*ulFileLength == 0)) { + return TFTPC_INVALID_PARAVALUE; + } + + if ((ucTftpTransMode != TRANSFER_MODE_BINARY) && (ucTftpTransMode != TRANSFER_MODE_ASCII)) { + return TFTPC_INVALID_PARAVALUE; + } + + /* check IP address not within ( 1.0.0.0 - 126.255.255.255 ) + and ( 128.0.0.0 - 223.255.255.255 ) range. */ + if (!(((ulHostAddr >= TFTPC_IP_ADDR_MIN) && + (ulHostAddr <= TFTPC_IP_ADDR_EX_RESV)) || + ((ulHostAddr >= TFTPC_IP_ADDR_CLASS_B) && + (ulHostAddr <= TFTPC_IP_ADDR_EX_CLASS_DE)))) { + return TFTPC_IP_NOT_WITHIN_RANGE; + } + + /*Check validity of source filename*/ + ulSrcStrLen = strlen(szSrcFileName); + if ((ulSrcStrLen == 0) || (ulSrcStrLen >= TFTP_MAX_PATH_LENGTH)) { + return TFTPC_SRC_FILENAME_LENGTH_ERROR; + } + + pstSendBuf = (TFTPC_PACKET_S *)mem_malloc(sizeof(TFTPC_PACKET_S)); + if (pstSendBuf == NULL) { + return TFTPC_MEMALLOC_ERROR; + } + + pstRecvBuf = (TFTPC_PACKET_S *)mem_malloc(sizeof(TFTPC_PACKET_S)); + if (pstRecvBuf == NULL) { + mem_free(pstSendBuf); + return TFTPC_MEMALLOC_ERROR; + } + + /* First time initialize the buffers */ + (void)memset_s((void *)pstSendBuf, sizeof(TFTPC_PACKET_S), 0, sizeof(TFTPC_PACKET_S)); + (void)memset_s((void *)pstRecvBuf, sizeof(TFTPC_PACKET_S), 0, sizeof(TFTPC_PACKET_S)); + + ulErrCode = lwip_tftp_create_bind_socket(&iSockNum); + if (ulErrCode != EOK) { + goto err_handler; + } + + if (usTftpServPort == 0) { + usTftpServPort = TFTPC_SERVER_PORT; + } + + usTempServPort = usTftpServPort; + + /* set server IP address */ + (void)memset_s(&stServerAddr, sizeof(stServerAddr), 0, sizeof(stServerAddr)); + stServerAddr.sin_family = AF_INET; + stServerAddr.sin_port = htons(usTempServPort); + stServerAddr.sin_addr.s_addr = htonl(ulHostAddr); + + /* Make a request packet - TFTPC_OP_RRQ */ + ulSize = (u32_t)lwip_tftp_make_tftp_packet(TFTPC_OP_RRQ, szSrcFileName, (u32_t)ucTftpTransMode, pstSendBuf); + ulErrCode = lwip_tftp_send_to_server(iSockNum, ulSize, pstSendBuf, &stServerAddr); + if (ulErrCode != ERR_OK) { + /* send to server failed */ + (void)lwip_close(iSockNum); + goto err_handler; + } + + for (;;) { + if (ulIgnorePkt > 0) { + ulIgnorePkt = 0; + } + + ulErrCode = lwip_tftp_recv_from_server(iSockNum, &ulRecvSize, pstRecvBuf, &ulIgnorePkt, + &stServerAddr, pstSendBuf); + /* If select timeout occured */ + if (ulErrCode == TFTPC_TIMEOUT_ERROR) { + ulTotalTime++; + if (ulTotalTime < TFTPC_MAX_SEND_REQ_ATTEMPTS) { + /* Max attempts not reached. Resend packet */ + ulErrCode = lwip_tftp_send_to_server(iSockNum, ulSize, + pstSendBuf, &stServerAddr); + if (ulErrCode != ERR_OK) { + (void)lwip_close(iSockNum); + goto err_handler; + } + + continue; + } else { + /* return from the function, max attempts limit reached */ + (void)lwip_close(iSockNum); + ulErrCode = TFTPC_TIMEOUT_ERROR; + goto err_handler; + } + } else if (ulErrCode != ERR_OK) { + (void)lwip_close(iSockNum); + goto err_handler; + } + + /* Now we have receive block from different server. */ + if (ulIgnorePkt > 0) { + /*Continue without processing this block. */ + continue; + } + + /* if this packet is unkonwn or incorrect packet */ + if (ntohs (pstRecvBuf->usOpcode) != TFTPC_OP_DATA) { + /* Send error packet to server */ + lwip_tftp_send_error(iSockNum, + TFTPC_PROTOCOL_PROTO_ERROR, + "Protocol error.", + &stServerAddr, pstSendBuf); + + (void)lwip_close(iSockNum); + + LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_get_file_by_filename : Received pkt not DATA pkt\n")); + + ulErrCode = TFTPC_PROTO_ERROR; + goto err_handler; + } + + /* Now the number of tries will be reset. */ + ulTotalTime = 0; + + /* Validate received DATA packet. */ + ulErrCode = lwip_tftp_validate_data_pkt(iSockNum, &ulRecvSize, + pstRecvBuf, (u16_t)ulCurrBlk, + &ulResendPkt, + &stServerAddr); + if (ulErrCode != ERR_OK) { + /* Send Error packet to server */ + if (ulErrCode != TFTPC_RECVFROM_ERROR) { + lwip_tftp_send_error(iSockNum, + TFTPC_PROTOCOL_PROTO_ERROR, + "Received unexpected packet", + &stServerAddr, pstSendBuf); + } + + (void)lwip_close(iSockNum); + + goto err_handler; + } + + /* Received previous data block again. Resend last packet */ + if (ulResendPkt > 0) { + /* Now set ulResendPkt to 0 to send the last packet. */ + ulResendPkt = 0; + ulErrCode = lwip_tftp_send_to_server(iSockNum, ulSize, + pstSendBuf, &stServerAddr); + if (ulErrCode != ERR_OK) { + (void)lwip_close(iSockNum); + + goto err_handler; + } + + /* Continue in loop to send last packet again. */ + continue; + } + + /* Get the size of the data block received */ + ulRecvSize -= TFTP_HDRSIZE; + + /* Check if the size of the received data block > max size */ + if (ulRecvSize > TFTP_BLKSIZE) { + /* Send Error packet to server */ + lwip_tftp_send_error(iSockNum, + TFTPC_PROTOCOL_PROTO_ERROR, + "Packet size > max size", + &stServerAddr, pstSendBuf); + + (void)lwip_close(iSockNum); + + LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_get_file_by_filename : Packet size > max size\n")); + + ulErrCode = TFTPC_PKT_SIZE_ERROR; + goto err_handler; + } + + usReadReq = (u16_t)TFTPC_OP_ACK; + pstSendBuf->usOpcode = htons(usReadReq); + pstSendBuf->u.usBlknum = htons((u16_t)ulCurrBlk); + ulSize = TFTP_HDRSIZE; + + if (ulRecvSize != TFTP_BLKSIZE) { + (void)lwip_tftp_send_to_server(iSockNum, ulSize, + pstSendBuf, &stServerAddr); + + /* If the received packet has only header and do not have payload, the return failure */ + if (ulRecvSize != 0) { + /* memcopy filed */ + if (*ulFileLength < (ulMemOffset + ulRecvSize)) { + ulErrCode = TFTPC_MEMCPY_FAILURE; + (void)lwip_close(iSockNum); + *ulFileLength = ulMemOffset; + goto err_handler; + } + /* copy the last packet to the memory */ + if (memcpy_s(szDestMemAddr + ulMemOffset, TFTP_MAX_BLK_NUM * TFTP_BLKSIZE, + (void *)pstRecvBuf->u.stTFTP_Data.ucDataBuf, (size_t)ulRecvSize) != EOK) { + ulErrCode = TFTPC_MEMCPY_FAILURE; + (void)lwip_close(iSockNum); + *ulFileLength = ulMemOffset; + goto err_handler; + } + ulMemOffset += ulRecvSize; + } + + /* Now free allocated resourdes and return, + data block receiving is already completed */ + (void)lwip_close(iSockNum); + ulErrCode = ERR_OK; + *ulFileLength = ulMemOffset; + goto err_handler; + } + + ulErrCode = lwip_tftp_send_to_server(iSockNum, ulSize, + pstSendBuf, &stServerAddr); + if (ulErrCode != ERR_OK) { + (void)lwip_close(iSockNum); + goto err_handler; + } + + /* memcopy filed */ + if (*ulFileLength < ulRecvSize * ulCurrBlk) { + ulErrCode = TFTPC_MEMCPY_FAILURE; + (void)lwip_close(iSockNum); + *ulFileLength = ulMemOffset; + goto err_handler; + } + if (memcpy_s(szDestMemAddr + ulMemOffset, TFTP_MAX_BLK_NUM * TFTP_BLKSIZE, + (void *)pstRecvBuf->u.stTFTP_Data.ucDataBuf, (size_t)ulRecvSize) != EOK) { + ulErrCode = TFTPC_MEMCPY_FAILURE; + (void)lwip_close(iSockNum); + *ulFileLength = ulMemOffset; + goto err_handler; + } + + ulMemOffset += ulRecvSize; + /* form the ACK packet for the DATA packet received */ + /* Go to the next packet no. */ + ulCurrBlk++; + /* if the file is too big, exit */ + if (ulCurrBlk > TFTP_MAX_BLK_NUM) { + /* Send error packet to server */ + lwip_tftp_send_error(iSockNum, + TFTPC_PROTOCOL_USER_DEFINED, + "File is too big.", + &stServerAddr, pstSendBuf); + + (void)lwip_close(iSockNum); + + LWIP_DEBUGF(TFTP_DEBUG, ("lwip_tftp_get_file_by_filename : Data block number exceeded max value\n")); + + ulErrCode = TFTPC_FILE_TOO_BIG; + goto err_handler; + } + } + +err_handler: + mem_free(pstSendBuf); + mem_free(pstRecvBuf); + return ulErrCode; +} +#endif + +#endif /* LOSCFG_NET_LWIP_SACK_TFTP */ +#endif /* LWIP_TFTP */ diff --git a/net/lwip-2.1/porting/include/lwip/dhcp.h b/net/lwip-2.1/porting/include/lwip/dhcp.h index 54938fb9..b6b37ad7 100755 --- a/net/lwip-2.1/porting/include/lwip/dhcp.h +++ b/net/lwip-2.1/porting/include/lwip/dhcp.h @@ -32,13 +32,32 @@ #ifndef _LWIP_PORTING_DHCP_H_ #define _LWIP_PORTING_DHCP_H_ +#include + +#if LWIP_DHCPS +#define DHCP_OPTION_IDX_SERVER_ID DHCP_OPTION_IDX_SERVER_ID, \ + DHCP_OPTION_IDX_REQUESTED_IP +#endif #include_next +#if LWIP_DHCPS +#undef DHCP_OPTION_IDX_SERVER_ID +#endif + #include // For DHCP_STATE_BOUND, DHCP_DISCOVER etc. by `mac/common/mac_data.c' #ifdef __cplusplus extern "C" { #endif +#if LWIP_DHCPS +#define LWIP_HOOK_DHCP_PARSE_OPTION(netif, dhcp, state, msg, msg_type, option, len, pbuf, offset) \ + LWIP_UNUSED_ARG(msg); \ + break; \ + case (DHCP_OPTION_REQUESTED_IP): \ + LWIP_ERROR("len == 4", len == 4, return ERR_VAL); \ + decode_idx = DHCP_OPTION_IDX_REQUESTED_IP; +#endif + err_t dhcp_is_bound(struct netif *netif); #ifdef __cplusplus diff --git a/net/lwip-2.1/porting/include/lwip/lwipopts.h b/net/lwip-2.1/porting/include/lwip/lwipopts.h index 8d446171..4baddb68 100755 --- a/net/lwip-2.1/porting/include/lwip/lwipopts.h +++ b/net/lwip-2.1/porting/include/lwip/lwipopts.h @@ -32,6 +32,7 @@ #ifndef _LWIP_PORTING_LWIPOPTS_H_ #define _LWIP_PORTING_LWIPOPTS_H_ +#include "menuconfig.h" // lwIP debug options, comment the ones you don't want #if LWIP_DEBUG @@ -215,6 +216,9 @@ #define LWIP_CONFIG_NUM_SOCKETS 128 #define IP_REASS_MAX_MEM_SIZE (MEM_SIZE / 4) +// Options for enhancement code, same for old lwipopts.h +#define LWIP_NETIF_PROMISC 1 +#define LWIP_TFTP LOSCFG_NET_LWIP_SACK_TFTP #define LWIP_DHCPS 1 #define LWIP_ENABLE_NET_CAPABILITY 1 diff --git a/net/lwip-2.1/porting/include/lwip/netif.h b/net/lwip-2.1/porting/include/lwip/netif.h index 51a5fbf3..06774ddf 100755 --- a/net/lwip-2.1/porting/include/lwip/netif.h +++ b/net/lwip-2.1/porting/include/lwip/netif.h @@ -35,16 +35,23 @@ #include // For IFNAMSIZ/IF_NAMESIZE and `struct ifreq', by `lwip/netif.h' and `api/sockets.c' #include // For IP_OFFMASK, by `core/ipv4/ip4_frag.c' -struct dhcps; +#define netif_find netifapi_netif_find_by_name + +#if LWIP_DHCPS +#define LWIP_NETIF_CLIENT_DATA_INDEX_DHCP LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, \ + LWIP_NETIF_CLIENT_DATA_INDEX_DHCPS +#endif #define linkoutput linkoutput; \ void (*drv_send)(struct netif *netif, struct pbuf *p); \ u8_t (*drv_set_hwaddr)(struct netif *netif, u8_t *addr, u8_t len); \ void (*drv_config)(struct netif *netif, u32_t config_flags, u8_t setBit); \ - struct dhcps *dhcps; \ char full_name[IFNAMSIZ]; \ u16_t link_layer_type #include_next #undef linkoutput +#if LWIP_DHCPS +#undef LWIP_NETIF_CLIENT_DATA_INDEX_DHCP +#endif #include // For ETHARP_HWADDR_LEN, by `hieth-sf src/interface.c' and `wal/wal_net.c' @@ -64,9 +71,7 @@ err_t driverif_init(struct netif *netif); void driverif_input(struct netif *netif, struct pbuf *p); #ifndef __LWIP__ -struct netif *netifapi_netif_find_by_name(const char *name); -#define PF_PKT_SUPPORT 1 // For netif->drv_config -#define netif_find(name) netifapi_netif_find_by_name(name) +#define PF_PKT_SUPPORT LWIP_NETIF_PROMISC #define netif_add(a, b, c, d) netif_add(a, b, c, d, (a)->state, driverif_init, tcpip_input) #else /* __LWIP__ */ #define netif_get_name(netif) ((netif)->full_name) diff --git a/net/lwip-2.1/porting/include/lwip/netifapi.h b/net/lwip-2.1/porting/include/lwip/netifapi.h index e88c78f0..c6a35e74 100755 --- a/net/lwip-2.1/porting/include/lwip/netifapi.h +++ b/net/lwip-2.1/porting/include/lwip/netifapi.h @@ -45,6 +45,7 @@ err_t netifapi_dhcps_stop(struct netif *netif); #define netifapi_dhcp_is_bound(n) netifapi_netif_common(n, NULL, dhcp_is_bound) void netifapi_netif_rmv_ip6_address(struct netif *netif, ip_addr_t *ipaddr); +struct netif *netifapi_netif_find_by_name(const char *name); #ifndef __LWIP__ #define netifapi_netif_add(a, b, c, d) netifapi_netif_add(a, b, c, d, (a)->state, driverif_init, tcpip_input) diff --git a/net/lwip-2.1/porting/src/driverif.c b/net/lwip-2.1/porting/src/driverif.c index 6eb5201d..a4441015 100755 --- a/net/lwip-2.1/porting/src/driverif.c +++ b/net/lwip-2.1/porting/src/driverif.c @@ -44,7 +44,6 @@ #define link_rx_drop cachehit #define link_rx_overrun cachehit -#define NETIF_NAME_LEN 2 #define LWIP_STATIC static #ifndef LWIP_NETIF_IFINDEX_MAX_EX @@ -57,6 +56,9 @@ driverif_init_ifname(struct netif *netif) struct netif *tmpnetif = NULL; const char *prefix = (netif->link_layer_type == WIFI_DRIVER_IF) ? "wlan" : "eth"; + netif->name[0] = prefix[0]; + netif->name[1] = prefix[1]; + for (int i = 0; i < LWIP_NETIF_IFINDEX_MAX_EX; ++i) { if (snprintf_s(netif->full_name, sizeof(netif->full_name), sizeof(netif->full_name) - 1, "%s%d", prefix, i) < 0) { @@ -140,7 +142,7 @@ driverif_input(struct netif *netif, struct pbuf *p) #endif #else u16_t ethhdr_type; - struct eth_hdr* ethhdr = NULL; + struct eth_hdr *ethhdr = NULL; #endif err_t ret = ERR_VAL; @@ -241,7 +243,6 @@ err_t driverif_init(struct netif *netif) { u16_t link_layer_type; - err_t ret; if (netif == NULL) { return ERR_IF; @@ -262,17 +263,7 @@ driverif_init(struct netif *netif) #if LWIP_NETIF_HOSTNAME /* Initialize interface hostname */ -#if LOSCFG_NET_LWIP_SACK_2_0 - if (strncpy_s(netif->hostname, NETIF_HOSTNAME_MAX_LEN, - LWIP_NETIF_HOSTNAME_DEFAULT, NETIF_HOSTNAME_MAX_LEN - 1) == EOK) { - netif->hostname[NETIF_HOSTNAME_MAX_LEN - 1] = '\0'; - } else { - LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_init: hostname %s in invalid\n", LWIP_NETIF_HOSTNAME_DEFAULT)); - netif->hostname[0] = '\0'; - } -#else netif->hostname = LWIP_NETIF_HOSTNAME_DEFAULT; -#endif #endif /* LWIP_NETIF_HOSTNAME */ /* @@ -285,21 +276,6 @@ driverif_init(struct netif *netif) netif->output = etharp_output; netif->linkoutput = driverif_output; - if (link_layer_type == ETHERNET_DRIVER_IF) { - ret = memcpy_s(netif->name, sizeof(netif->name), "et", NETIF_NAME_LEN); - } else { - ret = memcpy_s(netif->name, sizeof(netif->name), "wl", NETIF_NAME_LEN); - } - if (ret != EOK) { -#if LWIP_NETIF_HOSTNAME -#if LOSCFG_NET_LWIP_SACK_2_0 - netif->hostname[0] = '\0'; -#else - netif->hostname = NULL; -#endif -#endif - return ERR_IF; - } /* init the netif's full name */ driverif_init_ifname(netif); @@ -309,30 +285,30 @@ driverif_init(struct netif *netif) /* device capabilities */ /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | -#if DRIVER_STATUS_CHECK - NETIF_FLAG_DRIVER_RDY | -#endif -#if LWIP_IGMP - NETIF_FLAG_IGMP | -#endif + #if DRIVER_STATUS_CHECK + NETIF_FLAG_DRIVER_RDY | + #endif + #if LWIP_IGMP + NETIF_FLAG_IGMP | + #endif -/** -@page RFC-2710 RFC-2710 -@par Compliant Sections -Section 5. Node State Transition Diagram -@par Behavior Description -MLD messages are sent for multicast addresses whose scope is 2 -(link-local), including Solicited-Node multicast addresses.\n -Behavior:Stack will send MLD6 report /Done to solicited node multicast address -if the LWIP_MLD6_ENABLE_MLD_ON_DAD is enabled. By default, this is disabled. -*/ -/* Enable sending MLD report /done for solicited address during neighbour discovery */ -#if LWIP_IPV6 && LWIP_IPV6_MLD -#if LWIP_MLD6_ENABLE_MLD_ON_DAD - NETIF_FLAG_MLD6 | -#endif /* LWIP_MLD6_ENABLE_MLD_ON_DAD */ -#endif - NETIF_FLAG_LINK_UP; + /** + @page RFC-2710 RFC-2710 + @par Compliant Sections + Section 5. Node State Transition Diagram + @par Behavior Description + MLD messages are sent for multicast addresses whose scope is 2 + (link-local), including Solicited-Node multicast addresses.\n + Behavior:Stack will send MLD6 report /Done to solicited node multicast address + if the LWIP_MLD6_ENABLE_MLD_ON_DAD is enabled. By default, this is disabled. + */ + /* Enable sending MLD report /done for solicited address during neighbour discovery */ + #if LWIP_IPV6 && LWIP_IPV6_MLD + #if LWIP_MLD6_ENABLE_MLD_ON_DAD + NETIF_FLAG_MLD6 | + #endif /* LWIP_MLD6_ENABLE_MLD_ON_DAD */ + #endif + NETIF_FLAG_LINK_UP; #if DRIVER_STATUS_CHECK netif->waketime = -1; diff --git a/net/lwip-2.1/porting/src/fixme.c b/net/lwip-2.1/porting/src/fixme.c deleted file mode 100755 index e7b1268f..00000000 --- a/net/lwip-2.1/porting/src/fixme.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. - * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be used - * to endorse or promote products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include - -err_t dhcp_is_bound(struct netif *netif) -{ - return (netif_dhcp_data(netif) ? (netif_dhcp_data(netif)->state == DHCP_STATE_BOUND) ? ERR_OK : ERR_INPROGRESS : ERR_ARG); -} - -#if (LWIP_CHKSUM_ALGORITHM == 4) /* version #4, asm based */ -#include "in_cksum.h" -u16_t lwip_standard_chksum(const void *dataptr, int len) -{ - return ~(u16_t)(in_cksum(dataptr, len)); -} -#endif diff --git a/net/lwip-2.1/porting/src/sockets.c b/net/lwip-2.1/porting/src/sockets.c index 29f25598..4b6627e7 100755 --- a/net/lwip-2.1/porting/src/sockets.c +++ b/net/lwip-2.1/porting/src/sockets.c @@ -31,7 +31,7 @@ #include #include -#include +#include #if LWIP_ENABLE_NET_CAPABILITY #include "capability_type.h" @@ -39,8 +39,6 @@ #define BIND_SERVICE_CAP_MIN_PORT 1024 #endif -#define netif_find netifapi_netif_find_by_name - #define IOCTL_CMD_CASE_HANDLER() \ { \ err_t err; \ @@ -86,7 +84,8 @@ int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen) return lwip_bind_wrap(s, name, namelen); } -static ssize_t lwip_sendto_wrap(int s, const void *dataptr, size_t size, int flags, const struct sockaddr *to, socklen_t tolen); +static ssize_t lwip_sendto_wrap(int s, const void *dataptr, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen); ssize_t lwip_sendto(int s, const void *dataptr, size_t size, int flags, const struct sockaddr *to, socklen_t tolen) { return lwip_sendto_wrap(s, dataptr, size, flags, to, tolen); @@ -233,12 +232,12 @@ static int lwip_bind_wrap(int s, const struct sockaddr *name, socklen_t namelen) } static ssize_t lwip_sendto_wrap(int s, const void *dataptr, size_t size, int flags, - const struct sockaddr *to, socklen_t tolen) + const struct sockaddr *to, socklen_t tolen) { #if LWIP_ENABLE_NET_CAPABILITY if (to && ((to->sa_family == AF_INET && tolen >= sizeof(struct sockaddr_in)) || - (to->sa_family == AF_INET6 && tolen >= sizeof(struct sockaddr_in6)))) { + (to->sa_family == AF_INET6 && tolen >= sizeof(struct sockaddr_in6)))) { ip_addr_t ipaddr; u16_t port; @@ -372,7 +371,6 @@ int get_unused_socket_num(void) // Options for lwip ioctl #define LWIP_IOCTL_ROUTE 1 #define LWIP_IOCTL_IF 1 -#define LWIP_NETIF_PROMISC 1 #define LWIP_NETIF_ETHTOOL 0 #define LWIP_IOCTL_IPV6DPCTD 0 #undef LWIP_IPV6_DUP_DETECT_ATTEMPTS @@ -764,7 +762,7 @@ static u8_t lwip_ioctl_internal_SIOCSIFNETMASK(struct ifreq *ifr) loc_netif = loc_netif->next; } -#if LWIP_DHCP // LWIP_DHCP +#if LWIP_DHCP if ((netif_dhcp_data(netif) != NULL) && (netif_dhcp_data(netif)->state != DHCP_STATE_OFF)) { (void)netif_dhcp_off(netif); diff --git a/net/lwip-2.1/porting/src/sys_arch.c b/net/lwip-2.1/porting/src/sys_arch.c index da8d282d..e591e8c2 100755 --- a/net/lwip-2.1/porting/src/sys_arch.c +++ b/net/lwip-2.1/porting/src/sys_arch.c @@ -46,6 +46,7 @@ static u32_t lwprot_thread = LOS_ERRNO_TSK_ID_INVALID; static int lwprot_count = 0; #endif /* LOSCFG_KERNEL_SMP == YES */ +#define ROUND_UP_DIV(val, div) (((val) + (div) - 1) / (div)) /** * Thread and System misc @@ -59,11 +60,11 @@ sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, /* Create host Task */ task.pfnTaskEntry = (TSK_ENTRY_FUNC)thread; - task.uwStackSize = stackSize; + task.uwStackSize = stackSize; task.pcName = (char *)name; task.usTaskPrio = prio; task.auwArgs[0] = (UINTPTR)arg; - task.uwResved = LOS_TASK_STATUS_DETACHED; + task.uwResved = LOS_TASK_STATUS_DETACHED; ret = LOS_TaskCreate(&taskID, &task); if (ret != LOS_OK) { LWIP_DEBUGF(SYS_DEBUG, ("sys_thread_new: LOS_TaskCreate error %u\n", ret)); @@ -84,9 +85,17 @@ void sys_init(void) u32_t sys_now(void) { /* Lwip docs mentioned like wraparound is not a problem in this funtion */ - return (u32_t)(((double)LOS_TickCountGet() * OS_SYS_MS_PER_SECOND) / LOSCFG_BASE_CORE_TICK_PER_SECOND); + return (u32_t)((LOS_TickCountGet() * OS_SYS_MS_PER_SECOND) / LOSCFG_BASE_CORE_TICK_PER_SECOND); } +#if (LWIP_CHKSUM_ALGORITHM == 4) /* version #4, asm based */ +#include "in_cksum.h" +u16_t lwip_standard_chksum(const void *dataptr, int len) +{ + return ~(u16_t)(in_cksum(dataptr, len)); +} +#endif + /** * Protector @@ -140,7 +149,7 @@ void sys_arch_unprotect(sys_prot_t pval) err_t sys_mbox_new(sys_mbox_t *mbox, int size) { CHAR qName[] = "lwIP"; - UINT32 ret = LOS_QueueCreate(qName, (UINT16)size, mbox, 0, sizeof(void*)); + UINT32 ret = LOS_QueueCreate(qName, (UINT16)size, mbox, 0, sizeof(void *)); switch (ret) { case LOS_OK: return ERR_OK; @@ -184,8 +193,8 @@ err_t sys_mbox_trypost_fromisr(sys_mbox_t *mbox, void *msg); u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeoutMs) { void *ignore = 0; /* if msg==NULL, the fetched msg should be dropped */ - UINT64 tick = ((UINT64)timeoutMs * LOSCFG_BASE_CORE_TICK_PER_SECOND + OS_SYS_MS_PER_SECOND - 1) / OS_SYS_MS_PER_SECOND; - UINT32 ret = LOS_QueueRead(*mbox, msg ? msg : &ignore, sizeof(void*), tick ? (UINT32)tick : LOS_WAIT_FOREVER); + UINT64 tick = ROUND_UP_DIV((UINT64)timeoutMs * LOSCFG_BASE_CORE_TICK_PER_SECOND, OS_SYS_MS_PER_SECOND); + UINT32 ret = LOS_QueueRead(*mbox, msg ? msg : &ignore, sizeof(void *), tick ? (UINT32)tick : LOS_WAIT_FOREVER); switch (ret) { case LOS_OK: return ERR_OK; @@ -202,7 +211,7 @@ u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeoutMs) u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) { void *ignore = 0; /* if msg==NULL, the fetched msg should be dropped */ - UINT32 ret = LOS_QueueRead(*mbox, msg ? msg : &ignore, sizeof(void*), 0); + UINT32 ret = LOS_QueueRead(*mbox, msg ? msg : &ignore, sizeof(void *), 0); switch (ret) { case LOS_OK: return ERR_OK; @@ -255,7 +264,7 @@ void sys_sem_signal(sys_sem_t *sem) u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeoutMs) { - UINT64 tick = ((UINT64)timeoutMs * LOSCFG_BASE_CORE_TICK_PER_SECOND + OS_SYS_MS_PER_SECOND - 1) / OS_SYS_MS_PER_SECOND; + UINT64 tick = ROUND_UP_DIV((UINT64)timeoutMs * LOSCFG_BASE_CORE_TICK_PER_SECOND, OS_SYS_MS_PER_SECOND); UINT32 ret = LOS_SemPend(*sem, tick ? (UINT32)tick : LOS_WAIT_FOREVER); // timeoutMs 0 means wait forever switch (ret) { case LOS_OK: