Mercurial > nand-ecoscentric
changeset 2174:d07decb23fa2
* Updated the complete lwIP source to the latest lwIP
CVS version 1.1.1
* src/ecos/init.c Added call to netif_set_up(netif) in
function lwip_set_addr() - this is required since lwIP
version 1.0.0
* cdl/lwip_net.cdl Minor modifications for UDP configuration
options. Renamed CYGNUM_LWIP_TCPIP_THREAD_PRIORITY to
CYGNUM_LWIP_NETWORK_THREAD_PRIORITY and moved option outside
CYGPKG_LWIP_TCPIP component because the network thread needs to
run in all configurations.
* tests/nc_slave.c
* tests/tcpecho.c
* tests/udpecho.c
* tests/sockets.c
* tests/httpd.c Added eCos test infrastructure to tests and
made tests applicable depending on lwip configuration.
line wrap: on
line diff
--- a/packages/net/lwip_tcpip/current/ChangeLog +++ b/packages/net/lwip_tcpip/current/ChangeLog @@ -1,3 +1,22 @@ +2006-03-26 Uwe Kindler <uwe_kindler@web.de> + + * Updated the complete lwIP source to the latest lwIP + CVS version 1.1.1 + * src/ecos/init.c Added call to netif_set_up(netif) in + function lwip_set_addr() - this is required since lwIP + version 1.0.0 + * cdl/lwip_net.cdl Minor modifications for UDP configuration + options. Renamed CYGNUM_LWIP_TCPIP_THREAD_PRIORITY to + CYGNUM_LWIP_NETWORK_THREAD_PRIORITY and moved option outside + CYGPKG_LWIP_TCPIP component because the network thread needs to + run in all configurations. + * tests/nc_slave.c + * tests/tcpecho.c + * tests/udpecho.c + * tests/sockets.c + * tests/httpd.c Added eCos test infrastructure to tests and + made tests applicable depending on lwip configuration. + 2006-03-15 Andrew Lunn <andrew.lunn@ascom.ch> * tests/nc_test_slave.c (nc_slave): Fix some of the compiler
--- a/packages/net/lwip_tcpip/current/cdl/lwip_net.cdl +++ b/packages/net/lwip_tcpip/current/cdl/lwip_net.cdl @@ -327,28 +327,12 @@ cdl_package CYGPKG_NET_LWIP { } } - cdl_component CYGPKG_LWIP_TCP_OPTIONS { - display "TCP" - flavor none - no_define + cdl_component CYGPKG_LWIP_TCP { + display "TCP" + flavor bool + default_value 1 description " - Tune the TCP protocol details" - - cdl_option CYGFUN_LWIP_TCP { - display "Activate TCP" - flavor bool - default_value 1 - description "" - - } - - cdl_option CYGNUM_LWIP_TCPIP_THREAD_PRIORITY { - display "TCP/IP thread priority" - flavor data - default_value 7 - description "Pririty of the lwIP network thread.This thread handles all API messages and - network packets." - } + Support TCP protocol." cdl_option CYGNUM_LWIP_TCP_TTL { display "Time To Live" @@ -385,7 +369,7 @@ cdl_package CYGPKG_NET_LWIP { cdl_option CYGNUM_LWIP_TCP_SND_QUEUELEN { display "Sender pbufs" flavor data - calculated "4 * CYGNUM_LWIP_TCP_SND_BUF/CYGNUM_LWIP_TCP_MSS" + calculated CYGPKG_LWIP_TCP ? "4 * CYGNUM_LWIP_TCP_SND_BUF/CYGNUM_LWIP_TCP_MSS" : 0 description " TCP sender buffer space (pbufs). This must be at least = 2 * TCP_SND_BUF/TCP_MSS for things to work." @@ -487,12 +471,13 @@ cdl_package CYGPKG_NET_LWIP { } cdl_component CYGPKG_LWIP_DHCP { - display "Use DHCP" + display "DHCP" flavor bool + requires CYGPKG_LWIP_UDP default_value 0 requires { CYGNUM_LWIP_MEMP_NUM_SYS_TIMEOUT >= 6 } description " - Provide DHCP for initializing the IP address of network interfaces." + Provide DHCP support for initializing the IP address of network interfaces." compile core/dhcp.c cdl_option CYGOPT_LWIP_DHCP_MANAGEMENT { @@ -541,6 +526,14 @@ cdl_package CYGPKG_NET_LWIP { } } + + cdl_option CYGNUM_LWIP_NETWORK_THREAD_PRIORITY { + display "Network thread priority" + flavor data + default_value 7 + description "Priority of the lwIP network thread.This thread handles all API messages and + network packets." + } cdl_component CYGPKG_LWIP_SLIP { display "SLIP" @@ -615,18 +608,12 @@ cdl_package CYGPKG_NET_LWIP { } } - cdl_component CYGPKG_LWIP_UDP_OPTIONS { + cdl_component CYGPKG_LWIP_UDP { display "UDP" - flavor none - no_define - - cdl_option CYGFUN_LWIP_UDP { - display "Activate UDP" - flavor bool - default_value 1 - description "" - compile core/udp.c - } + flavor bool + default_value 1 + description "Support UDP protocol." + compile core/udp.c cdl_option CYGNUM_LWIP_UDP_TTL { display "Time To Live" @@ -643,6 +630,17 @@ cdl_package CYGPKG_NET_LWIP { description "" compile core/raw.c } + + cdl_option CYGFUN_LWIP_COMPAT_SOCKETS { + display "Provide compatible socket API" + flavor bool + default_value 1 + description " + The lwIP socket API uses defines to map the lwip socket functions + (lwip_accept(), lwip_bind(), lwip_listen()...) to BSD like names + (accept(), bind(), listen()...). If this causes trouble or naming + conficts for your application, then disable this option" + } cdl_component CYGPKG_LWIP_APP_MEM_OPTIONS { display "Memory options for apps"
--- a/packages/net/lwip_tcpip/current/include/arch/cc.h +++ b/packages/net/lwip_tcpip/current/include/arch/cc.h @@ -1,3 +1,68 @@ +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== + +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * 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 Institute 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 INSTITUTE 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 INSTITUTE 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels <adam@sics.se> + * + */ #ifndef __ARCH_CC_H__ #define __ARCH_CC_H__ @@ -27,6 +92,12 @@ typedef unsigned long u32_t; typedef signed long s32_t; typedef unsigned long mem_ptr_t; +#define U16_F "u" +#define S16_F "d" +#define X16_F "x" +#define U32_F "lu" +#define S32_F "ld" +#define X32_F "lx" #define PACK_STRUCT_FIELD(x) x __attribute__((packed)) #define PACK_STRUCT_STRUCT __attribute__((packed))
--- a/packages/net/lwip_tcpip/current/include/arch/perf.h +++ b/packages/net/lwip_tcpip/current/include/arch/perf.h @@ -1,3 +1,68 @@ +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== + +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * 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 Institute 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 INSTITUTE 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 INSTITUTE 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels <adam@sics.se> + * + */ #ifndef __PERF_H__ #define __PERF_H__
--- a/packages/net/lwip_tcpip/current/include/arch/sys_arch.h +++ b/packages/net/lwip_tcpip/current/include/arch/sys_arch.h @@ -1,3 +1,35 @@ +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== + #ifndef __SYS_ECOS_H__ #define __SYS_ECOS_H__ @@ -6,8 +38,8 @@ #define SYS_MBOX_NULL (sys_mbox_t)NULL #define SYS_SEM_NULL (sys_sem_t)NULL -typedef cyg_sem_t * sys_sem_t; +typedef cyg_sem_t* sys_sem_t; typedef cyg_handle_t sys_mbox_t; -typedef cyg_thread * sys_thread_t; +typedef cyg_handle_t sys_thread_t; #endif /* __SYS_ECOS_H__ */
--- a/packages/net/lwip_tcpip/current/include/lwip/api.h +++ b/packages/net/lwip_tcpip/current/include/lwip/api.h @@ -48,17 +48,11 @@ #define NETCONN_COPY 0x01 enum netconn_type { -#if LWIP_TCP NETCONN_TCP, -#endif -#if LWIP_UDP NETCONN_UDP, NETCONN_UDPLITE, NETCONN_UDPNOCHKSUM, -#endif -#if LWIP_RAW NETCONN_RAW -#endif }; enum netconn_state {
--- a/packages/net/lwip_tcpip/current/include/lwip/api_msg.h +++ b/packages/net/lwip_tcpip/current/include/lwip/api_msg.h @@ -75,7 +75,7 @@ struct api_msg_msg { struct { void *dataptr; u16_t len; - unsigned char copy; + u8_t copy; } w; sys_mbox_t mbox; u16_t len;
--- a/packages/net/lwip_tcpip/current/include/lwip/debug.h +++ b/packages/net/lwip_tcpip/current/include/lwip/debug.h @@ -71,7 +71,7 @@ /** print debug message only if debug message type is enabled... * AND is of correct type AND is at least DBG_LEVEL */ -# define LWIP_DEBUGF(debug,x) do { if (((debug) & DBG_ON) && ((debug) & DBG_TYPES_ON) && (((debug) & DBG_MASK_LEVEL) >= DBG_MIN_LEVEL)) { LWIP_PLATFORM_DIAG(x); if ((debug) & DBG_HALT) while(1); } } while(0) +# define LWIP_DEBUGF(debug,x) do { if (((debug) & DBG_ON) && ((debug) & DBG_TYPES_ON) && ((s16_t)((debug) & DBG_MASK_LEVEL) >= DBG_MIN_LEVEL)) { LWIP_PLATFORM_DIAG(x); if ((debug) & DBG_HALT) while(1); } } while(0) # define LWIP_ERROR(x) do { LWIP_PLATFORM_DIAG(x); } while(0) #else /* LWIP_DEBUG */ # define LWIP_DEBUGF(debug,x)
--- a/packages/net/lwip_tcpip/current/include/lwip/dhcp.h +++ b/packages/net/lwip_tcpip/current/include/lwip/dhcp.h @@ -43,6 +43,10 @@ struct dhcp struct ip_addr offered_sn_mask; struct ip_addr offered_gw_addr; struct ip_addr offered_bc_addr; +#define DHCP_MAX_DNS 2 + u32_t dns_count; /* actual number of DNS servers obtained */ + struct ip_addr offered_dns_addr[DHCP_MAX_DNS]; /* DNS server addresses */ + u32_t offered_t0_lease; /* lease period (in seconds) */ u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */ u32_t offered_t2_rebind; /* recommended rebind time (usually 66% of lease period) */ @@ -82,8 +86,12 @@ struct dhcp_msg PACK_STRUCT_FIELD(u8_t file[DHCP_FILE_LEN]); PACK_STRUCT_FIELD(u32_t cookie); #define DHCP_MIN_OPTIONS_LEN 68U +/** make sure user does not configure this too small */ +#if ((defined(DHCP_OPTIONS_LEN)) && (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN)) +# undef DHCP_OPTIONS_LEN +#endif /** allow this to be configured in lwipopts.h, but not too small */ -#if ((!defined(DHCP_OPTIONS_LEN)) || (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN)) +#if (!defined(DHCP_OPTIONS_LEN)) /** set this to be sufficient for your options in outgoing DHCP msgs */ # define DHCP_OPTIONS_LEN DHCP_MIN_OPTIONS_LEN #endif @@ -96,11 +104,13 @@ PACK_STRUCT_END /** start DHCP configuration */ err_t dhcp_start(struct netif *netif); +/** enforce early lease renewal (not needed normally)*/ +err_t dhcp_renew(struct netif *netif); +/** release the DHCP lease, usually called before dhcp_stop()*/ +err_t dhcp_release(struct netif *netif); /** stop DHCP configuration */ void dhcp_stop(struct netif *netif); -/** enforce lease renewal */ -err_t dhcp_renew(struct netif *netif); -/** inform server of our IP address */ +/** inform server of our manual IP address */ void dhcp_inform(struct netif *netif); /** if enabled, check whether the offered IP address is not in use, using ARP */ @@ -174,7 +184,8 @@ void dhcp_fine_tmr(void); /** BootP options */ #define DHCP_OPTION_PAD 0 #define DHCP_OPTION_SUBNET_MASK 1 /* RFC 2132 3.3 */ -#define DHCP_OPTION_ROUTER 3 +#define DHCP_OPTION_ROUTER 3 +#define DHCP_OPTION_DNS_SERVER 6 #define DHCP_OPTION_HOSTNAME 12 #define DHCP_OPTION_IP_TTL 23 #define DHCP_OPTION_MTU 26
--- a/packages/net/lwip_tcpip/current/include/lwip/inet.h +++ b/packages/net/lwip_tcpip/current/include/lwip/inet.h @@ -39,13 +39,16 @@ #include "lwip/ip_addr.h" u16_t inet_chksum(void *dataptr, u16_t len); +#if 0 /* optimized routine */ +u16_t inet_chksum4(u8_t *dataptr, u16_t len); +#endif u16_t inet_chksum_pbuf(struct pbuf *p); u16_t inet_chksum_pseudo(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, u8_t proto, u16_t proto_len); u32_t inet_addr(const char *cp); -int inet_aton(const char *cp, struct in_addr *addr); +s8_t inet_aton(const char *cp, struct in_addr *addr); char *inet_ntoa(struct in_addr addr); /* returns ptr to static buffer; not reentrant! */ #ifdef htons
--- a/packages/net/lwip_tcpip/current/include/lwip/ip.h +++ b/packages/net/lwip_tcpip/current/include/lwip/ip.h @@ -40,7 +40,6 @@ #include "lwip/err.h" -struct netif; void ip_init(void); struct netif *ip_route(struct ip_addr *dest); @@ -128,7 +127,7 @@ PACK_STRUCT_END #define IPH_V(hdr) (ntohs((hdr)->_v_hl_tos) >> 12) #define IPH_HL(hdr) ((ntohs((hdr)->_v_hl_tos) >> 8) & 0x0f) -#define IPH_TOS(hdr) (htons((ntohs((hdr)->_v_hl_tos) & 0xff))) +#define IPH_TOS(hdr) (ntohs((hdr)->_v_hl_tos) & 0xff) #define IPH_LEN(hdr) ((hdr)->_len) #define IPH_ID(hdr) ((hdr)->_id) #define IPH_OFFSET(hdr) ((hdr)->_offset)
--- a/packages/net/lwip_tcpip/current/include/lwip/ip_addr.h +++ b/packages/net/lwip_tcpip/current/include/lwip/ip_addr.h @@ -117,7 +117,15 @@ extern const struct ip_addr ip_addr_broa #define ip_addr_set(dest, src) (dest)->addr = \ ((src) == NULL? 0:\ (src)->addr) -#define ip_addr_maskcmp(addr1, addr2, mask) (((addr1)->addr & \ +/** + * Determine if two address are on the same network. + * + * @arg addr1 IP address 1 + * @arg addr2 IP address 2 + * @arg mask network identifier mask + * @return !0 if the network identifiers of both address match + */ +#define ip_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \ (mask)->addr) == \ ((addr2)->addr & \ (mask)->addr)) @@ -130,32 +138,18 @@ u8_t ip_addr_isbroadcast(struct ip_addr #define ip_addr_ismulticast(addr1) (((addr1)->addr & ntohl(0xf0000000)) == ntohl(0xe0000000)) -#define ip_addr_debug_print(debug, ipaddr) LWIP_DEBUGF(debug, ("%u.%u.%u.%u", \ - ipaddr?(unsigned int)(ntohl((ipaddr)->addr) >> 24) & 0xff:0, \ - ipaddr?(unsigned int)(ntohl((ipaddr)->addr) >> 16) & 0xff:0, \ - ipaddr?(unsigned int)(ntohl((ipaddr)->addr) >> 8) & 0xff:0, \ - ipaddr?(unsigned int)ntohl((ipaddr)->addr) & 0xff:0U)) +#define ip_addr_debug_print(debug, ipaddr) LWIP_DEBUGF(debug, ("%"U16_F".%"U16_F".%"U16_F".%"U16_F, \ + ipaddr?(u16_t)(ntohl((ipaddr)->addr) >> 24) & 0xff:0, \ + ipaddr?(u16_t)(ntohl((ipaddr)->addr) >> 16) & 0xff:0, \ + ipaddr?(u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff:0, \ + ipaddr?(u16_t)ntohl((ipaddr)->addr) & 0xff:0U)) /* cast to unsigned int, as it is used as argument to printf functions - * which expect integer arguments */ -#define ip4_addr1(ipaddr) ((unsigned int)(ntohl((ipaddr)->addr) >> 24) & 0xff) -#define ip4_addr2(ipaddr) ((unsigned int)(ntohl((ipaddr)->addr) >> 16) & 0xff) -#define ip4_addr3(ipaddr) ((unsigned int)(ntohl((ipaddr)->addr) >> 8) & 0xff) -#define ip4_addr4(ipaddr) ((unsigned int)(ntohl((ipaddr)->addr)) & 0xff) - -/** - * Determine if two address are on the same network. - * - * @arg addr1 IP address 1 - * @arg addr2 IP address 2 - * @arg mask network identifier mask - * @return !0 if the network identifiers of both address match - */ -#define ip_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \ - (mask)->addr) == \ - ((addr2)->addr & \ - (mask)->addr)) - + * which expect integer arguments. CSi: use cc.h formatters (conversion chars)! */ +#define ip4_addr1(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 24) & 0xff) +#define ip4_addr2(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 16) & 0xff) +#define ip4_addr3(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff) +#define ip4_addr4(ipaddr) ((u16_t)(ntohl((ipaddr)->addr)) & 0xff) #endif /* __LWIP_IP_ADDR_H__ */
--- a/packages/net/lwip_tcpip/current/include/lwip/ip_frag.h +++ b/packages/net/lwip_tcpip/current/include/lwip/ip_frag.h @@ -38,8 +38,9 @@ #include "lwip/netif.h" #include "lwip/ip_addr.h" -struct pbuf * ip_reass(struct pbuf *); -err_t ip_frag(struct pbuf *, struct netif *, struct ip_addr *); +void ip_reass_tmr(void); +struct pbuf * ip_reass(struct pbuf *p); +err_t ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest); #endif /* __LWIP_IP_FRAG_H__ */
--- a/packages/net/lwip_tcpip/current/include/lwip/netif.h +++ b/packages/net/lwip_tcpip/current/include/lwip/netif.h @@ -52,7 +52,8 @@ /** whether the network interface is 'up'. this is * a software flag used to control whether this network - * interface is enabled and processes traffic */ + * interface is enabled and processes traffic. + */ #define NETIF_FLAG_UP 0x1U /** if set, the netif has broadcast capability */ #define NETIF_FLAG_BROADCAST 0x2U @@ -61,52 +62,55 @@ /** if set, the interface is configured using DHCP */ #define NETIF_FLAG_DHCP 0x08U /** if set, the interface has an active link - * (set by the interface) */ + * (set by the network interface driver) */ #define NETIF_FLAG_LINK_UP 0x10U -/** generic data structure used for all lwIP network interfaces */ +/** Generic data structure used for all lwIP network interfaces. + * The following fields should be filled in by the initialization + * function for the device driver: hwaddr_len, hwaddr[], mtu, flags */ + struct netif { /** pointer to next in linked list */ struct netif *next; - /** The following fields should be filled in by the - initialization function for the device driver. */ - + /** IP address configuration in network byte order */ struct ip_addr ip_addr; struct ip_addr netmask; struct ip_addr gw; /** This function is called by the network device driver - to pass a packet up the TCP/IP stack. */ + * to pass a packet up the TCP/IP stack. */ err_t (* input)(struct pbuf *p, struct netif *inp); /** This function is called by the IP module when it wants - to send a packet on the interface. This function typically - first resolves the hardware address, then sends the packet. */ + * to send a packet on the interface. This function typically + * first resolves the hardware address, then sends the packet. */ err_t (* output)(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr); /** This function is called by the ARP module when it wants - to send a packet on the interface. This function outputs - the pbuf as-is on the link medium. */ + * to send a packet on the interface. This function outputs + * the pbuf as-is on the link medium. */ err_t (* linkoutput)(struct netif *netif, struct pbuf *p); /** This field can be set by the device driver and could point - to state information for the device. */ + * to state information for the device. */ void *state; #if LWIP_DHCP /** the DHCP client state information for this netif */ struct dhcp *dhcp; #endif /** number of bytes used in hwaddr */ - unsigned char hwaddr_len; + u8_t hwaddr_len; /** link level hardware address of this interface */ - unsigned char hwaddr[NETIF_MAX_HWADDR_LEN]; + u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; /** maximum transfer unit (in bytes) */ u16_t mtu; + /** flags (see NETIF_FLAG_ above) */ + u8_t flags; + /** link type */ + u8_t link_type; /** descriptive abbreviation */ char name[2]; /** number of this interface */ u8_t num; - /** NETIF_FLAG_* */ - u8_t flags; }; /** The list of network interfaces. */ @@ -139,5 +143,8 @@ void netif_set_default(struct netif *net void netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr); void netif_set_netmask(struct netif *netif, struct ip_addr *netmast); void netif_set_gw(struct netif *netif, struct ip_addr *gw); +void netif_set_up(struct netif *netif); +void netif_set_down(struct netif *netif); +u8_t netif_is_up(struct netif *netif); #endif /* __LWIP_NETIF_H__ */
--- a/packages/net/lwip_tcpip/current/include/lwip/opt.h +++ b/packages/net/lwip_tcpip/current/include/lwip/opt.h @@ -68,7 +68,7 @@ a lot of data that needs to be copied, t #endif #ifndef MEMP_SANITY_CHECK -#define MEMP_SANITY_CHECK 0 +#define MEMP_SANITY_CHECK 0 #endif /* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application @@ -146,10 +146,10 @@ a lot of data that needs to be copied, t #endif /* PBUF_LINK_HLEN: the number of bytes that should be allocated for a - link level header. */ + link level header. Defaults to 14 for Ethernet. */ #ifndef PBUF_LINK_HLEN -#define PBUF_LINK_HLEN 0 +#define PBUF_LINK_HLEN 14 #endif @@ -163,17 +163,23 @@ a lot of data that needs to be copied, t /** * If enabled, outgoing packets are queued during hardware address - * resolution. The etharp.c implementation queues 1 packet only. + * resolution. + * + * This feature has not stabilized yet. Single-packet queueing is + * believed to be stable, multi-packet queueing is believed to + * clash with the TCP segment queueing. + * + * As multi-packet-queueing is currently disabled, enabling this + * _should_ work, but we need your testing feedback on lwip-users. + * */ #ifndef ARP_QUEUEING #define ARP_QUEUEING 1 #endif -/** If enabled, the first packet queued will not be overwritten by - * later packets. If disabled, later packets overwrite early packets - * in the queue. Default is disabled, which is recommended. - */ -#ifndef ARP_QUEUE_FIRST -#define ARP_QUEUE_FIRST 0 + +/* This option is deprecated */ +#ifdef ETHARP_QUEUE_FIRST +#error ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h. #endif /* This option is removed to comply with the ARP standard */ @@ -305,7 +311,7 @@ a lot of data that needs to be copied, t /* Support loop interface (127.0.0.1) */ #ifndef LWIP_HAVE_LOOPIF -#define LWIP_HAVE_LOOPIF 1 +#define LWIP_HAVE_LOOPIF 0 #endif #ifndef LWIP_EVENT_API @@ -340,8 +346,11 @@ a lot of data that needs to be copied, t /* ---------- Socket Options ---------- */ /* Enable SO_REUSEADDR and SO_REUSEPORT options */ -#ifndef SO_REUSE -# define SO_REUSE 1 +#define SO_REUSE 0 +#if SO_REUSE +/* I removed the lot since this was an ugly hack. It broke the raw-API. + It also came with many ugly goto's, Christiaan Simons. */ +#error "SO_REUSE currently unavailable, this was a hack" #endif @@ -357,63 +366,63 @@ a lot of data that needs to be copied, t #endif #ifndef LINK_STATS -#define LINK_STATS 1 +#define LINK_STATS 1 #endif #ifndef IP_STATS -#define IP_STATS 1 +#define IP_STATS 1 #endif #ifndef IPFRAG_STATS -#define IPFRAG_STATS 1 +#define IPFRAG_STATS 1 #endif #ifndef ICMP_STATS -#define ICMP_STATS 1 +#define ICMP_STATS 1 #endif #ifndef UDP_STATS -#define UDP_STATS 1 +#define UDP_STATS 1 #endif #ifndef TCP_STATS -#define TCP_STATS 1 +#define TCP_STATS 1 #endif #ifndef MEM_STATS -#define MEM_STATS 1 +#define MEM_STATS 1 #endif #ifndef MEMP_STATS -#define MEMP_STATS 1 +#define MEMP_STATS 1 #endif #ifndef PBUF_STATS -#define PBUF_STATS 1 +#define PBUF_STATS 1 #endif #ifndef SYS_STATS -#define SYS_STATS 1 +#define SYS_STATS 1 #endif #ifndef RAW_STATS -#define RAW_STATS 0 +#define RAW_STATS 0 #endif #else -#define LINK_STATS 0 -#define IP_STATS 0 -#define IPFRAG_STATS 0 -#define ICMP_STATS 0 -#define UDP_STATS 0 -#define TCP_STATS 0 -#define MEM_STATS 0 -#define MEMP_STATS 0 -#define PBUF_STATS 0 -#define SYS_STATS 0 -#define RAW_STATS 0 -#define LWIP_STATS_DISPLAY 0 +#define LINK_STATS 0 +#define IP_STATS 0 +#define IPFRAG_STATS 0 +#define ICMP_STATS 0 +#define UDP_STATS 0 +#define TCP_STATS 0 +#define MEM_STATS 0 +#define MEMP_STATS 0 +#define PBUF_STATS 0 +#define SYS_STATS 0 +#define RAW_STATS 0 +#define LWIP_STATS_DISPLAY 0 #endif /* LWIP_STATS */
--- a/packages/net/lwip_tcpip/current/include/lwip/pbuf.h +++ b/packages/net/lwip_tcpip/current/include/lwip/pbuf.h @@ -53,8 +53,8 @@ typedef enum { PBUF_POOL } pbuf_flag; -/* Definitions for the pbuf flag field (these are not the flags that - are passed to pbuf_alloc()). */ +/* Definitions for the pbuf flag field. These are NOT the flags that + * are passed to pbuf_alloc(). */ #define PBUF_FLAG_RAM 0x00U /* Flags that pbuf data is stored in RAM */ #define PBUF_FLAG_ROM 0x01U /* Flags that pbuf data is stored in ROM */ #define PBUF_FLAG_POOL 0x02U /* Flags that the pbuf comes from the pbuf pool */ @@ -79,10 +79,10 @@ struct pbuf { */ u16_t tot_len; - /* length of this buffer */ + /** length of this buffer */ u16_t len; - /* flags telling the type of pbuf */ + /** flags telling the type of pbuf, see PBUF_FLAG_ */ u16_t flags; /** @@ -94,11 +94,6 @@ struct pbuf { }; -/* pbuf_init(): - - Initializes the pbuf module. The num parameter determines how many - pbufs that should be allocated to the pbuf pool, and the size - parameter specifies the size of the data allocated to those. */ void pbuf_init(void); struct pbuf *pbuf_alloc(pbuf_layer l, u16_t size, pbuf_flag flag);
--- a/packages/net/lwip_tcpip/current/include/lwip/raw.h +++ b/packages/net/lwip_tcpip/current/include/lwip/raw.h @@ -46,7 +46,7 @@ struct raw_pcb { u16_t protocol; - int (* recv)(void *arg, struct raw_pcb *pcb, struct pbuf *p, + u8_t (* recv)(void *arg, struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *addr); void *recv_arg; }; @@ -59,15 +59,15 @@ err_t raw_bind (struct err_t raw_connect (struct raw_pcb *pcb, struct ip_addr *ipaddr); void raw_recv (struct raw_pcb *pcb, - int (* recv)(void *arg, struct raw_pcb *pcb, + u8_t (* recv)(void *arg, struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *addr), void *recv_arg); -err_t raw_send_to (struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr); +err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr); err_t raw_send (struct raw_pcb *pcb, struct pbuf *p); /* The following functions are the lower layer interface to RAW. */ -int raw_input (struct pbuf *p, struct netif *inp); +u8_t raw_input (struct pbuf *p, struct netif *inp); void raw_init (void);
--- a/packages/net/lwip_tcpip/current/include/lwip/sockets.h +++ b/packages/net/lwip_tcpip/current/include/lwip/sockets.h @@ -209,7 +209,11 @@ struct linger { * only define this in sockets.c so it does not interfere * with other projects namespaces where timeval is present */ -#ifdef LWIP_TIMEVAL_PRIVATE +#ifndef LWIP_TIMEVAL_PRIVATE +#define LWIP_TIMEVAL_PRIVATE 1 +#endif + +#if LWIP_TIMEVAL_PRIVATE struct timeval { long tv_sec; /* seconds */ long tv_usec; /* and microseconds */
--- a/packages/net/lwip_tcpip/current/include/lwip/tcp.h +++ b/packages/net/lwip_tcpip/current/include/lwip/tcp.h @@ -105,6 +105,7 @@ void tcp_input (struct pbu /* Used within the TCP code only: */ err_t tcp_output (struct tcp_pcb *pcb); void tcp_rexmit (struct tcp_pcb *pcb); +void tcp_rexmit_rto (struct tcp_pcb *pcb); @@ -112,7 +113,11 @@ void tcp_rexmit (struct tcp #define TCP_SEQ_LEQ(a,b) ((s32_t)((a)-(b)) <= 0) #define TCP_SEQ_GT(a,b) ((s32_t)((a)-(b)) > 0) #define TCP_SEQ_GEQ(a,b) ((s32_t)((a)-(b)) >= 0) - +/* is b<=a<=c? */ +#if 0 /* see bug #10548 */ +#define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b)) +#endif +#define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c)) #define TCP_FIN 0x01U #define TCP_SYN 0x02U #define TCP_RST 0x04U @@ -208,18 +213,13 @@ enum tcp_state { TIME_WAIT = 10 }; - /* the TCP protocol control block */ struct tcp_pcb { -/* Common members of all PCB types */ +/** common PCB members */ IP_PCB; - -/* Protocol specific PCB members */ - - struct tcp_pcb *next; /* for the linked list */ - - enum tcp_state state; /* TCP state */ - +/** protocol specific PCB members */ + struct tcp_pcb *next; /* for the linked list */ + enum tcp_state state; /* TCP state */ u8_t prio; void *callback_arg; @@ -235,7 +235,7 @@ struct tcp_pcb { #define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */ #define TF_NODELAY (u8_t)0x40U /* Disable Nagle algorithm */ - /* receiver varables */ + /* receiver variables */ u32_t rcv_nxt; /* next seqno expected */ u16_t rcv_wnd; /* receiver window */ @@ -248,10 +248,10 @@ struct tcp_pcb { u16_t mss; /* maximum segment size */ - /* RTT estimation variables. */ - u16_t rttest; /* RTT estimate in 500ms ticks */ + /* RTT (round trip time) estimation variables */ + u32_t rttest; /* RTT estimate in 500ms ticks */ u32_t rtseq; /* sequence number being timed */ - s16_t sa, sv; + s16_t sa, sv; /* @todo document this */ u16_t rto; /* retransmission time-out */ u8_t nrtx; /* number of retransmissions */ @@ -375,7 +375,7 @@ err_t lwip_tcp_event(void *arg, struct t #define TCP_EVENT_RECV(pcb,p,err,ret) \ if((pcb)->recv != NULL) \ { ret = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); } else { \ - if (p) pbuf_free(p); } + if (p) pbuf_free(p); } #define TCP_EVENT_CONNECTED(pcb,err,ret) \ if((pcb)->connected != NULL) \ (ret = (pcb)->connected((pcb)->callback_arg,(pcb),(err))) @@ -387,7 +387,7 @@ err_t lwip_tcp_event(void *arg, struct t (errf)((arg),(err)) #endif /* LWIP_EVENT_API */ -/* This structure is used to repressent TCP segments when queued. */ +/* This structure represents a TCP segment on the unsent and unacked queues */ struct tcp_seg { struct tcp_seg *next; /* used when putting segements on a queue */ struct pbuf *p; /* buffer containing data + TCP header */ @@ -439,7 +439,7 @@ void tcp_debug_print(struct tcp_hdr *tcp void tcp_debug_print_flags(u8_t flags); void tcp_debug_print_state(enum tcp_state s); void tcp_debug_print_pcbs(void); -int tcp_pcbs_sane(void); +s16_t tcp_pcbs_sane(void); #else # define tcp_debug_print(tcphdr) # define tcp_debug_print_flags(flags)
--- a/packages/net/lwip_tcpip/current/include/lwip/udp.h +++ b/packages/net/lwip_tcpip/current/include/lwip/udp.h @@ -95,7 +95,7 @@ void udp_input (struct void udp_init (void); #if UDP_DEBUG -int udp_debug_print(struct udp_hdr *udphdr); +void udp_debug_print(struct udp_hdr *udphdr); #else #define udp_debug_print(udphdr) #endif
--- a/packages/net/lwip_tcpip/current/include/lwipopts.h +++ b/packages/net/lwip_tcpip/current/include/lwipopts.h @@ -93,22 +93,13 @@ a lot of data that needs to be copied, t #define PBUF_LINK_HLEN CYGNUM_LWIP_PBUF_LINK_HLEN /* ---------- TCP options ---------- */ -#ifdef CYGFUN_LWIP_TCP -#define LWIP_TCP 1 -#else -#define LWIP_TCP 0 -#endif - +#define LWIP_TCP defined(CYGPKG_LWIP_TCP) #define TCP_TTL CYGNUM_LWIP_TCP_TTL /* Controls if TCP should queue segments that arrive out of order. Define to 0 if your device is low on memory. */ -#ifdef CYGIMP_LWIP_TCP_QUEUE_OOSEQ -#define TCP_QUEUE_OOSEQ 1 -#else -#define TCP_QUEUE_OOSEQ 0 -#endif - +#define TCP_QUEUE_OOSEQ defined(CYGIMP_LWIP_TCP_QUEUE_OOSEQ) + /* TCP Maximum segment size. */ #define TCP_MSS CYGNUM_LWIP_TCP_MSS @@ -136,19 +127,13 @@ a lot of data that needs to be copied, t /* Define IP_FORWARD to 1 if you wish to have the ability to forward IP packets across network interfaces. If you are going to run lwIP on a device with only one network interface, define this to 0. */ -#ifdef CYGFUN_LWIP_IP_FORWARD -#define IP_FORWARD 1 -#else -#define IP_FORWARD 0 -#endif +#define IP_FORWARD defined(CYGFUN_LWIP_IP_FORWARD) + /* If defined to 1, IP options are allowed (but not parsed). If defined to 0, all packets with IP options are dropped. */ -#ifdef CYGFUN_LWIP_IP_OPTIONS -#define IP_OPTIONS 1 -#else -#define IP_OPTIONS 0 -#endif +#define IP_OPTIONS defined(CYGFUN_LWIP_IP_OPTIONS) + /* ---------- ICMP options ---------- */ #define ICMP_TTL CYGNUM_LWIP_ICMP_TTL @@ -157,84 +142,45 @@ a lot of data that needs to be copied, t /* ---------- DHCP options ---------- */ /* Define LWIP_DHCP to 1 if you want DHCP configuration of interfaces.*/ - -#ifdef CYGPKG_LWIP_DHCP - #define LWIP_DHCP 1 - -/* 1 if you want to do an ARP check on the offered address - (recommended). */ - #ifdef CYGOPT_LWIP_DHCP_DOES_ARP_CHECK - #define DHCP_DOES_ARP_CHECK 1 - #else - #define DHCP_DOES_ARP_CHECK 0 - #endif -#else - #define LWIP_DHCP 0 - #define DHCP_DOES_ARP_CHECK 0 -#endif +#define LWIP_DHCP defined(CYGPKG_LWIP_DHCP) +#define DHCP_DOES_ARP_CHECK defined(CYGOPT_LWIP_DHCP_DOES_ARP_CHECK) /* ---------- UDP options ---------- */ -#ifdef CYGFUN_LWIP_UDP -#define LWIP_UDP 1 -#else -#define LWIP_UDP 0 -#endif +#define LWIP_UDP defined(CYGPKG_LWIP_UDP) #define UDP_TTL CYGNUM_LWIP_UDP_TTL /* ---------- RAW socket support ---------- */ -#ifdef CYGFUN_LWIP_RAW -#define LWIP_RAW 1 -#else -#define LWIP_RAW 0 -#endif +#define LWIP_RAW defined(CYGFUN_LWIP_RAW) /* ---------- SLIP options --------- */ -#ifdef CYGPKG_LWIP_SLIP -#define LWIP_SLIP 1 -#else -#define LWIP_SLIP 0 -#endif +#define LWIP_SLIP defined(CYGPKG_LWIP_SLIP) #define SLIP_DEV CYGDAT_LWIP_SLIP_DEV -#ifdef CYGFUN_LWIP_LOOPIF -#define LWIP_HAVE_LOOPIF 1 -#else -#define LWIP_HAVE_LOOPIF 0 -#endif +/* ---------- LOOPIF options --------- */ +#define LWIP_HAVE_LOOPIF defined(CYGFUN_LWIP_LOOPIF) + /* ---------- PPP options --------- */ -#ifdef CYGPKG_LWIP_PPP -#define PPP_SUPPORT 1 -#else -#define PPP_SUPPORT 0 -#endif +#define PPP_SUPPORT defined(CYGPKG_LWIP_PPP) #define PPP_DEV CYGDAT_LWIP_PPP_DEV #define MD5_SUPPORT 1 +#define PAP_SUPPORT defined(CYGIMP_LWIP_PPP_PAP_AUTH) +#define CHAP_SUPPORT defined(CYGIMP_LWIP_PPP_CHAP_AUTH) -#ifdef CYGIMP_LWIP_PPP_PAP_AUTH -#define PAP_SUPPORT 1 -#else -#define PAP_SUPPORT 0 -#endif - -#ifdef CYGIMP_LWIP_PPP_CHAP_AUTH -#define CHAP_SUPPORT 1 -#else -#define CHAP_SUPPORT 0 -#endif /* ------- Thread priorities ---------------*/ -#define TCPIP_THREAD_PRIO CYGNUM_LWIP_TCPIP_THREAD_PRIORITY +#define TCPIP_THREAD_PRIO CYGNUM_LWIP_NETWORK_THREAD_PRIORITY #define SLIPIF_THREAD_PRIO CYGNUM_LWIP_SLIPIF_THREAD_PRIORITY #define PPP_THREAD_PRIO CYGNUM_LWIP_PPP_THREAD_PRIORITY /* ---------- Statistics options ---------- */ -#ifdef CYGDBG_LWIP_STATS -#define LWIP_STATS 1 -#else -#define LWIP_STATS 0 -#endif +#define LWIP_STATS defined(CYGDBG_LWIP_STATS) + + +// --------- Sockets options -------------- +#define LWIP_COMPAT_SOCKETS defined(CYGFUN_LWIP_COMPAT_SOCKETS) + /* ---------- Debug options ---------- */ #if !defined(CYGDBG_LWIP_ASSERTS)
--- a/packages/net/lwip_tcpip/current/include/network.h +++ b/packages/net/lwip_tcpip/current/include/network.h @@ -1,6 +1,76 @@ -/* network.h for compatibility with the other eCos network stacks */ +#ifndef CYGONCE_NETWORK_H +#define CYGONCE_NETWORK_H +//============================================================================= +// +// network.h +// +// Misc network support +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2002 Nick Garnett +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Jani Monoses +// Contributors: Jani Monoses +// Date: 2006-03-23 +// Purpose: +// Description: +// +// +// +//####DESCRIPTIONEND#### +// +//============================================================================= -#include <lwip/sys.h> /* lwIP stack includes */ -#define LWIP_COMPAT_SOCKETS 1 +#ifdef __cplusplus +extern "C" { +#endif + + +//============================================================================= +// INCLUDES +//============================================================================= +#include <lwip/sys.h> // lwIP stack includes #include <lwip/sockets.h> #include <lwip/inet.h> + + +#ifdef __cplusplus +} +#endif + +//----------------------------------------------------------------------------- +#endif // #ifndef CYGONCE_NETWORK_H
--- a/packages/net/lwip_tcpip/current/src/api/api_lib.c +++ b/packages/net/lwip_tcpip/current/src/api/api_lib.c @@ -165,7 +165,7 @@ netbuf_copy_partial(struct netbuf *buf, offset -= p->len; } else { for(i = offset; i < p->len; ++i) { - ((char *)dataptr)[left] = ((char *)p->payload)[i]; + ((u8_t *)dataptr)[left] = ((u8_t *)p->payload)[i]; if (++left >= len) { return; } @@ -280,9 +280,10 @@ netconn_delete(struct netconn *conn) if (conn->recvmbox != SYS_MBOX_NULL) { while (sys_arch_mbox_fetch(conn->recvmbox, &mem, 1) != SYS_ARCH_TIMEOUT) { if (conn->type == NETCONN_TCP) { - pbuf_free((struct pbuf *)mem); + if(mem != NULL) + pbuf_free((struct pbuf *)mem); } else { - netbuf_delete((struct netbuf *)mem); + netbuf_delete((struct netbuf *)mem); } } sys_mbox_free(conn->recvmbox); @@ -321,30 +322,29 @@ netconn_peer(struct netconn *conn, struc u16_t *port) { switch (conn->type) { -#if LWIP_RAW case NETCONN_RAW: /* return an error as connecting is only a helper for upper layers */ return ERR_CONN; -#endif -#if LWIP_UDP case NETCONN_UDPLITE: case NETCONN_UDPNOCHKSUM: case NETCONN_UDP: +#if LWIP_UDP if (conn->pcb.udp == NULL || ((conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0)) return ERR_CONN; *addr = (conn->pcb.udp->remote_ip); *port = conn->pcb.udp->remote_port; +#endif break; -#endif + + case NETCONN_TCP: #if LWIP_TCP - case NETCONN_TCP: if (conn->pcb.tcp == NULL) return ERR_CONN; *addr = (conn->pcb.tcp->remote_ip); *port = conn->pcb.tcp->remote_port; +#endif break; -#endif } return (conn->err = ERR_OK); } @@ -354,26 +354,27 @@ netconn_addr(struct netconn *conn, struc u16_t *port) { switch (conn->type) { + case NETCONN_RAW: #if LWIP_RAW - case NETCONN_RAW: *addr = &(conn->pcb.raw->local_ip); *port = conn->pcb.raw->protocol; +#endif break; -#endif -#if LWIP_UDP case NETCONN_UDPLITE: case NETCONN_UDPNOCHKSUM: case NETCONN_UDP: +#if LWIP_UDP *addr = &(conn->pcb.udp->local_ip); *port = conn->pcb.udp->local_port; +#endif break; -#endif + + case NETCONN_TCP: #if LWIP_TCP - case NETCONN_TCP: *addr = &(conn->pcb.tcp->local_ip); *port = conn->pcb.tcp->local_port; +#endif break; -#endif } return (conn->err = ERR_OK); } @@ -684,7 +685,7 @@ netconn_write(struct netconn *conn, void api_msg_post(msg); sys_mbox_fetch(conn->mbox, NULL); if (conn->err == ERR_OK) { - dataptr = (void *)((char *)dataptr + len); + dataptr = (void *)((u8_t *)dataptr + len); size -= len; } else if (conn->err == ERR_MEM) { conn->err = ERR_OK;
--- a/packages/net/lwip_tcpip/current/src/api/api_msg.c +++ b/packages/net/lwip_tcpip/current/src/api/api_msg.c @@ -38,7 +38,7 @@ #include "lwip/tcpip.h" #if LWIP_RAW -static int +static u8_t recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *addr) { @@ -281,14 +281,16 @@ do_newconn(struct api_msg_msg *msg) /* Allocate a PCB for this connection */ switch(msg->conn->type) { -#if LWIP_RAW case NETCONN_RAW: +#if LWIP_RAW msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field */ raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); +#endif break; -#endif + + + case NETCONN_UDPLITE: #if LWIP_UDP - case NETCONN_UDPLITE: msg->conn->pcb.udp = udp_new(); if(msg->conn->pcb.udp == NULL) { msg->conn->err = ERR_MEM; @@ -297,7 +299,9 @@ do_newconn(struct api_msg_msg *msg) udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); break; +#endif /* LWIP_UDP */ case NETCONN_UDPNOCHKSUM: +#if LWIP_UDP msg->conn->pcb.udp = udp_new(); if(msg->conn->pcb.udp == NULL) { msg->conn->err = ERR_MEM; @@ -306,25 +310,28 @@ do_newconn(struct api_msg_msg *msg) udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM); udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); break; +#endif /* LWIP_UDP */ case NETCONN_UDP: +#if LWIP_UDP msg->conn->pcb.udp = udp_new(); if(msg->conn->pcb.udp == NULL) { msg->conn->err = ERR_MEM; break; } udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); +#endif /* LWIP_UDP */ break; -#endif /* LWIP_UDP */ + + case NETCONN_TCP: #if LWIP_TCP - case NETCONN_TCP: msg->conn->pcb.tcp = tcp_new(); if(msg->conn->pcb.tcp == NULL) { msg->conn->err = ERR_MEM; break; } setup_tcp(msg->conn); +#endif break; -#endif } @@ -559,20 +566,19 @@ do_disconnect(struct api_msg_msg *msg) { switch (msg->conn->type) { -#if LWIP_RAW case NETCONN_RAW: /* Do nothing as connecting is only a helper for upper lwip layers */ break; -#endif -#if LWIP_UDP + case NETCONN_UDPLITE: /* FALLTHROUGH */ case NETCONN_UDPNOCHKSUM: /* FALLTHROUGH */ case NETCONN_UDP: +#if LWIP_UDP udp_disconnect(msg->conn->pcb.udp); +#endif break; -#endif case NETCONN_TCP: break; } @@ -585,37 +591,48 @@ do_listen(struct api_msg_msg *msg) { if (msg->conn->pcb.tcp != NULL) { switch (msg->conn->type) { + + case NETCONN_RAW: #if LWIP_RAW - case NETCONN_RAW: LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: listen RAW: cannot listen for RAW.\n")); +#endif break; -#endif -#if LWIP_UDP + case NETCONN_UDPLITE: /* FALLTHROUGH */ case NETCONN_UDPNOCHKSUM: /* FALLTHROUGH */ case NETCONN_UDP: +#if LWIP_UDP LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: listen UDP: cannot listen for UDP.\n")); - break; #endif /* LWIP_UDP */ -#if LWIP_TCP + break; + + case NETCONN_TCP: +#if LWIP_TCP msg->conn->pcb.tcp = tcp_listen(msg->conn->pcb.tcp); - if (msg->conn->pcb.tcp == NULL) { - msg->conn->err = ERR_MEM; - } else { - if (msg->conn->acceptmbox == SYS_MBOX_NULL) { - msg->conn->acceptmbox = sys_mbox_new(); - if (msg->conn->acceptmbox == SYS_MBOX_NULL) { - msg->conn->err = ERR_MEM; - break; - } - } - tcp_arg(msg->conn->pcb.tcp, msg->conn); - tcp_accept(msg->conn->pcb.tcp, accept_function); + if (msg->conn->pcb.tcp == NULL) + { + msg->conn->err = ERR_MEM; + } + else + { + if (msg->conn->acceptmbox == SYS_MBOX_NULL) + { + msg->conn->acceptmbox = sys_mbox_new(); + if (msg->conn->acceptmbox == SYS_MBOX_NULL) + { + msg->conn->err = ERR_MEM; + break; + } + } + tcp_arg(msg->conn->pcb.tcp, msg->conn); + tcp_accept(msg->conn->pcb.tcp, accept_function); } #endif + break; + default: break; } @@ -628,20 +645,22 @@ do_accept(struct api_msg_msg *msg) { if (msg->conn->pcb.tcp != NULL) { switch (msg->conn->type) { + + case NETCONN_RAW: #if LWIP_RAW - case NETCONN_RAW: LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: accept RAW: cannot accept for RAW.\n")); +#endif break; -#endif -#if LWIP_UDP + case NETCONN_UDPLITE: /* FALLTHROUGH */ case NETCONN_UDPNOCHKSUM: /* FALLTHROUGH */ - case NETCONN_UDP: + case NETCONN_UDP: +#if LWIP_UDP LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: accept UDP: cannot accept for UDP.\n")); +#endif /* LWIP_UDP */ break; -#endif /* LWIP_UDP */ case NETCONN_TCP: break; } @@ -653,20 +672,23 @@ do_send(struct api_msg_msg *msg) { if (msg->conn->pcb.tcp != NULL) { switch (msg->conn->type) { + + case NETCONN_RAW: #if LWIP_RAW - case NETCONN_RAW: raw_send(msg->conn->pcb.raw, msg->msg.p); +#endif break; -#endif -#if LWIP_UDP + case NETCONN_UDPLITE: /* FALLTHROUGH */ case NETCONN_UDPNOCHKSUM: /* FALLTHROUGH */ case NETCONN_UDP: +#if LWIP_UDP udp_send(msg->conn->pcb.udp, msg->msg.p); +#endif /* LWIP_UDP */ break; -#endif /* LWIP_UDP */ + case NETCONN_TCP: break; } @@ -695,22 +717,26 @@ do_write(struct api_msg_msg *msg) #endif if (msg->conn->pcb.tcp != NULL) { switch (msg->conn->type) { + + case NETCONN_RAW: #if LWIP_RAW - case NETCONN_RAW: msg->conn->err = ERR_VAL; +#endif break; -#endif -#if LWIP_UDP + + case NETCONN_UDPLITE: /* FALLTHROUGH */ case NETCONN_UDPNOCHKSUM: /* FALLTHROUGH */ case NETCONN_UDP: +#if LWIP_UDP msg->conn->err = ERR_VAL; - break; #endif /* LWIP_UDP */ -#if LWIP_TCP - case NETCONN_TCP: + break; + + case NETCONN_TCP: +#if LWIP_TCP err = tcp_write(msg->conn->pcb.tcp, msg->msg.w.dataptr, msg->msg.w.len, msg->msg.w.copy); /* This is the Nagle algorithm: inhibit the sending of new TCP @@ -728,6 +754,9 @@ do_write(struct api_msg_msg *msg) (*msg->conn->callback)(msg->conn, NETCONN_EVT_SENDMINUS, msg->msg.w.len); } #endif + break; + + default: break; } @@ -744,25 +773,28 @@ do_close(struct api_msg_msg *msg) if (msg->conn->pcb.tcp != NULL) { switch (msg->conn->type) { -#if LWIP_RAW + case NETCONN_RAW: break; -#endif -#if LWIP_UDP + + case NETCONN_UDPLITE: /* FALLTHROUGH */ case NETCONN_UDPNOCHKSUM: /* FALLTHROUGH */ case NETCONN_UDP: break; -#endif /* LWIP_UDP */ + + + case NETCONN_TCP: #if LWIP_TCP - case NETCONN_TCP: if (msg->conn->pcb.tcp->state == LISTEN) { err = tcp_close(msg->conn->pcb.tcp); } msg->conn->err = err; #endif + break; + default: break; }
--- a/packages/net/lwip_tcpip/current/src/api/sockets.c +++ b/packages/net/lwip_tcpip/current/src/api/sockets.c @@ -32,12 +32,14 @@ * */ +#include <string.h> +#include <errno.h> + #include "lwip/opt.h" #include "lwip/api.h" #include "lwip/arch.h" #include "lwip/sys.h" -#define LWIP_TIMEVAL_PRIVATE #include "lwip/sockets.h" #define NUM_SOCKETS MEMP_NUM_NETCONN @@ -85,9 +87,12 @@ static int err_to_errno_table[11] = { EADDRINUSE /* ERR_USE -10 Address in use. */ }; +#define ERR_TO_ERRNO_TABLE_SIZE \ + (sizeof(err_to_errno_table)/sizeof(err_to_errno_table[0])) + #define err_to_errno(err) \ - ((err) < (sizeof(err_to_errno_table)/sizeof(int))) ? \ - err_to_errno_table[-(err)] : EIO + (-(err) >= 0 && -(err) < ERR_TO_ERRNO_TABLE_SIZE ? \ + err_to_errno_table[-(err)] : EIO) #ifdef ERRNO #define set_errno(err) errno = (err) @@ -416,7 +421,7 @@ lwip_recvfrom(int s, void *mem, int len, ip_addr_debug_print(SOCKETS_DEBUG, addr); LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen)); } else { -#if SOCKETS_DEBUG > 0 +#if SOCKETS_DEBUG addr = netbuf_fromaddr(buf); port = netbuf_fromport(buf); @@ -1159,7 +1164,7 @@ int lwip_getsockopt (int s, int level, i LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", s, (*(int*)optval)?"on":"off") ); break; case TCP_KEEPALIVE: - *(int*)optval = sock->conn->pcb.tcp->keepalive; + *(int*)optval = (int)sock->conn->pcb.tcp->keepalive; LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n", s, *(int *)optval)); break; } /* switch */ @@ -1327,7 +1332,7 @@ int lwip_setsockopt (int s, int level, i break; case TCP_KEEPALIVE: sock->conn->pcb.tcp->keepalive = (u32_t)(*(int*)optval); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %u\n", s, sock->conn->pcb.tcp->keepalive)); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %lu\n", s, sock->conn->pcb.tcp->keepalive)); break; } /* switch */ break;
--- a/packages/net/lwip_tcpip/current/src/api/tcpip.c +++ b/packages/net/lwip_tcpip/current/src/api/tcpip.c @@ -38,6 +38,7 @@ #include "lwip/pbuf.h" #include "lwip/ip.h" +#include "lwip/ip_frag.h" #include "lwip/udp.h" #include "lwip/tcp.h" @@ -46,34 +47,51 @@ static void (* tcpip_init_done)(void *arg) = NULL; static void *tcpip_init_done_arg; static sys_mbox_t mbox; + #if LWIP_TCP static int tcpip_tcp_timer_active = 0; - - static void tcpip_tcp_timer(void *arg) { (void)arg; + /* call TCP timer handler */ tcp_tmr(); + /* timer still needed? */ if (tcp_active_pcbs || tcp_tw_pcbs) { + /* restart timer */ sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); } else { - tcpip_tcp_timer_active = 0; + /* disable timer */ + tcpip_tcp_timer_active = 0; } } +#if !NO_SYS void tcp_timer_needed(void) { + /* timer is off but needed again? */ if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) { - tcpip_tcp_timer_active = 1; + /* enable and start timer */ + tcpip_tcp_timer_active = 1; sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); } } +#endif /* !NO_SYS */ #endif /* LWIP_TCP */ +#if IP_REASSEMBLY +static void +ip_timer(void *data) +{ + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: ip_reass_tmr()\n")); + ip_reass_tmr(); + sys_timeout(1000, ip_timer, NULL); +} +#endif + static void tcpip_thread(void *arg) { @@ -88,6 +106,9 @@ tcpip_thread(void *arg) #if LWIP_TCP tcp_init(); #endif +#if IP_REASSEMBLY + sys_timeout(1000, ip_timer, NULL); +#endif if (tcpip_init_done != NULL) { tcpip_init_done(tcpip_init_done_arg); }
--- a/packages/net/lwip_tcpip/current/src/core/dhcp.c +++ b/packages/net/lwip_tcpip/current/src/core/dhcp.c @@ -67,6 +67,9 @@ * to remove the DHCP client. * */ + +#include <string.h> + #include "lwip/stats.h" #include "lwip/mem.h" #include "lwip/udp.h" @@ -82,7 +85,8 @@ #if LWIP_DHCP /* don't build if not configured for use in lwipopt.h */ /** global transaction identifier, must be - * unique for each DHCP request. */ + * unique for each DHCP request. We simply increment, starting + * with this value (easy to match with a packet analyzer) */ static u32_t xid = 0xABCD0000; /** DHCP client state machine functions */ @@ -96,8 +100,7 @@ static void dhcp_check(struct netif *net static void dhcp_bind(struct netif *netif); static err_t dhcp_decline(struct netif *netif); static err_t dhcp_rebind(struct netif *netif); -static err_t dhcp_release(struct netif *netif); -static void dhcp_set_state(struct dhcp *dhcp, unsigned char new_state); +static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state); /** receive, unfold, parse and free incoming messages */ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port); @@ -141,10 +144,10 @@ static void dhcp_option_trailer(struct d static void dhcp_handle_nak(struct netif *netif) { struct dhcp *dhcp = netif->dhcp; u16_t msecs = 10 * 1000; - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_handle_nak(netif=%p) %c%c%u\n", netif, - netif->name[0], netif->name[1], (unsigned int)netif->num)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n", + (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_handle_nak(): set request timeout %u msecs\n", msecs)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_handle_nak(): set request timeout %"U16_F" msecs\n", msecs)); dhcp_set_state(dhcp, DHCP_BACKING_OFF); } @@ -160,8 +163,8 @@ static void dhcp_check(struct netif *net struct dhcp *dhcp = netif->dhcp; err_t result; u16_t msecs; - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (unsigned int)netif->name[0], - (unsigned int)netif->name[1])); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0], + (s16_t)netif->name[1])); /* create an ARP query for the offered IP address, expecting that no host responds, as the IP address should not be in use. */ result = etharp_query(netif, &dhcp->offered_ip_addr, NULL); @@ -171,7 +174,7 @@ static void dhcp_check(struct netif *net dhcp->tries++; msecs = 500; dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_check(): set request timeout %u msecs\n", msecs)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_check(): set request timeout %"U16_F" msecs\n", msecs)); dhcp_set_state(dhcp, DHCP_CHECKING); } @@ -185,15 +188,15 @@ static void dhcp_handle_offer(struct net struct dhcp *dhcp = netif->dhcp; /* obtain the server address */ u8_t *option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_SERVER_ID); - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_handle_offer(netif=%p) %c%c%u\n", netif, - netif->name[0], netif->name[1], netif->num)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n", + (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); if (option_ptr != NULL) { dhcp->server_ip_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2])); - LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_handle_offer(): server 0x%08lx\n", dhcp->server_ip_addr.addr)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_handle_offer(): server 0x%08"X32_F"\n", dhcp->server_ip_addr.addr)); /* remember offered address */ ip_addr_set(&dhcp->offered_ip_addr, (struct ip_addr *)&dhcp->msg_in->yiaddr); - LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08lx\n", dhcp->offered_ip_addr.addr)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08"X32_F"\n", dhcp->offered_ip_addr.addr)); dhcp_select(netif); } @@ -212,7 +215,7 @@ static err_t dhcp_select(struct netif *n struct dhcp *dhcp = netif->dhcp; err_t result; u32_t msecs; - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_select(netif=%p) %c%c%u\n", netif, netif->name[0], netif->name[1], netif->num)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_select(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); /* create and initialize the DHCP message header */ result = dhcp_create_request(netif); @@ -231,10 +234,11 @@ static err_t dhcp_select(struct netif *n dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr)); - dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 3); + dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/); dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK); dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER); dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST); + dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER); dhcp_option_trailer(dhcp); /* shrink the pbuf to the actual content length */ @@ -257,7 +261,7 @@ static err_t dhcp_select(struct netif *n dhcp->tries++; msecs = dhcp->tries < 4 ? dhcp->tries * 1000 : 4 * 1000; dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_select(): set request timeout %u msecs\n", msecs)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_select(): set request timeout %"U32_F" msecs\n", msecs)); return result; } @@ -293,18 +297,20 @@ void dhcp_coarse_tmr() /** * DHCP transaction timeout handling * - * A DHCP server is expected to respond within a - * short period of time. + * A DHCP server is expected to respond within a short period of time. + * This timer checks whether an outstanding DHCP request is timed out. + * */ void dhcp_fine_tmr() { struct netif *netif = netif_list; - /* loop through clients */ + /* loop through netif's */ while (netif != NULL) { /* only act on DHCP configured interfaces */ if (netif->dhcp != NULL) { - /* timer is active (non zero), and triggers (zeroes) now */ + /* timer is active (non zero), and is about to trigger now */ if (netif->dhcp->request_timeout-- == 1) { + /* { netif->dhcp->request_timeout == 0 } */ LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_fine_tmr(): request timeout\n")); /* this clients' request timeout triggered */ dhcp_timeout(netif); @@ -383,8 +389,8 @@ static void dhcp_t1_timeout(struct netif struct dhcp *dhcp = netif->dhcp; LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_t1_timeout()\n")); if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || (dhcp->state == DHCP_RENEWING)) { - /* just retry to renew */ - /* note that the rebind timer will eventually time-out if renew does not work */ + /* just retry to renew - note that the rebind timer (t2) will + * eventually time-out if renew tries fail. */ LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_t1_timeout(): must renew\n")); dhcp_renew(netif); } @@ -479,6 +485,19 @@ static void dhcp_handle_ack(struct netif if (option_ptr != NULL) { dhcp->offered_bc_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2])); } + + /* DNS servers */ + option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_DNS_SERVER); + if (option_ptr != NULL) { + u8_t n; + dhcp->dns_count = dhcp_get_option_byte(&option_ptr[1]); + /* limit to at most DHCP_MAX_DNS DNS servers */ + if (dhcp->dns_count > DHCP_MAX_DNS) dhcp->dns_count = DHCP_MAX_DNS; + for (n = 0; n < dhcp->dns_count; n++) + { + dhcp->offered_dns_addr[n].addr = htonl(dhcp_get_option_long(&option_ptr[2+(n<<2)])); + } + } } /** @@ -500,40 +519,44 @@ err_t dhcp_start(struct netif *netif) err_t result = ERR_OK; LWIP_ASSERT("netif != NULL", netif != NULL); - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_start(netif=%p) %c%c%u\n", netif, netif->name[0], netif->name[1], netif->num)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + netif->flags &= ~NETIF_FLAG_DHCP; + /* no DHCP client attached yet? */ if (dhcp == NULL) { LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): starting new DHCP client\n")); dhcp = mem_malloc(sizeof(struct dhcp)); if (dhcp == NULL) { LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n")); - netif->flags &= ~NETIF_FLAG_DHCP; - return ERR_MEM; - } - /* clear data structure */ - memset(dhcp, 0, sizeof(struct dhcp)); - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): allocated dhcp")); - dhcp->pcb = udp_new(); - if (dhcp->pcb == NULL) { - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): could not obtain pcb\n")); - mem_free((void *)dhcp); - dhcp = NULL; - netif->flags &= ~NETIF_FLAG_DHCP; return ERR_MEM; } /* store this dhcp client in the netif */ netif->dhcp = dhcp; - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): created new udp pcb\n")); - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n")); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): allocated dhcp")); + /* already has DHCP client attached */ } else { LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE | 3, ("dhcp_start(): restarting DHCP configuration\n")); } + + /* clear data structure */ + memset(dhcp, 0, sizeof(struct dhcp)); + /* allocate UDP PCB */ + dhcp->pcb = udp_new(); + if (dhcp->pcb == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): could not obtain pcb\n")); + mem_free((void *)dhcp); + netif->dhcp = dhcp = NULL; + return ERR_MEM; + } + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n")); /* (re)start the DHCP negotiation */ result = dhcp_discover(netif); if (result != ERR_OK) { /* free resources allocated above */ dhcp_stop(netif); + return ERR_MEM; } + netif->flags |= NETIF_FLAG_DHCP; return result; } @@ -610,10 +633,11 @@ void dhcp_inform(struct netif *netif) */ void dhcp_arp_reply(struct netif *netif, struct ip_addr *addr) { + LWIP_ASSERT("netif != NULL", netif != NULL); LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_arp_reply()\n")); - /* is this DHCP client doing an ARP check? */ + /* is a DHCP client doing an ARP check? */ if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_CHECKING)) { - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08lx\n", addr->addr)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n", addr->addr)); /* did a host respond with the address we were offered by the DHCP server? */ if (ip_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) { @@ -656,8 +680,10 @@ static err_t dhcp_decline(struct netif * pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT); - udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT); - udp_send(dhcp->pcb, dhcp->p_out); + /* @todo: should we really connect here? we are performing sendto() */ + udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT); + /* per section 4.4.4, broadcast DECLINE messages */ + udp_sendto(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT); dhcp_delete_request(netif); LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_decline: BACKING OFF\n")); } else { @@ -666,7 +692,7 @@ static err_t dhcp_decline(struct netif * dhcp->tries++; msecs = 10*1000; dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_decline(): set request timeout %u msecs\n", msecs)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_decline(): set request timeout %"U16_F" msecs\n", msecs)); return result; } #endif @@ -694,10 +720,11 @@ static err_t dhcp_discover(struct netif dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); dhcp_option_short(dhcp, 576); - dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 3); + dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/); dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK); dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER); dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST); + dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER); dhcp_option_trailer(dhcp); @@ -720,7 +747,7 @@ static err_t dhcp_discover(struct netif dhcp->tries++; msecs = dhcp->tries < 4 ? (dhcp->tries + 1) * 1000 : 10 * 1000; dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_discover(): set request timeout %u msecs\n", msecs)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs)); return result; } @@ -736,22 +763,22 @@ static void dhcp_bind(struct netif *neti struct ip_addr sn_mask, gw_addr; LWIP_ASSERT("dhcp_bind: netif != NULL", netif != NULL); LWIP_ASSERT("dhcp_bind: dhcp != NULL", dhcp != NULL); - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_bind(netif=%p) %c%c%u\n", netif, netif->name[0], netif->name[1], netif->num)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_bind(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); /* temporary DHCP lease? */ if (dhcp->offered_t1_renew != 0xffffffffUL) { /* set renewal period timer */ - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_bind(): t1 renewal timer %lu secs\n", dhcp->offered_t1_renew)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_bind(): t1 renewal timer %"U32_F" secs\n", dhcp->offered_t1_renew)); dhcp->t1_timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; if (dhcp->t1_timeout == 0) dhcp->t1_timeout = 1; - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_bind(): set request timeout %u msecs\n", dhcp->offered_t1_renew*1000)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t1_renew*1000)); } /* set renewal period timer */ if (dhcp->offered_t2_rebind != 0xffffffffUL) { - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_bind(): t2 rebind timer %lu secs\n", dhcp->offered_t2_rebind)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_bind(): t2 rebind timer %"U32_F" secs\n", dhcp->offered_t2_rebind)); dhcp->t2_timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; if (dhcp->t2_timeout == 0) dhcp->t2_timeout = 1; - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_bind(): set request timeout %u msecs\n", dhcp->offered_t2_rebind*1000)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind*1000)); } /* copy offered network mask */ ip_addr_set(&sn_mask, &dhcp->offered_sn_mask); @@ -775,12 +802,14 @@ static void dhcp_bind(struct netif *neti gw_addr.addr |= htonl(0x00000001); } - LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): IP: 0x%08lx\n", dhcp->offered_ip_addr.addr)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F"\n", dhcp->offered_ip_addr.addr)); netif_set_ipaddr(netif, &dhcp->offered_ip_addr); - LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): SN: 0x%08lx\n", sn_mask.addr)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): SN: 0x%08"X32_F"\n", sn_mask.addr)); netif_set_netmask(netif, &sn_mask); - LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): GW: 0x%08lx\n", gw_addr.addr)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): GW: 0x%08"X32_F"\n", gw_addr.addr)); netif_set_gw(netif, &gw_addr); + /* bring the interface up */ + netif_set_up(netif); /* netif is now bound to DHCP leased address */ dhcp_set_state(dhcp, DHCP_BOUND); } @@ -836,7 +865,7 @@ err_t dhcp_renew(struct netif *netif) /* back-off on retries, but to a maximum of 20 seconds */ msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000; dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_renew(): set request timeout %u msecs\n", msecs)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_renew(): set request timeout %"U16_F" msecs\n", msecs)); return result; } @@ -889,7 +918,7 @@ static err_t dhcp_rebind(struct netif *n dhcp->tries++; msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_rebind(): set request timeout %u msecs\n", msecs)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_rebind(): set request timeout %"U16_F" msecs\n", msecs)); return result; } @@ -898,7 +927,7 @@ static err_t dhcp_rebind(struct netif *n * * @param netif network interface which must release its lease */ -static err_t dhcp_release(struct netif *netif) +err_t dhcp_release(struct netif *netif) { struct dhcp *dhcp = netif->dhcp; err_t result; @@ -907,8 +936,13 @@ static err_t dhcp_release(struct netif * /* idle DHCP client */ dhcp_set_state(dhcp, DHCP_OFF); - - + /* clean old DHCP offer */ + dhcp->server_ip_addr.addr = 0; + dhcp->offered_ip_addr.addr = dhcp->offered_sn_mask.addr = 0; + dhcp->offered_gw_addr.addr = dhcp->offered_bc_addr.addr = 0; + dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0; + dhcp->dns_count = 0; + /* create and initialize the DHCP message header */ result = dhcp_create_request(netif); if (result == ERR_OK) { @@ -930,11 +964,14 @@ static err_t dhcp_release(struct netif * dhcp->tries++; msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_release(): set request timeout %u msecs\n", msecs)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_release(): set request timeout %"U16_F" msecs\n", msecs)); + /* bring the interface down */ + netif_set_down(netif); /* remove IP address from interface */ netif_set_ipaddr(netif, IP_ADDR_ANY); netif_set_gw(netif, IP_ADDR_ANY); netif_set_netmask(netif, IP_ADDR_ANY); + /* TODO: netif_down(netif); */ return result; } @@ -976,7 +1013,7 @@ void dhcp_stop(struct netif *netif) * * TODO: we might also want to reset the timeout here? */ -static void dhcp_set_state(struct dhcp *dhcp, unsigned char new_state) +static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state) { if (new_state != dhcp->state) { @@ -1072,7 +1109,7 @@ static err_t dhcp_unfold_reply(struct dh j = 0; } } - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_unfold_reply(): copied %u bytes into dhcp->msg_in[]\n", i)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_unfold_reply(): copied %"U16_F" bytes into dhcp->msg_in[]\n", i)); if (dhcp->options_in != NULL) { ptr = (u8_t *)dhcp->options_in; /* proceed through options */ @@ -1085,7 +1122,7 @@ static err_t dhcp_unfold_reply(struct dh j = 0; } } - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_unfold_reply(): copied %u bytes to dhcp->options_in[]\n", i)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_unfold_reply(): copied %"U16_F" bytes to dhcp->options_in[]\n", i)); } return ERR_OK; } @@ -1121,17 +1158,17 @@ static void dhcp_recv(void *arg, struct u8_t *options_ptr; u8_t msg_type; u8_t i; - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_recv(pbuf = %p) from DHCP server %u.%u.%u.%u port %u\n", p, - (unsigned int)(ntohl(addr->addr) >> 24 & 0xff), (unsigned int)(ntohl(addr->addr) >> 16 & 0xff), - (unsigned int)(ntohl(addr->addr) >> 8 & 0xff), (unsigned int)(ntohl(addr->addr) & 0xff), port)); - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("pbuf->len = %u\n", p->len)); - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("pbuf->tot_len = %u\n", p->tot_len)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p, + (u16_t)(ntohl(addr->addr) >> 24 & 0xff), (u16_t)(ntohl(addr->addr) >> 16 & 0xff), + (u16_t)(ntohl(addr->addr) >> 8 & 0xff), (u16_t)(ntohl(addr->addr) & 0xff), port)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len)); /* prevent warnings about unused arguments */ (void)pcb; (void)addr; (void)port; dhcp->p = p; /* TODO: check packet length before reading them */ if (reply_msg->op != DHCP_BOOTREPLY) { - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("not a DHCP reply message, but type %u\n", reply_msg->op)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("not a DHCP reply message, but type %"U16_F"\n", (u16_t)reply_msg->op)); pbuf_free(p); dhcp->p = NULL; return; @@ -1139,8 +1176,8 @@ static void dhcp_recv(void *arg, struct /* iterate through hardware address and match against DHCP message */ for (i = 0; i < netif->hwaddr_len; i++) { if (netif->hwaddr[i] != reply_msg->chaddr[i]) { - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("netif->hwaddr[%u]==%02x != reply_msg->chaddr[%u]==%02x\n", - i, netif->hwaddr[i], i, reply_msg->chaddr[i])); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n", + (u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i])); pbuf_free(p); dhcp->p = NULL; return; @@ -1280,7 +1317,7 @@ static void dhcp_option_trailer(struct d dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END; /* packet is too small, or not 4 byte aligned? */ while ((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) { - /* LWIP_DEBUGF(DHCP_DEBUG, ("dhcp_option_trailer: dhcp->options_out_len=%u, DHCP_OPTIONS_LEN=%u", dhcp->options_out_len, DHCP_OPTIONS_LEN)); */ + /* LWIP_DEBUGF(DHCP_DEBUG,("dhcp_option_trailer:dhcp->options_out_len=%"U16_F", DHCP_OPTIONS_LEN=%"U16_F, dhcp->options_out_len, DHCP_OPTIONS_LEN)); */ LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN); /* add a fill/padding byte */ dhcp->msg_out->options[dhcp->options_out_len++] = 0; @@ -1307,7 +1344,7 @@ static u8_t *dhcp_get_option_ptr(struct u16_t offset = 0; /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */ while ((offset < dhcp->options_in_len) && (options[offset] != DHCP_OPTION_END)) { - /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%u, q->len=%u", msg_offset, q->len)); */ + /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */ /* are the sname and/or file field overloaded with options? */ if (options[offset] == DHCP_OPTION_OVERLOAD) { LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("overloaded message detected\n")); @@ -1317,11 +1354,11 @@ static u8_t *dhcp_get_option_ptr(struct } /* requested option found */ else if (options[offset] == option_type) { - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("option found at offset %u in options\n", offset)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("option found at offset %"U16_F" in options\n", offset)); return &options[offset]; /* skip option */ } else { - LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %u in options\n", options[offset])); + LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %"U16_F" in options\n", options[offset])); /* skip option type */ offset++; /* skip option length, and then length bytes */ @@ -1350,11 +1387,11 @@ static u8_t *dhcp_get_option_ptr(struct /* at least 1 byte to read and no end marker */ while ((offset < field_len) && (options[offset] != DHCP_OPTION_END)) { if (options[offset] == option_type) { - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("option found at offset=%u\n", offset)); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("option found at offset=%"U16_F"\n", offset)); return &options[offset]; /* skip option */ } else { - LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("skipping option %u\n", options[offset])); + LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("skipping option %"U16_F"\n", options[offset])); /* skip option type */ offset++; offset += 1 + options[offset]; @@ -1375,7 +1412,7 @@ static u8_t *dhcp_get_option_ptr(struct */ static u8_t dhcp_get_option_byte(u8_t *ptr) { - LWIP_DEBUGF(DHCP_DEBUG, ("option byte value=%u\n", *ptr)); + LWIP_DEBUGF(DHCP_DEBUG, ("option byte value=%"U16_F"\n", (u16_t)(*ptr))); return *ptr; } @@ -1392,7 +1429,7 @@ static u16_t dhcp_get_option_short(u8_t u16_t value; value = *ptr++ << 8; value |= *ptr; - LWIP_DEBUGF(DHCP_DEBUG, ("option short value=%u\n", value)); + LWIP_DEBUGF(DHCP_DEBUG, ("option short value=%"U16_F"\n", value)); return value; } @@ -1411,7 +1448,7 @@ static u32_t dhcp_get_option_long(u8_t * value |= (u32_t)(*ptr++) << 16; value |= (u32_t)(*ptr++) << 8; value |= (u32_t)(*ptr++); - LWIP_DEBUGF(DHCP_DEBUG, ("option long value=%lu\n", value)); + LWIP_DEBUGF(DHCP_DEBUG, ("option long value=%"U32_F"\n", value)); return value; }
--- a/packages/net/lwip_tcpip/current/src/core/inet.c +++ b/packages/net/lwip_tcpip/current/src/core/inet.c @@ -46,36 +46,195 @@ #include "lwip/def.h" #include "lwip/inet.h" +#include "lwip/sys.h" +/* This is a reference implementation of the checksum algorithm, with the + * aim of being simple, correct and fully portable. Checksumming is the + * first thing you would want to optimize for your platform. You will + * need to port it to your architecture and in your sys_arch.h: + * + * #define LWIP_CHKSUM <your_checksum_routine> +*/ +#ifndef LWIP_CHKSUM +#define LWIP_CHKSUM lwip_standard_chksum +/** + * lwip checksum + * + * @param dataptr points to start of data to be summed at any boundary + * @param len length of data to be summed + * @return host order (!) lwip checksum (non-inverted Internet sum) + * + * @note accumulator size limits summable lenght to 64k + * @note host endianess is irrelevant (p3 RFC1071) + */ static u16_t -lwip_chksum(void *dataptr, int len) +lwip_standard_chksum(void *dataptr, u16_t len) { u32_t acc; + u16_t src; + u8_t *octetptr; - LWIP_DEBUGF(INET_DEBUG, ("lwip_chksum(%p, %d)\n", (void *)dataptr, len)); - for(acc = 0; len > 1; len -= 2) { - /* acc = acc + *((u16_t *)dataptr)++;*/ - acc += *(u16_t *)dataptr; - dataptr = (void *)((u16_t *)dataptr + 1); + acc = 0; + /* dataptr may be at odd or even addresses */ + octetptr = (u8_t*)dataptr; + while (len > 1) + { + /* declare first octet as most significant + thus assume network order, ignoring host order */ + src = (*octetptr) << 8; + octetptr++; + /* declare second octet as least significant */ + src |= (*octetptr); + octetptr++; + acc += src; + len -= 2; + } + if (len > 0) + { + /* accumulate remaining octet */ + src = (*octetptr) << 8; + acc += src; + } + /* add deferred carry bits */ + acc = (acc >> 16) + (acc & 0x0000ffffUL); + if ((acc & 0xffff0000) != 0) { + acc = (acc >> 16) + (acc & 0x0000ffffUL); + } + /* This maybe a little confusing: reorder sum using htons() + instead of ntohs() since it has a little less call overhead. + The caller must invert bits for Internet sum ! */ + return htons((u16_t)acc); +} + +#endif + +#if 0 +/* + * Curt McDowell + * Broadcom Corp. + * csm@broadcom.com + * + * IP checksum two bytes at a time with support for + * unaligned buffer. + * Works for len up to and including 0x20000. + * by Curt McDowell, Broadcom Corp. 12/08/2005 + */ + +static u16_t +lwip_standard_chksum2(void *dataptr, int len) +{ + u8_t *pb = dataptr; + u16_t *ps, t = 0; + u32_t sum = 0; + int odd = ((u32_t)pb & 1); + + /* Get aligned to u16_t */ + if (odd && len > 0) { + ((u8_t *)&t)[1] = *pb++; + len--; } - /* add up any odd byte */ - if (len == 1) { - acc += htons((u16_t)((*(u8_t *)dataptr) & 0xff) << 8); - LWIP_DEBUGF(INET_DEBUG, ("inet: chksum: odd byte %d\n", (unsigned int)(*(u8_t *)dataptr))); - } else { - LWIP_DEBUGF(INET_DEBUG, ("inet: chksum: no odd byte\n")); - } - acc = (acc >> 16) + (acc & 0xffffUL); - - if ((acc & 0xffff0000) != 0) { - acc = (acc >> 16) + (acc & 0xffffUL); + /* Add the bulk of the data */ + ps = (u16_t *)pb; + while (len > 1) { + sum += *ps++; + len -= 2; } - return (u16_t)acc; + /* Consume left-over byte, if any */ + if (len > 0) + ((u8_t *)&t)[0] = *(u8_t *)ps;; + + /* Add end bytes */ + sum += t; + + /* Fold 32-bit sum to 16 bits */ + while (sum >> 16) + sum = (sum & 0xffff) + (sum >> 16); + + /* Swap if alignment was odd */ + if (odd) + sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8); + + return sum; } +/** + * An optimized checksum routine. Basically, it uses loop-unrolling on + * the checksum loop, treating the head and tail bytes specially, whereas + * the inner loop acts on 8 bytes at a time. + * + * @arg start of buffer to be checksummed. May be an odd byte address. + * @len number of bytes in the buffer to be checksummed. + * + * @todo First argument type conflicts with generic checksum routine. + * + * by Curt McDowell, Broadcom Corp. December 8th, 2005 + */ + +static u16_t +lwip_standard_chksum4(u8_t *pb, int len) +{ + u16_t *ps, t = 0; + u32_t *pl; + u32_t sum = 0, tmp; + /* starts at odd byte address? */ + int odd = ((u32_t)pb & 1); + + if (odd && len > 0) { + ((u8_t *)&t)[1] = *pb++; + len--; + } + + ps = (u16_t *)pb; + + if (((u32_t)ps & 3) && len > 1) { + sum += *ps++; + len -= 2; + } + + pl = (u32_t *)ps; + + while (len > 7) { + tmp = sum + *pl++; /* ping */ + if (tmp < sum) + tmp++; /* add back carry */ + + sum = tmp + *pl++; /* pong */ + if (sum < tmp) + sum++; /* add back carry */ + + len -= 8; + } + + /* make room in upper bits */ + sum = (sum >> 16) + (sum & 0xffff); + + ps = (u16_t *)pl; + + /* 16-bit aligned word remaining? */ + while (len > 1) { + sum += *ps++; + len -= 2; + } + + /* dangling tail byte remaining? */ + if (len > 0) /* include odd byte */ + ((u8_t *)&t)[0] = *(u8_t *)ps; + + sum += t; /* add end bytes */ + + while (sum >> 16) /* combine halves */ + sum = (sum >> 16) + (sum & 0xffff); + + if (odd) + sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8); + + return sum; +} +#endif + /* inet_chksum_pseudo: * * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain. @@ -96,8 +255,8 @@ inet_chksum_pseudo(struct pbuf *p, for(q = p; q != NULL; q = q->next) { LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", (void *)q, (void *)q->next)); - acc += lwip_chksum(q->payload, q->len); - /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%lx \n", acc));*/ + acc += LWIP_CHKSUM(q->payload, q->len); + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ while (acc >> 16) { acc = (acc & 0xffffUL) + (acc >> 16); } @@ -105,7 +264,7 @@ inet_chksum_pseudo(struct pbuf *p, swapped = 1 - swapped; acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8); } - /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%lx \n", acc));*/ + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ } if (swapped) { @@ -121,8 +280,8 @@ inet_chksum_pseudo(struct pbuf *p, while (acc >> 16) { acc = (acc & 0xffffUL) + (acc >> 16); } - LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%lx\n", acc)); - return ~(acc & 0xffffUL); + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); + return (u16_t)~(acc & 0xffffUL); } /* inet_chksum: @@ -136,11 +295,11 @@ inet_chksum(void *dataptr, u16_t len) { u32_t acc; - acc = lwip_chksum(dataptr, len); + acc = LWIP_CHKSUM(dataptr, len); while (acc >> 16) { acc = (acc & 0xffff) + (acc >> 16); } - return ~(acc & 0xffff); + return (u16_t)~(acc & 0xffff); } u16_t @@ -153,7 +312,7 @@ inet_chksum_pbuf(struct pbuf *p) acc = 0; swapped = 0; for(q = p; q != NULL; q = q->next) { - acc += lwip_chksum(q->payload, q->len); + acc += LWIP_CHKSUM(q->payload, q->len); while (acc >> 16) { acc = (acc & 0xffffUL) + (acc >> 16); } @@ -166,7 +325,7 @@ inet_chksum_pbuf(struct pbuf *p) if (swapped) { acc = ((acc & 0x00ffUL) << 8) | ((acc & 0xff00UL) >> 8); } - return ~(acc & 0xffffUL); + return (u16_t)~(acc & 0xffffUL); } /* Here for now until needed in other places in lwIP */ @@ -206,10 +365,11 @@ inet_chksum_pbuf(struct pbuf *p) */ /* */ /* inet_aton */ - int inet_aton(const char *cp, struct in_addr *addr) + s8_t + inet_aton(const char *cp, struct in_addr *addr) { u32_t val; - int base, n; + s32_t base, n; char c; u32_t parts[4]; u32_t* pp = parts; @@ -232,12 +392,12 @@ inet_chksum_pbuf(struct pbuf *p) base = 8; } for (;;) { - if (isascii(c) && isdigit(c)) { - val = (val * base) + (c - '0'); + if (isdigit(c)) { + val = (val * base) + (s16_t)(c - '0'); c = *++cp; - } else if (base == 16 && isascii(c) && isxdigit(c)) { + } else if (base == 16 && isxdigit(c)) { val = (val << 4) | - (c + 10 - (islower(c) ? 'a' : 'A')); + (s16_t)(c + 10 - (islower(c) ? 'a' : 'A')); c = *++cp; } else break; @@ -302,17 +462,17 @@ inet_chksum_pbuf(struct pbuf *p) */ char *inet_ntoa(struct in_addr addr) { - static u8_t str[16]; + static char str[16]; u32_t s_addr = addr.s_addr; - u8_t inv[3]; - u8_t *rp; + char inv[3]; + char *rp; u8_t *ap; u8_t rem; u8_t n; u8_t i; rp = str; - ap = (char *)&s_addr; + ap = (u8_t *)&s_addr; for(n = 0; n < 4; n++) { i = 0; do {
--- a/packages/net/lwip_tcpip/current/src/core/ipv4/icmp.c +++ b/packages/net/lwip_tcpip/current/src/core/ipv4/icmp.c @@ -33,22 +33,21 @@ /* Some ICMP messages should be passed to the transport protocols. This is not implemented. */ +#include <string.h> + #include "lwip/opt.h" - #include "lwip/icmp.h" #include "lwip/inet.h" #include "lwip/ip.h" #include "lwip/def.h" - #include "lwip/stats.h" - #include "lwip/snmp.h" void icmp_input(struct pbuf *p, struct netif *inp) { - unsigned char type; - unsigned char code; + u8_t type; + u8_t code; struct icmp_echo_hdr *iecho; struct ip_hdr *iphdr; struct ip_addr tmpaddr; @@ -61,7 +60,7 @@ icmp_input(struct pbuf *p, struct netif iphdr = p->payload; hlen = IPH_HL(iphdr) * 4; if (pbuf_header(p, -((s16_t)hlen)) || (p->tot_len < sizeof(u16_t)*2)) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%u bytes) received\n", p->tot_len)); + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len)); pbuf_free(p); ICMP_STATS_INC(icmp.lenerr); snmp_inc_icmpinerrors(); @@ -74,7 +73,7 @@ icmp_input(struct pbuf *p, struct netif case ICMP_ECHO: /* broadcast or multicast destination address? */ if (ip_addr_isbroadcast(&iphdr->dest, inp) || ip_addr_ismulticast(&iphdr->dest)) { - LWIP_DEBUGF(ICMP_DEBUG, ("Smurf.\n")); + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast or broadcast pings\n")); ICMP_STATS_INC(icmp.err); pbuf_free(p); return; @@ -117,7 +116,7 @@ icmp_input(struct pbuf *p, struct netif IPH_TTL(iphdr), 0, IP_PROTO_ICMP, inp); break; default: - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %d code %d not supported.\n", (int)type, (int)code)); + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" code %"S16_F" not supported.\n", (s16_t)type, (s16_t)code)); ICMP_STATS_INC(icmp.proterr); ICMP_STATS_INC(icmp.drop); } @@ -140,7 +139,7 @@ icmp_dest_unreach(struct pbuf *p, enum i ICMPH_TYPE_SET(idur, ICMP_DUR); ICMPH_CODE_SET(idur, t); - memcpy((char *)q->payload + 8, p->payload, IP_HLEN + 8); + memcpy((u8_t *)q->payload + 8, p->payload, IP_HLEN + 8); /* calculate checksum */ idur->chksum = 0; @@ -178,7 +177,7 @@ icmp_time_exceeded(struct pbuf *p, enum ICMPH_CODE_SET(tehdr, t); /* copy fields from original packet */ - memcpy((char *)q->payload + 8, (char *)p->payload, IP_HLEN + 8); + memcpy((u8_t *)q->payload + 8, (u8_t *)p->payload, IP_HLEN + 8); /* calculate checksum */ tehdr->chksum = 0;
--- a/packages/net/lwip_tcpip/current/src/core/ipv4/ip.c +++ b/packages/net/lwip_tcpip/current/src/core/ipv4/ip.c @@ -1,3 +1,10 @@ +/* @file + * + * This is the IP layer implementation for incoming and outgoing IP traffic. + * + * @see ip_frag.c + * + */ /* * Copyright (c) 2001-2004 Swedish Institute of Computer Science. * All rights reserved. @@ -30,18 +37,8 @@ * */ - - -/* ip.c - * - * This is the code for the IP layer. - * - */ - - #include "lwip/opt.h" - #include "lwip/def.h" #include "lwip/mem.h" #include "lwip/ip.h" @@ -63,18 +60,17 @@ #endif /* LWIP_DHCP */ -/* ip_init: - * +/** * Initializes the IP layer. */ void ip_init(void) { + /* no initializations as of yet */ } -/* ip_route: - * +/** * Finds the appropriate network interface for a given IP address. It * searches the list of network interfaces linearly. A match is found * if the masked IP address of the network interface equals the masked @@ -89,7 +85,7 @@ ip_route(struct ip_addr *dest) /* iterate through netifs */ for(netif = netif_list; netif != NULL; netif = netif->next) { /* network mask matches? */ - if (ip_addr_maskcmp(dest, &(netif->ip_addr), &(netif->netmask))) { + if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) { /* return netif on which to forward IP packet */ return netif; } @@ -99,14 +95,13 @@ ip_route(struct ip_addr *dest) } #if IP_FORWARD -/* ip_forward: - * +/** * Forwards an IP packet. It finds an appropriate route for the * packet, decrements the TTL value of the packet, adjusts the * checksum and outputs the packet on the appropriate interface. */ -static void +static struct netif * ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp) { struct netif *netif; @@ -115,17 +110,17 @@ ip_forward(struct pbuf *p, struct ip_hdr /* Find network interface where to forward this IP packet to. */ netif = ip_route((struct ip_addr *)&(iphdr->dest)); if (netif == NULL) { - LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for 0x%lx found\n", + LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for 0x%"X32_F" found\n", iphdr->dest.addr)); snmp_inc_ipnoroutes(); - return; + return (struct netif *)NULL; } /* Do not forward packets onto the same network interface on which - they arrived. */ + * they arrived. */ if (netif == inp) { LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n")); snmp_inc_ipnoroutes(); - return; + return (struct netif *)NULL; } /* decrement TTL */ @@ -137,7 +132,7 @@ ip_forward(struct pbuf *p, struct ip_hdr icmp_time_exceeded(p, ICMP_TE_TTL); snmp_inc_icmpouttimeexcds(); } - return; + return (struct netif *)NULL; } /* Incrementally update the IP checksum. */ @@ -147,7 +142,7 @@ ip_forward(struct pbuf *p, struct ip_hdr IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100)); } - LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%lx\n", + LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%"X32_F"\n", iphdr->dest.addr)); IP_STATS_INC(ip.fw); @@ -157,11 +152,11 @@ ip_forward(struct pbuf *p, struct ip_hdr PERF_STOP("ip_forward"); /* transmit pbuf on chosen interface */ netif->output(netif, p, (struct ip_addr *)&(iphdr->dest)); + return netif; } #endif /* IP_FORWARD */ -/* ip_input: - * +/** * This function is called by the network interface device driver when * an IP packet is received. The function does the basic checks of the * IP header such as packet size being at least larger than the header @@ -169,13 +164,16 @@ ip_forward(struct pbuf *p, struct ip_hdr * forwarded (using ip_forward). The IP checksum is always checked. * * Finally, the packet is sent to the upper layer protocol input function. + * + * + * */ err_t ip_input(struct pbuf *p, struct netif *inp) { - static struct ip_hdr *iphdr; - static struct netif *netif; - static u16_t iphdrlen; + struct ip_hdr *iphdr; + struct netif *netif; + u16_t iphdrlen; IP_STATS_INC(ip.recv); snmp_inc_ipinreceives(); @@ -183,7 +181,7 @@ ip_input(struct pbuf *p, struct netif *i /* identify the IP header */ iphdr = p->payload; if (IPH_V(iphdr) != 4) { - LWIP_DEBUGF(IP_DEBUG | 1, ("IP packet dropped due to bad version number %u\n", IPH_V(iphdr))); + LWIP_DEBUGF(IP_DEBUG | 1, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr))); ip_debug_print(p); pbuf_free(p); IP_STATS_INC(ip.err); @@ -198,7 +196,7 @@ ip_input(struct pbuf *p, struct netif *i /* header length exceeds first pbuf length? */ if (iphdrlen > p->len) { - LWIP_DEBUGF(IP_DEBUG | 2, ("IP header (len %u) does not fit in first pbuf (len %u), IP packet droppped.\n", + LWIP_DEBUGF(IP_DEBUG | 2, ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet droppped.\n", iphdrlen, p->len)); /* free (drop) packet pbufs */ pbuf_free(p); @@ -212,7 +210,7 @@ ip_input(struct pbuf *p, struct netif *i #if CHECKSUM_CHECK_IP if (inet_chksum(iphdr, iphdrlen) != 0) { - LWIP_DEBUGF(IP_DEBUG | 2, ("Checksum (0x%x) failed, IP packet dropped.\n", inet_chksum(iphdr, iphdrlen))); + LWIP_DEBUGF(IP_DEBUG | 2, ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdrlen))); ip_debug_print(p); pbuf_free(p); IP_STATS_INC(ip.chkerr); @@ -223,43 +221,41 @@ ip_input(struct pbuf *p, struct netif *i #endif /* Trim pbuf. This should have been done at the netif layer, - but we'll do it anyway just to be sure that its done. */ + * but we'll do it anyway just to be sure that its done. */ pbuf_realloc(p, ntohs(IPH_LEN(iphdr))); - /* is this packet for us? */ - for(netif = netif_list; netif != NULL; netif = netif->next) { + /* match packet against an interface, i.e. is this packet for us? */ + for (netif = netif_list; netif != NULL; netif = netif->next) { - LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%lx netif->ip_addr 0x%lx (0x%lx, 0x%lx, 0x%lx)\n", - iphdr->dest.addr, netif->ip_addr.addr, - iphdr->dest.addr & netif->netmask.addr, - netif->ip_addr.addr & netif->netmask.addr, - iphdr->dest.addr & ~(netif->netmask.addr))); + LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n", + iphdr->dest.addr, netif->ip_addr.addr, + iphdr->dest.addr & netif->netmask.addr, + netif->ip_addr.addr & netif->netmask.addr, + iphdr->dest.addr & ~(netif->netmask.addr))); - /* interface configured? */ - if (!ip_addr_isany(&(netif->ip_addr))) + /* interface is up and configured? */ + if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr)))) { /* unicast to this interface address? */ if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) || - /* or broadcast matching this interface network address? */ - (ip_addr_isbroadcast(&(iphdr->dest), netif) && - ip_addr_maskcmp(&(iphdr->dest), &(netif->ip_addr), &(netif->netmask))) || - /* or restricted broadcast? */ - ip_addr_cmp(&(iphdr->dest), IP_ADDR_BROADCAST)) { - LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n", - netif->name[0], netif->name[1])); - /* break out of for loop */ - break; + /* or broadcast on this interface network address? */ + ip_addr_isbroadcast(&(iphdr->dest), netif)) { + LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n", + netif->name[0], netif->name[1])); + /* break out of for loop */ + break; } } } #if LWIP_DHCP /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed - using link layer addressing (such as Ethernet MAC) so we must not filter on IP. - According to RFC 1542 section 3.1.1, referred by RFC 2131). */ + * using link layer addressing (such as Ethernet MAC) so we must not filter on IP. + * According to RFC 1542 section 3.1.1, referred by RFC 2131). + */ if (netif == NULL) { /* remote port is DHCP server? */ if (IPH_PROTO(iphdr) == IP_PROTO_UDP) { - LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: UDP packet to DHCP client port %u\n", + LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: UDP packet to DHCP client port %"U16_F"\n", ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest))); if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest) == DHCP_CLIENT_PORT) { LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: DHCP packet accepted.\n")); @@ -268,7 +264,7 @@ ip_input(struct pbuf *p, struct netif *i } } #endif /* LWIP_DHCP */ - /* packet not for us? */ + /* packet not for us? */ if (netif == NULL) { /* packet not for us, route or discard */ LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: packet not for us.\n")); @@ -286,30 +282,30 @@ ip_input(struct pbuf *p, struct netif *i pbuf_free(p); return ERR_OK; } - -#if IP_REASSEMBLY + /* packet consists of multiple fragments? */ if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) { - LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04x tot_len=%u len=%u MF=%u offset=%u), calling ip_reass()\n", +#if IP_REASSEMBLY /* packet fragment reassembly code present? */ + LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip_reass()\n", ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & htons(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8)); + /* reassemble the packet*/ p = ip_reass(p); + /* packet not fully reassembled yet? */ if (p == NULL) { return ERR_OK; } iphdr = p->payload; - } -#else /* IP_REASSEMBLY */ - if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) { +#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */ pbuf_free(p); - LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%x) (while IP_REASSEMBLY == 0).\n", - ntohs(IPH_OFFSET(iphdr)))); + LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n", + ntohs(IPH_OFFSET(iphdr)))); IP_STATS_INC(ip.opterr); IP_STATS_INC(ip.drop); snmp_inc_ipunknownprotos(); return ERR_OK; +#endif /* IP_REASSEMBLY */ } -#endif /* IP_REASSEMBLY */ -#if IP_OPTIONS == 0 +#if IP_OPTIONS == 0 /* no support for IP options in the IP header? */ if (iphdrlen > IP_HLEN) { LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since there were IP options (while IP_OPTIONS == 0).\n")); pbuf_free(p); @@ -323,10 +319,11 @@ ip_input(struct pbuf *p, struct netif *i /* send to upper layers */ LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n")); ip_debug_print(p); - LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %d p->tot_len %d\n", p->len, p->tot_len)); + LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); #if LWIP_RAW - if (!raw_input(p, inp)) { + /* raw input did not eat the packet? */ + if (raw_input(p, inp) == 0) { #endif /* LWIP_RAW */ switch (IPH_PROTO(iphdr)) { @@ -356,12 +353,11 @@ ip_input(struct pbuf *p, struct netif *i } pbuf_free(p); - LWIP_DEBUGF(IP_DEBUG | 2, ("Unsupported transport protocol %d\n", IPH_PROTO(iphdr))); + LWIP_DEBUGF(IP_DEBUG | 2, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr))); IP_STATS_INC(ip.proterr); IP_STATS_INC(ip.drop); snmp_inc_ipunknownprotos(); - } #if LWIP_RAW } /* LWIP_RAW */ @@ -369,9 +365,7 @@ ip_input(struct pbuf *p, struct netif *i return ERR_OK; } - -/* ip_output_if: - * +/** * Sends an IP packet on a network interface. This function constructs * the IP header and calculates the IP header checksum. If the source * IP address is NULL, the IP address of the outgoing network @@ -383,8 +377,8 @@ ip_output_if(struct pbuf *p, struct ip_a u8_t ttl, u8_t tos, u8_t proto, struct netif *netif) { - static struct ip_hdr *iphdr; - static u16_t ip_id = 0; + struct ip_hdr *iphdr; + u16_t ip_id = 0; snmp_inc_ipoutrequests(); @@ -433,7 +427,7 @@ ip_output_if(struct pbuf *p, struct ip_a IP_STATS_INC(ip.xmit); - LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%u\n", netif->name[0], netif->name[1], netif->num)); + LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num)); ip_debug_print(p); LWIP_DEBUGF(IP_DEBUG, ("netif->output()")); @@ -441,8 +435,7 @@ ip_output_if(struct pbuf *p, struct ip_a return netif->output(netif, p, dest); } -/* ip_output: - * +/** * Simple interface to ip_output_if. It finds the outgoing network * interface and calls upon ip_output_if to do the actual work. */ @@ -454,7 +447,7 @@ ip_output(struct pbuf *p, struct ip_addr struct netif *netif; if ((netif = ip_route(dest)) == NULL) { - LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: No route to 0x%lx\n", dest->addr)); + LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: No route to 0x%"X32_F"\n", dest->addr)); IP_STATS_INC(ip.rterr); snmp_inc_ipoutdiscards(); @@ -475,35 +468,35 @@ ip_debug_print(struct pbuf *p) LWIP_DEBUGF(IP_DEBUG, ("IP header:\n")); LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP_DEBUG, ("|%2d |%2d | 0x%02x | %5u | (v, hl, tos, len)\n", + LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n", IPH_V(iphdr), IPH_HL(iphdr), IPH_TOS(iphdr), ntohs(IPH_LEN(iphdr)))); LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP_DEBUG, ("| %5u |%u%u%u| %4u | (id, flags, offset)\n", + LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n", ntohs(IPH_ID(iphdr)), ntohs(IPH_OFFSET(iphdr)) >> 15 & 1, ntohs(IPH_OFFSET(iphdr)) >> 14 & 1, ntohs(IPH_OFFSET(iphdr)) >> 13 & 1, ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)); LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP_DEBUG, ("| %3u | %3u | 0x%04x | (ttl, proto, chksum)\n", + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n", IPH_TTL(iphdr), IPH_PROTO(iphdr), ntohs(IPH_CHKSUM(iphdr)))); LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP_DEBUG, ("| %3ld | %3ld | %3ld | %3ld | (src)\n", - ntohl(iphdr->src.addr) >> 24 & 0xff, - ntohl(iphdr->src.addr) >> 16 & 0xff, - ntohl(iphdr->src.addr) >> 8 & 0xff, - ntohl(iphdr->src.addr) & 0xff)); + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n", + ip4_addr1(&iphdr->src), + ip4_addr2(&iphdr->src), + ip4_addr3(&iphdr->src), + ip4_addr4(&iphdr->src))); LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP_DEBUG, ("| %3ld | %3ld | %3ld | %3ld | (dest)\n", - ntohl(iphdr->dest.addr) >> 24 & 0xff, - ntohl(iphdr->dest.addr) >> 16 & 0xff, - ntohl(iphdr->dest.addr) >> 8 & 0xff, - ntohl(iphdr->dest.addr) & 0xff)); + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n", + ip4_addr1(&iphdr->dest), + ip4_addr2(&iphdr->dest), + ip4_addr3(&iphdr->dest), + ip4_addr4(&iphdr->dest))); LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); } #endif /* IP_DEBUG */
--- a/packages/net/lwip_tcpip/current/src/core/ipv4/ip_addr.c +++ b/packages/net/lwip_tcpip/current/src/core/ipv4/ip_addr.c @@ -60,9 +60,12 @@ u8_t ip_addr_isbroadcast(struct ip_addr /* address matches network interface address exactly? => no broadcast */ else if (addr->addr == netif->ip_addr.addr) return 0; - /* host identifier bits are all ones? => network broadcast address */ - else if ((addr->addr & ~netif->netmask.addr) == - (ip_addr_broadcast.addr & ~netif->netmask.addr)) + /* on the same (sub) network... */ + else if (ip_addr_netcmp(addr, &(netif->ip_addr), &(netif->netmask)) + /* ...and host identifier bits are all ones? =>... */ + && ((addr->addr & ~netif->netmask.addr) == + (ip_addr_broadcast.addr & ~netif->netmask.addr))) + /* => network broadcast address */ return 1; else return 0;
--- a/packages/net/lwip_tcpip/current/src/core/ipv4/ip_frag.c +++ b/packages/net/lwip_tcpip/current/src/core/ipv4/ip_frag.c @@ -1,3 +1,9 @@ +/* @file + * + * This is the IP packet segmentation and reassembly implementation. + * + */ + /* * Copyright (c) 2001-2004 Swedish Institute of Computer Science. * All rights reserved. @@ -31,20 +37,13 @@ * */ - -/* ip_frag.c - * - * This is the code for IP segmentation and reassembly - * - */ - +#include <string.h> #include "lwip/opt.h" -#include "lwip/sys.h" +/* #include "lwip/sys.h" */ #include "lwip/ip.h" #include "lwip/ip_frag.h" #include "lwip/netif.h" - #include "lwip/stats.h" @@ -79,7 +78,7 @@ copy_from_pbuf(struct pbuf *p, u16_t * o #define IP_REASS_TMO 1000 static u8_t ip_reassbuf[IP_HLEN + IP_REASS_BUFSIZE]; -static u8_t ip_reassbitmap[IP_REASS_BUFSIZE / (8 * 8)]; +static u8_t ip_reassbitmap[IP_REASS_BUFSIZE / (8 * 8) + 1]; static const u8_t bitmap_bits[8] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 }; @@ -89,18 +88,26 @@ static u8_t ip_reassflags; static u8_t ip_reasstmr; -/* Reassembly timer */ -static void -ip_reass_timer(void *arg) +/** + * Reassembly timer base function + * for both NO_SYS == 0 and 1 (!). + * + * Should be called every 1000 msec. + */ +void +ip_reass_tmr(void) { - (void)arg; - if (ip_reasstmr > 1) { + if (ip_reasstmr > 0) { ip_reasstmr--; - sys_timeout(IP_REASS_TMO, ip_reass_timer, NULL); - } else if (ip_reasstmr == 1) - ip_reasstmr = 0; + } } +/** + * Reassembles incoming IP fragments into an IP datagram. + * + * @param p points to a pbuf chain of the fragment + * @return NULL if reassembly is incomplete, ? otherwise + */ struct pbuf * ip_reass(struct pbuf *p) { @@ -120,7 +127,6 @@ ip_reass(struct pbuf *p) LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: new packet\n")); memcpy(iphdr, fraghdr, IP_HLEN); ip_reasstmr = IP_REASS_MAXAGE; - sys_timeout(IP_REASS_TMO, ip_reass_timer, NULL); ip_reassflags = 0; /* Clear the bitmap. */ memset(ip_reassbitmap, 0, sizeof(ip_reassbitmap)); @@ -132,7 +138,8 @@ ip_reass(struct pbuf *p) if (ip_addr_cmp(&iphdr->src, &fraghdr->src) && ip_addr_cmp(&iphdr->dest, &fraghdr->dest) && IPH_ID(iphdr) == IPH_ID(fraghdr)) { - LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching old packet\n")); + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching previous fragment ID=%"X16_F"\n", + ntohs(IPH_ID(fraghdr)))); IPFRAG_STATS_INC(ip_frag.cachehit); /* Find out the offset in the reassembly buffer where we should copy the fragment. */ @@ -143,9 +150,8 @@ ip_reass(struct pbuf *p) reassembly buffer, we discard the entire packet. */ if (offset > IP_REASS_BUFSIZE || offset + len > IP_REASS_BUFSIZE) { LWIP_DEBUGF(IP_REASS_DEBUG, - ("ip_reass: fragment outside of buffer (%d:%d/%d).\n", offset, + ("ip_reass: fragment outside of buffer (%"S16_F":%"S16_F"/%"S16_F").\n", offset, offset + len, IP_REASS_BUFSIZE)); - sys_untimeout(ip_reass_timer, NULL); ip_reasstmr = 0; goto nullreturn; } @@ -153,7 +159,7 @@ ip_reass(struct pbuf *p) /* Copy the fragment into the reassembly buffer, at the right offset. */ LWIP_DEBUGF(IP_REASS_DEBUG, - ("ip_reass: copying with offset %d into %d:%d\n", offset, + ("ip_reass: copying with offset %"S16_F" into %"S16_F":%"S16_F"\n", offset, IP_HLEN + offset, IP_HLEN + offset + len)); i = IPH_HL(fraghdr) * 4; copy_from_pbuf(p, &i, &ip_reassbuf[IP_HLEN + offset], len); @@ -162,24 +168,29 @@ ip_reass(struct pbuf *p) if (offset / (8 * 8) == (offset + len) / (8 * 8)) { LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: updating single byte in bitmap.\n")); - /* If the two endpoints are in the same byte, we only update - that byte. */ + /* If the two endpoints are in the same byte, we only update that byte. */ + LWIP_ASSERT("offset / (8 * 8) < sizeof(ip_reassbitmap)", + offset / (8 * 8) < sizeof(ip_reassbitmap)); ip_reassbitmap[offset / (8 * 8)] |= - bitmap_bits[(offset / 8) & 7] & - ~bitmap_bits[((offset + len) / 8) & 7]; + bitmap_bits[(offset / 8) & 7] & + ~bitmap_bits[((offset + len) / 8) & 7]; } else { /* If the two endpoints are in different bytes, we update the bytes in the endpoints and fill the stuff inbetween with 0xff. */ + LWIP_ASSERT("offset / (8 * 8) < sizeof(ip_reassbitmap)", + offset / (8 * 8) < sizeof(ip_reassbitmap)); ip_reassbitmap[offset / (8 * 8)] |= bitmap_bits[(offset / 8) & 7]; LWIP_DEBUGF(IP_REASS_DEBUG, - ("ip_reass: updating many bytes in bitmap (%d:%d).\n", + ("ip_reass: updating many bytes in bitmap (%"S16_F":%"S16_F").\n", 1 + offset / (8 * 8), (offset + len) / (8 * 8))); for (i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) { - ip_reassbitmap[i] = 0xff; + ip_reassbitmap[i] = 0xff; } + LWIP_ASSERT("(offset + len) / (8 * 8) < sizeof(ip_reassbitmap)", + (offset + len) / (8 * 8) < sizeof(ip_reassbitmap)); ip_reassbitmap[(offset + len) / (8 * 8)] |= - ~bitmap_bits[((offset + len) / 8) & 7]; + ~bitmap_bits[((offset + len) / 8) & 7]; } /* If this fragment has the More Fragments flag set to zero, we @@ -192,7 +203,7 @@ ip_reass(struct pbuf *p) ip_reassflags |= IP_REASS_FLAG_LASTFRAG; ip_reasslen = offset + len; LWIP_DEBUGF(IP_REASS_DEBUG, - ("ip_reass: last fragment seen, total len %d\n", + ("ip_reass: last fragment seen, total len %"S16_F"\n", ip_reasslen)); } @@ -202,23 +213,27 @@ ip_reass(struct pbuf *p) if (ip_reassflags & IP_REASS_FLAG_LASTFRAG) { /* Check all bytes up to and including all but the last byte in the bitmap. */ + LWIP_ASSERT("ip_reasslen / (8 * 8) - 1 < sizeof(ip_reassbitmap)", + ip_reasslen / (8 * 8) - 1 < sizeof(ip_reassbitmap)); for (i = 0; i < ip_reasslen / (8 * 8) - 1; ++i) { - if (ip_reassbitmap[i] != 0xff) { - LWIP_DEBUGF(IP_REASS_DEBUG, - ("ip_reass: last fragment seen, bitmap %d/%d failed (%x)\n", - i, ip_reasslen / (8 * 8) - 1, ip_reassbitmap[i])); - goto nullreturn; - } + if (ip_reassbitmap[i] != 0xff) { + LWIP_DEBUGF(IP_REASS_DEBUG, + ("ip_reass: last fragment seen, bitmap %"S16_F"/%"S16_F" failed (%"X16_F")\n", + i, ip_reasslen / (8 * 8) - 1, ip_reassbitmap[i])); + goto nullreturn; + } } /* Check the last byte in the bitmap. It should contain just the right amount of bits. */ + LWIP_ASSERT("ip_reasslen / (8 * 8) < sizeof(ip_reassbitmap)", + ip_reasslen / (8 * 8) < sizeof(ip_reassbitmap)); if (ip_reassbitmap[ip_reasslen / (8 * 8)] != - (u8_t) ~ bitmap_bits[ip_reasslen / 8 & 7]) { - LWIP_DEBUGF(IP_REASS_DEBUG, - ("ip_reass: last fragment seen, bitmap %d didn't contain %x (%x)\n", - ip_reasslen / (8 * 8), ~bitmap_bits[ip_reasslen / 8 & 7], - ip_reassbitmap[ip_reasslen / (8 * 8)])); - goto nullreturn; + (u8_t) ~ bitmap_bits[ip_reasslen / 8 & 7]) { + LWIP_DEBUGF(IP_REASS_DEBUG, + ("ip_reass: last fragment seen, bitmap %"S16_F" didn't contain %"X16_F" (%"X16_F")\n", + ip_reasslen / (8 * 8), ~bitmap_bits[ip_reasslen / 8 & 7], + ip_reassbitmap[ip_reasslen / (8 * 8)])); + goto nullreturn; } /* Pretend to be a "normal" (i.e., not fragmented) IP packet @@ -233,27 +248,25 @@ ip_reass(struct pbuf *p) /* If we have come this far, we have a full packet in the buffer, so we allocate a pbuf and copy the packet into it. We also reset the timer. */ - sys_untimeout(ip_reass_timer, NULL); ip_reasstmr = 0; pbuf_free(p); p = pbuf_alloc(PBUF_LINK, ip_reasslen, PBUF_POOL); if (p != NULL) { - i = 0; - for (q = p; q != NULL; q = q->next) { - /* Copy enough bytes to fill this pbuf in the chain. The - available data in the pbuf is given by the q->len - variable. */ - LWIP_DEBUGF(IP_REASS_DEBUG, - ("ip_reass: memcpy from %p (%d) to %p, %d bytes\n", - &ip_reassbuf[i], i, q->payload, - q->len > ip_reasslen - i ? ip_reasslen - i : q->len)); - memcpy(q->payload, &ip_reassbuf[i], - q->len > ip_reasslen - i ? ip_reasslen - i : q->len); - i += q->len; - } - IPFRAG_STATS_INC(ip_frag.fw); + i = 0; + for (q = p; q != NULL; q = q->next) { + /* Copy enough bytes to fill this pbuf in the chain. The + available data in the pbuf is given by the q->len variable. */ + LWIP_DEBUGF(IP_REASS_DEBUG, + ("ip_reass: memcpy from %p (%"S16_F") to %p, %"S16_F" bytes\n", + (void *)&ip_reassbuf[i], i, q->payload, + q->len > ip_reasslen - i ? ip_reasslen - i : q->len)); + memcpy(q->payload, &ip_reassbuf[i], + q->len > ip_reasslen - i ? ip_reasslen - i : q->len); + i += q->len; + } + IPFRAG_STATS_INC(ip_frag.fw); } else { - IPFRAG_STATS_INC(ip_frag.memerr); + IPFRAG_STATS_INC(ip_frag.memerr); } LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: p %p\n", (void*)p)); return p; @@ -270,9 +283,9 @@ nullreturn: static u8_t buf[MEM_ALIGN_SIZE(MAX_MTU)]; /** - * Fragment an IP packet if too large + * Fragment an IP datagram if too large for the netif. * - * Chop the packet in mtu sized chunks and send them in order + * Chop the datagram in MTU sized chunks and send them in order * by using a fixed size static memory buffer (PBUF_ROM) */ err_t @@ -291,10 +304,12 @@ ip_frag(struct pbuf *p, struct netif *ne /* Get a RAM based MTU sized pbuf */ rambuf = pbuf_alloc(PBUF_LINK, 0, PBUF_REF); + if (rambuf == NULL) { + return ERR_MEM; + } rambuf->tot_len = rambuf->len = mtu; rambuf->payload = MEM_ALIGN((void *)buf); - /* Copy the IP header in it */ iphdr = rambuf->payload; memcpy(iphdr, p->payload, IP_HLEN); @@ -335,11 +350,15 @@ ip_frag(struct pbuf *p, struct netif *ne * worked would make things simpler. */ header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM); - pbuf_chain(header, rambuf); - netif->output(netif, header, dest); - IPFRAG_STATS_INC(ip_frag.xmit); - pbuf_free(header); - + if (header != NULL) { + pbuf_chain(header, rambuf); + netif->output(netif, header, dest); + IPFRAG_STATS_INC(ip_frag.xmit); + pbuf_free(header); + } else { + pbuf_free(rambuf); + return ERR_MEM; + } left -= cop; } pbuf_free(rambuf);
--- a/packages/net/lwip_tcpip/current/src/core/mem.c +++ b/packages/net/lwip_tcpip/current/src/core/mem.c @@ -36,6 +36,7 @@ * */ +#include <string.h> #include "lwip/arch.h" #include "lwip/opt.h" @@ -300,7 +301,7 @@ mem_malloc(mem_size_t size) return (u8_t *)mem + SIZEOF_STRUCT_MEM; } } - LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %d bytes\n", (int)size)); + LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size)); #if MEM_STATS ++lwip_stats.mem.err; #endif /* MEM_STATS */
--- a/packages/net/lwip_tcpip/current/src/core/memp.c +++ b/packages/net/lwip_tcpip/current/src/core/memp.c @@ -124,7 +124,7 @@ static sys_sem_t mutex; static int memp_sanity(void) { - int i, c; + s16_t i, c; struct memp *m, *n; for(i = 0; i < MEMP_MAX; i++) { @@ -222,7 +222,7 @@ memp_malloc(memp_t type) mem = MEM_ALIGN((u8_t *)memp + sizeof(struct memp)); return mem; } else { - LWIP_DEBUGF(MEMP_DEBUG | 2, ("memp_malloc: out of memory in pool %d\n", type)); + LWIP_DEBUGF(MEMP_DEBUG | 2, ("memp_malloc: out of memory in pool %"S16_F"\n", type)); #if MEMP_STATS ++lwip_stats.memp[type].err; #endif /* MEMP_STATS */
--- a/packages/net/lwip_tcpip/current/src/core/netif.c +++ b/packages/net/lwip_tcpip/current/src/core/netif.c @@ -67,8 +67,7 @@ netif_add(struct netif *netif, struct ip err_t (* init)(struct netif *netif), err_t (* input)(struct pbuf *p, struct netif *netif)) { - static int netifnum = 0; - + static s16_t netifnum = 0; #if LWIP_DHCP /* netif not under DHCP control by default */ @@ -198,36 +197,44 @@ netif_set_ipaddr(struct netif *netif, st } #endif ip_addr_set(&(netif->ip_addr), ipaddr); - LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: IP address of interface %c%c set to %u.%u.%u.%u\n", +#if 0 /* only allowed for Ethernet interfaces TODO: how can we check? */ + /** For Ethernet network interfaces, we would like to send a + * "gratuitous ARP"; this is an ARP packet sent by a node in order + * to spontaneously cause other nodes to update an entry in their + * ARP cache. From RFC 3220 "IP Mobility Support for IPv4" section 4.6. + */ + etharp_query(netif, ipaddr, NULL); +#endif + LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", netif->name[0], netif->name[1], - (unsigned int)(ntohl(netif->ip_addr.addr) >> 24 & 0xff), - (unsigned int)(ntohl(netif->ip_addr.addr) >> 16 & 0xff), - (unsigned int)(ntohl(netif->ip_addr.addr) >> 8 & 0xff), - (unsigned int)(ntohl(netif->ip_addr.addr) & 0xff))); + ip4_addr1(&netif->ip_addr), + ip4_addr2(&netif->ip_addr), + ip4_addr3(&netif->ip_addr), + ip4_addr4(&netif->ip_addr))); } void netif_set_gw(struct netif *netif, struct ip_addr *gw) { ip_addr_set(&(netif->gw), gw); - LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: GW address of interface %c%c set to %u.%u.%u.%u\n", - netif->name[0], netif->name[1], - (unsigned int)(ntohl(netif->gw.addr) >> 24 & 0xff), - (unsigned int)(ntohl(netif->gw.addr) >> 16 & 0xff), - (unsigned int)(ntohl(netif->gw.addr) >> 8 & 0xff), - (unsigned int)(ntohl(netif->gw.addr) & 0xff))); + LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + netif->name[0], netif->name[1], + ip4_addr1(&netif->gw), + ip4_addr2(&netif->gw), + ip4_addr3(&netif->gw), + ip4_addr4(&netif->gw))); } void netif_set_netmask(struct netif *netif, struct ip_addr *netmask) { ip_addr_set(&(netif->netmask), netmask); - LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: netmask of interface %c%c set to %u.%u.%u.%u\n", - netif->name[0], netif->name[1], - (unsigned int)(ntohl(netif->netmask.addr) >> 24 & 0xff), - (unsigned int)(ntohl(netif->netmask.addr) >> 16 & 0xff), - (unsigned int)(ntohl(netif->netmask.addr) >> 8 & 0xff), - (unsigned int)(ntohl(netif->netmask.addr) & 0xff))); + LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + netif->name[0], netif->name[1], + ip4_addr1(&netif->netmask), + ip4_addr2(&netif->netmask), + ip4_addr3(&netif->netmask), + ip4_addr4(&netif->netmask))); } void @@ -238,6 +245,41 @@ netif_set_default(struct netif *netif) netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\'')); } +/** + * Bring an interface up, available for processing + * traffic. + * + * @note: Enabling DHCP on a down interface will make it come + * up once configured. + * + * @see dhcp_start() + */ +void netif_set_up(struct netif *netif) +{ + netif->flags |= NETIF_FLAG_UP; +} + +/** + * Ask if an interface is up + */ +u8_t netif_is_up(struct netif *netif) +{ + return (netif->flags & NETIF_FLAG_UP)?1:0; +} + +/** + * Bring an interface down, disabling any traffic processing. + * + * @note: Enabling DHCP on a down interface will make it come + * up once configured. + * + * @see dhcp_start() + */ +void netif_set_down(struct netif *netif) +{ + netif->flags &= ~NETIF_FLAG_UP; +} + void netif_init(void) {
--- a/packages/net/lwip_tcpip/current/src/core/pbuf.c +++ b/packages/net/lwip_tcpip/current/src/core/pbuf.c @@ -62,20 +62,18 @@ * */ -#include "lwip/opt.h" +#include <string.h> +#include "lwip/opt.h" #include "lwip/stats.h" - #include "lwip/def.h" #include "lwip/mem.h" #include "lwip/memp.h" #include "lwip/pbuf.h" - #include "lwip/sys.h" - #include "arch/perf.h" -static u8_t pbuf_pool_memory[(PBUF_POOL_SIZE * MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE + sizeof(struct pbuf)))]; +static u8_t pbuf_pool_memory[MEM_ALIGNMENT - 1 + PBUF_POOL_SIZE * MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE + sizeof(struct pbuf))]; #if !SYS_LIGHTWEIGHT_PROT static volatile u8_t pbuf_pool_free_lock, pbuf_pool_alloc_lock; @@ -102,8 +100,7 @@ pbuf_init(void) struct pbuf *p, *q = NULL; u16_t i; - pbuf_pool = (struct pbuf *)&pbuf_pool_memory[0]; - LWIP_ASSERT("pbuf_init: pool aligned", (mem_ptr_t)pbuf_pool % MEM_ALIGNMENT == 0); + pbuf_pool = (struct pbuf *)MEM_ALIGN(pbuf_pool_memory); #if PBUF_STATS lwip_stats.pbuf.avail = PBUF_POOL_SIZE; @@ -183,7 +180,7 @@ pbuf_pool_alloc(void) /** - * Allocates a pbuf. + * Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type). * * The actual memory allocated for the pbuf is determined by the * layer at which the pbuf is allocated and the requested size @@ -217,7 +214,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, p struct pbuf *p, *q, *r; u16_t offset; s32_t rem_len; /* remaining length */ - LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%u)\n", length)); + LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%"U16_F")\n", length)); /* determine header offset */ offset = 0; @@ -306,7 +303,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, p break; case PBUF_RAM: /* If pbuf is to be allocated in RAM, allocate memory for it. */ - p = mem_malloc(MEM_ALIGN_SIZE(sizeof(struct pbuf) + length + offset)); + p = mem_malloc(MEM_ALIGN_SIZE(sizeof(struct pbuf) + offset) + MEM_ALIGN_SIZE(length)); if (p == NULL) { return NULL; } @@ -319,7 +316,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, p LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned", ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); break; - /* pbuf references existing (static constant) ROM payload? */ + /* pbuf references existing (non-volatile static constant) ROM payload? */ case PBUF_ROM: /* pbuf references existing (externally allocated) RAM payload? */ case PBUF_REF: @@ -341,7 +338,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, p } /* set reference count */ p->ref = 1; - LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%u) == %p\n", length, (void *)p)); + LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p)); return p; } @@ -453,55 +450,60 @@ pbuf_realloc(struct pbuf *p, u16_t new_l * * The ->payload, ->tot_len and ->len fields are adjusted. * - * @param hdr_size Number of bytes to increment header size which + * @param hdr_size_inc Number of bytes to increment header size which * increases the size of the pbuf. New space is on the front. * (Using a negative value decreases the header size.) + * If hdr_size_inc is 0, this function does nothing and returns succesful. * * PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so * the call will fail. A check is made that the increase in header size does * not move the payload pointer in front of the start of the buffer. - * @return 1 on failure, 0 on success. + * @return non-zero on failure, zero on success. * - * @note May not be called on a packet queue. */ u8_t -pbuf_header(struct pbuf *p, s16_t header_size) +pbuf_header(struct pbuf *p, s16_t header_size_increment) { void *payload; + LWIP_ASSERT("p != NULL", p != NULL); + if ((header_size_increment == 0) || (p == NULL)) return 0; + /* remember current payload pointer */ payload = p->payload; /* pbuf types containing payloads? */ if (p->flags == PBUF_FLAG_RAM || p->flags == PBUF_FLAG_POOL) { /* set new payload pointer */ - p->payload = (u8_t *)p->payload - header_size; + p->payload = (u8_t *)p->payload - header_size_increment; /* boundary check fails? */ if ((u8_t *)p->payload < (u8_t *)p + sizeof(struct pbuf)) { - LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_header: failed as %p < %p\n", - (u8_t *)p->payload, - (u8_t *)p + sizeof(struct pbuf)) );\ + LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_header: failed as %p < %p (not enough space for new header size)\n", + (void *)p->payload, + (void *)(p + 1)));\ /* restore old payload pointer */ p->payload = payload; /* bail out unsuccesfully */ return 1; } - /* pbuf types refering to payloads? */ + /* pbuf types refering to external payloads? */ } else if (p->flags == PBUF_FLAG_REF || p->flags == PBUF_FLAG_ROM) { /* hide a header in the payload? */ - if ((header_size < 0) && (header_size - p->len <= 0)) { + if ((header_size_increment < 0) && (header_size_increment - p->len <= 0)) { /* increase payload pointer */ - p->payload = (u8_t *)p->payload - header_size; + p->payload = (u8_t *)p->payload - header_size_increment; } else { /* cannot expand payload to front (yet!) * bail out unsuccesfully */ return 1; } } - LWIP_DEBUGF( PBUF_DEBUG, ("pbuf_header: old %p new %p (%d)\n", (void *)payload, (void *)p->payload, header_size) ); /* modify pbuf length fields */ - p->len += header_size; - p->tot_len += header_size; + p->len += header_size_increment; + p->tot_len += header_size_increment; + + LWIP_DEBUGF( PBUF_DEBUG, ("pbuf_header: old %p new %p (%"S16_F")\n", + (void *)payload, (void *)p->payload, header_size_increment)); return 0; } @@ -510,19 +512,20 @@ pbuf_header(struct pbuf *p, s16_t header * Dereference a pbuf chain or queue and deallocate any no-longer-used * pbufs at the head of this chain or queue. * - * Decrements the pbuf reference count. If it reaches - * zero, the pbuf is deallocated. + * Decrements the pbuf reference count. If it reaches zero, the pbuf is + * deallocated. * * For a pbuf chain, this is repeated for each pbuf in the chain, * up to the first pbuf which has a non-zero reference count after - * decrementing. (This might de-allocate the whole chain.) + * decrementing. So, when all reference counts are one, the whole + * chain is free'd. * * @param pbuf The pbuf (chain) to be dereferenced. * * @return the number of pbufs that were de-allocated * from the head of the chain. * - * @note MUST NOT be called on a packet queue. + * @note MUST NOT be called on a packet queue (Not verified to work yet). * @note the reference counter of a pbuf equals the number of pointers * that refer to the pbuf (or into the pbuf). * @@ -581,7 +584,7 @@ pbuf_free(struct pbuf *p) p->len = p->tot_len = PBUF_POOL_BUFSIZE; p->payload = (void *)((u8_t *)p + sizeof(struct pbuf)); PBUF_POOL_FREE(p); - /* a ROM or RAM referencing pbuf */ + /* is this a ROM or RAM referencing pbuf? */ } else if (p->flags == PBUF_FLAG_ROM || p->flags == PBUF_FLAG_REF) { memp_free(MEMP_PBUF, p); /* p->flags == PBUF_FLAG_RAM */ @@ -594,8 +597,8 @@ pbuf_free(struct pbuf *p) /* p->ref > 0, this pbuf is still referenced to */ /* (and so the remaining pbufs in chain as well) */ } else { - LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: %p has ref %u, ending here.\n", (void *)p, (unsigned int)p->ref)); - /* stop walking through chain */ + LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, (u16_t)p->ref)); + /* stop walking through the chain */ p = NULL; } } @@ -658,8 +661,8 @@ pbuf_cat(struct pbuf *h, struct pbuf *t) { struct pbuf *p; - LWIP_ASSERT("h != NULL", h != NULL); - LWIP_ASSERT("t != NULL", t != NULL); + LWIP_ASSERT("h != NULL (programmer violates API)", h != NULL); + LWIP_ASSERT("t != NULL (programmer violates API)", t != NULL); if ((h == NULL) || (t == NULL)) return; /* proceed to last pbuf of chain */ @@ -669,10 +672,14 @@ pbuf_cat(struct pbuf *h, struct pbuf *t) } /* { p is last pbuf of first h chain, p->next == NULL } */ LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len); + LWIP_ASSERT("p->next == NULL", p->next == NULL); /* add total length of second chain to last pbuf total of first chain */ p->tot_len += t->tot_len; /* chain last pbuf of head (p) with first of tail (t) */ p->next = t; + /* p->next now references t, but the caller will drop its reference to t, + * so netto there is no change to the reference count of t. + */ } /** @@ -700,8 +707,8 @@ pbuf_chain(struct pbuf *h, struct pbuf * LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t)); } -/* For packet queueing. Note that queued packets must be dequeued first - * before calling any pbuf functions. */ +/* For packet queueing. Note that queued packets MUST be dequeued first + * using pbuf_dequeue() before calling other pbuf_() functions. */ #if ARP_QUEUEING /** * Add a packet to the end of a queue. @@ -709,13 +716,22 @@ pbuf_chain(struct pbuf *h, struct pbuf * * @param q pointer to first packet on the queue * @param n packet to be queued * + * Both packets MUST be given, and must be different. */ void pbuf_queue(struct pbuf *p, struct pbuf *n) { - LWIP_ASSERT("p != NULL", p != NULL); - LWIP_ASSERT("n != NULL", n != NULL); - if ((p == NULL) || (n == NULL)) return; +#if PBUF_DEBUG /* remember head of queue */ + struct pbuf *q = p; +#endif + /* programmer stupidity checks */ + LWIP_ASSERT("p == NULL in pbuf_queue: this indicates a programmer error\n", p != NULL); + LWIP_ASSERT("n == NULL in pbuf_queue: this indicates a programmer error\n", n != NULL); + LWIP_ASSERT("p == n in pbuf_queue: this indicates a programmer error\n", p != n); + if ((p == NULL) || (n == NULL) || (p == n)){ + LWIP_DEBUGF(PBUF_DEBUG | DBG_HALT | 3, ("pbuf_queue: programmer argument error\n")); + return; + } /* iterate through all packets on queue */ while (p->next != NULL) { @@ -728,26 +744,33 @@ pbuf_queue(struct pbuf *p, struct pbuf * /* make sure each packet is complete */ LWIP_ASSERT("p->next != NULL", p->next != NULL); p = p->next; - /* { p->tot_len == p->len } => p is last pbuf of a packet */ + /* { p->tot_len == p->len => p is last pbuf of a packet } */ } + /* { p is last pbuf of a packet } */ + /* proceed to next packet on queue */ #endif - /* { p->tot_len == p->len } => p is last pbuf of a packet */ - /* proceed to next packet on queue */ + /* proceed to next pbuf */ if (p->next != NULL) p = p->next; } /* { p->tot_len == p->len and p->next == NULL } ==> * { p is last pbuf of last packet on queue } */ /* chain last pbuf of queue with n */ p->next = n; - /* n is now referenced to one more time */ + /* n is now referenced to by the (packet p in the) queue */ pbuf_ref(n); - LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_queue: referencing queued packet %p\n", (void *)n)); +#if PBUF_DEBUG + LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, + ("pbuf_queue: newly queued packet %p sits after packet %p in queue %p\n", + (void *)n, (void *)p, (void *)q)); +#endif } /** * Remove a packet from the head of a queue. * - * The caller MUST reference the remainder of the queue (as returned). + * The caller MUST reference the remainder of the queue (as returned). The + * caller MUST NOT call pbuf_ref() as it implicitly takes over the reference + * from p. * * @param p pointer to first packet on the queue which will be dequeued. * @return first packet on the remaining queue (NULL if no further packets). @@ -759,7 +782,7 @@ pbuf_dequeue(struct pbuf *p) struct pbuf *q; LWIP_ASSERT("p != NULL", p != NULL); - /* iterate through all pbufs in packet */ + /* iterate through all pbufs in packet p */ while (p->tot_len != p->len) { /* make sure invariant condition holds */ LWIP_ASSERT("p->len < p->tot_len", p->len < p->tot_len); @@ -768,15 +791,16 @@ pbuf_dequeue(struct pbuf *p) p = p->next; } /* { p->tot_len == p->len } => p is the last pbuf of the first packet */ - /* remember next packet on queue */ + /* remember next packet on queue in q */ q = p->next; - /* dequeue p from queue */ + /* dequeue packet p from queue */ p->next = NULL; /* any next packet on queue? */ if (q != NULL) { /* although q is no longer referenced by p, it MUST be referenced by - * the caller, who is maintaining this packet queue */ - LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_dequeue: at least one packet on queue, first %p\n", (void *)q)); + * the caller, who is maintaining this packet queue. So, we do not call + * pbuf_free(q) here, resulting in an implicit pbuf_ref(q) for the caller. */ + LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_dequeue: first remaining packet on queue is %p\n", (void *)q)); } else { LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_dequeue: no further packets on queue\n")); } @@ -797,7 +821,7 @@ pbuf_dequeue(struct pbuf *p) * * @note You MUST explicitly use p = pbuf_take(p); * The pbuf you give as argument, may have been replaced - * by pbuf_take()! + * by a (differently located) copy through pbuf_take()! * * @note Any replaced pbufs will be freed through pbuf_free(). * This may deallocate them if they become no longer referenced. @@ -825,7 +849,9 @@ pbuf_take(struct pbuf *p) /* PBUF_POOL buffers are faster if we can use them */ if (p->len <= PBUF_POOL_BUFSIZE) { q = pbuf_alloc(PBUF_RAW, p->len, PBUF_POOL); - if (q == NULL) LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_POOL\n")); + if (q == NULL) { + LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_POOL\n")); + } } else { /* no replacement pbuf yet */ q = NULL; @@ -834,7 +860,9 @@ pbuf_take(struct pbuf *p) /* no (large enough) PBUF_POOL was available? retry with PBUF_RAM */ if (q == NULL) { q = pbuf_alloc(PBUF_RAW, p->len, PBUF_RAM); - if (q == NULL) LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_RAM\n")); + if (q == NULL) { + LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_RAM\n")); + } } /* replacement pbuf could be allocated? */ if (q != NULL) @@ -917,8 +945,10 @@ pbuf_dechain(struct pbuf *p) /* q is no longer referenced by p, free it */ LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE, ("pbuf_dechain: unreferencing %p\n", (void *)q)); tail_gone = pbuf_free(q); - if (tail_gone > 0) LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE, - ("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q)); + if (tail_gone > 0) { + LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE, + ("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q)); + } /* return remaining tail or NULL if deallocated */ } /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */
--- a/packages/net/lwip_tcpip/current/src/core/raw.c +++ b/packages/net/lwip_tcpip/current/src/core/raw.c @@ -1,6 +1,9 @@ /** * @file - * Raw Access module + * + * Implementation of raw protocol PCBs for low-level handling of + * different types of protocols besides (or overriding) those + * already available in lwIP. * */ /* @@ -35,12 +38,7 @@ * */ - -/* raw.c - * - * The code for the Raw Access to the IP - * - */ +#include <string.h> #include "lwip/opt.h" @@ -57,11 +55,10 @@ #include "lwip/snmp.h" #if LWIP_RAW -/* The list of RAW PCBs */ +/** The list of RAW PCBs */ static struct raw_pcb *raw_pcbs = NULL; - void raw_init(void) { @@ -69,42 +66,54 @@ raw_init(void) } /** - * Determine if in incoming IP packet is covered by a RAW pcb and - * and process it if possible + * Determine if in incoming IP packet is covered by a RAW PCB + * and if so, pass it to a user-provided receive callback function. * * Given an incoming IP datagram (as a chain of pbufs) this function - * finds a corresponding RAW PCB and + * finds a corresponding RAW PCB and calls the corresponding receive + * callback function. * * @param pbuf pbuf to be demultiplexed to a RAW PCB. * @param netif network interface on which the datagram was received. - * @return 0 if packet is not eated (pbuf needs to be freed then) - * or 1 if the packet has been eaten (pbuf needs not to be freed - * then) + * @Return - 1 if the packet has been eaten by a RAW PCB receive + * callback function. The caller MAY NOT not reference the + * packet any longer, and MAY NOT call pbuf_free(). + * @return - 0 if packet is not eaten (pbuf is still referenced by the + * caller). * */ -int +u8_t raw_input(struct pbuf *p, struct netif *inp) { struct raw_pcb *pcb; struct ip_hdr *iphdr; - int proto; - int rc = 0; + s16_t proto; + u8_t eaten = 0; iphdr = p->payload; proto = IPH_PROTO(iphdr); - for(pcb = raw_pcbs; pcb != NULL; pcb = pcb->next) { + pcb = raw_pcbs; + /* loop through all raw pcbs until the packet is eaten by one */ + /* this allows multiple pcbs to match against the packet by design */ + while ((eaten == 0) && (pcb != NULL)) { if (pcb->protocol == proto) { - if (pcb->recv) { - if (!pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src))) - return 0; + /* receive callback function available? */ + if (pcb->recv != NULL) { + /* the receive callback function did not eat the packet? */ + if (pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src)) != 0) + { + /* receive function ate the packet */ + p = NULL; + eaten = 1; + } } - pbuf_free(p); - rc = 1; - break; + /* no receive callback function was set for this raw PCB */ + /* drop the packet */ } + pcb = pcb->next; } - return rc; + return eaten; } /** @@ -116,7 +125,7 @@ raw_input(struct pbuf *p, struct netif * * * @return lwIP error code. * - ERR_OK. Successful. No error occured. - * - ERR_USE. The specified ipaddr is already bound to by + * - ERR_USE. The specified IP address is already bound to by * another RAW PCB. * * @see raw_disconnect() @@ -130,7 +139,7 @@ raw_bind(struct raw_pcb *pcb, struct ip_ /** * Connect an RAW PCB. This function is required by upper layers - * of lwip. Using the raw api you could use raw_send_to() instead + * of lwip. Using the raw api you could use raw_sendto() instead * * This will associate the RAW PCB with the remote address. * @@ -139,7 +148,7 @@ raw_bind(struct raw_pcb *pcb, struct ip_ * * @return lwIP error code * - * @see raw_disconnect() and raw_send_to() + * @see raw_disconnect() and raw_sendto() */ err_t raw_connect(struct raw_pcb *pcb, struct ip_addr *ipaddr) @@ -150,14 +159,21 @@ raw_connect(struct raw_pcb *pcb, struct /** - * Set the callback function if a RAW packet with the pcb's protocol - * is received. If the callback function returns a value unequal 0 - * the raw packet is "eaten" and not forwarded to any other raw pcb - * including lwip itself + * Set the callback function for received packets that match the + * raw PCB's protocol and binding. + * + * The callback function MUST either + * - eat the packet by calling pbuf_free() and returning non-zero. The + * packet will not be passed to other raw PCBs or other protocol layers. + * - not free the packet, and return zero. The packet will be matched + * against further PCBs and/or forwarded to another protocol layers. + * + * @return non-zero if the packet was free()d, zero if the packet remains + * available for others. */ void raw_recv(struct raw_pcb *pcb, - int (* recv)(void *arg, struct raw_pcb *upcb, struct pbuf *p, + u8_t (* recv)(void *arg, struct raw_pcb *upcb, struct pbuf *p, struct ip_addr *addr), void *recv_arg) { @@ -168,25 +184,25 @@ raw_recv(struct raw_pcb *pcb, /** * Send the raw IP packet to the given address. Note that actually you cannot - * modify the IP headers (this is inconsitent with the receive callback where - * you actually get the IP headers), you can only specifiy the ip payload here. - * It requires some more changes in LWIP. (there will be a raw_send() function - * then) + * modify the IP headers (this is inconsistent with the receive callback where + * you actually get the IP headers), you can only specify the IP payload here. + * It requires some more changes in lwIP. (there will be a raw_send() function + * then.) * * @param pcb the raw pcb which to send - * @param p the ip payload to send - * @param ipaddr the destination address of the whole IP packet + * @param p the IP payload to send + * @param ipaddr the destination address of the IP packet * */ err_t -raw_send_to(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr) +raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr) { err_t err; struct netif *netif; struct ip_addr *src_ip; struct pbuf *q; /* q will be sent down the stack */ - LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 3, ("raw_send_to\n")); + LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 3, ("raw_sendto\n")); /* not enough space to add an IP header to first pbuf in given p chain? */ if (pbuf_header(p, IP_HLEN)) { @@ -194,13 +210,13 @@ raw_send_to(struct raw_pcb *pcb, struct q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM); /* new header pbuf could not be allocated? */ if (q == NULL) { - LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 2, ("raw_send_to: could not allocate header\n")); + LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 2, ("raw_sendto: could not allocate header\n")); return ERR_MEM; } /* chain header q in front of given pbuf p */ pbuf_chain(q, p); /* { first pbuf q points to header pbuf } */ - LWIP_DEBUGF(RAW_DEBUG, ("raw_send_to: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); + LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); } else { /* first pbuf q equals given pbuf */ q = p; @@ -208,10 +224,11 @@ raw_send_to(struct raw_pcb *pcb, struct } if ((netif = ip_route(ipaddr)) == NULL) { - LWIP_DEBUGF(RAW_DEBUG | 1, ("raw_send_to: No route to 0x%lx\n", ipaddr->addr)); + LWIP_DEBUGF(RAW_DEBUG | 1, ("raw_sendto: No route to 0x%"X32_F"\n", ipaddr->addr)); #if RAW_STATS /* ++lwip_stats.raw.rterr;*/ #endif /* RAW_STATS */ + /* free any temporary header pbuf allocated by pbuf_header() */ if (q != p) { pbuf_free(q); } @@ -240,14 +257,14 @@ raw_send_to(struct raw_pcb *pcb, struct * Send the raw IP packet to the address given by raw_connect() * * @param pcb the raw pcb which to send - * @param p the ip payload to send - * @param ipaddr the destination address of the whole IP packet + * @param p the IP payload to send + * @param ipaddr the destination address of the IP packet * */ err_t raw_send(struct raw_pcb *pcb, struct pbuf *p) { - return raw_send_to(pcb,p,&pcb->remote_ip); + return raw_sendto(pcb, p, &pcb->remote_ip); } /** @@ -266,7 +283,7 @@ raw_remove(struct raw_pcb *pcb) if (raw_pcbs == pcb) { /* make list start at 2nd pcb */ raw_pcbs = raw_pcbs->next; - /* pcb not 1st in list */ + /* pcb not 1st in list */ } else for(pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { /* find pcb in raw_pcbs list */ if (pcb2->next != NULL && pcb2->next == pcb) { @@ -303,7 +320,6 @@ raw_new(u16_t proto) { pcb->next = raw_pcbs; raw_pcbs = pcb; } - return pcb; }
--- a/packages/net/lwip_tcpip/current/src/core/stats.c +++ b/packages/net/lwip_tcpip/current/src/core/stats.c @@ -30,6 +30,7 @@ * */ +#include <string.h> #include "lwip/opt.h" @@ -52,48 +53,48 @@ void stats_display_proto(struct stats_proto *proto, char *name) { LWIP_PLATFORM_DIAG(("\n%s\n\t", name)); - LWIP_PLATFORM_DIAG(("xmit: %d\n\t", proto->xmit)); - LWIP_PLATFORM_DIAG(("rexmit: %d\n\t", proto->rexmit)); - LWIP_PLATFORM_DIAG(("recv: %d\n\t", proto->recv)); - LWIP_PLATFORM_DIAG(("fw: %d\n\t", proto->fw)); - LWIP_PLATFORM_DIAG(("drop: %d\n\t", proto->drop)); - LWIP_PLATFORM_DIAG(("chkerr: %d\n\t", proto->chkerr)); - LWIP_PLATFORM_DIAG(("lenerr: %d\n\t", proto->lenerr)); - LWIP_PLATFORM_DIAG(("memerr: %d\n\t", proto->memerr)); - LWIP_PLATFORM_DIAG(("rterr: %d\n\t", proto->rterr)); - LWIP_PLATFORM_DIAG(("proterr: %d\n\t", proto->proterr)); - LWIP_PLATFORM_DIAG(("opterr: %d\n\t", proto->opterr)); - LWIP_PLATFORM_DIAG(("err: %d\n\t", proto->err)); - LWIP_PLATFORM_DIAG(("cachehit: %d\n", proto->cachehit)); + LWIP_PLATFORM_DIAG(("xmit: %"S16_F"\n\t", proto->xmit)); + LWIP_PLATFORM_DIAG(("rexmit: %"S16_F"\n\t", proto->rexmit)); + LWIP_PLATFORM_DIAG(("recv: %"S16_F"\n\t", proto->recv)); + LWIP_PLATFORM_DIAG(("fw: %"S16_F"\n\t", proto->fw)); + LWIP_PLATFORM_DIAG(("drop: %"S16_F"\n\t", proto->drop)); + LWIP_PLATFORM_DIAG(("chkerr: %"S16_F"\n\t", proto->chkerr)); + LWIP_PLATFORM_DIAG(("lenerr: %"S16_F"\n\t", proto->lenerr)); + LWIP_PLATFORM_DIAG(("memerr: %"S16_F"\n\t", proto->memerr)); + LWIP_PLATFORM_DIAG(("rterr: %"S16_F"\n\t", proto->rterr)); + LWIP_PLATFORM_DIAG(("proterr: %"S16_F"\n\t", proto->proterr)); + LWIP_PLATFORM_DIAG(("opterr: %"S16_F"\n\t", proto->opterr)); + LWIP_PLATFORM_DIAG(("err: %"S16_F"\n\t", proto->err)); + LWIP_PLATFORM_DIAG(("cachehit: %"S16_F"\n", proto->cachehit)); } void stats_display_pbuf(struct stats_pbuf *pbuf) { LWIP_PLATFORM_DIAG(("\nPBUF\n\t")); - LWIP_PLATFORM_DIAG(("avail: %d\n\t", pbuf->avail)); - LWIP_PLATFORM_DIAG(("used: %d\n\t", pbuf->used)); - LWIP_PLATFORM_DIAG(("max: %d\n\t", pbuf->max)); - LWIP_PLATFORM_DIAG(("err: %d\n\t", pbuf->err)); - LWIP_PLATFORM_DIAG(("alloc_locked: %d\n\t", pbuf->alloc_locked)); - LWIP_PLATFORM_DIAG(("refresh_locked: %d\n", pbuf->refresh_locked)); + LWIP_PLATFORM_DIAG(("avail: %"S16_F"\n\t", pbuf->avail)); + LWIP_PLATFORM_DIAG(("used: %"S16_F"\n\t", pbuf->used)); + LWIP_PLATFORM_DIAG(("max: %"S16_F"\n\t", pbuf->max)); + LWIP_PLATFORM_DIAG(("err: %"S16_F"\n\t", pbuf->err)); + LWIP_PLATFORM_DIAG(("alloc_locked: %"S16_F"\n\t", pbuf->alloc_locked)); + LWIP_PLATFORM_DIAG(("refresh_locked: %"S16_F"\n", pbuf->refresh_locked)); } void stats_display_mem(struct stats_mem *mem, char *name) { LWIP_PLATFORM_DIAG(("\n MEM %s\n\t", name)); - LWIP_PLATFORM_DIAG(("avail: %d\n\t", mem->avail)); - LWIP_PLATFORM_DIAG(("used: %d\n\t", mem->used)); - LWIP_PLATFORM_DIAG(("max: %d\n\t", mem->max)); - LWIP_PLATFORM_DIAG(("err: %d\n", mem->err)); + LWIP_PLATFORM_DIAG(("avail: %"S16_F"\n\t", mem->avail)); + LWIP_PLATFORM_DIAG(("used: %"S16_F"\n\t", mem->used)); + LWIP_PLATFORM_DIAG(("max: %"S16_F"\n\t", mem->max)); + LWIP_PLATFORM_DIAG(("err: %"S16_F"\n", mem->err)); } void stats_display(void) { - int i; + s16_t i; char * memp_names[] = {"PBUF", "RAW_PCB", "UDP_PCB", "TCP_PCB", "TCP_PCB_LISTEN", "TCP_SEG", "NETBUF", "NETCONN", "API_MSG", "TCP_MSG", "TIMEOUT"}; stats_display_proto(&lwip_stats.link, "LINK");
--- a/packages/net/lwip_tcpip/current/src/core/sys.c +++ b/packages/net/lwip_tcpip/current/src/core/sys.c @@ -39,7 +39,7 @@ struct sswt_cb { - int timeflag; + s16_t timeflag; sys_sem_t *psem; }; @@ -170,7 +170,7 @@ sys_timeout(u32_t msecs, sys_timeout_han timeouts = sys_arch_timeouts(); - LWIP_DEBUGF(SYS_DEBUG, ("sys_timeout: %p msecs=%lu h=%p arg=%p\n", + LWIP_DEBUGF(SYS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" h=%p arg=%p\n", (void *)timeout, msecs, (void *)h, (void *)arg)); LWIP_ASSERT("sys_timeout: timeouts != NULL", timeouts != NULL);
--- a/packages/net/lwip_tcpip/current/src/core/tcp.c +++ b/packages/net/lwip_tcpip/current/src/core/tcp.c @@ -41,6 +41,8 @@ * */ +#include <string.h> + #include "lwip/opt.h" #include "lwip/def.h" #include "lwip/mem.h" @@ -120,6 +122,18 @@ tcp_close(struct tcp_pcb *pcb) LWIP_DEBUGF(TCP_DEBUG, ("\n")); #endif /* TCP_DEBUG */ switch (pcb->state) { + case CLOSED: + /* Closing a pcb in the CLOSED state might seem erroneous, + * however, it is in this state once allocated and as yet unused + * and the user needs some way to free it should the need arise. + * Calling tcp_close() with a pcb that has already been closed, (i.e. twice) + * or for a pcb that has been used and then entered the CLOSED state + * is erroneous, but this should never happen as the pcb has in those cases + * been freed, and so any remaining handles are bogus. */ + err = ERR_OK; + memp_free(MEMP_TCP_PCB, pcb); + pcb = NULL; + break; case LISTEN: err = ERR_OK; tcp_pcb_remove((struct tcp_pcb **)&tcp_listen_pcbs.pcbs, pcb); @@ -223,14 +237,10 @@ err_t tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port) { struct tcp_pcb *cpcb; -#if SO_REUSE - int reuse_port_all_set = 1; -#endif /* SO_REUSE */ if (port == 0) { port = tcp_new_port(); } -#if SO_REUSE == 0 /* Check if the address already is in use. */ for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; cpcb != NULL; cpcb = cpcb->next) { @@ -252,107 +262,12 @@ tcp_bind(struct tcp_pcb *pcb, struct ip_ } } } -#else /* SO_REUSE */ - /* Search through list of PCB's in LISTEN state. - - If there is a PCB bound to specified port and IP_ADDR_ANY another PCB can be bound to the interface IP - or to the loopback address on the same port if SOF_REUSEADDR is set. Any combination of PCB's bound to - the same local port, but to one address out of {IP_ADDR_ANY, 127.0.0.1, interface IP} at a time is valid. - But no two PCB's bound to same local port and same local address is valid. - - If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then - all PCB's must have the SOF_REUSEPORT option set. - - When the two options aren't set and specified port is already bound, ERR_USE is returned saying that - address is already in use. */ - for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; cpcb != NULL; cpcb = cpcb->next) { - if(cpcb->local_port == port) { - if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) { - if(pcb->so_options & SOF_REUSEPORT) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT set and same address.\n")); - reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT)); - } - else { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT not set and same address.\n")); - return ERR_USE; - } - } - else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(cpcb->local_ip))) || - (!ip_addr_isany(ipaddr) && ip_addr_isany(&(cpcb->local_ip)))) { - if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n")); - return ERR_USE; - } - else { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's SO_REUSEPORT or SO_REUSEADDR set and not the same address.\n")); - } - } - } - } - - /* Search through list of PCB's in a state in which they can accept or send data. Same decription as for - PCB's in state LISTEN applies to this PCB's regarding the options SOF_REUSEADDR and SOF_REUSEPORT. */ - for(cpcb = tcp_active_pcbs; cpcb != NULL; cpcb = cpcb->next) { - if(cpcb->local_port == port) { - if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) { - if(pcb->so_options & SOF_REUSEPORT) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT set and same address.\n")); - reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT)); - } - else { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT not set and same address.\n")); - return ERR_USE; - } - } - else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(cpcb->local_ip))) || - (!ip_addr_isany(ipaddr) && ip_addr_isany(&(cpcb->local_ip)))) { - if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n")); - return ERR_USE; - } - else { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT or SO_REUSEADDR set and not the same address.\n")); - } - } - } - } - - /* Search through list of PCB's in TIME_WAIT state. If SO_REUSEADDR is set a bound combination [IP, port} - can be rebound. The same applies when SOF_REUSEPORT is set. - - If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then - all PCB's must have the SOF_REUSEPORT option set. - - When the two options aren't set and specified port is already bound, ERR_USE is returned saying that - address is already in use. */ - for(cpcb = tcp_tw_pcbs; cpcb != NULL; cpcb = cpcb->next) { - if(cpcb->local_port == port) { - if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) { - if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in TIME_WAIT PCB's SO_REUSEPORT or SO_REUSEADDR not set and same address.\n")); - return ERR_USE; - } - else if(pcb->so_options & SOF_REUSEPORT) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in TIME_WAIT PCB's SO_REUSEPORT set and same address.\n")); - reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT)); - } - } - } - } - - /* If SOF_REUSEPORT isn't set in all PCB's bound to specified port and local address specified then - {IP, port} can't be reused. */ - if(!reuse_port_all_set) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: not all sockets have SO_REUSEPORT set.\n")); - return ERR_USE; - } -#endif /* SO_REUSE */ if (!ip_addr_isany(ipaddr)) { pcb->local_ip = *ipaddr; } pcb->local_port = port; - LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %u\n", port)); + LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port)); return ERR_OK; } #if LWIP_CALLBACK_API @@ -430,9 +345,19 @@ tcp_recved(struct tcp_pcb *pcb, u16_t le * continue to transmit. */ tcp_ack(pcb); + } + else if (pcb->flags & TF_ACK_DELAY && pcb->rcv_wnd >= TCP_WND/2) { + /* If we can send a window update such that there is a full + * segment available in the window, do so now. This is sort of + * nagle-like in its goals, and tries to hit a compromise between + * sending acks each time the window is updated, and only sending + * window updates when a timer expires. The "threshold" used + * above (currently TCP_WND/2) can be tuned to be more or less + * aggressive */ + tcp_ack_now(pcb); } - LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %u bytes, wnd %u (%u).\n", + LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %"U16_F" bytes, wnd %"U16_F" (%"U16_F").\n", len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd)); } @@ -486,7 +411,7 @@ tcp_connect(struct tcp_pcb *pcb, struct err_t ret; u32_t iss; - LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %u\n", port)); + LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port)); if (ipaddr != NULL) { pcb->remote_ip = *ipaddr; } else { @@ -545,7 +470,9 @@ tcp_slowtmr(void) /* Steps through all of the active PCBs. */ prev = NULL; pcb = tcp_active_pcbs; - if (pcb == NULL) LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n")); + if (pcb == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n")); + } while (pcb != NULL) { LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n")); LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED); @@ -566,7 +493,7 @@ tcp_slowtmr(void) if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) { /* Time for a retransmission. */ - LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %u pcb->rto %u\n", + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"U16_F" pcb->rto %"U16_F"\n", pcb->rtime, pcb->rto)); /* Double retransmission time-out unless we are trying to @@ -574,7 +501,6 @@ tcp_slowtmr(void) if (pcb->state != SYN_SENT) { pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx]; } - tcp_rexmit(pcb); /* Reduce congestion window and ssthresh. */ eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd); pcb->ssthresh = eff_wnd >> 1; @@ -582,9 +508,12 @@ tcp_slowtmr(void) pcb->ssthresh = pcb->mss * 2; } pcb->cwnd = pcb->mss; - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %u ssthresh %u\n", + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"U16_F" ssthresh %"U16_F"\n", pcb->cwnd, pcb->ssthresh)); - } + + /* The following needs to be called AFTER cwnd is set to one mss - STJ */ + tcp_rexmit_rto(pcb); + } } /* Check if this PCB has stayed too long in FIN-WAIT-2 */ if (pcb->state == FIN_WAIT_2) { @@ -598,7 +527,7 @@ tcp_slowtmr(void) /* Check if KEEPALIVE should be sent */ if((pcb->so_options & SOF_KEEPALIVE) && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) { if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + TCP_MAXIDLE) / TCP_SLOW_INTERVAL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %u.%u.%u.%u.\n", + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %"U16_F".%"U16_F".%"U16_F".%"U16_F".\n", ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip), ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip))); @@ -626,12 +555,19 @@ tcp_slowtmr(void) /* Check if this PCB has stayed too long in SYN-RCVD */ if (pcb->state == SYN_RCVD) { if ((u32_t)(tcp_ticks - pcb->tmr) > - TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) { + TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) { ++pcb_remove; LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n")); } } + /* Check if this PCB has stayed too long in LAST-ACK */ + if (pcb->state == LAST_ACK) { + if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in LAST-ACK\n")); + } + } /* If the PCB should be removed, do it. */ if (pcb_remove) { @@ -786,7 +722,7 @@ tcp_seg_copy(struct tcp_seg *seg) if (cseg == NULL) { return NULL; } - memcpy((char *)cseg, (const char *)seg, sizeof(struct tcp_seg)); + memcpy((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg)); pbuf_ref(cseg->p); return cseg; } @@ -830,7 +766,7 @@ tcp_kill_prio(u8_t prio) } } if (inactive != NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB 0x%p (%ld)\n", + LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n", (void *)inactive, inactivity)); tcp_abort(inactive); } @@ -852,7 +788,7 @@ tcp_kill_timewait(void) } } if (inactive != NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB 0x%p (%ld)\n", + LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n", (void *)inactive, inactivity)); tcp_abort(inactive); } @@ -1084,16 +1020,16 @@ tcp_debug_print(struct tcp_hdr *tcphdr) { LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n")); LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(TCP_DEBUG, ("| %5u | %5u | (src port, dest port)\n", + LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", ntohs(tcphdr->src), ntohs(tcphdr->dest))); LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(TCP_DEBUG, ("| %010lu | (seq no)\n", + LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n", ntohl(tcphdr->seqno))); LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(TCP_DEBUG, ("| %010lu | (ack no)\n", + LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n", ntohl(tcphdr->ackno))); LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(TCP_DEBUG, ("| %2u | |%u%u%u%u%u%u| %5u | (hdrlen, flags (", + LWIP_DEBUGF(TCP_DEBUG, ("| %2"U16_F" | |%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"| %5"U16_F" | (hdrlen, flags (", TCPH_HDRLEN(tcphdr), TCPH_FLAGS(tcphdr) >> 5 & 1, TCPH_FLAGS(tcphdr) >> 4 & 1, @@ -1105,7 +1041,7 @@ tcp_debug_print(struct tcp_hdr *tcphdr) tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); LWIP_DEBUGF(TCP_DEBUG, ("), win)\n")); LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04x | %5u | (chksum, urgp)\n", + LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n", ntohs(tcphdr->chksum), ntohs(tcphdr->urgp))); LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); } @@ -1186,28 +1122,28 @@ tcp_debug_print_pcbs(void) struct tcp_pcb *pcb; LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n")); for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { - LWIP_DEBUGF(TCP_DEBUG, ("Local port %u, foreign port %u snd_nxt %lu rcv_nxt %lu ", + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", pcb->local_port, pcb->remote_port, pcb->snd_nxt, pcb->rcv_nxt)); tcp_debug_print_state(pcb->state); } LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n")); for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) { - LWIP_DEBUGF(TCP_DEBUG, ("Local port %u, foreign port %u snd_nxt %lu rcv_nxt %lu ", + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", pcb->local_port, pcb->remote_port, pcb->snd_nxt, pcb->rcv_nxt)); tcp_debug_print_state(pcb->state); } LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n")); for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { - LWIP_DEBUGF(TCP_DEBUG, ("Local port %u, foreign port %u snd_nxt %lu rcv_nxt %lu ", + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", pcb->local_port, pcb->remote_port, pcb->snd_nxt, pcb->rcv_nxt)); tcp_debug_print_state(pcb->state); } } -int +s16_t tcp_pcbs_sane(void) { struct tcp_pcb *pcb;
--- a/packages/net/lwip_tcpip/current/src/core/tcp_in.c +++ b/packages/net/lwip_tcpip/current/src/core/tcp_in.c @@ -97,12 +97,6 @@ tcp_input(struct pbuf *p, struct netif * u8_t hdrlen; err_t err; -#if SO_REUSE - struct tcp_pcb *pcb_temp; - int reuse = 0; - int reuse_port = 0; -#endif /* SO_REUSE */ - PERF_START; TCP_STATS_INC(tcp.recv); @@ -117,7 +111,7 @@ tcp_input(struct pbuf *p, struct netif * /* remove header from payload */ if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) { /* drop short packets */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%u bytes) discarded\n", p->tot_len)); + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len)); TCP_STATS_INC(tcp.lenerr); TCP_STATS_INC(tcp.drop); pbuf_free(p); @@ -136,7 +130,7 @@ tcp_input(struct pbuf *p, struct netif * if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src), (struct ip_addr *)&(iphdr->dest), IP_PROTO_TCP, p->tot_len) != 0) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04x\n", + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n", inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src), (struct ip_addr *)&(iphdr->dest), IP_PROTO_TCP, p->tot_len))); #if TCP_DEBUG @@ -169,16 +163,8 @@ tcp_input(struct pbuf *p, struct netif * for an active connection. */ prev = NULL; -#if SO_REUSE - pcb_temp = tcp_active_pcbs; - again_1: - - /* Iterate through the TCP pcb list for a fully matching pcb */ - for(pcb = pcb_temp; pcb != NULL; pcb = pcb->next) { -#else /* SO_REUSE */ for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { -#endif /* SO_REUSE */ LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED); LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN); @@ -187,32 +173,6 @@ tcp_input(struct pbuf *p, struct netif * ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) && ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) { -#if SO_REUSE - if(pcb->so_options & SOF_REUSEPORT) { - if(reuse) { - /* We processed one PCB already */ - LWIP_DEBUGF(TCP_INPUT_DEBUG,("tcp_input: second or later PCB and SOF_REUSEPORT set.\n")); - } else { - /* First PCB with this address */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: first PCB and SOF_REUSEPORT set.\n")); - reuse = 1; - } - - reuse_port = 1; - p->ref++; - - /* We want to search on next socket after receiving */ - pcb_temp = pcb->next; - - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: reference counter on PBUF set to %i\n", p->ref)); - } else { - if(reuse) { - /* We processed one PCB already */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: second or later PCB but SOF_REUSEPORT not set !\n")); - } - } -#endif /* SO_REUSE */ - /* Move this PCB to the front of the list so that subsequent lookups will be faster (we exploit locality in TCP segment arrivals). */ @@ -357,25 +317,9 @@ tcp_input(struct pbuf *p, struct netif * tcp_debug_print_state(pcb->state); #endif /* TCP_DEBUG */ #endif /* TCP_INPUT_DEBUG */ -#if SO_REUSE - /* First socket should receive now */ - if(reuse_port) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: searching next PCB.\n")); - reuse_port = 0; - /* We are searching connected sockets */ - goto again_1; - } -#endif /* SO_REUSE */ + } else { - } else { -#if SO_REUSE - if(reuse) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: freeing PBUF with reference counter set to %i\n", p->ref)); - pbuf_free(p); - goto end; - } -#endif /* SO_REUSE */ /* If no matching PCB was found, send a TCP RST (reset) to the sender. */ LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n")); @@ -388,9 +332,7 @@ tcp_input(struct pbuf *p, struct netif * } pbuf_free(p); } -#if SO_REUSE - end: -#endif /* SO_REUSE */ + LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane()); PERF_STOP("tcp_input"); } @@ -417,7 +359,7 @@ tcp_listen_input(struct tcp_pcb_listen * &(iphdr->dest), &(iphdr->src), tcphdr->dest, tcphdr->src); } else if (flags & TCP_SYN) { - LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %u -> %u.\n", tcphdr->src, tcphdr->dest)); + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest)); npcb = tcp_alloc(pcb->prio); /* If a new PCB could not be created (probably due to lack of memory), we don't do anything, but rely on the sender will retransmit the @@ -503,12 +445,14 @@ tcp_process(struct tcp_pcb *pcb) /* First, determine if the reset is acceptable. */ if (pcb->state == SYN_SENT) { if (ackno == pcb->snd_nxt) { - acceptable = 1; + acceptable = 1; } } else { - if (TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) && - TCP_SEQ_LEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) { - acceptable = 1; + /*if (TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) && + TCP_SEQ_LEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) { + */ + if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) { + acceptable = 1; } } @@ -519,9 +463,9 @@ tcp_process(struct tcp_pcb *pcb) pcb->flags &= ~TF_ACK_DELAY; return ERR_RST; } else { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %lu rcv_nxt %lu\n", + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", seqno, pcb->rcv_nxt)); - LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %lu rcv_nxt %lu\n", + LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", seqno, pcb->rcv_nxt)); return ERR_OK; } @@ -534,10 +478,12 @@ tcp_process(struct tcp_pcb *pcb) /* Do different things depending on the TCP state. */ switch (pcb->state) { case SYN_SENT: - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %lu pcb->snd_nxt %lu unacked %lu\n", ackno, + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno, pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno))); + /* received SYN ACK with expected sequence number? */ if ((flags & TCP_ACK) && (flags & TCP_SYN) && ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) { + pcb->snd_buf++; pcb->rcv_nxt = seqno + 1; pcb->lastack = ackno; pcb->snd_wnd = tcphdr->wnd; @@ -545,7 +491,7 @@ tcp_process(struct tcp_pcb *pcb) pcb->state = ESTABLISHED; pcb->cwnd = pcb->mss; --pcb->snd_queuelen; - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %u\n", (unsigned int)pcb->snd_queuelen)); + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen)); rseg = pcb->unacked; pcb->unacked = rseg->next; tcp_seg_free(rseg); @@ -558,14 +504,20 @@ tcp_process(struct tcp_pcb *pcb) TCP_EVENT_CONNECTED(pcb, ERR_OK, err); tcp_ack(pcb); } + /* received ACK? possibly a half-open connection */ + else if (flags & TCP_ACK) { + /* send a RST to bring the other side in a non-synchronized state. */ + tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src), + tcphdr->dest, tcphdr->src); + } break; case SYN_RCVD: if (flags & TCP_ACK && !(flags & TCP_RST)) { - if (TCP_SEQ_LT(pcb->lastack, ackno) && - TCP_SEQ_LEQ(ackno, pcb->snd_nxt)) { + /* expected ACK number? */ + if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) { pcb->state = ESTABLISHED; - LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); #if LWIP_CALLBACK_API LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL); #endif @@ -582,6 +534,12 @@ tcp_process(struct tcp_pcb *pcb) tcp_receive(pcb); pcb->cwnd = pcb->mss; } + /* incorrect ACK number */ + else { + /* send RST */ + tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src), + tcphdr->dest, tcphdr->src); + } } break; case CLOSE_WAIT: @@ -598,15 +556,15 @@ tcp_process(struct tcp_pcb *pcb) if (flags & TCP_FIN) { if (flags & TCP_ACK && ackno == pcb->snd_nxt) { LWIP_DEBUGF(TCP_DEBUG, - ("TCP connection closed %d -> %d.\n", inseg.tcphdr->src, inseg.tcphdr->dest)); - tcp_ack_now(pcb); - tcp_pcb_purge(pcb); - TCP_RMV(&tcp_active_pcbs, pcb); - pcb->state = TIME_WAIT; - TCP_REG(&tcp_tw_pcbs, pcb); + ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + tcp_ack_now(pcb); + tcp_pcb_purge(pcb); + TCP_RMV(&tcp_active_pcbs, pcb); + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); } else { - tcp_ack_now(pcb); - pcb->state = CLOSING; + tcp_ack_now(pcb); + pcb->state = CLOSING; } } else if (flags & TCP_ACK && ackno == pcb->snd_nxt) { pcb->state = FIN_WAIT_2; @@ -615,7 +573,7 @@ tcp_process(struct tcp_pcb *pcb) case FIN_WAIT_2: tcp_receive(pcb); if (flags & TCP_FIN) { - LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); tcp_ack_now(pcb); tcp_pcb_purge(pcb); TCP_RMV(&tcp_active_pcbs, pcb); @@ -626,7 +584,7 @@ tcp_process(struct tcp_pcb *pcb) case CLOSING: tcp_receive(pcb); if (flags & TCP_ACK && ackno == pcb->snd_nxt) { - LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); tcp_ack_now(pcb); tcp_pcb_purge(pcb); TCP_RMV(&tcp_active_pcbs, pcb); @@ -637,7 +595,7 @@ tcp_process(struct tcp_pcb *pcb) case LAST_ACK: tcp_receive(pcb); if (flags & TCP_ACK && ackno == pcb->snd_nxt) { - LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); pcb->state = CLOSED; recv_flags = TF_CLOSED; } @@ -645,7 +603,6 @@ tcp_process(struct tcp_pcb *pcb) default: break; } - return ERR_OK; } @@ -670,8 +627,9 @@ tcp_receive(struct tcp_pcb *pcb) #endif struct pbuf *p; s32_t off; - int m; + s16_t m; u32_t right_wnd_edge; + u16_t new_tot_len; if (flags & TCP_ACK) { @@ -684,11 +642,11 @@ tcp_receive(struct tcp_pcb *pcb) pcb->snd_wnd = tcphdr->wnd; pcb->snd_wl1 = seqno; pcb->snd_wl2 = ackno; - LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %lu\n", pcb->snd_wnd)); + LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"U32_F"\n", pcb->snd_wnd)); #if TCP_WND_DEBUG } else { if (pcb->snd_wnd != tcphdr->wnd) { - LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: no window update lastack %lu snd_max %lu ackno %lu wl1 %lu seqno %lu wl2 %lu\n", + LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: no window update lastack %"U32_F" snd_max %"U32_F" ackno %"U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n", pcb->lastack, pcb->snd_max, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2)); } #endif /* TCP_WND_DEBUG */ @@ -699,43 +657,50 @@ tcp_receive(struct tcp_pcb *pcb) pcb->acked = 0; if (pcb->snd_wl1 + pcb->snd_wnd == right_wnd_edge){ - ++pcb->dupacks; - if (pcb->dupacks >= 3 && pcb->unacked != NULL) { - if (!(pcb->flags & TF_INFR)) { - /* This is fast retransmit. Retransmit the first unacked segment. */ - LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupacks %u (%lu), fast retransmit %lu\n", - (unsigned int)pcb->dupacks, pcb->lastack, - ntohl(pcb->unacked->tcphdr->seqno))); - tcp_rexmit(pcb); - /* Set ssthresh to max (FlightSize / 2, 2*SMSS) */ - pcb->ssthresh = LWIP_MAX((pcb->snd_max - - pcb->lastack) / 2, - 2 * pcb->mss); + ++pcb->dupacks; + if (pcb->dupacks >= 3 && pcb->unacked != NULL) { + if (!(pcb->flags & TF_INFR)) { + /* This is fast retransmit. Retransmit the first unacked segment. */ + LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupacks %"U16_F" (%"U32_F"), fast retransmit %"U32_F"\n", + (u16_t)pcb->dupacks, pcb->lastack, + ntohl(pcb->unacked->tcphdr->seqno))); + tcp_rexmit(pcb); + /* Set ssthresh to max (FlightSize / 2, 2*SMSS) */ + /*pcb->ssthresh = LWIP_MAX((pcb->snd_max - + pcb->lastack) / 2, + 2 * pcb->mss);*/ + /* Set ssthresh to half of the minimum of the currenct cwnd and the advertised window */ + if(pcb->cwnd > pcb->snd_wnd) + pcb->ssthresh = pcb->snd_wnd / 2; + else + pcb->ssthresh = pcb->cwnd / 2; - pcb->cwnd = pcb->ssthresh + 3 * pcb->mss; - pcb->flags |= TF_INFR; - } else { - /* Inflate the congestion window, but not if it means that - the value overflows. */ - if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { - pcb->cwnd += pcb->mss; + pcb->cwnd = pcb->ssthresh + 3 * pcb->mss; + pcb->flags |= TF_INFR; + } else { + /* Inflate the congestion window, but not if it means that + the value overflows. */ + if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { + pcb->cwnd += pcb->mss; + } + } + } + } else { + LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupack averted %"U32_F" %"U32_F"\n", + pcb->snd_wl1 + pcb->snd_wnd, right_wnd_edge)); } - } - } - } else { - LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupack averted %lu %lu\n", - pcb->snd_wl1 + pcb->snd_wnd, right_wnd_edge)); - } - } else if (TCP_SEQ_LT(pcb->lastack, ackno) && - TCP_SEQ_LEQ(ackno, pcb->snd_max)) { + } else + /*if (TCP_SEQ_LT(pcb->lastack, ackno) && + TCP_SEQ_LEQ(ackno, pcb->snd_max)) { */ + if(TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_max)){ /* We come here when the ACK acknowledges new data. */ - + /* Reset the "IN Fast Retransmit" flag, since we are no longer in fast retransmit. Also reset the congestion window to the slow start threshold. */ if (pcb->flags & TF_INFR) { - pcb->flags &= ~TF_INFR; - pcb->cwnd = pcb->ssthresh; + pcb->flags &= ~TF_INFR; + pcb->cwnd = pcb->ssthresh; } /* Reset the number of retransmissions. */ @@ -746,6 +711,7 @@ tcp_receive(struct tcp_pcb *pcb) /* Update the send buffer space. */ pcb->acked = ackno - pcb->lastack; + pcb->snd_buf += pcb->acked; /* Reset the fast retransmit variables. */ @@ -756,86 +722,85 @@ tcp_receive(struct tcp_pcb *pcb) ssthresh). */ if (pcb->state >= ESTABLISHED) { if (pcb->cwnd < pcb->ssthresh) { - if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { - pcb->cwnd += pcb->mss; - } - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %u\n", pcb->cwnd)); + if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { + pcb->cwnd += pcb->mss; + } + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"U16_F"\n", pcb->cwnd)); } else { - u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd); - if (new_cwnd > pcb->cwnd) { - pcb->cwnd = new_cwnd; - } - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %u\n", pcb->cwnd)); + u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd); + if (new_cwnd > pcb->cwnd) { + pcb->cwnd = new_cwnd; + } + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"U16_F"\n", pcb->cwnd)); } } - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %lu, unacked->seqno %lu:%lu\n", - ackno, - pcb->unacked != NULL? - ntohl(pcb->unacked->tcphdr->seqno): 0, - pcb->unacked != NULL? - ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0)); + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n", + ackno, + pcb->unacked != NULL? + ntohl(pcb->unacked->tcphdr->seqno): 0, + pcb->unacked != NULL? + ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0)); /* Remove segment from the unacknowledged list if the incoming - ACK acknowlegdes them. */ + ACK acknowlegdes them. */ while (pcb->unacked != NULL && - TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) + - TCP_TCPLEN(pcb->unacked), ackno)) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %lu:%lu from pcb->unacked\n", - ntohl(pcb->unacked->tcphdr->seqno), - ntohl(pcb->unacked->tcphdr->seqno) + - TCP_TCPLEN(pcb->unacked))); + TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) + + TCP_TCPLEN(pcb->unacked), ackno)) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n", + ntohl(pcb->unacked->tcphdr->seqno), + ntohl(pcb->unacked->tcphdr->seqno) + + TCP_TCPLEN(pcb->unacked))); - next = pcb->unacked; - pcb->unacked = pcb->unacked->next; + next = pcb->unacked; + pcb->unacked = pcb->unacked->next; - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %u ... ", (unsigned int)pcb->snd_queuelen)); - pcb->snd_queuelen -= pbuf_clen(next->p); - tcp_seg_free(next); + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); + pcb->snd_queuelen -= pbuf_clen(next->p); + tcp_seg_free(next); - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%u (after freeing unacked)\n", (unsigned int)pcb->snd_queuelen)); - if (pcb->snd_queuelen != 0) { - LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL || - pcb->unsent != NULL); - } + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL || + pcb->unsent != NULL); + } } pcb->polltmr = 0; } - /* We go through the ->unsent list to see if any of the segments - on the list are acknowledged by the ACK. This may seem - strange since an "unsent" segment shouldn't be acked. The - rationale is that lwIP puts all outstanding segments on the - ->unsent list after a retransmission, so these segments may - in fact have been sent once. */ - while (pcb->unsent != NULL && - TCP_SEQ_LEQ(ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent), - ackno) && - TCP_SEQ_LEQ(ackno, pcb->snd_max)) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %lu:%lu from pcb->unsent\n", - ntohl(pcb->unsent->tcphdr->seqno), - ntohl(pcb->unsent->tcphdr->seqno) + - TCP_TCPLEN(pcb->unsent))); + /* We go through the ->unsent list to see if any of the segments + on the list are acknowledged by the ACK. This may seem + strange since an "unsent" segment shouldn't be acked. The + rationale is that lwIP puts all outstanding segments on the + ->unsent list after a retransmission, so these segments may + in fact have been sent once. */ + while (pcb->unsent != NULL && + /*TCP_SEQ_LEQ(ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent), ackno) && + TCP_SEQ_LEQ(ackno, pcb->snd_max)*/ + TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent), pcb->snd_max) + ) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n", + ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) + + TCP_TCPLEN(pcb->unsent))); - next = pcb->unsent; - pcb->unsent = pcb->unsent->next; - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %u ... ", (unsigned int)pcb->snd_queuelen)); - pcb->snd_queuelen -= pbuf_clen(next->p); - tcp_seg_free(next); - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%u (after freeing unsent)\n", (unsigned int)pcb->snd_queuelen)); - if (pcb->snd_queuelen != 0) { - LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL || - pcb->unsent != NULL); - } - - if (pcb->unsent != NULL) { - pcb->snd_nxt = htonl(pcb->unsent->tcphdr->seqno); - } + next = pcb->unsent; + pcb->unsent = pcb->unsent->next; + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); + pcb->snd_queuelen -= pbuf_clen(next->p); + tcp_seg_free(next); + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_receive: valid queue length", + pcb->unacked != NULL || pcb->unsent != NULL); } + if (pcb->unsent != NULL) { + pcb->snd_nxt = htonl(pcb->unsent->tcphdr->seqno); + } + } /* End of ACK for new data processing. */ - LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %u rtseq %lu ackno %lu\n", - pcb->rttest, pcb->rtseq, ackno)); + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n", + pcb->rttest, pcb->rtseq, ackno)); /* RTT estimation calculations. This is done by checking if the incoming segment acknowledges the segment we use to take a @@ -843,21 +808,21 @@ tcp_receive(struct tcp_pcb *pcb) if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) { m = tcp_ticks - pcb->rttest; - LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %u ticks (%u msec).\n", - m, m * TCP_SLOW_INTERVAL)); + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n", + m, m * TCP_SLOW_INTERVAL)); /* This is taken directly from VJs original code in his paper */ m = m - (pcb->sa >> 3); pcb->sa += m; if (m < 0) { - m = -m; + m = -m; } m = m - (pcb->sv >> 2); pcb->sv += m; pcb->rto = (pcb->sa >> 3) + pcb->sv; - LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %u (%u miliseconds)\n", - pcb->rto, pcb->rto * TCP_SLOW_INTERVAL)); + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" miliseconds)\n", + pcb->rto, pcb->rto * TCP_SLOW_INTERVAL)); pcb->rttest = 0; } @@ -868,290 +833,314 @@ tcp_receive(struct tcp_pcb *pcb) if (tcplen > 0) { /* This code basically does three things: - +) If the incoming segment contains data that is the next - in-sequence data, this data is passed to the application. This - might involve trimming the first edge of the data. The rcv_nxt - variable and the advertised window are adjusted. + +) If the incoming segment contains data that is the next + in-sequence data, this data is passed to the application. This + might involve trimming the first edge of the data. The rcv_nxt + variable and the advertised window are adjusted. - +) If the incoming segment has data that is above the next - sequence number expected (->rcv_nxt), the segment is placed on - the ->ooseq queue. This is done by finding the appropriate - place in the ->ooseq queue (which is ordered by sequence - number) and trim the segment in both ends if needed. An - immediate ACK is sent to indicate that we received an - out-of-sequence segment. + +) If the incoming segment has data that is above the next + sequence number expected (->rcv_nxt), the segment is placed on + the ->ooseq queue. This is done by finding the appropriate + place in the ->ooseq queue (which is ordered by sequence + number) and trim the segment in both ends if needed. An + immediate ACK is sent to indicate that we received an + out-of-sequence segment. - +) Finally, we check if the first segment on the ->ooseq queue - now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If - rcv_nxt > ooseq->seqno, we must trim the first edge of the - segment on ->ooseq before we adjust rcv_nxt. The data in the - segments that are now on sequence are chained onto the - incoming segment so that we only need to call the application - once. + +) Finally, we check if the first segment on the ->ooseq queue + now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If + rcv_nxt > ooseq->seqno, we must trim the first edge of the + segment on ->ooseq before we adjust rcv_nxt. The data in the + segments that are now on sequence are chained onto the + incoming segment so that we only need to call the application + once. */ /* First, we check if we must trim the first edge. We have to do this if the sequence number of the incoming segment is less than rcv_nxt, and the sequence number plus the length of the segment is larger than rcv_nxt. */ - if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){ - if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) { - /* Trimming the first edge is done by pushing the payload - pointer in the pbuf downwards. This is somewhat tricky since - we do not want to discard the full contents of the pbuf up to - the new starting point of the data since we have to keep the - TCP header which is present in the first pbuf in the chain. - - What is done is really quite a nasty hack: the first pbuf in - the pbuf chain is pointed to by inseg.p. Since we need to be - able to deallocate the whole pbuf, we cannot change this - inseg.p pointer to point to any of the later pbufs in the - chain. Instead, we point the ->payload pointer in the first - pbuf to data in one of the later pbufs. We also set the - inseg.data pointer to point to the right place. This way, the - ->p pointer will still point to the first pbuf, but the - ->p->payload pointer will point to data in another pbuf. - - After we are done with adjusting the pbuf pointers we must - adjust the ->data pointer in the seg and the segment - length.*/ - off = pcb->rcv_nxt - seqno; - if (inseg.p->len < off) { - p = inseg.p; - while (p->len < off) { - off -= p->len; - inseg.p->tot_len -= p->len; - p->len = 0; - p = p->next; + /* if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){ + if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/ + if(TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno+1, seqno+tcplen-1)){ + /* Trimming the first edge is done by pushing the payload + pointer in the pbuf downwards. This is somewhat tricky since + we do not want to discard the full contents of the pbuf up to + the new starting point of the data since we have to keep the + TCP header which is present in the first pbuf in the chain. + + What is done is really quite a nasty hack: the first pbuf in + the pbuf chain is pointed to by inseg.p. Since we need to be + able to deallocate the whole pbuf, we cannot change this + inseg.p pointer to point to any of the later pbufs in the + chain. Instead, we point the ->payload pointer in the first + pbuf to data in one of the later pbufs. We also set the + inseg.data pointer to point to the right place. This way, the + ->p pointer will still point to the first pbuf, but the + ->p->payload pointer will point to data in another pbuf. + + After we are done with adjusting the pbuf pointers we must + adjust the ->data pointer in the seg and the segment + length.*/ + + off = pcb->rcv_nxt - seqno; + p = inseg.p; + if (inseg.p->len < off) { + new_tot_len = inseg.p->tot_len - off; + while (p->len < off) { + off -= p->len; + /* KJM following line changed (with addition of new_tot_len var) + to fix bug #9076 + inseg.p->tot_len -= p->len; */ + p->tot_len = new_tot_len; + p->len = 0; + p = p->next; + } + pbuf_header(p, -off); + } else { + pbuf_header(inseg.p, -off); + } + /* KJM following line changed to use p->payload rather than inseg->p->payload + to fix bug #9076 */ + inseg.dataptr = p->payload; + inseg.len -= pcb->rcv_nxt - seqno; + inseg.tcphdr->seqno = seqno = pcb->rcv_nxt; } - pbuf_header(p, -off); - } else { - pbuf_header(inseg.p, -off); - } - inseg.dataptr = inseg.p->payload; - inseg.len -= pcb->rcv_nxt - seqno; - inseg.tcphdr->seqno = seqno = pcb->rcv_nxt; - } - else{ - /* the whole segment is < rcv_nxt */ - /* must be a duplicate of a packet that has already been correctly handled */ - - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %lu\n", seqno)); - tcp_ack_now(pcb); + else{ + if(TCP_SEQ_LT(seqno, pcb->rcv_nxt)){ + /* the whole segment is < rcv_nxt */ + /* must be a duplicate of a packet that has already been correctly handled */ + + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno)); + tcp_ack_now(pcb); } } /* The sequence number must be within the window (above rcv_nxt and below rcv_nxt + rcv_wnd) in order to be further processed. */ - if (TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) && - TCP_SEQ_LT(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) { + /*if (TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) && + TCP_SEQ_LT(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/ + if(TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd - 1)){ if (pcb->rcv_nxt == seqno) { - /* The incoming segment is the next in sequence. We check if + /* The incoming segment is the next in sequence. We check if we have to trim the end of the segment and update rcv_nxt and pass the data to the application. */ #if TCP_QUEUE_OOSEQ - if (pcb->ooseq != NULL && - TCP_SEQ_LEQ(pcb->ooseq->tcphdr->seqno, seqno + inseg.len)) { - /* We have to trim the second edge of the incoming + if (pcb->ooseq != NULL && + TCP_SEQ_LEQ(pcb->ooseq->tcphdr->seqno, seqno + inseg.len)) { + /* We have to trim the second edge of the incoming segment. */ - inseg.len = pcb->ooseq->tcphdr->seqno - seqno; - pbuf_realloc(inseg.p, inseg.len); - } + inseg.len = pcb->ooseq->tcphdr->seqno - seqno; + pbuf_realloc(inseg.p, inseg.len); + } #endif /* TCP_QUEUE_OOSEQ */ - tcplen = TCP_TCPLEN(&inseg); - - pcb->rcv_nxt += tcplen; + tcplen = TCP_TCPLEN(&inseg); - /* Update the receiver's (our) window. */ - if (pcb->rcv_wnd < tcplen) { - pcb->rcv_wnd = 0; - } else { - pcb->rcv_wnd -= tcplen; - } + /* First received FIN will be ACKed +1, on any successive (duplicate) + * FINs we are already in CLOSE_WAIT and have already done +1. + */ + if (pcb->state != CLOSE_WAIT) { + pcb->rcv_nxt += tcplen; + } + + /* Update the receiver's (our) window. */ + if (pcb->rcv_wnd < tcplen) { + pcb->rcv_wnd = 0; + } else { + pcb->rcv_wnd -= tcplen; + } - /* If there is data in the segment, we make preparations to - pass this up to the application. The ->recv_data variable - is used for holding the pbuf that goes to the - application. The code for reassembling out-of-sequence data - chains its data on this pbuf as well. + /* If there is data in the segment, we make preparations to + pass this up to the application. The ->recv_data variable + is used for holding the pbuf that goes to the + application. The code for reassembling out-of-sequence data + chains its data on this pbuf as well. - If the segment was a FIN, we set the TF_GOT_FIN flag that will - be used to indicate to the application that the remote side has - closed its end of the connection. */ - if (inseg.p->tot_len > 0) { - recv_data = inseg.p; - /* Since this pbuf now is the responsibility of the - application, we delete our reference to it so that we won't - (mistakingly) deallocate it. */ - inseg.p = NULL; - } - if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n")); - recv_flags = TF_GOT_FIN; - } + If the segment was a FIN, we set the TF_GOT_FIN flag that will + be used to indicate to the application that the remote side has + closed its end of the connection. */ + if (inseg.p->tot_len > 0) { + recv_data = inseg.p; + /* Since this pbuf now is the responsibility of the + application, we delete our reference to it so that we won't + (mistakingly) deallocate it. */ + inseg.p = NULL; + } + if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n")); + recv_flags = TF_GOT_FIN; + } #if TCP_QUEUE_OOSEQ - /* We now check if we have segments on the ->ooseq queue that + /* We now check if we have segments on the ->ooseq queue that is now in sequence. */ - while (pcb->ooseq != NULL && - pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) { + while (pcb->ooseq != NULL && + pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) { - cseg = pcb->ooseq; - seqno = pcb->ooseq->tcphdr->seqno; + cseg = pcb->ooseq; + seqno = pcb->ooseq->tcphdr->seqno; - pcb->rcv_nxt += TCP_TCPLEN(cseg); - if (pcb->rcv_wnd < TCP_TCPLEN(cseg)) { - pcb->rcv_wnd = 0; - } else { - pcb->rcv_wnd -= TCP_TCPLEN(cseg); - } - if (cseg->p->tot_len > 0) { - /* Chain this pbuf onto the pbuf that we will pass to - the application. */ - if (recv_data) { + pcb->rcv_nxt += TCP_TCPLEN(cseg); + if (pcb->rcv_wnd < TCP_TCPLEN(cseg)) { + pcb->rcv_wnd = 0; + } else { + pcb->rcv_wnd -= TCP_TCPLEN(cseg); + } + if (cseg->p->tot_len > 0) { + /* Chain this pbuf onto the pbuf that we will pass to + the application. */ + if (recv_data) { pbuf_cat(recv_data, cseg->p); } else { - recv_data = cseg->p; - } - cseg->p = NULL; - } - if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n")); - recv_flags = TF_GOT_FIN; - } + recv_data = cseg->p; + } + cseg->p = NULL; + } + if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n")); + recv_flags = TF_GOT_FIN; + } - pcb->ooseq = cseg->next; - tcp_seg_free(cseg); - } + pcb->ooseq = cseg->next; + tcp_seg_free(cseg); + } #endif /* TCP_QUEUE_OOSEQ */ - /* Acknowledge the segment(s). */ - tcp_ack(pcb); + /* Acknowledge the segment(s). */ + tcp_ack(pcb); } else { - /* We get here if the incoming segment is out-of-sequence. */ - tcp_ack_now(pcb); + /* We get here if the incoming segment is out-of-sequence. */ + tcp_ack_now(pcb); #if TCP_QUEUE_OOSEQ - /* We queue the segment on the ->ooseq queue. */ - if (pcb->ooseq == NULL) { - pcb->ooseq = tcp_seg_copy(&inseg); - } else { - /* If the queue is not empty, we walk through the queue and - try to find a place where the sequence number of the - incoming segment is between the sequence numbers of the - previous and the next segment on the ->ooseq queue. That is - the place where we put the incoming segment. If needed, we - trim the second edges of the previous and the incoming - segment so that it will fit into the sequence. + /* We queue the segment on the ->ooseq queue. */ + if (pcb->ooseq == NULL) { + pcb->ooseq = tcp_seg_copy(&inseg); + } else { + /* If the queue is not empty, we walk through the queue and + try to find a place where the sequence number of the + incoming segment is between the sequence numbers of the + previous and the next segment on the ->ooseq queue. That is + the place where we put the incoming segment. If needed, we + trim the second edges of the previous and the incoming + segment so that it will fit into the sequence. - If the incoming segment has the same sequence number as a - segment on the ->ooseq queue, we discard the segment that - contains less data. */ + If the incoming segment has the same sequence number as a + segment on the ->ooseq queue, we discard the segment that + contains less data. */ - prev = NULL; - for(next = pcb->ooseq; next != NULL; next = next->next) { - if (seqno == next->tcphdr->seqno) { - /* The sequence number of the incoming segment is the + prev = NULL; + for(next = pcb->ooseq; next != NULL; next = next->next) { + if (seqno == next->tcphdr->seqno) { + /* The sequence number of the incoming segment is the same as the sequence number of the segment on ->ooseq. We check the lengths to see which one to discard. */ - if (inseg.len > next->len) { - /* The incoming segment is larger than the old + if (inseg.len > next->len) { + /* The incoming segment is larger than the old segment. We replace the old segment with the new one. */ - cseg = tcp_seg_copy(&inseg); - if (cseg != NULL) { - cseg->next = next->next; - if (prev != NULL) { - prev->next = cseg; - } else { - pcb->ooseq = cseg; - } - } - break; - } else { - /* Either the lenghts are the same or the incoming + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + cseg->next = next->next; + if (prev != NULL) { + prev->next = cseg; + } else { + pcb->ooseq = cseg; + } + } + break; + } else { + /* Either the lenghts are the same or the incoming segment was smaller than the old one; in either case, we ditch the incoming segment. */ - break; - } - } else { - if (prev == NULL) { - if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) { - /* The sequence number of the incoming segment is lower - than the sequence number of the first segment on the - queue. We put the incoming segment first on the - queue. */ + break; + } + } else { + if (prev == NULL) { + if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) { + /* The sequence number of the incoming segment is lower + than the sequence number of the first segment on the + queue. We put the incoming segment first on the + queue. */ - if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) { - /* We need to trim the incoming segment. */ - inseg.len = next->tcphdr->seqno - seqno; - pbuf_realloc(inseg.p, inseg.len); - } - cseg = tcp_seg_copy(&inseg); - if (cseg != NULL) { - cseg->next = next; - pcb->ooseq = cseg; - } - break; - } - } else if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) && - TCP_SEQ_LT(seqno, next->tcphdr->seqno)) { - /* The sequence number of the incoming segment is in + if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) { + /* We need to trim the incoming segment. */ + inseg.len = next->tcphdr->seqno - seqno; + pbuf_realloc(inseg.p, inseg.len); + } + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + cseg->next = next; + pcb->ooseq = cseg; + } + break; + } + } else + /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) && + TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/ + if(TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)){ + /* The sequence number of the incoming segment is in between the sequence numbers of the previous and the next segment on ->ooseq. We trim and insert the incoming segment and trim the previous segment, if needed. */ - if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) { - /* We need to trim the incoming segment. */ - inseg.len = next->tcphdr->seqno - seqno; - pbuf_realloc(inseg.p, inseg.len); - } + if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) { + /* We need to trim the incoming segment. */ + inseg.len = next->tcphdr->seqno - seqno; + pbuf_realloc(inseg.p, inseg.len); + } - cseg = tcp_seg_copy(&inseg); - if (cseg != NULL) { - cseg->next = next; - prev->next = cseg; - if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) { - /* We need to trim the prev segment. */ - prev->len = seqno - prev->tcphdr->seqno; - pbuf_realloc(prev->p, prev->len); - } - } - break; - } - /* If the "next" segment is the last segment on the + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + cseg->next = next; + prev->next = cseg; + if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) { + /* We need to trim the prev segment. */ + prev->len = seqno - prev->tcphdr->seqno; + pbuf_realloc(prev->p, prev->len); + } + } + break; + } + /* If the "next" segment is the last segment on the ooseq queue, we add the incoming segment to the end of the list. */ - if (next->next == NULL && - TCP_SEQ_GT(seqno, next->tcphdr->seqno)) { - next->next = tcp_seg_copy(&inseg); - if (next->next != NULL) { - if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) { - /* We need to trim the last segment. */ - next->len = seqno - next->tcphdr->seqno; - pbuf_realloc(next->p, next->len); - } - } - break; + if (next->next == NULL && + TCP_SEQ_GT(seqno, next->tcphdr->seqno)) { + next->next = tcp_seg_copy(&inseg); + if (next->next != NULL) { + if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) { + /* We need to trim the last segment. */ + next->len = seqno - next->tcphdr->seqno; + pbuf_realloc(next->p, next->len); + } + } + break; + } + } + prev = next; + } } - } - prev = next; - } - } #endif /* TCP_QUEUE_OOSEQ */ } + } else { + /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) || + TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/ + if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){ + tcp_ack_now(pcb); + } } } else { /* Segments with length 0 is taken care of here. Segments that fall out of the window are ACKed. */ - if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) || - TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) { + /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) || + TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/ + if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){ tcp_ack_now(pcb); } } @@ -1185,7 +1174,7 @@ tcp_parseopt(struct tcp_pcb *pcb) ++c; /* NOP option. */ } else if (opt == 0x02 && - opts[c + 1] == 0x04) { + opts[c + 1] == 0x04) { /* An MSS option with the right option length. */ mss = (opts[c + 2] << 8) | opts[c + 3]; pcb->mss = mss > TCP_MSS? TCP_MSS: mss;
--- a/packages/net/lwip_tcpip/current/src/core/tcp_out.c +++ b/packages/net/lwip_tcpip/current/src/core/tcp_out.c @@ -39,19 +39,17 @@ * */ +#include <string.h> + #include "lwip/def.h" #include "lwip/opt.h" - #include "lwip/mem.h" #include "lwip/memp.h" #include "lwip/sys.h" - #include "lwip/ip_addr.h" #include "lwip/netif.h" - #include "lwip/inet.h" #include "lwip/tcp.h" - #include "lwip/stats.h" #if LWIP_TCP @@ -62,27 +60,33 @@ static void tcp_output_segment(struct tc err_t tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags) { + /* no data, no length, flags, copy=1, no optdata, no optdatalen */ return tcp_enqueue(pcb, NULL, 0, flags, 1, NULL, 0); - } -/* - * NB. tcp_write() enqueues data for sending, but does not send it - * straight away. It waits in the expectation of more data being sent - * soon (as it can send them more efficiently by combining them - * together). To prompt the system to send data now, call - * tcp_output() after calling tcp_write(). +/** + * Write data for sending (but does not send it immediately). + * + * It waits in the expectation of more data being sent soon (as + * it can send them more efficiently by combining them together). + * To prompt the system to send data now, call tcp_output() after + * calling tcp_write(). + * + * @arg pcb Protocol control block of the TCP connection to enqueue data for. + * + * @see tcp_write() */ err_t tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, arg=%p, len=%u, copy=%d)\n", (void *)pcb, - arg, len, (unsigned int)copy)); - if (pcb->state == SYN_SENT || - pcb->state == SYN_RCVD || - pcb->state == ESTABLISHED || - pcb->state == CLOSE_WAIT) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, arg=%p, len=%"U16_F", copy=%"U16_F")\n", (void *)pcb, + arg, len, (u16_t)copy)); + /* connection is in valid state for data transmission? */ + if (pcb->state == ESTABLISHED || + pcb->state == CLOSE_WAIT || + pcb->state == SYN_SENT || + pcb->state == SYN_RCVD) { if (len > 0) { return tcp_enqueue(pcb, (void *)arg, len, 0, copy, NULL, 0); } @@ -93,10 +97,24 @@ tcp_write(struct tcp_pcb *pcb, const voi } } +/** + * Enqueue either data or TCP options (but not both) for tranmission + * + * + * + * @arg pcb Protocol control block for the TCP connection to enqueue data for. + * @arg arg Pointer to the data to be enqueued for sending. + * @arg len Data length in bytes + * @arg flags + * @arg copy 1 if data must be copied, 0 if data is non-volatile and can be + * referenced. + * @arg optdata + * @arg optlen + */ err_t tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len, - u8_t flags, u8_t copy, - u8_t *optdata, u8_t optlen) + u8_t flags, u8_t copy, + u8_t *optdata, u8_t optlen) { struct pbuf *p; struct tcp_seg *seg, *useg, *queue; @@ -105,41 +123,46 @@ tcp_enqueue(struct tcp_pcb *pcb, void *a void *ptr; u8_t queuelen; - LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue(pcb=%p, arg=%p, len=%u, flags=%x, copy=%u)\n", - (void *)pcb, arg, len, (unsigned int)flags, (unsigned int)copy)); + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue(pcb=%p, arg=%p, len=%"U16_F", flags=%"X16_F", copy=%"U16_F")\n", + (void *)pcb, arg, len, (u16_t)flags, (u16_t)copy)); + LWIP_ASSERT("tcp_enqueue: len == 0 || optlen == 0 (programmer violates API)", + len == 0 || optlen == 0); + LWIP_ASSERT("tcp_enqueue: arg == NULL || optdata == NULL (programmer violates API)", + arg == NULL || optdata == NULL); + /* fail on too much data */ + if (len > pcb->snd_buf) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", len, pcb->snd_buf)); + return ERR_MEM; + } left = len; ptr = arg; - /* fail on too much data */ - if (len > pcb->snd_buf) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too much data (len=%u > snd_buf=%u)\n", len, pcb->snd_buf)); - return ERR_MEM; - } /* seqno will be the sequence number of the first segment enqueued * by the call to this function. */ seqno = pcb->snd_lbb; - queue = NULL; - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %u\n", (unsigned int)pcb->snd_queuelen)); + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen)); - /* Check if the queue length exceeds the configured maximum queue - * length. If so, we return an error. */ + /* If total number of pbufs on the unsent/unacked queues exceeds the + * configured maximum, return an error */ queuelen = pcb->snd_queuelen; if (queuelen >= TCP_SND_QUEUELEN) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too long queue %u (max %u)\n", queuelen, TCP_SND_QUEUELEN)); - goto memerr; + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too long queue %"U16_F" (max %"U16_F")\n", queuelen, TCP_SND_QUEUELEN)); + TCP_STATS_INC(tcp.memerr); + return ERR_MEM; } - - if (pcb->snd_queuelen != 0) { - LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL || - pcb->unsent != NULL); + if (queuelen != 0) { + LWIP_ASSERT("tcp_enqueue: pbufs on queue => at least one queue non-empty", + pcb->unacked != NULL || pcb->unsent != NULL); + } else { + LWIP_ASSERT("tcp_enqueue: no pbufs on queue => both queues empty", + pcb->unacked == NULL && pcb->unsent == NULL); } - seg = useg = NULL; - seglen = 0; - /* First, break up the data into segments and tuck them together in * the local "queue" variable. */ + useg = queue = seg = NULL; + seglen = 0; while (queue == NULL || left > 0) { /* The segment length should be the MSS if the data to be enqueued @@ -155,20 +178,25 @@ tcp_enqueue(struct tcp_pcb *pcb, void *a seg->next = NULL; seg->p = NULL; + /* first segment of to-be-queued data? */ if (queue == NULL) { - useg = queue = seg; + queue = seg; } + /* subsequent segments of to-be-queued data */ else { - /* Attach the segment to the end of the queued segments. */ + /* Attach the segment to the end of the queued segments */ LWIP_ASSERT("useg != NULL", useg != NULL); useg->next = seg; - useg = seg; } + /* remember last segment of to-be-queued data for next iteration */ + useg = seg; /* If copy is set, memory should be allocated * and data copied into pbuf, otherwise data comes from * ROM or other static memory, and need not be copied. If * optdata is != NULL, we have options instead of data. */ + + /* options? */ if (optdata != NULL) { if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) { goto memerr; @@ -176,9 +204,10 @@ tcp_enqueue(struct tcp_pcb *pcb, void *a ++queuelen; seg->dataptr = seg->p->payload; } + /* copy from volatile memory? */ else if (copy) { if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_RAM)) == NULL) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue : could not allocate memory for pbuf copy size %u\n", seglen)); + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue : could not allocate memory for pbuf copy size %"U16_F"\n", seglen)); goto memerr; } ++queuelen; @@ -189,8 +218,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *a } /* do not copy data */ else { - - /* first, allocate a pbuf for holding the data. + /* First, allocate a pbuf for holding the data. * since the referenced data is available at least until it is sent out on the * link (as it has to be ACKed by the remote party) we can safely use PBUF_ROM * instead of PBUF_REF here. @@ -200,6 +228,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *a goto memerr; } ++queuelen; + /* reference the non-volatile payload data */ p->payload = ptr; seg->dataptr = ptr; @@ -214,28 +243,22 @@ tcp_enqueue(struct tcp_pcb *pcb, void *a ++queuelen; /* Concatenate the headers and data pbufs together. */ - pbuf_cat(seg->p, p); + pbuf_cat(seg->p/*header*/, p/*data*/); p = NULL; } /* Now that there are more segments queued, we check again if the length of the queue exceeds the configured maximum. */ if (queuelen > TCP_SND_QUEUELEN) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: queue too long %u (%u)\n", queuelen, TCP_SND_QUEUELEN)); + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN)); goto memerr; } seg->len = seglen; -#if 0 /* Was commented out. TODO: can someone say why this is here? */ - if ((flags & TCP_SYN) || (flags & TCP_FIN)) { - ++seg->len; - } -#endif - /* Build TCP header. */ + + /* build TCP header */ if (pbuf_header(seg->p, TCP_HLEN)) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: no room for TCP header in pbuf.\n")); - TCP_STATS_INC(tcp.err); goto memerr; } @@ -258,17 +281,16 @@ tcp_enqueue(struct tcp_pcb *pcb, void *a segments such as SYN|ACK. */ memcpy(seg->dataptr, optdata, optlen); } - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE, ("tcp_enqueue: queueing %lu:%lu (0x%x)\n", + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE, ("tcp_enqueue: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n", ntohl(seg->tcphdr->seqno), ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg), - flags)); + (u16_t)flags)); left -= seglen; seqno += seglen; - ptr = (void *)((char *)ptr + seglen); + ptr = (void *)((u8_t *)ptr + seglen); } - /* Now that the data to be enqueued has been broken up into TCP segments in the queue variable, we add them to the end of the pcb->unsent queue. */ @@ -278,6 +300,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *a else { for (useg = pcb->unsent; useg->next != NULL; useg = useg->next); } + /* { useg is last segment on the unsent queue, NULL if list is empty } */ /* If there is room in the last pbuf on the unsent queue, chain the first pbuf on the queue together with that. */ @@ -285,24 +308,27 @@ tcp_enqueue(struct tcp_pcb *pcb, void *a TCP_TCPLEN(useg) != 0 && !(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) && !(flags & (TCP_SYN | TCP_FIN)) && + /* fit within max seg size */ useg->len + queue->len <= pcb->mss) { - /* Remove TCP header from first segment. */ + /* Remove TCP header from first segment of our to-be-queued list */ pbuf_header(queue->p, -TCP_HLEN); pbuf_cat(useg->p, queue->p); useg->len += queue->len; useg->next = queue->next; - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE | DBG_STATE, ("tcp_enqueue: chaining, new len %u\n", useg->len)); + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE | DBG_STATE, ("tcp_enqueue: chaining segments, new len %"U16_F"\n", useg->len)); if (seg == queue) { seg = NULL; } memp_free(MEMP_TCP_SEG, queue); } else { + /* empty list */ if (useg == NULL) { + /* initialize list with this segment */ pcb->unsent = queue; - } + /* enqueue segment */ else { useg->next = queue; } @@ -311,13 +337,15 @@ tcp_enqueue(struct tcp_pcb *pcb, void *a ++len; } pcb->snd_lbb += len; + pcb->snd_buf -= len; + + /* update number of segments on the queues */ pcb->snd_queuelen = queuelen; - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %d (after enqueued)\n", pcb->snd_queuelen)); + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %"S16_F" (after enqueued)\n", pcb->snd_queuelen)); if (pcb->snd_queuelen != 0) { - LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL || - pcb->unsent != NULL); - + LWIP_ASSERT("tcp_enqueue: valid queue length", + pcb->unacked != NULL || pcb->unsent != NULL); } /* Set the PSH flag in the last segment that we enqueued, but only @@ -327,7 +355,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *a } return ERR_OK; - memerr: +memerr: TCP_STATS_INC(tcp.memerr); if (queue != NULL) { @@ -336,9 +364,8 @@ tcp_enqueue(struct tcp_pcb *pcb, void *a if (pcb->snd_queuelen != 0) { LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL || pcb->unsent != NULL); - } - LWIP_DEBUGF(TCP_QLEN_DEBUG | DBG_STATE, ("tcp_enqueue: %d (with mem err)\n", pcb->snd_queuelen)); + LWIP_DEBUGF(TCP_QLEN_DEBUG | DBG_STATE, ("tcp_enqueue: %"S16_F" (with mem err)\n", pcb->snd_queuelen)); return ERR_MEM; } @@ -351,7 +378,7 @@ tcp_output(struct tcp_pcb *pcb) struct tcp_seg *seg, *useg; u32_t wnd; #if TCP_CWND_DEBUG - int i = 0; + s16_t i = 0; #endif /* TCP_CWND_DEBUG */ /* First, check if we are invoked by the TCP input processing @@ -364,7 +391,6 @@ tcp_output(struct tcp_pcb *pcb) wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd); - seg = pcb->unsent; /* useg should point to last segment on unacked queue */ @@ -372,24 +398,24 @@ tcp_output(struct tcp_pcb *pcb) if (useg != NULL) { for (; useg->next != NULL; useg = useg->next); } - - /* If the TF_ACK_NOW flag is set, we check if there is data that is - to be sent. If data is to be sent out, we'll just piggyback our - acknowledgement with the outgoing segment. If no data will be - sent (either because the ->unsent queue is empty or because the - window doesn't allow it) we'll have to construct an empty ACK - segment and send it. */ + /* If the TF_ACK_NOW flag is set and no data will be sent (either + * because the ->unsent queue is empty or because the window does + * not allow it), construct an empty ACK segment and send it. + * + * If data is to be sent, we will just piggyback the ACK (see below). + */ if (pcb->flags & TF_ACK_NOW && (seg == NULL || ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) { - pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM); if (p == NULL) { LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n")); return ERR_BUF; } - LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: sending ACK for %lu\n", pcb->rcv_nxt)); + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt)); + /* remove ACK flags from the PCB, as we send an empty ACK now */ + pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); tcphdr = p->payload; tcphdr->src = htons(pcb->local_port); @@ -406,7 +432,6 @@ tcp_output(struct tcp_pcb *pcb) tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip), IP_PROTO_TCP, p->tot_len); #endif - ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos, IP_PROTO_TCP); pbuf_free(p); @@ -416,26 +441,26 @@ tcp_output(struct tcp_pcb *pcb) #if TCP_OUTPUT_DEBUG if (seg == NULL) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", pcb->unsent)); + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", (void*)pcb->unsent)); } #endif /* TCP_OUTPUT_DEBUG */ #if TCP_CWND_DEBUG if (seg == NULL) { - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, seg == NULL, ack %lu\n", + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", seg == NULL, ack %"U32_F"\n", pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack)); } else { - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, effwnd %lu, seq %lu, ack %lu\n", + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n", pcb->snd_wnd, pcb->cwnd, wnd, ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len, ntohl(seg->tcphdr->seqno), pcb->lastack)); } #endif /* TCP_CWND_DEBUG */ - + /* data available and window allows it to be sent? */ while (seg != NULL && ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) { #if TCP_CWND_DEBUG - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, effwnd %lu, seq %lu, ack %lu, i%d\n", + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n", pcb->snd_wnd, pcb->cwnd, wnd, ntohl(seg->tcphdr->seqno) + seg->len - pcb->lastack, @@ -458,13 +483,26 @@ tcp_output(struct tcp_pcb *pcb) /* put segment on unacknowledged list if length > 0 */ if (TCP_TCPLEN(seg) > 0) { seg->next = NULL; + /* unacked list is empty? */ if (pcb->unacked == NULL) { pcb->unacked = seg; useg = seg; + /* unacked list is not empty? */ } else { - useg->next = seg; - useg = useg->next; + /* In the case of fast retransmit, the packet should not go to the tail + * of the unacked queue, but rather at the head. We need to check for + * this case. -STJ Jul 27, 2004 */ + if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))){ + /* add segment to head of unacked list */ + seg->next = pcb->unacked; + pcb->unacked = seg; + } else { + /* add segment to tail of unacked list */ + useg->next = seg; + useg = useg->next; + } } + /* do not queue empty segments on the unacked list */ } else { tcp_seg_free(seg); } @@ -473,6 +511,9 @@ tcp_output(struct tcp_pcb *pcb) return ERR_OK; } +/** + * Actually send a TCP segment over IP + */ static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb) { @@ -507,9 +548,9 @@ tcp_output_segment(struct tcp_seg *seg, pcb->rttest = tcp_ticks; pcb->rtseq = ntohl(seg->tcphdr->seqno); - LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %lu\n", pcb->rtseq)); + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq)); } - LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %lu:%lu\n", + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n", htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) + seg->len)); @@ -565,7 +606,37 @@ tcp_rst(u32_t seqno, u32_t ackno, /* Send output with hardcoded TTL since we have no access to the pcb */ ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP); pbuf_free(p); - LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %lu ackno %lu.\n", seqno, ackno)); + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno)); +} + +/* requeue all unacked segments for retransmission */ +void +tcp_rexmit_rto(struct tcp_pcb *pcb) +{ + struct tcp_seg *seg; + + if (pcb->unacked == NULL) { + return; + } + + /* Move all unacked segments to the head of the unsent queue */ + for (seg = pcb->unacked; seg->next != NULL; seg = seg->next); + /* concatenate unsent queue after unacked queue */ + seg->next = pcb->unsent; + /* unsent queue is the concatenated queue (of unacked, unsent) */ + pcb->unsent = pcb->unacked; + /* unacked queue is now empty */ + pcb->unacked = NULL; + + pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno); + /* increment number of retransmissions */ + ++pcb->nrtx; + + /* Don't take any RTT measurements after retransmitting. */ + pcb->rttest = 0; + + /* Do the actual retransmission */ + tcp_output(pcb); } void @@ -577,14 +648,11 @@ tcp_rexmit(struct tcp_pcb *pcb) return; } - /* Move all unacked segments to the unsent queue. */ - for (seg = pcb->unacked; seg->next != NULL; seg = seg->next); - - seg->next = pcb->unsent; + /* Move the first unacked segment to the unsent queue */ + seg = pcb->unacked->next; + pcb->unacked->next = pcb->unsent; pcb->unsent = pcb->unacked; - - pcb->unacked = NULL; - + pcb->unacked = seg; pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno); @@ -598,17 +666,18 @@ tcp_rexmit(struct tcp_pcb *pcb) } + void tcp_keepalive(struct tcp_pcb *pcb) { struct pbuf *p; struct tcp_hdr *tcphdr; - LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %u.%u.%u.%u\n", + LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip), ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip))); - LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %ld pcb->tmr %ld pcb->keep_cnt %ld\n", tcp_ticks, pcb->tmr, pcb->keep_cnt)); + LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt %"U16_F"\n", tcp_ticks, pcb->tmr, pcb->keep_cnt)); p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM); @@ -637,7 +706,7 @@ tcp_keepalive(struct tcp_pcb *pcb) pbuf_free(p); - LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_keepalive: seqno %lu ackno %lu.\n", pcb->snd_nxt - 1, pcb->rcv_nxt)); + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n", pcb->snd_nxt - 1, pcb->rcv_nxt)); } #endif /* LWIP_TCP */
--- a/packages/net/lwip_tcpip/current/src/core/udp.c +++ b/packages/net/lwip_tcpip/current/src/core/udp.c @@ -42,6 +42,8 @@ * */ +#include <string.h> + #include "lwip/opt.h" #include "lwip/def.h" @@ -64,7 +66,6 @@ struct udp_pcb *udp_pcbs = NULL; static struct udp_pcb *pcb_cache = NULL; - void udp_init(void) { @@ -86,16 +87,11 @@ udp_input(struct pbuf *p, struct netif * { struct udp_hdr *udphdr; struct udp_pcb *pcb; + struct udp_pcb *uncon_pcb; struct ip_hdr *iphdr; u16_t src, dest; + u8_t local_match; -#if SO_REUSE - struct udp_pcb *pcb_temp; - int reuse = 0; - int reuse_port_1 = 0; - int reuse_port_2 = 0; -#endif /* SO_REUSE */ - PERF_START; UDP_STATS_INC(udp.recv); @@ -104,7 +100,7 @@ udp_input(struct pbuf *p, struct netif * if (pbuf_header(p, -((s16_t)(UDP_HLEN + IPH_HL(iphdr) * 4)))) { /* drop short packets */ - LWIP_DEBUGF(UDP_DEBUG, ("udp_input: short UDP datagram (%u bytes) discarded\n", p->tot_len)); + LWIP_DEBUGF(UDP_DEBUG, ("udp_input: short UDP datagram (%"U16_F" bytes) discarded\n", p->tot_len)); UDP_STATS_INC(udp.lenerr); UDP_STATS_INC(udp.drop); snmp_inc_udpinerrors(); @@ -114,7 +110,7 @@ udp_input(struct pbuf *p, struct netif * udphdr = (struct udp_hdr *)((u8_t *)p->payload - UDP_HLEN); - LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %u\n", p->tot_len)); + LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len)); src = ntohs(udphdr->src); dest = ntohs(udphdr->dest); @@ -122,117 +118,46 @@ udp_input(struct pbuf *p, struct netif * udp_debug_print(udphdr); /* print the UDP source and destination */ - LWIP_DEBUGF(UDP_DEBUG, ("udp (%u.%u.%u.%u, %u) <-- (%u.%u.%u.%u, %u)\n", + LWIP_DEBUGF(UDP_DEBUG, ("udp (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") <-- (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n", ip4_addr1(&iphdr->dest), ip4_addr2(&iphdr->dest), ip4_addr3(&iphdr->dest), ip4_addr4(&iphdr->dest), ntohs(udphdr->dest), ip4_addr1(&iphdr->src), ip4_addr2(&iphdr->src), ip4_addr3(&iphdr->src), ip4_addr4(&iphdr->src), ntohs(udphdr->src))); -#if SO_REUSE - pcb_temp = udp_pcbs; - - again_1: - - /* Iterate through the UDP pcb list for a fully matching pcb */ - for(pcb = pcb_temp; pcb != NULL; pcb = pcb->next) { -#else /* SO_REUSE */ - /* Iterate through the UDP pcb list for a fully matching pcb */ - for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { -#endif /* SO_REUSE */ + local_match = 0; + uncon_pcb = NULL; + /* Iterate through the UDP pcb list for a matching pcb */ + for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { /* print the PCB local and remote address */ - LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n", + LWIP_DEBUGF(UDP_DEBUG, ("pcb (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") --- (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n", ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip), ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port, ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip), ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip), pcb->remote_port)); - /* PCB remote port matches UDP source port? */ - if ((pcb->remote_port == src) && - /* PCB local port matches UDP destination port? */ - (pcb->local_port == dest) && - /* accepting from any remote (source) IP address? or... */ - (ip_addr_isany(&pcb->remote_ip) || - /* PCB remote IP address matches UDP source IP address? */ - ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) && - /* accepting on any local (netif) IP address? or... */ + /* compare PCB local addr+port to UDP destination addr+port */ + if ((pcb->local_port == dest) && (ip_addr_isany(&pcb->local_ip) || - /* PCB local IP address matches UDP destination IP address? */ ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) { -#if SO_REUSE - if(pcb->so_options & SOF_REUSEPORT) { - if(reuse) { - /* We processed one PCB already */ - LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB and SOF_REUSEPORT set.\n")); - } else { - /* First PCB with this address */ - LWIP_DEBUGF(UDP_DEBUG, ("udp_input: first PCB and SOF_REUSEPORT set.\n")); - reuse = 1; - } - - reuse_port_1 = 1; - p->ref++; - LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref)); - } else { - if(reuse) { - /* We processed one PCB already */ - LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n")); - } - } -#endif /* SO_REUSE */ + local_match = 1; + if ((uncon_pcb == NULL) && + ((pcb->flags & UDP_FLAGS_CONNECTED) == 0)) { + /* the first unconnected matching PCB */ + uncon_pcb = pcb; + } + } + /* compare PCB remote addr+port to UDP source addr+port */ + if ((local_match != 0) && + (pcb->remote_port == src) && + (ip_addr_isany(&pcb->remote_ip) || + ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)))) { + /* the first fully matching PCB */ break; } } /* no fully matching pcb found? then look for an unconnected pcb */ if (pcb == NULL) { - /* Iterate through the UDP PCB list for a pcb that matches - the local address. */ - -#if SO_REUSE - pcb_temp = udp_pcbs; - - again_2: - - for(pcb = pcb_temp; pcb != NULL; pcb = pcb->next) { -#else /* SO_REUSE */ - for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { -#endif /* SO_REUSE */ - LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n", - ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip), - ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port, - ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip), - ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip), pcb->remote_port)); - /* unconnected? */ - if (((pcb->flags & UDP_FLAGS_CONNECTED) == 0) && - /* destination port matches? */ - (pcb->local_port == dest) && - /* not bound to a specific (local) interface address? or... */ - (ip_addr_isany(&pcb->local_ip) || - /* ...matching interface address? */ - ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) { -#if SO_REUSE - if(pcb->so_options & SOF_REUSEPORT) { - if(reuse) { - /* We processed one PCB already */ - LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB and SOF_REUSEPORT set.\n")); - } else { - /* First PCB with this address */ - LWIP_DEBUGF(UDP_DEBUG, ("udp_input: first PCB and SOF_REUSEPORT set.\n")); - reuse = 1; - } - - reuse_port_2 = 1; - p->ref++; - LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref)); - } else { - if(reuse) { - /* We processed one PCB already */ - LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n")); - } - } -#endif /* SO_REUSE */ - break; - } - } + pcb = uncon_pcb; } /* Check checksum if this is a match or if it was directed at us. */ @@ -278,34 +203,12 @@ udp_input(struct pbuf *p, struct netif * pbuf_header(p, -UDP_HLEN); if (pcb != NULL) { snmp_inc_udpindatagrams(); - pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src); -#if SO_REUSE - /* First socket should receive now */ - if(reuse_port_1 || reuse_port_2) { - /* We want to search on next socket after receiving */ - pcb_temp = pcb->next; - - if(reuse_port_1) { - /* We are searching connected sockets */ - reuse_port_1 = 0; - reuse_port_2 = 0; - goto again_1; + /* callback */ + if (pcb->recv != NULL) + { + pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src); + } } else { - /* We are searching unconnected sockets */ - reuse_port_1 = 0; - reuse_port_2 = 0; - goto again_2; - } - } -#endif /* SO_REUSE */ - } else { -#if SO_REUSE - if(reuse) { - LWIP_DEBUGF(UDP_DEBUG, ("udp_input: freeing PBUF with reference counter set to %i\n", p->ref)); - pbuf_free(p); - goto end; - } -#endif /* SO_REUSE */ LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE, ("udp_input: not for us.\n")); /* No match was found, send ICMP destination port unreachable unless @@ -354,9 +257,10 @@ udp_sendto(struct udp_pcb *pcb, struct p struct ip_addr *dst_ip, u16_t dst_port) { err_t err; + /* temporary space for current PCB remote address */ struct ip_addr pcb_remote_ip; u16_t pcb_remote_port; - /* remember remote peer address of PCB */ + /* remember current remote peer address of PCB */ pcb_remote_ip.addr = pcb->remote_ip.addr; pcb_remote_port = pcb->remote_port; /* copy packet destination address to PCB remote peer address */ @@ -364,7 +268,7 @@ udp_sendto(struct udp_pcb *pcb, struct p pcb->remote_port = dst_port; /* send to the packet destination address */ err = udp_send(pcb, p); - /* reset PCB remote peer address */ + /* restore PCB remote peer address */ pcb->remote_ip.addr = pcb_remote_ip.addr; pcb->remote_port = pcb_remote_port; return err; @@ -403,6 +307,14 @@ udp_send(struct udp_pcb *pcb, struct pbu return err; } } + /* find the outgoing network interface for this packet */ + netif = ip_route(&(pcb->remote_ip)); + /* no outgoing network interface could be found? */ + if (netif == NULL) { + LWIP_DEBUGF(UDP_DEBUG | 1, ("udp_send: No route to 0x%"X32_F"\n", pcb->remote_ip.addr)); + UDP_STATS_INC(udp.rterr); + return ERR_RTE; + } /* not enough space to add an UDP header to first pbuf in given p chain? */ if (pbuf_header(p, UDP_HLEN)) { @@ -430,12 +342,6 @@ udp_send(struct udp_pcb *pcb, struct pbu /* in UDP, 0 checksum means 'no checksum' */ udphdr->chksum = 0x0000; - /* find the outgoing network interface for this packet */ - if ((netif = ip_route(&(pcb->remote_ip))) == NULL) { - LWIP_DEBUGF(UDP_DEBUG | 1, ("udp_send: No route to 0x%lx\n", pcb->remote_ip.addr)); - UDP_STATS_INC(udp.rterr); - return ERR_RTE; - } /* PCB local address is IP_ANY_ADDR? */ if (ip_addr_isany(&pcb->local_ip)) { /* use outgoing network interface IP address as source address */ @@ -445,11 +351,11 @@ udp_send(struct udp_pcb *pcb, struct pbu src_ip = &(pcb->local_ip); } - LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %u\n", q->tot_len)); + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len)); /* UDP Lite protocol? */ if (pcb->flags & UDP_FLAGS_UDPLITE) { - LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %u\n", q->tot_len)); + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %"U16_F"\n", q->tot_len)); /* set UDP message length in UDP header */ udphdr->len = htons(pcb->chksum_len); /* calculate checksum */ @@ -466,7 +372,7 @@ udp_send(struct udp_pcb *pcb, struct pbu err = ip_output_if (q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif); /* UDP */ } else { - LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %u\n", q->tot_len)); + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %"U16_F"\n", q->tot_len)); udphdr->len = htons(q->tot_len); /* calculate checksum */ #if CHECKSUM_GEN_UDP @@ -478,7 +384,7 @@ udp_send(struct udp_pcb *pcb, struct pbu #else udphdr->chksum = 0x0000; #endif - LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04x\n", udphdr->chksum)); + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum)); LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n")); /* output to IP */ err = ip_output_if(q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif); @@ -517,12 +423,10 @@ udp_bind(struct udp_pcb *pcb, struct ip_ { struct udp_pcb *ipcb; u8_t rebind; -#if SO_REUSE - int reuse_port_all_set = 1; -#endif /* SO_REUSE */ + LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, ("udp_bind(ipaddr = ")); ip_addr_debug_print(UDP_DEBUG, ipaddr); - LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, (", port = %u)\n", port)); + LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, (", port = %"U16_F")\n", port)); rebind = 0; /* Check for double bind and rebind of the same pcb */ @@ -535,7 +439,6 @@ udp_bind(struct udp_pcb *pcb, struct ip_ rebind = 1; } -#if SO_REUSE == 0 /* this code does not allow upper layer to share a UDP port for listening to broadcast or multicast traffic (See SO_REUSE_ADDR and SO_REUSE_PORT under *BSD). TODO: See where it fits instead, OR @@ -548,56 +451,13 @@ udp_bind(struct udp_pcb *pcb, struct ip_ ip_addr_isany(ipaddr) || ip_addr_cmp(&(ipcb->local_ip), ipaddr))) { /* other PCB already binds to this local IP and port */ - LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: local port %u already bound by another pcb\n", port)); + LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: local port %"U16_F" already bound by another pcb\n", port)); return ERR_USE; } #endif -#else /* SO_REUSE */ - /* Search through list of PCB's. - - If there is a PCB bound to specified port and IP_ADDR_ANY another PCB can be bound to the interface IP - or to the loopback address on the same port if SOF_REUSEADDR is set. Any combination of PCB's bound to - the same local port, but to one address out of {IP_ADDR_ANY, 127.0.0.1, interface IP} at a time is valid. - But no two PCB's bound to same local port and same local address is valid. - - If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then - all PCB's must have the SOF_REUSEPORT option set. - - When the two options aren't set and specified port is already bound, ERR_USE is returned saying that - address is already in use. */ - else if (ipcb->local_port == port) { - if(ip_addr_cmp(&(ipcb->local_ip), ipaddr)) { - if(pcb->so_options & SOF_REUSEPORT) { - LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT set and same address.\n")); - reuse_port_all_set = (reuse_port_all_set && (ipcb->so_options & SOF_REUSEPORT)); - } - else { - LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT not set and same address.\n")); - return ERR_USE; - } - } - else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(ipcb->local_ip))) || - (!ip_addr_isany(ipaddr) && ip_addr_isany(&(ipcb->local_ip)))) { - if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) { - LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n")); - return ERR_USE; - } - } - } -#endif /* SO_REUSE */ - } -#if SO_REUSE - /* If SOF_REUSEPORT isn't set in all PCB's bound to specified port and local address specified then - {IP, port} can't be reused. */ - if(!reuse_port_all_set) { - LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: not all sockets have SO_REUSEPORT set.\n")); - return ERR_USE; - } -#endif /* SO_REUSE */ - ip_addr_set(&pcb->local_ip, ipaddr); /* no port specified? */ if (port == 0) { @@ -627,11 +487,11 @@ udp_bind(struct udp_pcb *pcb, struct ip_ pcb->next = udp_pcbs; udp_pcbs = pcb; } - LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE, ("udp_bind: bound to %u.%u.%u.%u, port %u\n", - (unsigned int)(ntohl(pcb->local_ip.addr) >> 24 & 0xff), - (unsigned int)(ntohl(pcb->local_ip.addr) >> 16 & 0xff), - (unsigned int)(ntohl(pcb->local_ip.addr) >> 8 & 0xff), - (unsigned int)(ntohl(pcb->local_ip.addr) & 0xff), pcb->local_port)); + LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE, ("udp_bind: bound to %"U16_F".%"U16_F".%"U16_F".%"U16_F", port %"U16_F"\n", + (u16_t)(ntohl(pcb->local_ip.addr) >> 24 & 0xff), + (u16_t)(ntohl(pcb->local_ip.addr) >> 16 & 0xff), + (u16_t)(ntohl(pcb->local_ip.addr) >> 8 & 0xff), + (u16_t)(ntohl(pcb->local_ip.addr) & 0xff), pcb->local_port)); return ERR_OK; } /** @@ -680,11 +540,11 @@ udp_connect(struct udp_pcb *pcb, struct pcb->local_ip.addr = 0; } #endif - LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE, ("udp_connect: connected to %u.%u.%u.%u, port %u\n", - (unsigned int)(ntohl(pcb->remote_ip.addr) >> 24 & 0xff), - (unsigned int)(ntohl(pcb->remote_ip.addr) >> 16 & 0xff), - (unsigned int)(ntohl(pcb->remote_ip.addr) >> 8 & 0xff), - (unsigned int)(ntohl(pcb->remote_ip.addr) & 0xff), pcb->remote_port)); + LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE, ("udp_connect: connected to %"U16_F".%"U16_F".%"U16_F".%"U16_F",port %"U16_F"\n", + (u16_t)(ntohl(pcb->remote_ip.addr) >> 24 & 0xff), + (u16_t)(ntohl(pcb->remote_ip.addr) >> 16 & 0xff), + (u16_t)(ntohl(pcb->remote_ip.addr) >> 8 & 0xff), + (u16_t)(ntohl(pcb->remote_ip.addr) & 0xff), pcb->remote_port)); /* Insert UDP PCB into the list of active UDP PCBs. */ for(ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { @@ -769,18 +629,17 @@ udp_new(void) { } #if UDP_DEBUG -int +void udp_debug_print(struct udp_hdr *udphdr) { LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n")); LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(UDP_DEBUG, ("| %5u | %5u | (src port, dest port)\n", + LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", ntohs(udphdr->src), ntohs(udphdr->dest))); LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(UDP_DEBUG, ("| %5u | 0x%04x | (len, chksum)\n", + LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | 0x%04"X16_F" | (len, chksum)\n", ntohs(udphdr->len), ntohs(udphdr->chksum))); LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); - return 0; } #endif /* UDP_DEBUG */
--- a/packages/net/lwip_tcpip/current/src/ecos/init.c +++ b/packages/net/lwip_tcpip/current/src/ecos/init.c @@ -225,6 +225,7 @@ lwip_set_addr(struct netif *netif) netif_add(netif, &ipaddr, &netmask, &gw, netif->state, lwip_dummy_netif_init, tcpip_input); netif_set_default(netif); + netif_set_up(netif); // new step from lwip 1.0.0 #else IP_ADDR(&gw, CYGDAT_LWIP_SERV_ADDR); IP_ADDR(&ipaddr, CYGDAT_LWIP_MY_ADDR); @@ -232,6 +233,7 @@ lwip_set_addr(struct netif *netif) netif_add(netif, &ipaddr, &netmask, &gw, netif->state, lwip_dummy_netif_init, tcpip_input); netif_set_default(netif); + netif_set_up(netif); // new step from lwip 1.0.0 #endif } @@ -306,8 +308,13 @@ ecosglue_init(void) { etharp_init(); cyg_semaphore_init(&delivery, 0); + // + // start input thread before hardware drivers are initialized because + // init_hw_drivers() calls dhcp_init() if DHCP support is configured + // and dhcp_init() requires a running input thread + // + sys_thread_new(input_thread, (void*)0, CYGNUM_LWIP_ETH_THREAD_PRIORITY); init_hw_drivers(); - sys_thread_new(input_thread, (void*)0, CYGNUM_LWIP_ETH_THREAD_PRIORITY); } #endif //CYGPKG_LWIP_ETH
--- a/packages/net/lwip_tcpip/current/src/ecos/sys_arch.c +++ b/packages/net/lwip_tcpip/current/src/ecos/sys_arch.c @@ -255,7 +255,7 @@ sys_thread_t sys_thread_new(void (*funct (char *)arg , stack, CYGNUM_LWIP_THREAD_STACK_SIZE, &(nt->th), &(nt->t) ); cyg_thread_resume(nt->th); - return NULL; + return nt->th; } /*
--- a/packages/net/lwip_tcpip/current/src/netif/etharp.c +++ b/packages/net/lwip_tcpip/current/src/netif/etharp.c @@ -39,7 +39,7 @@ * 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. - * + * * This file is part of the lwIP TCP/IP stack. * */
--- a/packages/net/lwip_tcpip/current/src/netif/loopif.c +++ b/packages/net/lwip_tcpip/current/src/netif/loopif.c @@ -58,7 +58,7 @@ loopif_output(struct netif *netif, struc struct ip_addr *ipaddr) { struct pbuf *q, *r; - char *ptr; + u8_t *ptr; void **arg; #if defined(LWIP_DEBUG) && defined(LWIP_TCPDUMP)
--- a/packages/net/lwip_tcpip/current/src/netif/ppp/chap.h +++ b/packages/net/lwip_tcpip/current/src/netif/ppp/chap.h @@ -62,7 +62,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: chap.h,v 1.1 2004/05/04 12:32:33 jani Exp $ + * $Id: chap.h,v 1.2 2006/03/29 10:33:28 asl Exp $ */ #ifndef CHAP_H
--- a/packages/net/lwip_tcpip/current/src/netif/ppp/chpms.h +++ b/packages/net/lwip_tcpip/current/src/netif/ppp/chpms.h @@ -51,7 +51,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: chpms.h,v 1.1 2004/05/04 12:32:33 jani Exp $ + * $Id: chpms.h,v 1.2 2006/03/29 10:33:28 asl Exp $ */ #ifndef CHPMS_H
--- a/packages/net/lwip_tcpip/current/src/netif/ppp/fsm.h +++ b/packages/net/lwip_tcpip/current/src/netif/ppp/fsm.h @@ -48,7 +48,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: fsm.h,v 1.1 2004/05/04 12:32:33 jani Exp $ + * $Id: fsm.h,v 1.2 2006/03/29 10:33:28 asl Exp $ */ #ifndef FSM_H
--- a/packages/net/lwip_tcpip/current/src/netif/ppp/ipcp.c +++ b/packages/net/lwip_tcpip/current/src/netif/ppp/ipcp.c @@ -49,6 +49,8 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ +#include <string.h> + #include "ppp.h" #if PPP_SUPPORT > 0 #include "auth.h"
--- a/packages/net/lwip_tcpip/current/src/netif/ppp/ipcp.h +++ b/packages/net/lwip_tcpip/current/src/netif/ppp/ipcp.h @@ -48,7 +48,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: ipcp.h,v 1.1 2004/05/04 12:32:33 jani Exp $ + * $Id: ipcp.h,v 1.2 2006/03/29 10:33:28 asl Exp $ */ #ifndef IPCP_H
--- a/packages/net/lwip_tcpip/current/src/netif/ppp/lcp.c +++ b/packages/net/lwip_tcpip/current/src/netif/ppp/lcp.c @@ -49,6 +49,9 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ + +#include <string.h> + #include "ppp.h" #if PPP_SUPPORT > 0 #include "fsm.h" @@ -1232,7 +1235,7 @@ static int lcp_reqci(fsm *f, ho->neg_mru = 1; /* Remember he sent MRU */ ho->mru = cishort; /* And remember value */ #if TRACELCP > 0 - sprintf(&traceBuf[traceNdx], " MRU %d", cishort); + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " MRU %d", cishort); traceNdx = strlen(traceBuf); #endif break; @@ -1265,7 +1268,7 @@ static int lcp_reqci(fsm *f, ho->neg_asyncmap = 1; ho->asyncmap = cilong; #if TRACELCP > 0 - sprintf(&traceBuf[traceNdx], " ASYNCMAP=%lX", cilong); + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " ASYNCMAP=%lX", cilong); traceNdx = strlen(traceBuf); #endif break; @@ -1317,7 +1320,7 @@ static int lcp_reqci(fsm *f, } ho->neg_upap = 1; #if TRACELCP > 0 - sprintf(&traceBuf[traceNdx], " PAP (%X)", cishort); + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " PAP (%X)", cishort); traceNdx = strlen(traceBuf); #endif break; @@ -1355,7 +1358,7 @@ static int lcp_reqci(fsm *f, break; } #if TRACELCP > 0 - sprintf(&traceBuf[traceNdx], " CHAP %X,%d", cishort, cichar); + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CHAP %X,%d", cishort, cichar); traceNdx = strlen(traceBuf); #endif ho->chap_mdtype = cichar; /* save md type */ @@ -1387,7 +1390,7 @@ static int lcp_reqci(fsm *f, GETSHORT(cishort, p); GETLONG(cilong, p); #if TRACELCP > 0 - sprintf(&traceBuf[traceNdx], " QUALITY (%x %x)", cishort, (unsigned int) cilong); + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " QUALITY (%x %x)", cishort, (unsigned int) cilong); traceNdx = strlen(traceBuf); #endif @@ -1419,7 +1422,7 @@ static int lcp_reqci(fsm *f, } GETLONG(cilong, p); #if TRACELCP > 0 - sprintf(&traceBuf[traceNdx], " MAGICNUMBER (%lX)", cilong); + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " MAGICNUMBER (%lX)", cilong); traceNdx = strlen(traceBuf); #endif @@ -1442,7 +1445,7 @@ static int lcp_reqci(fsm *f, case CI_PCOMPRESSION: #if TRACELCP > 0 - sprintf(&traceBuf[traceNdx], " PCOMPRESSION"); + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " PCOMPRESSION"); traceNdx = strlen(traceBuf); #endif if (!ao->neg_pcompression || @@ -1455,7 +1458,7 @@ static int lcp_reqci(fsm *f, case CI_ACCOMPRESSION: #if TRACELCP > 0 - sprintf(&traceBuf[traceNdx], " ACCOMPRESSION"); + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " ACCOMPRESSION"); traceNdx = strlen(traceBuf); #endif if (!ao->neg_accompression || @@ -1468,7 +1471,7 @@ static int lcp_reqci(fsm *f, case CI_MRRU: #if TRACELCP > 0 - sprintf(&traceBuf[traceNdx], " CI_MRRU"); + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_MRRU"); traceNdx = strlen(traceBuf); #endif orc = CONFREJ; @@ -1476,7 +1479,7 @@ static int lcp_reqci(fsm *f, case CI_SSNHF: #if TRACELCP > 0 - sprintf(&traceBuf[traceNdx], " CI_SSNHF"); + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_SSNHF"); traceNdx = strlen(traceBuf); #endif orc = CONFREJ; @@ -1484,7 +1487,7 @@ static int lcp_reqci(fsm *f, case CI_EPDISC: #if TRACELCP > 0 - sprintf(&traceBuf[traceNdx], " CI_EPDISC"); + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_EPDISC"); traceNdx = strlen(traceBuf); #endif orc = CONFREJ; @@ -1492,7 +1495,7 @@ static int lcp_reqci(fsm *f, default: #if TRACELCP - sprintf(&traceBuf[traceNdx], " unknown %d", citype); + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " unknown %d", citype); traceNdx = strlen(traceBuf); #endif orc = CONFREJ;
--- a/packages/net/lwip_tcpip/current/src/netif/ppp/lcp.h +++ b/packages/net/lwip_tcpip/current/src/netif/ppp/lcp.h @@ -48,7 +48,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: lcp.h,v 1.1 2004/05/04 12:32:33 jani Exp $ + * $Id: lcp.h,v 1.2 2006/03/29 10:33:28 asl Exp $ */ #ifndef LCP_H
--- a/packages/net/lwip_tcpip/current/src/netif/ppp/magic.h +++ b/packages/net/lwip_tcpip/current/src/netif/ppp/magic.h @@ -48,7 +48,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: magic.h,v 1.1 2004/05/04 12:32:33 jani Exp $ + * $Id: magic.h,v 1.2 2006/03/29 10:33:28 asl Exp $ */ #ifndef MAGIC_H
--- a/packages/net/lwip_tcpip/current/src/netif/ppp/ppp.c +++ b/packages/net/lwip_tcpip/current/src/netif/ppp/ppp.c @@ -78,6 +78,9 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ + +#include <string.h> + #include "ppp.h" #if PPP_SUPPORT > 0 #include "randm.h"
--- a/packages/net/lwip_tcpip/current/src/netif/ppp/vj.c +++ b/packages/net/lwip_tcpip/current/src/netif/ppp/vj.c @@ -28,11 +28,12 @@ * for a 16 bit processor. */ +#include <string.h> + #include "ppp.h" #include "vj.h" #include "pppdebug.h" - #if VJ_SUPPORT > 0 #if LINK_STATS
--- a/packages/net/lwip_tcpip/current/src/netif/ppp/vj.h +++ b/packages/net/lwip_tcpip/current/src/netif/ppp/vj.h @@ -1,7 +1,7 @@ /* * Definitions for tcp compression routines. * - * $Id: vj.h,v 1.1 2004/05/04 12:32:33 jani Exp $ + * $Id: vj.h,v 1.2 2006/03/29 10:33:28 asl Exp $ * * Copyright (c) 1989 Regents of the University of California. * All rights reserved.
--- a/packages/net/lwip_tcpip/current/src/netif/slipif.c +++ b/packages/net/lwip_tcpip/current/src/netif/slipif.c @@ -32,9 +32,9 @@ */ /* - * This is an arch independent SLIP netif. The specific serial hooks must be provided - * by another file.They are sio_open, sio_recv and sio_send - */ + * This is an arch independent SLIP netif. The specific serial hooks must be + * provided by another file. They are sio_open, sio_recv and sio_send + */ #include "netif/slipif.h" #include "lwip/opt.h" @@ -55,32 +55,32 @@ * Send a pbuf doing the necessary SLIP encapsulation * * Uses the serial layer's sio_send() - */ + */ err_t slipif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr) { struct pbuf *q; - int i; + u16_t i; u8_t c; /* Send pbuf out on the serial I/O device. */ sio_send(SLIP_END, netif->state); - for(q = p; q != NULL; q = q->next) { - for(i = 0; i < q->len; i++) { + for (q = p; q != NULL; q = q->next) { + for (i = 0; i < q->len; i++) { c = ((u8_t *)q->payload)[i]; switch (c) { case SLIP_END: - sio_send(SLIP_ESC, netif->state); - sio_send(SLIP_ESC_END, netif->state); - break; + sio_send(SLIP_ESC, netif->state); + sio_send(SLIP_ESC_END, netif->state); + break; case SLIP_ESC: - sio_send(SLIP_ESC, netif->state); - sio_send(SLIP_ESC_ESC, netif->state); - break; + sio_send(SLIP_ESC, netif->state); + sio_send(SLIP_ESC_ESC, netif->state); + break; default: - sio_send(c, netif->state); - break; + sio_send(c, netif->state); + break; } } } @@ -94,14 +94,14 @@ slipif_output(struct netif *netif, struc * Poll the serial layer by calling sio_recv() * * @return The IP packet when SLIP_END is received - */ + */ static struct pbuf * -slipif_input( struct netif * netif ) +slipif_input(struct netif *netif) { u8_t c; struct pbuf *p, *q; - int recved; - int i; + u16_t recved; + u16_t i; q = p = NULL; recved = i = 0; @@ -112,13 +112,13 @@ slipif_input( struct netif * netif ) switch (c) { case SLIP_END: if (recved > 0) { - /* Received whole packet. */ - pbuf_realloc(q, recved); - - LINK_STATS_INC(link.recv); - - LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n")); - return q; + /* Received whole packet. */ + pbuf_realloc(q, recved); + + LINK_STATS_INC(link.recv); + + LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n")); + return q; } break; @@ -126,51 +126,54 @@ slipif_input( struct netif * netif ) c = sio_recv(netif->state); switch (c) { case SLIP_ESC_END: - c = SLIP_END; - break; + c = SLIP_END; + break; case SLIP_ESC_ESC: - c = SLIP_ESC; - break; + c = SLIP_ESC; + break; } /* FALLTHROUGH */ - + default: if (p == NULL) { - LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n")); - p = pbuf_alloc(PBUF_LINK, PBUF_POOL_BUFSIZE, PBUF_POOL); + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n")); + p = pbuf_alloc(PBUF_LINK, PBUF_POOL_BUFSIZE, PBUF_POOL); - if (p == NULL) { - LINK_STATS_INC(link.drop); - LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n")); - } - - if (q != NULL) { - pbuf_cat(q, p); - } else { - q = p; - } + if (p == NULL) { + LINK_STATS_INC(link.drop); + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n")); + } + + if (q != NULL) { + pbuf_cat(q, p); + } else { + q = p; + } } if (p != NULL && recved < MAX_SIZE) { - ((u8_t *)p->payload)[i] = c; - recved++; - i++; - if (i >= p->len) { - i = 0; - p = NULL; - } + ((u8_t *)p->payload)[i] = c; + recved++; + i++; + if (i >= p->len) { + i = 0; + if (p->next != NULL && p->next->len > 0) + p = p->next; + else + p = NULL; + } } break; } - + } return NULL; } /** - * The SLIP input thread + * The SLIP input thread. * * Feed the IP layer with incoming packets - */ + */ static void slipif_loop(void *nf) { @@ -188,22 +191,22 @@ slipif_loop(void *nf) * * Call the arch specific sio_open and remember * the opened device in the state field of the netif. - */ + */ err_t slipif_init(struct netif *netif) { - - LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%x\n", (int)netif->num)); + + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%"U16_F"\n", (u16_t)netif->num)); netif->name[0] = 's'; netif->name[1] = 'l'; netif->output = slipif_output; - netif->mtu = 1500; + netif->mtu = 1500; netif->flags = NETIF_FLAG_POINTTOPOINT; netif->state = sio_open(netif->num); if (!netif->state) - return ERR_IF; + return ERR_IF; sys_thread_new(slipif_loop, netif, SLIPIF_THREAD_PRIO); return ERR_OK;
--- a/packages/net/lwip_tcpip/current/tests/httpd.c +++ b/packages/net/lwip_tcpip/current/tests/httpd.c @@ -33,10 +33,11 @@ */ #include "lwip/debug.h" +#include "lwip/stats.h" +#include "lwip/tcp.h" +#include <cyg/infra/testcase.h> -#include "lwip/stats.h" - -#include "lwip/tcp.h" +#ifdef CYGPKG_LWIP_TCP struct http_state { const char *file; @@ -256,8 +257,9 @@ static cyg_thread thread_data; static cyg_handle_t thread_handle; void -cyg_user_start(void) +httpd_main(void) { + CYG_TEST_INIT(); // Create a main thread, so we can run the scheduler and have time 'pass' cyg_thread_create(10, // Priority - just a number tmain, // entry @@ -269,5 +271,26 @@ cyg_user_start(void) &thread_data // Thread data structure ); cyg_thread_resume(thread_handle); // Start it + cyg_scheduler_start(); + CYG_TEST_FAIL_FINISH("Not reached"); +} + +externC void +cyg_start( void ) +{ + httpd_main(); } +#else // def CYGPKG_LWIP_TCP +#define N_A_MSG "TCP support disabled" +#endif // def CYGFUN_KERNEL_API_C + +#ifdef N_A_MSG +externC void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA(N_A_MSG); +} +#endif // N_A_MSG +
--- a/packages/net/lwip_tcpip/current/tests/nc_test_slave.c +++ b/packages/net/lwip_tcpip/current/tests/nc_test_slave.c @@ -35,19 +35,20 @@ #include "nc_test_framework.h" -#include <cyg/error/errno.h> -#include <cyg/error/codes.h> -#include <cyg/error/strerror.h> #include <cyg/infra/diag.h> #include <lwip/inet.h> #include <lwip/arch.h> #include <lwip/sys.h> -#define LWIP_TIMEVAL_PRIVATE +#define LWIP_TIMEVAL_PRIVATE 1 #include <lwip/sockets.h> +#include <cyg/infra/testcase.h> #ifndef CYGPKG_LIBC_STDIO +#include <cyg/error/errno.h> #define perror(s) diag_printf(#s ": %s\n", strerror(errno)) +#else +#include <stdio.h> #endif #define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x1000) #define MAX_LOAD_THREAD_LEVEL 20 @@ -60,6 +61,11 @@ #define DESIRED_BACKGROUND_LOAD 20 #define CYGHWR_NET_DRIVERS 1 +#if SO_REUSE +#ifdef CYGPKG_LWIP_TCP +#ifdef CYGPKG_LWIP_UDP + + #if 0 static char main_thread_stack[CYGHWR_NET_DRIVERS][STACK_SIZE]; static cyg_thread main_thread_data[CYGHWR_NET_DRIVERS]; @@ -185,13 +191,13 @@ do_udp_test(int s1, struct nc_request *r if ((ntohl(tdp->key1) == NC_TEST_DATA_KEY1) && (ntohl(tdp->key2) == NC_TEST_DATA_KEY2)) { if (ntohl(tdp->seq) != seq) { - test_printf("Packets out of sequence - recvd: %ld, expected: %d\n", + test_printf("Packets out of sequence - recvd: %d, expected: %d\n", ntohl(tdp->seq), seq); seq = ntohl(tdp->seq); seq_errors++; } } else { - test_printf("Bad data packet - key: %lx/%lx, seq: %ld\n", + test_printf("Bad data packet - key: %lx/%lx, seq: %d\n", ntohl(tdp->key1), ntohl(tdp->key2), ntohl(tdp->seq)); } @@ -358,13 +364,13 @@ do_tcp_test(int s1, struct nc_request *r if ((ntohl(tdp->key1) == NC_TEST_DATA_KEY1) && (ntohl(tdp->key2) == NC_TEST_DATA_KEY2)) { if (ntohl(tdp->seq) != seq) { - test_printf("Packets out of sequence - recvd: %ld, expected: %d\n", + test_printf("Packets out of sequence - recvd: %d, expected: %d\n", ntohl(tdp->seq), seq); seq = ntohl(tdp->seq); seq_errors++; } } else { - test_printf("Bad data packet - key: %lx/%lx, seq: %ld\n", + test_printf("Bad data packet - key: %lx/%lx, seq: %d\n", ntohl(tdp->key1), ntohl(tdp->key2), ntohl(tdp->seq)); } @@ -452,22 +458,22 @@ nc_slave(test_param_t param) done = true; break; case NC_REQUEST_UDP_SEND: - test_printf("UDP send - %ld buffers, %ld bytes\n", ntohl(req.nbufs), ntohl(req.buflen)); + test_printf("UDP send - %d buffers, %d bytes\n", ntohl(req.nbufs), ntohl(req.buflen)); break; case NC_REQUEST_UDP_RECV: - test_printf("UDP recv - %ld buffers, %ld bytes\n", ntohl(req.nbufs), ntohl(req.buflen)); + test_printf("UDP recv - %d buffers, %d bytes\n", ntohl(req.nbufs), ntohl(req.buflen)); break; case NC_REQUEST_UDP_ECHO: - test_printf("UDP echo - %ld buffers, %ld bytes\n", ntohl(req.nbufs), ntohl(req.buflen)); + test_printf("UDP echo - %d buffers, %d bytes\n", ntohl(req.nbufs), ntohl(req.buflen)); break; case NC_REQUEST_TCP_SEND: - test_printf("TCP send - %ld buffers, %ld bytes\n", ntohl(req.nbufs), ntohl(req.buflen)); + test_printf("TCP send - %d buffers, %d bytes\n", ntohl(req.nbufs), ntohl(req.buflen)); break; case NC_REQUEST_TCP_RECV: - test_printf("TCP recv - %ld buffers, %ld bytes\n", ntohl(req.nbufs), ntohl(req.buflen)); + test_printf("TCP recv - %d buffers, %d bytes\n", ntohl(req.nbufs), ntohl(req.buflen)); break; case NC_REQUEST_TCP_ECHO: - test_printf("TCP echo - %ld buffers, %ld bytes\n", ntohl(req.nbufs), ntohl(req.buflen)); + test_printf("TCP echo - %d buffers, %d bytes\n", ntohl(req.nbufs), ntohl(req.buflen)); break; case NC_REQUEST_SET_LOAD: start_load(ntohl(req.nbufs)); @@ -487,7 +493,7 @@ nc_slave(test_param_t param) reply.misc.idle_results.count[1] = htonl((long)idle_thread_count); break; default: - test_printf("Unrecognized request: %ld\n", ntohl(req.type)); + test_printf("Unrecognized request: %d\n", ntohl(req.type)); reply.response = htonl(NC_REPLY_NAK); reply.reason = htonl(NC_REPLY_NAK_UNKNOWN_REQUEST); break; @@ -757,9 +763,11 @@ static cyg_thread thread_data; static cyg_handle_t thread_handle; void -cyg_user_start(void) +nc_slave_main(void) { int i; + + CYG_TEST_INIT(); // Create the idle thread environment cyg_semaphore_init(&idle_thread_sem, 0); cyg_thread_create(IDLE_THREAD_PRIORITY, // Priority @@ -797,4 +805,32 @@ cyg_user_start(void) &thread_data // Thread data structure ); cyg_thread_resume(thread_handle); // Start it + cyg_scheduler_start(); + CYG_TEST_FAIL_FINISH("Not reached"); } + + +externC void +cyg_start( void ) +{ + nc_slave_main(); +} + +#else // def CYGPKG_LWIP_UDP +#define N_A_MSG "UDP support disabled" +#endif // def CYGPKG_LWIP_UDP +#else // def CYGPKG_LWIP_TCP +#define N_A_MSG "TCP support disabled" +#endif // def CYGPKG_LWIP_TCP +#else // SO_REUSE +#define N_A_MSG "SO_REUSE currently unavailable" +#endif // SO_REUSE + +#ifdef N_A_MSG +externC void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA(N_A_MSG); +} +#endif // N_A_MSG
--- a/packages/net/lwip_tcpip/current/tests/socket.c +++ b/packages/net/lwip_tcpip/current/tests/socket.c @@ -33,9 +33,13 @@ /* Simple test-case for the BSD socket API : echo on TCP port 7 */ #include <lwip/sys.h> +#undef LWIP_COMPAT_SOCKETS #define LWIP_COMPAT_SOCKETS 1 #include <lwip/sockets.h> #include <lwip/inet.h> +#include <cyg/infra/testcase.h> + +#ifdef CYGPKG_LWIP_TCP char buf[400]; static void @@ -74,8 +78,9 @@ static cyg_thread thread_data; static cyg_handle_t thread_handle; void -cyg_user_start(void) +socket_main(void) { + CYG_TEST_INIT(); // Create a main thread, so we can run the scheduler and have time 'pass' cyg_thread_create(10, // Priority - just a number tmain, // entry @@ -87,5 +92,26 @@ cyg_user_start(void) &thread_data // Thread data structure ); cyg_thread_resume(thread_handle); // Start it + cyg_scheduler_start(); + CYG_TEST_FAIL_FINISH("Not reached"); +} + +externC void +cyg_start( void ) +{ + socket_main(); } +#else // def CYGPKG_LWIP_TCP +#define N_A_MSG "TCP support disabled" +#endif // def CYGFUN_KERNEL_API_C + +#ifdef N_A_MSG +externC void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA(N_A_MSG); +} +#endif // N_A_MSG +
--- a/packages/net/lwip_tcpip/current/tests/tcpecho.c +++ b/packages/net/lwip_tcpip/current/tests/tcpecho.c @@ -34,6 +34,9 @@ #include "lwip/sys.h" #include "lwip/api.h" +#include <cyg/infra/testcase.h> + +#ifdef CYGPKG_LWIP_TCP static void tcpecho_thread(void *arg) @@ -88,8 +91,10 @@ static cyg_thread thread_data; static cyg_handle_t thread_handle; void -cyg_user_start(void) +tcpecho_main(void) { + CYG_TEST_INIT(); + // Create a main thread, so we can run the scheduler and have time 'pass' cyg_thread_create(10, // Priority - just a number tmain, // entry @@ -100,6 +105,27 @@ cyg_user_start(void) &thread_handle, // Handle &thread_data // Thread data structure ); - cyg_thread_resume(thread_handle); // Start it + + cyg_thread_resume(thread_handle); // Start it + cyg_scheduler_start(); + CYG_TEST_FAIL_FINISH("Not reached"); +} + +externC void +cyg_start( void ) +{ + tcpecho_main(); } +#else // def CYGPKG_LWIP_TCP +#define N_A_MSG "TCP support disabled" +#endif // def CYGFUN_KERNEL_API_C + +#ifdef N_A_MSG +externC void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA(N_A_MSG); +} +#endif // N_A_MSG
--- a/packages/net/lwip_tcpip/current/tests/udpecho.c +++ b/packages/net/lwip_tcpip/current/tests/udpecho.c @@ -34,6 +34,9 @@ #include "lwip/api.h" #include "lwip/sys.h" +#include <cyg/infra/testcase.h> + +#ifdef CYGPKG_LWIP_UDP /*-----------------------------------------------------------------------------------*/ char buffer[100]; @@ -71,8 +74,9 @@ static cyg_thread thread_data; static cyg_handle_t thread_handle; void -cyg_user_start(void) +udpecho_main(void) { + CYG_TEST_INIT(); // Create a main thread, so we can run the scheduler and have time 'pass' cyg_thread_create(10, // Priority - just a number tmain, // entry @@ -84,5 +88,29 @@ cyg_user_start(void) &thread_data // Thread data structure ); cyg_thread_resume(thread_handle); // Start it + + cyg_scheduler_start(); + + CYG_TEST_FAIL_FINISH("Not reached"); +} + +externC void +cyg_start( void ) +{ + udpecho_main(); } +#else // def CYGPKG_LWIP_UDP +#define N_A_MSG "UDP support disabled" +#endif // def CYGFUN_KERNEL_API_C + +#ifdef N_A_MSG +externC void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA(N_A_MSG); +} +#endif // N_A_MSG + +
