提交 8122da71 编写于 作者: O openharmony_ci 提交者: Gitee

!11 修复tftp功能,重构部分lwIP移植代码

Merge pull request !11 from Caoruihong/caoruihong_20200924094756
...@@ -44,7 +44,7 @@ LOCAL_FLAGS += $(LOCAL_INCLUDE) ...@@ -44,7 +44,7 @@ LOCAL_FLAGS += $(LOCAL_INCLUDE)
LOCAL_SRCS := $(wildcard porting/src/*.c $(LWIPNOAPPSFILES)) LOCAL_SRCS := $(wildcard porting/src/*.c $(LWIPNOAPPSFILES))
LOCAL_SRCS += $(wildcard enhancement/src/*.c) 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)/core/ipv4/etharp.c, $(LOCAL_SRCS))
LOCAL_SRCS := $(filter-out $(LWIPDIR)/api/sockets.c, $(LOCAL_SRCS)) LOCAL_SRCS := $(filter-out $(LWIPDIR)/api/sockets.c, $(LOCAL_SRCS))
......
/*
* 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
...@@ -29,8 +29,8 @@ ...@@ -29,8 +29,8 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef LWIP_API_SHELL_H #ifndef LWIP_HDR_API_SHELL_H
#define LWIP_API_SHELL_H #define LWIP_HDR_API_SHELL_H
#include "arch/cc.h" #include "arch/cc.h"
#include "lwip/opt.h" #include "lwip/opt.h"
...@@ -58,6 +58,4 @@ void netstat_internal(void *ctx); ...@@ -58,6 +58,4 @@ void netstat_internal(void *ctx);
} }
#endif #endif
#endif /* LWIP_HDR_API_SHELL_H */
#endif
...@@ -63,16 +63,6 @@ extern "C" { ...@@ -63,16 +63,6 @@ extern "C" {
err_t dhcps_start(struct netif *netif, const char *start_ip, u16_t ip_num); err_t dhcps_start(struct netif *netif, const char *start_ip, u16_t ip_num);
void dhcps_stop(struct netif *netif); 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 #if defined (__cplusplus) && __cplusplus
} }
......
...@@ -29,17 +29,12 @@ ...@@ -29,17 +29,12 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef LITEOS_A_FIXME_H #ifndef LWIP_HDR_FIXME_H
#define LITEOS_A_FIXME_H #define LWIP_HDR_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
#include "lwip/opt.h" #include "lwip/opt.h"
#include "netif/etharp.h"
#if LWIP_ENABLE_LOS_SHELL_CMD #include "lwip/netif.h"
#define link_rx_drop cachehit #define link_rx_drop cachehit
#define link_tx_drop cachehit #define link_tx_drop cachehit
...@@ -51,61 +46,56 @@ ...@@ -51,61 +46,56 @@
#define ip_rx_bytes cachehit #define ip_rx_bytes cachehit
#define ip_tx_bytes cachehit #define ip_tx_bytes cachehit
#define LWIP_STATIC static #define DUP_ARP_DETECT_TIME 2000 /* 2 seconds period */
#define SYS_ARCH_ERROR SYS_ARCH_TIMEOUT #define SOF_BINDNONUNICAST 0x0800U /* socket has bind to a non unicast */
#define NETCONN_PKT_RAW 0x80
#include "netif/etharp.h" #define SYS_ARCH_ERROR SYS_ARCH_TIMEOUT
#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_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 #define ip_addr_set_val(dest, src) do { \
IP_SET_TYPE_VAL(*dest, IP_GET_TYPE(src)); \
u32_t lwip_tftp_get_file_by_filename(u32_t ulHostAddr, if(IP_IS_V6_VAL(*(src))) { \
u16_t usTftpServPort, ip6_addr_set(ip_2_ip6(dest), ip_2_ip6(src)); \
u8_t ucTftpTransMode, } else { \
s8_t *szSrcFileName, ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); \
s8_t *szDestDirPath); } \
} while (0)
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_ismulticast_val(ipaddr) ((IP_IS_V6_VAL(*ipaddr)) ? \ #define ip_addr_ismulticast_val(ipaddr) ((IP_IS_V6_VAL(*ipaddr)) ? \
ip6_addr_ismulticast(ip_2_ip6(ipaddr)) : \ ip6_addr_ismulticast(ip_2_ip6(ipaddr)) : \
ip4_addr_ismulticast(ip_2_ip4(ipaddr))) ip4_addr_ismulticast(ip_2_ip4(ipaddr)))
#define ip_addr_isbroadcast_val(ipaddr, netif) ((IP_IS_V6_VAL(*ipaddr)) ? \ #define ip_addr_isbroadcast_val(ipaddr, netif) ((IP_IS_V6_VAL(*ipaddr)) ? \
0 : \ 0 : \
ip4_addr_isbroadcast(ip_2_ip4(ipaddr), netif)) 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))) ? \ #define ip_addr_netcmp_val(addr1, addr2, mask) ((IP_IS_V6_VAL(*(addr1)) && IP_IS_V6_VAL(*(addr2))) ? \
0 : \ 0 : \
ip4_addr_netcmp(ip_2_ip4(addr1), ip_2_ip4(addr2), mask)) ip4_addr_netcmp(ip_2_ip4(addr1), ip_2_ip4(addr2), mask))
#if LWIP_DHCP #define ip6_addr_isnone_val(ip6addr) (((ip6addr).addr[0] == 0xffffffffUL) && \
((ip6addr).addr[1] == 0xffffffffUL) && \
((ip6addr).addr[2] == 0xffffffffUL) && \
((ip6addr).addr[3] == 0xffffffffUL))
/* #define ip6_addr_isnone(ip6addr) (((ip6addr) == NULL) || ip6_addr_isnone_val(*(ip6addr)))
* Close DHCP and set static network.
* #define ipaddr_ntoa_unsafe(addr) ((IP_IS_V6_VAL(*addr)) ? ip6addr_ntoa(ip_2_ip6(addr)) : ip4addr_ntoa(ip_2_ip4(addr)))
* @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 */ #ifdef ip6_addr_cmp
#undef ip6_addr_cmp
#define ip6_addr_cmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \
((addr1)->addr[1] == (addr2)->addr[1]) && \
((addr1)->addr[2] == (addr2)->addr[2]) && \
((addr1)->addr[3] == (addr2)->addr[3]))
#endif
#include "lwip/prot/dhcp.h" err_t netif_dhcp_off(struct netif *netif);
err_t netif_do_rmv_ipv6_addr(struct netif *netif, void *arguments); err_t netif_do_rmv_ipv6_addr(struct netif *netif, void *arguments);
...@@ -113,49 +103,20 @@ err_t netif_set_mtu(struct netif *netif, u16_t netif_mtu); ...@@ -113,49 +103,20 @@ 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 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_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 etharp_delete_arp_entry(struct netif *netif, ip4_addr_t *ipaddr);
#define LWIP_MAX_UDP_RAW_SEND_SIZE 65332
#define ip6_addr_isnone_val(ip6addr) (((ip6addr).addr[0] == 0xffffffffUL) && \
((ip6addr).addr[1] == 0xffffffffUL) && \
((ip6addr).addr[2] == 0xffffffffUL) && \
((ip6addr).addr[3] == 0xffffffffUL))
#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_setserver(u8_t numdns, ip_addr_t *dnsserver);
err_t lwip_dns_getserver(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 #if PF_PKT_SUPPORT
extern struct raw_pcb *pkt_raw_pcbs; extern struct raw_pcb *pkt_raw_pcbs;
#endif #endif
#if LWIP_RAW
extern struct raw_pcb *raw_pcbs; extern struct raw_pcb *raw_pcbs;
#endif
#ifdef ip6_addr_cmp #endif /* LWIP_HDR_FIXME_H */
#undef ip6_addr_cmp
#define ip6_addr_cmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \
((addr1)->addr[1] == (addr2)->addr[1]) && \
((addr1)->addr[2] == (addr2)->addr[2]) && \
((addr1)->addr[3] == (addr2)->addr[3]))
#endif //ip6_addr_cmp
#define LWIP_EXT_POLL_SUPPORT LWIP_SOCKET_POLL
#endif //LWIP_ENABLE_LOS_SHELL_CMD
#endif //LITEOS_A_FIXME_H
/*
* 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 */
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
#define icmp6_hdr netinet_icmp6_hdr #define icmp6_hdr netinet_icmp6_hdr
#include <netinet/icmp6.h> #include <netinet/icmp6.h>
#undef icmp6_hdr #undef icmp6_hdr
#include "api_shell_fix.h" #include "lwip/fixme.h"
#include "lwip/opt.h" #include "lwip/opt.h"
#if LWIP_ENABLE_LOS_SHELL_CMD #if LWIP_ENABLE_LOS_SHELL_CMD
...@@ -62,7 +62,8 @@ ...@@ -62,7 +62,8 @@
#include <ctype.h> #include <ctype.h>
#include <poll.h> #include <poll.h>
#include "api_shell.h" #include "lwip/api_shell.h"
#include "lwip/tftpc.h"
#include "lwip/dns.h" #include "lwip/dns.h"
#include "lwip/netdb.h" #include "lwip/netdb.h"
...@@ -78,7 +79,7 @@ ...@@ -78,7 +79,7 @@
#include "shell.h" #include "shell.h"
#endif #endif
#define netif_find netifapi_netif_find_by_name #define LWIP_STATIC static
#if LWIP_ARP #if LWIP_ARP
extern sys_sem_t ip_conflict_detect; extern sys_sem_t ip_conflict_detect;
...@@ -3163,8 +3164,10 @@ void netstat_internal(void *ctx) ...@@ -3163,8 +3164,10 @@ void netstat_internal(void *ctx)
int recvQlen = 0; int recvQlen = 0;
int sendQlen = 0; int sendQlen = 0;
u_int proto; u_int proto;
#if PF_PKT_SUPPORT
u8_t netif_name[IFNAMSIZ]; u8_t netif_name[IFNAMSIZ];
struct netif *netif = NULL; struct netif *netif = NULL;
#endif
if (ndata == NULL) { if (ndata == NULL) {
return; return;
......
/*
* 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 <string.h>
#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, &ethaddr) != 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, &ethaddr)) {
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
...@@ -29,46 +29,26 @@ ...@@ -29,46 +29,26 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "api_shell_fix.h" #include "lwip/fixme.h"
#include <time.h>
#include <lwip/sys.h> #include <lwip/sys.h>
#include <lwip/snmp.h> #include <lwip/snmp.h>
#include <lwip/etharp.h> #include <lwip/etharp.h>
#include <lwip/netifapi.h> #include <lwip/netifapi.h>
#include <lwip/sockets.h>
#include <lwip/priv/api_msg.h> #include <lwip/priv/api_msg.h>
#include "securec.h"
#define NETIFAPI_VAR_REF(name) API_VAR_REF(name) #define NETIFAPI_VAR_REF(name) API_VAR_REF(name)
#define NETIFAPI_VAR_DECLARE(name) API_VAR_DECLARE(struct netifapi_msg, 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_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) #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 #if LWIP_DHCP
#include <lwip/dhcp.h> #include <lwip/dhcp.h>
/* /*
* Close DHCP and set static network. * Close DHCP and set static network.
*
* @param netif a pre-allocated netif structure * @param netif a pre-allocated netif structure
*
* @return ERR_OK, or ERR_VAL if failed. * @return ERR_OK, or ERR_VAL if failed.
*/ */
err_t netif_dhcp_off(struct netif *netif) err_t netif_dhcp_off(struct netif *netif)
...@@ -85,32 +65,48 @@ err_t netif_dhcp_off(struct netif *netif) ...@@ -85,32 +65,48 @@ err_t netif_dhcp_off(struct netif *netif)
old_gateway = netif->gw; old_gateway = netif->gw;
if (netif_dhcp_data(netif)) { if (netif_dhcp_data(netif)) {
(void) dhcp_release(netif); (void)dhcp_release(netif);
(void) dhcp_stop(netif); (void)dhcp_stop(netif);
(void) dhcp_cleanup(netif); (void)dhcp_cleanup(netif);
LWIP_DEBUGF(NETIF_DEBUG, ("DHCP is close;set static IP\n")); 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->ip_addr, &old_ipaddr);
ip_addr_set_val(&netif->netmask, &old_netmask); ip_addr_set_val(&netif->netmask, &old_netmask);
ip_addr_set_val(&netif->gw, &old_gateway); ip_addr_set_val(&netif->gw, &old_gateway);
(void) netif_set_up(netif); (void)netif_set_up(netif);
return ERR_OK; 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 */ #endif /* LWIP_DHCP */
#if LWIP_DHCPS #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. /* cast through void* to silence alignment warnings.
* We know it works because the structs have been instantiated as struct netifapi_msg */ * We know it works because the structs have been instantiated as struct netifapi_msg */
err_t ret; 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); ret = dhcps_start(msg->netif, msg->msg.dhcp_start_params.start_ip, msg->msg.dhcp_start_params.ip_num);
return ret; return ret;
} }
...@@ -124,8 +120,8 @@ err_t netifapi_dhcps_start(struct netif *netif, char *start_ip, u16_t ip_num) ...@@ -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_ALLOC(msg);
NETIFAPI_VAR_REF(msg).netif = netif; 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.start_ip = start_ip;
NETIFAPI_VAR_REF(msg).msg.dhcp_start_params.ip_num = ip_num ; 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); 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) ...@@ -216,19 +212,19 @@ static struct netif *netif_find_by_name(const char *name)
return NULL; 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) { 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) { 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; 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; return NULL;
} }
...@@ -294,7 +290,7 @@ err_t netif_set_mtu(struct netif *netif, u16_t netif_mtu) ...@@ -294,7 +290,7 @@ err_t netif_set_mtu(struct netif *netif, u16_t netif_mtu)
#endif /* LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES */ #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", 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; return ERR_OK;
} }
...@@ -322,31 +318,35 @@ err_t netif_set_hwaddr(struct netif *netif, const unsigned char *hw_addr, int hw ...@@ -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, 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: HW address of interface %s set to %02X:%02X:%02X:%02X:%02X:%02X\n",
netif_get_name(netif), netif_get_name(netif),
netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2], netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2],
netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5])); netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5]));
return ERR_OK; return ERR_OK;
} }
err_t etharp_update_arp_entry(struct netif *netif, const ip4_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags) err_t etharp_update_arp_entry(struct netif *netif, const ip4_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags)
{ {
// FIXME
return 0; return 0;
} }
err_t etharp_delete_arp_entry(struct netif *netif, ip4_addr_t *ipaddr) err_t etharp_delete_arp_entry(struct netif *netif, ip4_addr_t *ipaddr)
{ {
// FIXME
return 0; return 0;
} }
err_t lwip_dns_setserver(u8_t numdns, ip_addr_t *dnsserver) err_t lwip_dns_setserver(u8_t numdns, ip_addr_t *dnsserver)
{ {
// FIXME
return 0; return 0;
} }
err_t lwip_dns_getserver(u8_t numdns, ip_addr_t *dnsserver) err_t lwip_dns_getserver(u8_t numdns, ip_addr_t *dnsserver)
{ {
// FIXME
return 0; return 0;
} }
...@@ -354,57 +354,42 @@ err_t lwip_dns_getserver(u8_t numdns, ip_addr_t *dnsserver) ...@@ -354,57 +354,42 @@ err_t lwip_dns_getserver(u8_t numdns, ip_addr_t *dnsserver)
struct raw_pcb *pkt_raw_pcbs; struct raw_pcb *pkt_raw_pcbs;
#endif #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 #if LWIP_ENABLE_IP_CONFLICT_SIGNAL
u32_t is_ip_conflict_signal = 0; u32_t is_ip_conflict_signal = 0;
sys_sem_t ip_conflict_detect; sys_sem_t ip_conflict_detect;
#endif #endif
u32_t is_dup_detect_initialized = 0; u32_t is_dup_detect_initialized = 0;
sys_sem_t dup_addr_detect; sys_sem_t dup_addr_detect;
int lwip_sntp_start(int server_num, char **sntp_server, struct timeval *time) #if LWIP_SNTP
{
return 0;
}
u32_t lwip_tftp_get_file_by_filename(u32_t ulHostAddr, #include <time.h>
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, int lwip_sntp_start(int server_num, char **sntp_server, struct timeval *time)
u16_t usTftpServPort,
u8_t cTftpTransMode,
s8_t *szSrcFileName,
s8_t *szDestDirPath)
{ {
// FIXME
return 0; return 0;
} }
#endif
const char *const tcp_state_str[] = { const char *const tcp_state_str[] = {
"CLOSED", "CLOSED",
"LISTEN", "LISTEN",
"SYN_SENT", "SYN_SENT",
"SYN_RCVD", "SYN_RCVD",
"ESTABLISHED", "ESTABLISHED",
"FIN_WAIT_1", "FIN_WAIT_1",
"FIN_WAIT_2", "FIN_WAIT_2",
"CLOSE_WAIT", "CLOSE_WAIT",
"CLOSING", "CLOSING",
"LAST_ACK", "LAST_ACK",
"TIME_WAIT" "TIME_WAIT"
}; };
volatile int tcpip_init_finish = 1; // needed by api_shell.c volatile int tcpip_init_finish = 1; // needed by api_shell.c
#endif
/*
* 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 <string.h>
#include <unistd.h>
#include <sys/stat.h>
/* 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 */
...@@ -32,13 +32,32 @@ ...@@ -32,13 +32,32 @@
#ifndef _LWIP_PORTING_DHCP_H_ #ifndef _LWIP_PORTING_DHCP_H_
#define _LWIP_PORTING_DHCP_H_ #define _LWIP_PORTING_DHCP_H_
#include <lwip/opt.h>
#if LWIP_DHCPS
#define DHCP_OPTION_IDX_SERVER_ID DHCP_OPTION_IDX_SERVER_ID, \
DHCP_OPTION_IDX_REQUESTED_IP
#endif
#include_next <lwip/dhcp.h> #include_next <lwip/dhcp.h>
#if LWIP_DHCPS
#undef DHCP_OPTION_IDX_SERVER_ID
#endif
#include <lwip/prot/dhcp.h> // For DHCP_STATE_BOUND, DHCP_DISCOVER etc. by `mac/common/mac_data.c' #include <lwip/prot/dhcp.h> // For DHCP_STATE_BOUND, DHCP_DISCOVER etc. by `mac/common/mac_data.c'
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #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); err_t dhcp_is_bound(struct netif *netif);
#ifdef __cplusplus #ifdef __cplusplus
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#ifndef _LWIP_PORTING_LWIPOPTS_H_ #ifndef _LWIP_PORTING_LWIPOPTS_H_
#define _LWIP_PORTING_LWIPOPTS_H_ #define _LWIP_PORTING_LWIPOPTS_H_
#include "menuconfig.h"
// lwIP debug options, comment the ones you don't want // lwIP debug options, comment the ones you don't want
#if LWIP_DEBUG #if LWIP_DEBUG
...@@ -215,6 +216,9 @@ ...@@ -215,6 +216,9 @@
#define LWIP_CONFIG_NUM_SOCKETS 128 #define LWIP_CONFIG_NUM_SOCKETS 128
#define IP_REASS_MAX_MEM_SIZE (MEM_SIZE / 4) #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_DHCPS 1
#define LWIP_ENABLE_NET_CAPABILITY 1 #define LWIP_ENABLE_NET_CAPABILITY 1
......
...@@ -35,16 +35,23 @@ ...@@ -35,16 +35,23 @@
#include <net/if.h> // For IFNAMSIZ/IF_NAMESIZE and `struct ifreq', by `lwip/netif.h' and `api/sockets.c' #include <net/if.h> // For IFNAMSIZ/IF_NAMESIZE and `struct ifreq', by `lwip/netif.h' and `api/sockets.c'
#include <netinet/ip.h> // For IP_OFFMASK, by `core/ipv4/ip4_frag.c' #include <netinet/ip.h> // 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; \ #define linkoutput linkoutput; \
void (*drv_send)(struct netif *netif, struct pbuf *p); \ void (*drv_send)(struct netif *netif, struct pbuf *p); \
u8_t (*drv_set_hwaddr)(struct netif *netif, u8_t *addr, u8_t len); \ 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); \ void (*drv_config)(struct netif *netif, u32_t config_flags, u8_t setBit); \
struct dhcps *dhcps; \
char full_name[IFNAMSIZ]; \ char full_name[IFNAMSIZ]; \
u16_t link_layer_type u16_t link_layer_type
#include_next <lwip/netif.h> #include_next <lwip/netif.h>
#undef linkoutput #undef linkoutput
#if LWIP_DHCPS
#undef LWIP_NETIF_CLIENT_DATA_INDEX_DHCP
#endif
#include <lwip/etharp.h> // For ETHARP_HWADDR_LEN, by `hieth-sf src/interface.c' and `wal/wal_net.c' #include <lwip/etharp.h> // 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); ...@@ -64,9 +71,7 @@ err_t driverif_init(struct netif *netif);
void driverif_input(struct netif *netif, struct pbuf *p); void driverif_input(struct netif *netif, struct pbuf *p);
#ifndef __LWIP__ #ifndef __LWIP__
struct netif *netifapi_netif_find_by_name(const char *name); #define PF_PKT_SUPPORT LWIP_NETIF_PROMISC
#define PF_PKT_SUPPORT 1 // For netif->drv_config
#define netif_find(name) netifapi_netif_find_by_name(name)
#define netif_add(a, b, c, d) netif_add(a, b, c, d, (a)->state, driverif_init, tcpip_input) #define netif_add(a, b, c, d) netif_add(a, b, c, d, (a)->state, driverif_init, tcpip_input)
#else /* __LWIP__ */ #else /* __LWIP__ */
#define netif_get_name(netif) ((netif)->full_name) #define netif_get_name(netif) ((netif)->full_name)
......
...@@ -45,6 +45,7 @@ err_t netifapi_dhcps_stop(struct netif *netif); ...@@ -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) #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); 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__ #ifndef __LWIP__
#define netifapi_netif_add(a, b, c, d) netifapi_netif_add(a, b, c, d, (a)->state, driverif_init, tcpip_input) #define netifapi_netif_add(a, b, c, d) netifapi_netif_add(a, b, c, d, (a)->state, driverif_init, tcpip_input)
......
...@@ -44,7 +44,6 @@ ...@@ -44,7 +44,6 @@
#define link_rx_drop cachehit #define link_rx_drop cachehit
#define link_rx_overrun cachehit #define link_rx_overrun cachehit
#define NETIF_NAME_LEN 2
#define LWIP_STATIC static #define LWIP_STATIC static
#ifndef LWIP_NETIF_IFINDEX_MAX_EX #ifndef LWIP_NETIF_IFINDEX_MAX_EX
...@@ -57,6 +56,9 @@ driverif_init_ifname(struct netif *netif) ...@@ -57,6 +56,9 @@ driverif_init_ifname(struct netif *netif)
struct netif *tmpnetif = NULL; struct netif *tmpnetif = NULL;
const char *prefix = (netif->link_layer_type == WIFI_DRIVER_IF) ? "wlan" : "eth"; 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) { 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, if (snprintf_s(netif->full_name, sizeof(netif->full_name), sizeof(netif->full_name) - 1,
"%s%d", prefix, i) < 0) { "%s%d", prefix, i) < 0) {
...@@ -140,7 +142,7 @@ driverif_input(struct netif *netif, struct pbuf *p) ...@@ -140,7 +142,7 @@ driverif_input(struct netif *netif, struct pbuf *p)
#endif #endif
#else #else
u16_t ethhdr_type; u16_t ethhdr_type;
struct eth_hdr* ethhdr = NULL; struct eth_hdr *ethhdr = NULL;
#endif #endif
err_t ret = ERR_VAL; err_t ret = ERR_VAL;
...@@ -241,7 +243,6 @@ err_t ...@@ -241,7 +243,6 @@ err_t
driverif_init(struct netif *netif) driverif_init(struct netif *netif)
{ {
u16_t link_layer_type; u16_t link_layer_type;
err_t ret;
if (netif == NULL) { if (netif == NULL) {
return ERR_IF; return ERR_IF;
...@@ -262,17 +263,7 @@ driverif_init(struct netif *netif) ...@@ -262,17 +263,7 @@ driverif_init(struct netif *netif)
#if LWIP_NETIF_HOSTNAME #if LWIP_NETIF_HOSTNAME
/* Initialize interface 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; netif->hostname = LWIP_NETIF_HOSTNAME_DEFAULT;
#endif
#endif /* LWIP_NETIF_HOSTNAME */ #endif /* LWIP_NETIF_HOSTNAME */
/* /*
...@@ -285,21 +276,6 @@ driverif_init(struct netif *netif) ...@@ -285,21 +276,6 @@ driverif_init(struct netif *netif)
netif->output = etharp_output; netif->output = etharp_output;
netif->linkoutput = driverif_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 */ /* init the netif's full name */
driverif_init_ifname(netif); driverif_init_ifname(netif);
...@@ -309,30 +285,30 @@ driverif_init(struct netif *netif) ...@@ -309,30 +285,30 @@ driverif_init(struct netif *netif)
/* device capabilities */ /* device capabilities */
/* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP |
#if DRIVER_STATUS_CHECK #if DRIVER_STATUS_CHECK
NETIF_FLAG_DRIVER_RDY | NETIF_FLAG_DRIVER_RDY |
#endif #endif
#if LWIP_IGMP #if LWIP_IGMP
NETIF_FLAG_IGMP | NETIF_FLAG_IGMP |
#endif #endif
/** /**
@page RFC-2710 RFC-2710 @page RFC-2710 RFC-2710
@par Compliant Sections @par Compliant Sections
Section 5. Node State Transition Diagram Section 5. Node State Transition Diagram
@par Behavior Description @par Behavior Description
MLD messages are sent for multicast addresses whose scope is 2 MLD messages are sent for multicast addresses whose scope is 2
(link-local), including Solicited-Node multicast addresses.\n (link-local), including Solicited-Node multicast addresses.\n
Behavior:Stack will send MLD6 report /Done to solicited node multicast address 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. 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 */ /* Enable sending MLD report /done for solicited address during neighbour discovery */
#if LWIP_IPV6 && LWIP_IPV6_MLD #if LWIP_IPV6 && LWIP_IPV6_MLD
#if LWIP_MLD6_ENABLE_MLD_ON_DAD #if LWIP_MLD6_ENABLE_MLD_ON_DAD
NETIF_FLAG_MLD6 | NETIF_FLAG_MLD6 |
#endif /* LWIP_MLD6_ENABLE_MLD_ON_DAD */ #endif /* LWIP_MLD6_ENABLE_MLD_ON_DAD */
#endif #endif
NETIF_FLAG_LINK_UP; NETIF_FLAG_LINK_UP;
#if DRIVER_STATUS_CHECK #if DRIVER_STATUS_CHECK
netif->waketime = -1; netif->waketime = -1;
......
/*
* 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 <lwip/netif.h>
#include <lwip/dhcp.h>
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
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#include <lwip/sockets.h> #include <lwip/sockets.h>
#include <lwip/priv/tcpip_priv.h> #include <lwip/priv/tcpip_priv.h>
#include <api_shell_fix.h> #include <lwip/fixme.h>
#if LWIP_ENABLE_NET_CAPABILITY #if LWIP_ENABLE_NET_CAPABILITY
#include "capability_type.h" #include "capability_type.h"
...@@ -39,8 +39,6 @@ ...@@ -39,8 +39,6 @@
#define BIND_SERVICE_CAP_MIN_PORT 1024 #define BIND_SERVICE_CAP_MIN_PORT 1024
#endif #endif
#define netif_find netifapi_netif_find_by_name
#define IOCTL_CMD_CASE_HANDLER() \ #define IOCTL_CMD_CASE_HANDLER() \
{ \ { \
err_t err; \ err_t err; \
...@@ -86,7 +84,8 @@ int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen) ...@@ -86,7 +84,8 @@ int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
return lwip_bind_wrap(s, name, 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) 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); return lwip_sendto_wrap(s, dataptr, size, flags, to, tolen);
...@@ -227,12 +226,12 @@ static int lwip_bind_wrap(int s, const struct sockaddr *name, socklen_t namelen) ...@@ -227,12 +226,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, 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 LWIP_ENABLE_NET_CAPABILITY
if (to && if (to &&
((to->sa_family == AF_INET && tolen >= sizeof(struct sockaddr_in)) || ((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; ip_addr_t ipaddr;
u16_t port; u16_t port;
...@@ -366,7 +365,6 @@ int get_unused_socket_num(void) ...@@ -366,7 +365,6 @@ int get_unused_socket_num(void)
// Options for lwip ioctl // Options for lwip ioctl
#define LWIP_IOCTL_ROUTE 1 #define LWIP_IOCTL_ROUTE 1
#define LWIP_IOCTL_IF 1 #define LWIP_IOCTL_IF 1
#define LWIP_NETIF_PROMISC 1
#define LWIP_NETIF_ETHTOOL 0 #define LWIP_NETIF_ETHTOOL 0
#define LWIP_IOCTL_IPV6DPCTD 0 #define LWIP_IOCTL_IPV6DPCTD 0
#undef LWIP_IPV6_DUP_DETECT_ATTEMPTS #undef LWIP_IPV6_DUP_DETECT_ATTEMPTS
...@@ -758,7 +756,7 @@ static u8_t lwip_ioctl_internal_SIOCSIFNETMASK(struct ifreq *ifr) ...@@ -758,7 +756,7 @@ static u8_t lwip_ioctl_internal_SIOCSIFNETMASK(struct ifreq *ifr)
loc_netif = loc_netif->next; loc_netif = loc_netif->next;
} }
#if LWIP_DHCP // LWIP_DHCP #if LWIP_DHCP
if ((netif_dhcp_data(netif) != NULL) && if ((netif_dhcp_data(netif) != NULL) &&
(netif_dhcp_data(netif)->state != DHCP_STATE_OFF)) { (netif_dhcp_data(netif)->state != DHCP_STATE_OFF)) {
(void)netif_dhcp_off(netif); (void)netif_dhcp_off(netif);
......
...@@ -46,6 +46,7 @@ static u32_t lwprot_thread = LOS_ERRNO_TSK_ID_INVALID; ...@@ -46,6 +46,7 @@ static u32_t lwprot_thread = LOS_ERRNO_TSK_ID_INVALID;
static int lwprot_count = 0; static int lwprot_count = 0;
#endif /* LOSCFG_KERNEL_SMP == YES */ #endif /* LOSCFG_KERNEL_SMP == YES */
#define ROUND_UP_DIV(val, div) (((val) + (div) - 1) / (div))
/** /**
* Thread and System misc * Thread and System misc
...@@ -59,11 +60,11 @@ sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, ...@@ -59,11 +60,11 @@ sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg,
/* Create host Task */ /* Create host Task */
task.pfnTaskEntry = (TSK_ENTRY_FUNC)thread; task.pfnTaskEntry = (TSK_ENTRY_FUNC)thread;
task.uwStackSize = stackSize; task.uwStackSize = stackSize;
task.pcName = (char *)name; task.pcName = (char *)name;
task.usTaskPrio = prio; task.usTaskPrio = prio;
task.auwArgs[0] = (UINTPTR)arg; task.auwArgs[0] = (UINTPTR)arg;
task.uwResved = LOS_TASK_STATUS_DETACHED; task.uwResved = LOS_TASK_STATUS_DETACHED;
ret = LOS_TaskCreate(&taskID, &task); ret = LOS_TaskCreate(&taskID, &task);
if (ret != LOS_OK) { if (ret != LOS_OK) {
LWIP_DEBUGF(SYS_DEBUG, ("sys_thread_new: LOS_TaskCreate error %u\n", ret)); LWIP_DEBUGF(SYS_DEBUG, ("sys_thread_new: LOS_TaskCreate error %u\n", ret));
...@@ -84,9 +85,17 @@ void sys_init(void) ...@@ -84,9 +85,17 @@ void sys_init(void)
u32_t sys_now(void) u32_t sys_now(void)
{ {
/* Lwip docs mentioned like wraparound is not a problem in this funtion */ /* 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 * Protector
...@@ -140,7 +149,7 @@ void sys_arch_unprotect(sys_prot_t pval) ...@@ -140,7 +149,7 @@ void sys_arch_unprotect(sys_prot_t pval)
err_t sys_mbox_new(sys_mbox_t *mbox, int size) err_t sys_mbox_new(sys_mbox_t *mbox, int size)
{ {
CHAR qName[] = "lwIP"; 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) { switch (ret) {
case LOS_OK: case LOS_OK:
return ERR_OK; return ERR_OK;
...@@ -184,8 +193,8 @@ err_t sys_mbox_trypost_fromisr(sys_mbox_t *mbox, void *msg); ...@@ -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) 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 */ 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; 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); UINT32 ret = LOS_QueueRead(*mbox, msg ? msg : &ignore, sizeof(void *), tick ? (UINT32)tick : LOS_WAIT_FOREVER);
switch (ret) { switch (ret) {
case LOS_OK: case LOS_OK:
return ERR_OK; return ERR_OK;
...@@ -202,7 +211,7 @@ u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeoutMs) ...@@ -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) u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
{ {
void *ignore = 0; /* if msg==NULL, the fetched msg should be dropped */ 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) { switch (ret) {
case LOS_OK: case LOS_OK:
return ERR_OK; return ERR_OK;
...@@ -255,7 +264,7 @@ void sys_sem_signal(sys_sem_t *sem) ...@@ -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) 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 UINT32 ret = LOS_SemPend(*sem, tick ? (UINT32)tick : LOS_WAIT_FOREVER); // timeoutMs 0 means wait forever
switch (ret) { switch (ret) {
case LOS_OK: case LOS_OK:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册