Upgraded lwIP to 2.0.3

This commit is contained in:
Joseph Henry
2017-09-19 10:50:17 -07:00
parent 4991c85598
commit 91eb869e02
24 changed files with 568 additions and 304 deletions

View File

@@ -4,6 +4,22 @@ HISTORY
* [Enter new changes just after this line - do not remove this line] * [Enter new changes just after this line - do not remove this line]
(STABLE-2.0.3)
++ Bugfixes:
2017-09-11: Simon Goldschmidt
* tcp_in.c: fix bug #51937 (leaking tcp_pcbs on passive close with unacked data)
2017-08-02: Abroz Bizjak/Simon Goldschmidt
* multiple fixes in IPv4 reassembly (leading to corrupted datagrams received)
2017-03-30: Simon Goldschmidt
* dhcp.c: return ERR_VAL instead of asserting on offset-out-of-pbuf
2017-03-23: Dirk Ziegelmeier
* dhcp.h: fix bug #50618 (dhcp_remove_struct() macro does not work)
(STABLE-2.0.2) (STABLE-2.0.2)
++ New features: ++ New features:
@@ -13,6 +29,9 @@ HISTORY
We now have a #define for a header file name that is #included in every .c We now have a #define for a header file name that is #included in every .c
file that provides hooks. file that provides hooks.
2017-02-10: Simon Goldschmidt
* tcp_close does not fail on memory error (instead, FIN is sent from tcp_tmr)
++ Bugfixes: ++ Bugfixes:
2017-03-08 2017-03-08

View File

@@ -1,235 +1,243 @@
This file lists major changes between release versions that require This file lists major changes between release versions that require
ports or applications to be changed. Use it to update a port or an ports or applications to be changed. Use it to update a port or an
application written for an older version of lwIP to correctly work application written for an older version of lwIP to correctly work
with newer versions. with newer versions.
(git master) (git master)
* [Enter new changes just after this line - do not remove this line] * [Enter new changes just after this line - do not remove this line]
(2.0.2)
++ Application changes:
* slipif: The way to pass serial port number has changed. netif->num is not
supported any more, netif->state is interpreted as an u8_t port number now
(it's not a POINTER to an u8_t any more!)
(2.0.1) (2.0.1)
++ Application changes: ++ Application changes:
* UDP does NOT receive multicast traffic from ALL netifs on an UDP PCB bound to a specific * UDP does NOT receive multicast traffic from ALL netifs on an UDP PCB bound to a specific
netif any more. Users need to bind to IP_ADDR_ANY to receive multicast traffic and compare netif any more. Users need to bind to IP_ADDR_ANY to receive multicast traffic and compare
ip_current_netif() to the desired netif for every packet. ip_current_netif() to the desired netif for every packet.
See bug #49662 for an explanation. See bug #49662 for an explanation.
(2.0.0) (2.0.0)
++ Application changes: ++ Application changes:
* Changed netif "up" flag handling to be an administrative flag (as opposed to the previous meaning of * Changed netif "up" flag handling to be an administrative flag (as opposed to the previous meaning of
"ip4-address-valid", a netif will now not be used for transmission if not up) -> even a DHCP netif "ip4-address-valid", a netif will now not be used for transmission if not up) -> even a DHCP netif
has to be set "up" before starting the DHCP client has to be set "up" before starting the DHCP client
* Added IPv6 support (dual-stack or IPv4/IPv6 only) * Added IPv6 support (dual-stack or IPv4/IPv6 only)
* Changed ip_addr_t to be a union in dual-stack mode (use ip4_addr_t where referring to IPv4 only). * Changed ip_addr_t to be a union in dual-stack mode (use ip4_addr_t where referring to IPv4 only).
* Major rewrite of SNMP (added MIB parser that creates code stubs for custom MIBs); * Major rewrite of SNMP (added MIB parser that creates code stubs for custom MIBs);
supports SNMPv2c (experimental v3 support) supports SNMPv2c (experimental v3 support)
* Moved some core applications from contrib repository to src/apps (and include/lwip/apps) * Moved some core applications from contrib repository to src/apps (and include/lwip/apps)
+++ Raw API: +++ Raw API:
* Changed TCP listen backlog: removed tcp_accepted(), added the function pair tcp_backlog_delayed()/ * Changed TCP listen backlog: removed tcp_accepted(), added the function pair tcp_backlog_delayed()/
tcp_backlog_accepted() to explicitly delay backlog handling on a connection pcb tcp_backlog_accepted() to explicitly delay backlog handling on a connection pcb
+++ Socket API: +++ Socket API:
* Added an implementation for posix sendmsg() * Added an implementation for posix sendmsg()
* Added LWIP_FIONREAD_LINUXMODE that makes ioctl/FIONREAD return the size of the next pending datagram * Added LWIP_FIONREAD_LINUXMODE that makes ioctl/FIONREAD return the size of the next pending datagram
++ Port changes ++ Port changes
+++ new files: +++ new files:
* MANY new and moved files! * MANY new and moved files!
* Added src/Filelists.mk for use in Makefile projects * Added src/Filelists.mk for use in Makefile projects
* Continued moving stack-internal parts from abc.h to abc_priv.h in sub-folder "priv" * Continued moving stack-internal parts from abc.h to abc_priv.h in sub-folder "priv"
to let abc.h only contain the actual application programmer's API to let abc.h only contain the actual application programmer's API
+++ sys layer: +++ sys layer:
* Made LWIP_TCPIP_CORE_LOCKING==1 the default as it usually performs better than * Made LWIP_TCPIP_CORE_LOCKING==1 the default as it usually performs better than
the traditional message passing (although with LWIP_COMPAT_MUTEX you are still the traditional message passing (although with LWIP_COMPAT_MUTEX you are still
open to priority inversion, so this is not recommended any more) open to priority inversion, so this is not recommended any more)
* Added LWIP_NETCONN_SEM_PER_THREAD to use one "op_completed" semaphore per thread * Added LWIP_NETCONN_SEM_PER_THREAD to use one "op_completed" semaphore per thread
instead of using one per netconn (these semaphores are used even with core locking instead of using one per netconn (these semaphores are used even with core locking
enabled as some longer lasting functions like big writes still need to delay) enabled as some longer lasting functions like big writes still need to delay)
* Added generalized abstraction for itoa(), strnicmp(), stricmp() and strnstr() * Added generalized abstraction for itoa(), strnicmp(), stricmp() and strnstr()
in def.h (to be overridden in cc.h) instead of config in def.h (to be overridden in cc.h) instead of config
options for netbiosns, httpd, dns, etc. ... options for netbiosns, httpd, dns, etc. ...
* New abstraction for hton* and ntoh* functions in def.h. * New abstraction for hton* and ntoh* functions in def.h.
To override them, use the following in cc.h: To override them, use the following in cc.h:
#define lwip_htons(x) <your_htons> #define lwip_htons(x) <your_htons>
#define lwip_htonl(x) <your_htonl> #define lwip_htonl(x) <your_htonl>
+++ new options: +++ new options:
* TODO * TODO
+++ new pools: +++ new pools:
* Added LWIP_MEMPOOL_* (declare/init/alloc/free) to declare private memp pools * Added LWIP_MEMPOOL_* (declare/init/alloc/free) to declare private memp pools
that share memp.c code but do not have to be made global via lwippools.h that share memp.c code but do not have to be made global via lwippools.h
* Added pools for IPv6, MPU_COMPATIBLE, dns-api, netif-api, etc. * Added pools for IPv6, MPU_COMPATIBLE, dns-api, netif-api, etc.
* added hook LWIP_HOOK_MEMP_AVAILABLE() to get informed when a memp pool was empty and an item * added hook LWIP_HOOK_MEMP_AVAILABLE() to get informed when a memp pool was empty and an item
is now available is now available
* Signature of LWIP_HOOK_VLAN_SET macro was changed * Signature of LWIP_HOOK_VLAN_SET macro was changed
* LWIP_DECLARE_MEMORY_ALIGNED() may be used to declare aligned memory buffers (mem/memp) * LWIP_DECLARE_MEMORY_ALIGNED() may be used to declare aligned memory buffers (mem/memp)
or to move buffers to dedicated memory using compiler attributes or to move buffers to dedicated memory using compiler attributes
* Standard C headers are used to define sized types and printf formatters * Standard C headers are used to define sized types and printf formatters
(disable by setting LWIP_NO_STDINT_H=1 or LWIP_NO_INTTYPES_H=1 if your compiler (disable by setting LWIP_NO_STDINT_H=1 or LWIP_NO_INTTYPES_H=1 if your compiler
does not support these) does not support these)
++ Major bugfixes/improvements ++ Major bugfixes/improvements
* Added IPv6 support (dual-stack or IPv4/IPv6 only) * Added IPv6 support (dual-stack or IPv4/IPv6 only)
* Major rewrite of PPP (incl. keep-up with apache pppd) * Major rewrite of PPP (incl. keep-up with apache pppd)
see doc/ppp.txt for an upgrading how-to see doc/ppp.txt for an upgrading how-to
* Major rewrite of SNMP (incl. MIB parser) * Major rewrite of SNMP (incl. MIB parser)
* Fixed timing issues that might have lead to losing a DHCP lease * Fixed timing issues that might have lead to losing a DHCP lease
* Made rx processing path more robust against crafted errors * Made rx processing path more robust against crafted errors
* TCP window scaling support * TCP window scaling support
* modification of api modules to support FreeRTOS-MPU (don't pass stack-pointers to other threads) * modification of api modules to support FreeRTOS-MPU (don't pass stack-pointers to other threads)
* made DNS client more robust * made DNS client more robust
* support PBUF_REF for RX packets * support PBUF_REF for RX packets
* LWIP_NETCONN_FULLDUPLEX allows netconn/sockets to be used for reading/writing from separate * LWIP_NETCONN_FULLDUPLEX allows netconn/sockets to be used for reading/writing from separate
threads each (needs LWIP_NETCONN_SEM_PER_THREAD) threads each (needs LWIP_NETCONN_SEM_PER_THREAD)
* Moved and reordered stats (mainly memp/mib2) * Moved and reordered stats (mainly memp/mib2)
(1.4.0) (1.4.0)
++ Application changes: ++ Application changes:
* Replaced struct ip_addr by typedef ip_addr_t (struct ip_addr is kept for * Replaced struct ip_addr by typedef ip_addr_t (struct ip_addr is kept for
compatibility to old applications, but will be removed in the future). compatibility to old applications, but will be removed in the future).
* Renamed mem_realloc() to mem_trim() to prevent confusion with realloc() * Renamed mem_realloc() to mem_trim() to prevent confusion with realloc()
+++ Raw API: +++ Raw API:
* Changed the semantics of tcp_close() (since it was rather a * Changed the semantics of tcp_close() (since it was rather a
shutdown before): Now the application does *NOT* get any calls to the recv shutdown before): Now the application does *NOT* get any calls to the recv
callback (aside from NULL/closed) after calling tcp_close() callback (aside from NULL/closed) after calling tcp_close()
* When calling tcp_abort() from a raw API TCP callback function, * When calling tcp_abort() from a raw API TCP callback function,
make sure you return ERR_ABRT to prevent accessing unallocated memory. make sure you return ERR_ABRT to prevent accessing unallocated memory.
(ERR_ABRT now means the applicaiton has called tcp_abort!) (ERR_ABRT now means the applicaiton has called tcp_abort!)
+++ Netconn API: +++ Netconn API:
* Changed netconn_receive() and netconn_accept() to return * Changed netconn_receive() and netconn_accept() to return
err_t, not a pointer to new data/netconn. err_t, not a pointer to new data/netconn.
+++ Socket API: +++ Socket API:
* LWIP_SO_RCVTIMEO: when accept() or recv() time out, they * LWIP_SO_RCVTIMEO: when accept() or recv() time out, they
now set errno to EWOULDBLOCK/EAGAIN, not ETIMEDOUT. now set errno to EWOULDBLOCK/EAGAIN, not ETIMEDOUT.
* Added a minimal version of posix fctl() to have a * Added a minimal version of posix fctl() to have a
standardised way to set O_NONBLOCK for nonblocking sockets. standardised way to set O_NONBLOCK for nonblocking sockets.
+++ all APIs: +++ all APIs:
* correctly implemented SO(F)_REUSEADDR * correctly implemented SO(F)_REUSEADDR
++ Port changes ++ Port changes
+++ new files: +++ new files:
* Added 4 new files: def.c, timers.c, timers.h, tcp_impl.h: * Added 4 new files: def.c, timers.c, timers.h, tcp_impl.h:
* Moved stack-internal parts of tcp.h to tcp_impl.h, tcp.h now only contains * Moved stack-internal parts of tcp.h to tcp_impl.h, tcp.h now only contains
the actual application programmer's API the actual application programmer's API
* Separated timer implementation from sys.h/.c, moved to timers.h/.c; * Separated timer implementation from sys.h/.c, moved to timers.h/.c;
Added timer implementation for NO_SYS==1, set NO_SYS_NO_TIMERS==1 if you Added timer implementation for NO_SYS==1, set NO_SYS_NO_TIMERS==1 if you
still want to use your own timer implementation for NO_SYS==0 (as before). still want to use your own timer implementation for NO_SYS==0 (as before).
+++ sys layer: +++ sys layer:
* Converted mbox- and semaphore-functions to take pointers to sys_mbox_t/ * Converted mbox- and semaphore-functions to take pointers to sys_mbox_t/
sys_sem_t; sys_sem_t;
* Converted sys_mbox_new/sys_sem_new to take pointers and return err_t; * Converted sys_mbox_new/sys_sem_new to take pointers and return err_t;
* Added Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX to let sys.h use * Added Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX to let sys.h use
binary semaphores instead of mutexes - as before) binary semaphores instead of mutexes - as before)
+++ new options: +++ new options:
* Don't waste memory when chaining segments, added option TCP_OVERSIZE to * Don't waste memory when chaining segments, added option TCP_OVERSIZE to
prevent creating many small pbufs when calling tcp_write with many small prevent creating many small pbufs when calling tcp_write with many small
blocks of data. Instead, pbufs are allocated larger than needed and the blocks of data. Instead, pbufs are allocated larger than needed and the
space is used for later calls to tcp_write. space is used for later calls to tcp_write.
* Added LWIP_NETIF_TX_SINGLE_PBUF to always copy to try to create single pbufs * Added LWIP_NETIF_TX_SINGLE_PBUF to always copy to try to create single pbufs
in tcp_write/udp_send. in tcp_write/udp_send.
* Added an additional option LWIP_ETHERNET to support ethernet without ARP * Added an additional option LWIP_ETHERNET to support ethernet without ARP
(necessary for pure PPPoE) (necessary for pure PPPoE)
* Add MEMP_SEPARATE_POOLS to place memory pools in separate arrays. This may * Add MEMP_SEPARATE_POOLS to place memory pools in separate arrays. This may
be used to place these pools into user-defined memory by using external be used to place these pools into user-defined memory by using external
declaration. declaration.
* Added TCP_SNDQUEUELOWAT corresponding to TCP_SNDLOWAT * Added TCP_SNDQUEUELOWAT corresponding to TCP_SNDLOWAT
+++ new pools: +++ new pools:
* Netdb uses a memp pool for allocating memory when getaddrinfo() is called, * Netdb uses a memp pool for allocating memory when getaddrinfo() is called,
so MEMP_NUM_NETDB has to be set accordingly. so MEMP_NUM_NETDB has to be set accordingly.
* DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses a memp pool instead of the heap, so * DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses a memp pool instead of the heap, so
MEMP_NUM_LOCALHOSTLIST has to be set accordingly. MEMP_NUM_LOCALHOSTLIST has to be set accordingly.
* Snmp-agent uses a memp pools instead of the heap, so MEMP_NUM_SNMP_* have * Snmp-agent uses a memp pools instead of the heap, so MEMP_NUM_SNMP_* have
to be set accordingly. to be set accordingly.
* PPPoE uses a MEMP pool instead of the heap, so MEMP_NUM_PPPOE_INTERFACES * PPPoE uses a MEMP pool instead of the heap, so MEMP_NUM_PPPOE_INTERFACES
has to be set accordingly has to be set accordingly
* Integrated loopif into netif.c - loopif does not have to be created by the * Integrated loopif into netif.c - loopif does not have to be created by the
port any more, just define LWIP_HAVE_LOOPIF to 1. port any more, just define LWIP_HAVE_LOOPIF to 1.
* Added define LWIP_RAND() for lwip-wide randomization (needs to be defined * Added define LWIP_RAND() for lwip-wide randomization (needs to be defined
in cc.h, e.g. used by igmp) in cc.h, e.g. used by igmp)
* Added printf-formatter X8_F to printf u8_t as hex * Added printf-formatter X8_F to printf u8_t as hex
* The heap now may be moved to user-defined memory by defining * The heap now may be moved to user-defined memory by defining
LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address
* added autoip_set_struct() and dhcp_set_struct() to let autoip and dhcp work * added autoip_set_struct() and dhcp_set_struct() to let autoip and dhcp work
with user-allocated structs instead of calling mem_malloc with user-allocated structs instead of calling mem_malloc
* Added const char* name to mem- and memp-stats for easier debugging. * Added const char* name to mem- and memp-stats for easier debugging.
* Calculate the TCP/UDP checksum while copying to only fetch data once: * Calculate the TCP/UDP checksum while copying to only fetch data once:
Define LWIP_CHKSUM_COPY to a memcpy-like function that returns the checksum Define LWIP_CHKSUM_COPY to a memcpy-like function that returns the checksum
* Added SO_REUSE_RXTOALL to pass received UDP broadcast/multicast packets to * Added SO_REUSE_RXTOALL to pass received UDP broadcast/multicast packets to
more than one pcb. more than one pcb.
* Changed the semantics of ARP_QUEUEING==0: ARP_QUEUEING now cannot be turned * Changed the semantics of ARP_QUEUEING==0: ARP_QUEUEING now cannot be turned
off any more, if this is set to 0, only one packet (the most recent one) is off any more, if this is set to 0, only one packet (the most recent one) is
queued (like demanded by RFC 1122). queued (like demanded by RFC 1122).
++ Major bugfixes/improvements ++ Major bugfixes/improvements
* Implemented tcp_shutdown() to only shut down one end of a connection * Implemented tcp_shutdown() to only shut down one end of a connection
* Implemented shutdown() at socket- and netconn-level * Implemented shutdown() at socket- and netconn-level
* Added errorset support to select() + improved select speed overhead * Added errorset support to select() + improved select speed overhead
* Merged pppd to v2.3.11 (including some backported bugfixes from 2.4.x) * Merged pppd to v2.3.11 (including some backported bugfixes from 2.4.x)
* Added timer implementation for NO_SYS==1 (may be disabled with NO_SYS_NO_TIMERS==1 * Added timer implementation for NO_SYS==1 (may be disabled with NO_SYS_NO_TIMERS==1
* Use macros defined in ip_addr.h to work with IP addresses * Use macros defined in ip_addr.h to work with IP addresses
* Implemented many nonblocking socket/netconn functions * Implemented many nonblocking socket/netconn functions
* Fixed ARP input processing: only add a new entry if a request was directed as us * Fixed ARP input processing: only add a new entry if a request was directed as us
* mem_realloc() to mem_trim() to prevent confusion with realloc() * mem_realloc() to mem_trim() to prevent confusion with realloc()
* Some improvements for AutoIP (don't route/forward link-local addresses, don't break * Some improvements for AutoIP (don't route/forward link-local addresses, don't break
existing connections when assigning a routable address) existing connections when assigning a routable address)
* Correctly handle remote side overrunning our rcv_wnd in ooseq case * Correctly handle remote side overrunning our rcv_wnd in ooseq case
* Removed packing from ip_addr_t, the packed version is now only used in protocol headers * Removed packing from ip_addr_t, the packed version is now only used in protocol headers
* Corrected PBUF_POOL_BUFSIZE for ports where ETH_PAD_SIZE > 0 * Corrected PBUF_POOL_BUFSIZE for ports where ETH_PAD_SIZE > 0
* Added support for static ARP table entries * Added support for static ARP table entries
(STABLE-1.3.2) (STABLE-1.3.2)
* initial version of this file * initial version of this file

View File

@@ -1,4 +1,5 @@
void eth_mac_irq() void
eth_mac_irq()
{ {
/* Service MAC IRQ here */ /* Service MAC IRQ here */
@@ -17,7 +18,8 @@ void eth_mac_irq()
} }
} }
static err_t netif_output(struct netif *netif, struct pbuf *p) static err_t
netif_output(struct netif *netif, struct pbuf *p)
{ {
LINK_STATS_INC(link.xmit); LINK_STATS_INC(link.xmit);
@@ -38,12 +40,14 @@ static err_t netif_output(struct netif *netif, struct pbuf *p)
return ERR_OK; return ERR_OK;
} }
static void netif_status_callback(struct netif *netif) static void
netif_status_callback(struct netif *netif)
{ {
printf("netif status changed %s\n", ip4addr_ntoa(netif_ip4_addr(netif))); printf("netif status changed %s\n", ip4addr_ntoa(netif_ip4_addr(netif)));
} }
static err_t netif_init(struct netif *netif) static err_t
netif_init(struct netif *netif)
{ {
netif->linkoutput = netif_output; netif->linkoutput = netif_output;
netif->output = etharp_output; netif->output = etharp_output;
@@ -58,7 +62,8 @@ static err_t netif_init(struct netif *netif)
return ERR_OK; return ERR_OK;
} }
void main(void) void
main(void)
{ {
struct netif netif; struct netif netif;
@@ -74,7 +79,7 @@ void main(void)
netif_set_up(&netif); netif_set_up(&netif);
/* Start DHCP and HTTPD */ /* Start DHCP and HTTPD */
dhcp_init(); dhcp_start(&netif );
httpd_init(); httpd_init();
while(1) { while(1) {

View File

@@ -177,14 +177,20 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL); LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL);
LWIP_ASSERT("recv_udp must have an argument", arg != NULL); LWIP_ASSERT("recv_udp must have an argument", arg != NULL);
conn = (struct netconn *)arg; conn = (struct netconn *)arg;
if (conn == NULL) {
pbuf_free(p);
return;
}
LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb); LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb);
#if LWIP_SO_RCVBUF #if LWIP_SO_RCVBUF
SYS_ARCH_GET(conn->recv_avail, recv_avail); SYS_ARCH_GET(conn->recv_avail, recv_avail);
if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox) || if (!sys_mbox_valid(&conn->recvmbox) ||
((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) { ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) {
#else /* LWIP_SO_RCVBUF */ #else /* LWIP_SO_RCVBUF */
if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox)) { if (!sys_mbox_valid(&conn->recvmbox)) {
#endif /* LWIP_SO_RCVBUF */ #endif /* LWIP_SO_RCVBUF */
pbuf_free(p); pbuf_free(p);
return; return;
@@ -471,8 +477,6 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
struct netconn *newconn; struct netconn *newconn;
struct netconn *conn = (struct netconn *)arg; struct netconn *conn = (struct netconn *)arg;
LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: newpcb->tate: %s\n", tcp_debug_state_str(newpcb->state)));
if (conn == NULL) { if (conn == NULL) {
return ERR_VAL; return ERR_VAL;
} }
@@ -490,6 +494,8 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
return ERR_VAL; return ERR_VAL;
} }
LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: newpcb->tate: %s\n", tcp_debug_state_str(newpcb->state)));
/* We have to set the callback here even though /* We have to set the callback here even though
* the new socket is unknown. newconn->socket is marked as -1. */ * the new socket is unknown. newconn->socket is marked as -1. */
newconn = netconn_alloc(conn->type, conn->callback); newconn = netconn_alloc(conn->type, conn->callback);

View File

@@ -41,6 +41,7 @@
#include "lwip/sys.h" #include "lwip/sys.h"
#include <errno.h> #include <errno.h>
//#include "lwip/errno.h"
#if !NO_SYS #if !NO_SYS
/** Table to quickly map an lwIP error (err_t) to a socket error /** Table to quickly map an lwIP error (err_t) to a socket error

View File

@@ -360,8 +360,9 @@ mqtt_take_request(struct mqtt_request_t **tail, u16_t pkt_id)
static void static void
mqtt_request_time_elapsed(struct mqtt_request_t **tail, u8_t t) mqtt_request_time_elapsed(struct mqtt_request_t **tail, u8_t t)
{ {
struct mqtt_request_t *r = *tail; struct mqtt_request_t *r;
LWIP_ASSERT("mqtt_request_time_elapsed: tail != NULL", tail != NULL); LWIP_ASSERT("mqtt_request_time_elapsed: tail != NULL", tail != NULL);
r = *tail;
while (t > 0 && r != NULL) { while (t > 0 && r != NULL) {
if (t >= r->timeout_diff) { if (t >= r->timeout_diff) {
t -= (u8_t)r->timeout_diff; t -= (u8_t)r->timeout_diff;

View File

@@ -337,7 +337,7 @@ void
lwip_init(void) lwip_init(void)
{ {
#ifndef LWIP_SKIP_CONST_CHECK #ifndef LWIP_SKIP_CONST_CHECK
int a; int a = 0;
LWIP_UNUSED_ARG(a); LWIP_UNUSED_ARG(a);
LWIP_ASSERT("LWIP_CONST_CAST not implemented correctly. Check your lwIP port.", LWIP_CONST_CAST(void*, &a) == &a); LWIP_ASSERT("LWIP_CONST_CAST not implemented correctly. Check your lwIP port.", LWIP_CONST_CAST(void*, &a) == &a);
#endif #endif

View File

@@ -736,7 +736,7 @@ dhcp_start(struct netif *netif)
/* no DHCP client attached yet? */ /* no DHCP client attached yet? */
if (dhcp == NULL) { if (dhcp == NULL) {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting new DHCP client\n")); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): mallocing new DHCP client\n"));
dhcp = (struct dhcp *)mem_malloc(sizeof(struct dhcp)); dhcp = (struct dhcp *)mem_malloc(sizeof(struct dhcp));
if (dhcp == NULL) { if (dhcp == NULL) {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n")); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n"));
@@ -1500,7 +1500,7 @@ again:
offset_max = options_idx_max; offset_max = options_idx_max;
options = (u8_t*)q->payload; options = (u8_t*)q->payload;
/* at least 1 byte to read and no end marker, then at least 3 bytes to read? */ /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */
while ((q != NULL) && (options[offset] != DHCP_OPTION_END) && (offset < offset_max)) { while ((q != NULL) && (offset < offset_max) && (options[offset] != DHCP_OPTION_END)) {
u8_t op = options[offset]; u8_t op = options[offset];
u8_t len; u8_t len;
u8_t decode_len = 0; u8_t decode_len = 0;
@@ -1617,7 +1617,7 @@ decode_next:
offset_max -= q->len; offset_max -= q->len;
if ((offset < offset_max) && offset_max) { if ((offset < offset_max) && offset_max) {
q = q->next; q = q->next;
LWIP_ASSERT("next pbuf was null", q); LWIP_ERROR("next pbuf was null", q != NULL, return ERR_VAL;);
options = (u8_t*)q->payload; options = (u8_t*)q->payload;
} else { } else {
/* We've run out of bytes, probably no end marker. Don't proceed. */ /* We've run out of bytes, probably no end marker. Don't proceed. */
@@ -1832,7 +1832,7 @@ dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type)
(dhcp->p_out->len >= sizeof(struct dhcp_msg))); (dhcp->p_out->len >= sizeof(struct dhcp_msg)));
/* DHCP_REQUEST should reuse 'xid' from DHCPOFFER */ /* DHCP_REQUEST should reuse 'xid' from DHCPOFFER */
if (message_type != DHCP_REQUEST) { if ((message_type != DHCP_REQUEST) || (dhcp->state == DHCP_STATE_REBOOTING)) {
/* reuse transaction identifier in retransmissions */ /* reuse transaction identifier in retransmissions */
if (dhcp->tries == 0) { if (dhcp->tries == 0) {
#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND) #if DHCP_CREATE_RAND_XID && defined(LWIP_RAND)
@@ -1942,7 +1942,8 @@ dhcp_supplied_address(const struct netif *netif)
{ {
if ((netif != NULL) && (netif_dhcp_data(netif) != NULL)) { if ((netif != NULL) && (netif_dhcp_data(netif) != NULL)) {
struct dhcp* dhcp = netif_dhcp_data(netif); struct dhcp* dhcp = netif_dhcp_data(netif);
return (dhcp->state == DHCP_STATE_BOUND) || (dhcp->state == DHCP_STATE_RENEWING); return (dhcp->state == DHCP_STATE_BOUND) || (dhcp->state == DHCP_STATE_RENEWING) ||
(dhcp->state == DHCP_STATE_REBINDING);
} }
return 0; return 0;
} }

View File

@@ -79,6 +79,10 @@
#define IP_REASS_FLAG_LASTFRAG 0x01 #define IP_REASS_FLAG_LASTFRAG 0x01
#define IP_REASS_VALIDATE_TELEGRAM_FINISHED 1
#define IP_REASS_VALIDATE_PBUF_QUEUED 0
#define IP_REASS_VALIDATE_PBUF_DROPPED -1
/** This is a helper struct which holds the starting /** This is a helper struct which holds the starting
* offset and the ending offset of this fragment to * offset and the ending offset of this fragment to
* easily chain the fragments. * easily chain the fragments.
@@ -333,10 +337,11 @@ ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev)
* fragment was received at least once). * fragment was received at least once).
* @param ipr points to the reassembly state * @param ipr points to the reassembly state
* @param new_p points to the pbuf for the current fragment * @param new_p points to the pbuf for the current fragment
* @return 0 if invalid, >0 otherwise * @param is_last is 1 if this pbuf has MF==0 (ipr->flags not updated yet)
* @return see IP_REASS_VALIDATE_* defines
*/ */
static int static int
ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct pbuf *new_p) ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct pbuf *new_p, int is_last)
{ {
struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL; struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL;
struct pbuf *q; struct pbuf *q;
@@ -375,7 +380,18 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
} }
#endif /* IP_REASS_CHECK_OVERLAP */ #endif /* IP_REASS_CHECK_OVERLAP */
iprh_prev->next_pbuf = new_p; iprh_prev->next_pbuf = new_p;
if (iprh_prev->end != iprh->start) {
/* There is a fragment missing between the current
* and the previous fragment */
valid = 0;
}
} else { } else {
#if IP_REASS_CHECK_OVERLAP
if (iprh->end > iprh_tmp->start) {
/* fragment overlaps with following, throw away */
goto freepbuf;
}
#endif /* IP_REASS_CHECK_OVERLAP */
/* fragment with the lowest offset */ /* fragment with the lowest offset */
ipr->p = new_p; ipr->p = new_p;
} }
@@ -426,7 +442,7 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
/* At this point, the validation part begins: */ /* At this point, the validation part begins: */
/* If we already received the last fragment */ /* If we already received the last fragment */
if ((ipr->flags & IP_REASS_FLAG_LASTFRAG) != 0) { if (is_last || ((ipr->flags & IP_REASS_FLAG_LASTFRAG) != 0)) {
/* and had no holes so far */ /* and had no holes so far */
if (valid) { if (valid) {
/* then check if the rest of the fragments is here */ /* then check if the rest of the fragments is here */
@@ -454,23 +470,21 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
((struct ip_reass_helper*)ipr->p->payload) != iprh); ((struct ip_reass_helper*)ipr->p->payload) != iprh);
LWIP_ASSERT("validate_datagram:next_pbuf!=NULL", LWIP_ASSERT("validate_datagram:next_pbuf!=NULL",
iprh->next_pbuf == NULL); iprh->next_pbuf == NULL);
LWIP_ASSERT("validate_datagram:datagram end!=datagram len",
iprh->end == ipr->datagram_len);
} }
} }
} }
/* If valid is 0 here, there are some fragments missing in the middle /* If valid is 0 here, there are some fragments missing in the middle
* (since MF == 0 has already arrived). Such datagrams simply time out if * (since MF == 0 has already arrived). Such datagrams simply time out if
* no more fragments are received... */ * no more fragments are received... */
return valid; return valid ? IP_REASS_VALIDATE_TELEGRAM_FINISHED : IP_REASS_VALIDATE_PBUF_QUEUED;
} }
/* If we come here, not all fragments were received, yet! */ /* If we come here, not all fragments were received, yet! */
return 0; /* not yet valid! */ return IP_REASS_VALIDATE_PBUF_QUEUED; /* not yet valid! */
#if IP_REASS_CHECK_OVERLAP #if IP_REASS_CHECK_OVERLAP
freepbuf: freepbuf:
ip_reass_pbufcount -= pbuf_clen(new_p); ip_reass_pbufcount -= pbuf_clen(new_p);
pbuf_free(new_p); pbuf_free(new_p);
return 0; return IP_REASS_VALIDATE_PBUF_DROPPED;
#endif /* IP_REASS_CHECK_OVERLAP */ #endif /* IP_REASS_CHECK_OVERLAP */
} }
@@ -488,6 +502,8 @@ ip4_reass(struct pbuf *p)
struct ip_reassdata *ipr; struct ip_reassdata *ipr;
struct ip_reass_helper *iprh; struct ip_reass_helper *iprh;
u16_t offset, len, clen; u16_t offset, len, clen;
int valid;
int is_last;
IPFRAG_STATS_INC(ip_frag.recv); IPFRAG_STATS_INC(ip_frag.recv);
MIB2_STATS_INC(mib2.ipreasmreqds); MIB2_STATS_INC(mib2.ipreasmreqds);
@@ -552,24 +568,41 @@ ip4_reass(struct pbuf *p)
SMEMCPY(&ipr->iphdr, fraghdr, IP_HLEN); SMEMCPY(&ipr->iphdr, fraghdr, IP_HLEN);
} }
} }
/* Track the current number of pbufs current 'in-flight', in order to limit
the number of fragments that may be enqueued at any one time */
ip_reass_pbufcount += clen;
/* At this point, we have either created a new entry or pointing /* At this point, we have either created a new entry or pointing
* to an existing one */ * to an existing one */
/* check for 'no more fragments', and update queue entry*/ /* check for 'no more fragments', and update queue entry*/
if ((IPH_OFFSET(fraghdr) & PP_NTOHS(IP_MF)) == 0) { is_last = (IPH_OFFSET(fraghdr) & PP_NTOHS(IP_MF)) == 0;
if (is_last) {
u16_t datagram_len = (u16_t)(offset + len);
if ((datagram_len < offset) || (datagram_len > (0xFFFF - IP_HLEN))) {
/* u16_t overflow, cannot handle this */
goto nullreturn;
}
}
/* find the right place to insert this pbuf */
/* @todo: trim pbufs if fragments are overlapping */
valid = ip_reass_chain_frag_into_datagram_and_validate(ipr, p, is_last);
if (valid == IP_REASS_VALIDATE_PBUF_DROPPED) {
goto nullreturn;
}
/* if we come here, the pbuf has been enqueued */
/* Track the current number of pbufs current 'in-flight', in order to limit
the number of fragments that may be enqueued at any one time
(overflow checked by testing against IP_REASS_MAX_PBUFS) */
ip_reass_pbufcount = (u16_t)(ip_reass_pbufcount + clen);
if (is_last) {
u16_t datagram_len = (u16_t)(offset + len);
ipr->datagram_len = datagram_len;
ipr->flags |= IP_REASS_FLAG_LASTFRAG; ipr->flags |= IP_REASS_FLAG_LASTFRAG;
ipr->datagram_len = offset + len;
LWIP_DEBUGF(IP_REASS_DEBUG, LWIP_DEBUGF(IP_REASS_DEBUG,
("ip4_reass: last fragment seen, total len %"S16_F"\n", ("ip4_reass: last fragment seen, total len %"S16_F"\n",
ipr->datagram_len)); ipr->datagram_len));
} }
/* find the right place to insert this pbuf */
/* @todo: trim pbufs if fragments are overlapping */ if (valid == IP_REASS_VALIDATE_TELEGRAM_FINISHED) {
if (ip_reass_chain_frag_into_datagram_and_validate(ipr, p)) {
struct ip_reassdata *ipr_prev; struct ip_reassdata *ipr_prev;
/* the totally last fragment (flag more fragments = 0) was received at least /* the totally last fragment (flag more fragments = 0) was received at least
* once AND all fragments are received */ * once AND all fragments are received */

View File

@@ -849,7 +849,9 @@ netif_loop_output(struct netif *netif, struct pbuf *p)
netif_poll(). */ netif_poll(). */
/* let last point to the last pbuf in chain r */ /* let last point to the last pbuf in chain r */
for (last = r; last->next != NULL; last = last->next); for (last = r; last->next != NULL; last = last->next) {
/* nothing to do here, just get to the last pbuf */
}
SYS_ARCH_PROTECT(lev); SYS_ARCH_PROTECT(lev);
if (netif->loop_first != NULL) { if (netif->loop_first != NULL) {

View File

@@ -358,7 +358,6 @@ tcp_close_shutdown_fin(struct tcp_pcb *pcb)
default: default:
/* Has already been closed, do nothing. */ /* Has already been closed, do nothing. */
return ERR_OK; return ERR_OK;
break;
} }
if (err == ERR_OK) { if (err == ERR_OK) {
@@ -371,6 +370,12 @@ tcp_close_shutdown_fin(struct tcp_pcb *pcb)
} else if (err == ERR_MEM) { } else if (err == ERR_MEM) {
/* Mark this pcb for closing. Closing is retried from tcp_tmr. */ /* Mark this pcb for closing. Closing is retried from tcp_tmr. */
pcb->flags |= TF_CLOSEPEND; pcb->flags |= TF_CLOSEPEND;
/* We have to return ERR_OK from here to indicate to the callers that this
pcb should not be used any more as it will be freed soon via tcp_tmr.
This is OK here since sending FIN does not guarantee a time frime for
actually freeing the pcb, either (it is left in closure states for
remote ACK or timeout) */
return ERR_OK;
} }
return err; return err;
} }
@@ -408,8 +413,8 @@ tcp_close(struct tcp_pcb *pcb)
* @ingroup tcp_raw * @ingroup tcp_raw
* Causes all or part of a full-duplex connection of this PCB to be shut down. * Causes all or part of a full-duplex connection of this PCB to be shut down.
* This doesn't deallocate the PCB unless shutting down both sides! * This doesn't deallocate the PCB unless shutting down both sides!
* Shutting down both sides is the same as calling tcp_close, so if it succeds, * Shutting down both sides is the same as calling tcp_close, so if it succeds
* the PCB should not be referenced any more. * (i.e. returns ER_OK), the PCB must not be referenced any more!
* *
* @param pcb PCB to shutdown * @param pcb PCB to shutdown
* @param shut_rx shut down receive side if this is != 0 * @param shut_rx shut down receive side if this is != 0

View File

@@ -89,6 +89,8 @@ static void tcp_parseopt(struct tcp_pcb *pcb);
static void tcp_listen_input(struct tcp_pcb_listen *pcb); static void tcp_listen_input(struct tcp_pcb_listen *pcb);
static void tcp_timewait_input(struct tcp_pcb *pcb); static void tcp_timewait_input(struct tcp_pcb *pcb);
static int tcp_input_delayed_close(struct tcp_pcb *pcb);
/** /**
* The initial input processing of TCP. It verifies the TCP header, demultiplexes * The initial input processing of TCP. It verifies the TCP header, demultiplexes
* the segment between the PCBs and passes it on to tcp_process(), which implements * the segment between the PCBs and passes it on to tcp_process(), which implements
@@ -404,17 +406,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
} }
recv_acked = 0; recv_acked = 0;
} }
if (recv_flags & TF_CLOSED) { if (tcp_input_delayed_close(pcb)) {
/* The connection has been closed and we will deallocate the
PCB. */
if (!(pcb->flags & TF_RXCLOSED)) {
/* Connection closed although the application has only shut down the
tx side: call the PCB's err callback and indicate the closure to
ensure the application doesn't continue using the PCB. */
TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_CLSD);
}
tcp_pcb_remove(&tcp_active_pcbs, pcb);
memp_free(MEMP_TCP_PCB, pcb);
goto aborted; goto aborted;
} }
#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE #if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
@@ -488,6 +480,9 @@ tcp_input(struct pbuf *p, struct netif *inp)
} }
tcp_input_pcb = NULL; tcp_input_pcb = NULL;
if (tcp_input_delayed_close(pcb)) {
goto aborted;
}
/* Try to send something out. */ /* Try to send something out. */
tcp_output(pcb); tcp_output(pcb);
#if TCP_INPUT_DEBUG #if TCP_INPUT_DEBUG
@@ -532,6 +527,30 @@ dropped:
pbuf_free(p); pbuf_free(p);
} }
/** Called from tcp_input to check for TF_CLOSED flag. This results in closing
* and deallocating a pcb at the correct place to ensure noone references it
* any more.
* @returns 1 if the pcb has been closed and deallocated, 0 otherwise
*/
static int
tcp_input_delayed_close(struct tcp_pcb *pcb)
{
if (recv_flags & TF_CLOSED) {
/* The connection has been closed and we will deallocate the
PCB. */
if (!(pcb->flags & TF_RXCLOSED)) {
/* Connection closed although the application has only shut down the
tx side: call the PCB's err callback and indicate the closure to
ensure the application doesn't continue using the PCB. */
TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_CLSD);
}
tcp_pcb_remove(&tcp_active_pcbs, pcb);
memp_free(MEMP_TCP_PCB, pcb);
return 1;
}
return 0;
}
/** /**
* Called by tcp_input() when a segment arrives for a listening * Called by tcp_input() when a segment arrives for a listening
* connection (from tcp_input()). * connection (from tcp_input()).
@@ -1749,11 +1768,11 @@ tcp_parseopt(struct tcp_pcb *pcb)
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
return; return;
} }
/* An WND_SCALE option with the right option length. */
data = tcp_getoptbyte();
/* If syn was received with wnd scale option, /* If syn was received with wnd scale option,
activate wnd scale opt, but only if this is not a retransmission */ activate wnd scale opt, but only if this is not a retransmission */
if ((flags & TCP_SYN) && !(pcb->flags & TF_WND_SCALE)) { if ((flags & TCP_SYN) && !(pcb->flags & TF_WND_SCALE)) {
/* An WND_SCALE option with the right option length. */
data = tcp_getoptbyte();
pcb->snd_scale = data; pcb->snd_scale = data;
if (pcb->snd_scale > 14U) { if (pcb->snd_scale > 14U) {
pcb->snd_scale = 14U; pcb->snd_scale = 14U;

View File

@@ -176,7 +176,7 @@ void sys_timeouts_init(void)
{ {
size_t i; size_t i;
/* tcp_tmr() at index 0 is started on demand */ /* tcp_tmr() at index 0 is started on demand */
for (i = 1; i < LWIP_ARRAYSIZE(lwip_cyclic_timers); i++) { for (i = (LWIP_TCP ? 1 : 0); i < LWIP_ARRAYSIZE(lwip_cyclic_timers); i++) {
/* we have to cast via size_t to get rid of const warning /* we have to cast via size_t to get rid of const warning
(this is OK as cyclic_timer() casts back to const* */ (this is OK as cyclic_timer() casts back to const* */
sys_timeout(lwip_cyclic_timers[i].interval_ms, cyclic_timer, LWIP_CONST_CAST(void*, &lwip_cyclic_timers[i])); sys_timeout(lwip_cyclic_timers[i].interval_ms, cyclic_timer, LWIP_CONST_CAST(void*, &lwip_cyclic_timers[i]));

View File

@@ -76,8 +76,7 @@
* systems, this should be defined to something less resource-consuming. * systems, this should be defined to something less resource-consuming.
*/ */
#ifndef LWIP_PLATFORM_DIAG #ifndef LWIP_PLATFORM_DIAG
#include "Debug.hpp" #define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0)
#define LWIP_PLATFORM_DIAG(x) printf(x);
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#endif #endif

View File

@@ -91,14 +91,6 @@ u32_t lwip_htonl(u32_t x);
#endif #endif
#define lwip_ntohl(x) lwip_htonl(x) #define lwip_ntohl(x) lwip_htonl(x)
/* Provide usual function names as macros for users, but this can be turned off */
#ifndef LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS
#define htons(x) lwip_htons(x)
#define ntohs(x) lwip_ntohs(x)
#define htonl(x) lwip_htonl(x)
#define ntohl(x) lwip_ntohl(x)
#endif
/* These macros should be calculated by the preprocessor and are used /* These macros should be calculated by the preprocessor and are used
with compile-time constants only (so that there is no little-endian with compile-time constants only (so that there is no little-endian
overhead at runtime). */ overhead at runtime). */
@@ -109,9 +101,16 @@ u32_t lwip_htonl(u32_t x);
(((x) & 0x00ff0000UL) >> 8) | \ (((x) & 0x00ff0000UL) >> 8) | \
(((x) & 0xff000000UL) >> 24)) (((x) & 0xff000000UL) >> 24))
#define PP_NTOHL(x) PP_HTONL(x) #define PP_NTOHL(x) PP_HTONL(x)
#endif /* BYTE_ORDER == BIG_ENDIAN */ #endif /* BYTE_ORDER == BIG_ENDIAN */
/* Provide usual function names as macros for users, but this can be turned off */
#ifndef LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS
#define htons(x) lwip_htons(x)
#define ntohs(x) lwip_ntohs(x)
#define htonl(x) lwip_htonl(x)
#define ntohl(x) lwip_ntohl(x)
#endif
/* Functions that are not available as standard implementations. /* Functions that are not available as standard implementations.
* In cc.h, you can #define these to implementations available on * In cc.h, you can #define these to implementations available on
* your platform to save some code bytes if you use these functions * your platform to save some code bytes if you use these functions

View File

@@ -108,7 +108,7 @@ struct dhcp
void dhcp_set_struct(struct netif *netif, struct dhcp *dhcp); void dhcp_set_struct(struct netif *netif, struct dhcp *dhcp);
/** Remove a struct dhcp previously set to the netif using dhcp_set_struct() */ /** Remove a struct dhcp previously set to the netif using dhcp_set_struct() */
#define dhcp_remove_struct(netif) do { (netif)->dhcp = NULL; } while(0) #define dhcp_remove_struct(netif) netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, NULL)
void dhcp_cleanup(struct netif *netif); void dhcp_cleanup(struct netif *netif);
err_t dhcp_start(struct netif *netif); err_t dhcp_start(struct netif *netif);
err_t dhcp_renew(struct netif *netif); err_t dhcp_renew(struct netif *netif);

View File

@@ -43,8 +43,6 @@
extern "C" { extern "C" {
#endif #endif
#define LWIP_PROVIDE_ERRNO 0
#ifdef LWIP_PROVIDE_ERRNO #ifdef LWIP_PROVIDE_ERRNO
#define EPERM 1 /* Operation not permitted */ #define EPERM 1 /* Operation not permitted */
@@ -176,13 +174,12 @@ extern "C" {
#define EMEDIUMTYPE 124 /* Wrong medium type */ #define EMEDIUMTYPE 124 /* Wrong medium type */
#ifndef errno #ifndef errno
//extern int errno; extern int errno;
#endif #endif
#else /* LWIP_PROVIDE_ERRNO */ #else /* LWIP_PROVIDE_ERRNO */
/* Define LWIP_ERRNO_INCLUDE to <errno.h> to include the error defines here */ /* Define LWIP_ERRNO_INCLUDE to <errno.h> to include the error defines here */
#define LWIP_ERRNO_INCLUDE <errno.h>
#ifdef LWIP_ERRNO_INCLUDE #ifdef LWIP_ERRNO_INCLUDE
#include LWIP_ERRNO_INCLUDE #include LWIP_ERRNO_INCLUDE
#endif /* LWIP_ERRNO_INCLUDE */ #endif /* LWIP_ERRNO_INCLUDE */

View File

@@ -54,7 +54,7 @@ extern "C" {
/** x.X.x: Minor version of the stack */ /** x.X.x: Minor version of the stack */
#define LWIP_VERSION_MINOR 0 #define LWIP_VERSION_MINOR 0
/** x.x.X: Revision of the stack */ /** x.x.X: Revision of the stack */
#define LWIP_VERSION_REVISION 2 #define LWIP_VERSION_REVISION 3
/** For release candidates, this is set to 1..254 /** For release candidates, this is set to 1..254
* For official releases, this is set to 255 (LWIP_RC_RELEASE) * For official releases, this is set to 255 (LWIP_RC_RELEASE)
* For development versions (Git), this is set to 0 (LWIP_RC_DEVELOPMENT) */ * For development versions (Git), this is set to 0 (LWIP_RC_DEVELOPMENT) */

View File

@@ -38,6 +38,8 @@
#ifndef LWIP_HDR_MEMP_H #ifndef LWIP_HDR_MEMP_H
#define LWIP_HDR_MEMP_H #define LWIP_HDR_MEMP_H
#include "lwip/opt.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif

View File

@@ -387,9 +387,9 @@ void stats_init(void);
#if MEM_STATS #if MEM_STATS
#define MEM_STATS_AVAIL(x, y) lwip_stats.mem.x = y #define MEM_STATS_AVAIL(x, y) lwip_stats.mem.x = y
#define MEM_STATS_INC(x) STATS_INC(mem.x) #define MEM_STATS_INC(x) SYS_ARCH_INC(lwip_stats.mem.x, 1)
#define MEM_STATS_INC_USED(x, y) STATS_INC_USED(mem, y) #define MEM_STATS_INC_USED(x, y) SYS_ARCH_INC(lwip_stats.mem.x, y)
#define MEM_STATS_DEC_USED(x, y) lwip_stats.mem.x -= y #define MEM_STATS_DEC_USED(x, y) SYS_ARCH_DEC(lwip_stats.mem.x, y)
#define MEM_STATS_DISPLAY() stats_display_mem(&lwip_stats.mem, "HEAP") #define MEM_STATS_DISPLAY() stats_display_mem(&lwip_stats.mem, "HEAP")
#else #else
#define MEM_STATS_AVAIL(x, y) #define MEM_STATS_AVAIL(x, y)

154
ext/lwip/test/unit/ip4/test_ip4.c Executable file
View File

@@ -0,0 +1,154 @@
#include "test_ip4.h"
#include "lwip/ip4.h"
#include "lwip/inet_chksum.h"
#include "lwip/stats.h"
#include "lwip/prot/ip.h"
#include "lwip/prot/ip4.h"
#if !LWIP_IPV4 || !IP_REASSEMBLY || !MIB2_STATS || !IPFRAG_STATS
#error "This tests needs LWIP_IPV4, IP_REASSEMBLY; MIB2- and IPFRAG-statistics enabled"
#endif
/* Helper functions */
static void
create_ip4_input_fragment(u16_t ip_id, u16_t start, u16_t len, int last)
{
struct pbuf *p;
struct netif *input_netif = netif_list; /* just use any netif */
fail_unless((start & 7) == 0);
fail_unless(((len & 7) == 0) || last);
fail_unless(input_netif != NULL);
p = pbuf_alloc(PBUF_RAW, len + sizeof(struct ip_hdr), PBUF_RAM);
fail_unless(p != NULL);
if (p != NULL) {
err_t err;
struct ip_hdr *iphdr = (struct ip_hdr *)p->payload;
IPH_VHL_SET(iphdr, 4, sizeof(struct ip_hdr) / 4);
IPH_TOS_SET(iphdr, 0);
IPH_LEN_SET(iphdr, lwip_htons(p->tot_len));
IPH_ID_SET(iphdr, lwip_htons(ip_id));
if (last) {
IPH_OFFSET_SET(iphdr, lwip_htons(start / 8));
} else {
IPH_OFFSET_SET(iphdr, lwip_htons((start / 8) | IP_MF));
}
IPH_TTL_SET(iphdr, 5);
IPH_PROTO_SET(iphdr, IP_PROTO_UDP);
IPH_CHKSUM_SET(iphdr, 0);
ip4_addr_copy(iphdr->src, *netif_ip4_addr(input_netif));
iphdr->src.addr = lwip_htonl(lwip_htonl(iphdr->src.addr) + 1);
ip4_addr_copy(iphdr->dest, *netif_ip4_addr(input_netif));
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, sizeof(struct ip_hdr)));
err = ip4_input(p, input_netif);
if (err != ERR_OK) {
pbuf_free(p);
}
fail_unless(err == ERR_OK);
}
}
/* Setups/teardown functions */
static void
ip4_setup(void)
{
}
static void
ip4_teardown(void)
{
if (netif_list->loop_first != NULL) {
pbuf_free(netif_list->loop_first);
netif_list->loop_first = NULL;
}
netif_list->loop_last = NULL;
}
/* Test functions */
START_TEST(test_ip4_reass)
{
const u16_t ip_id = 128;
LWIP_UNUSED_ARG(_i);
memset(&lwip_stats.mib2, 0, sizeof(lwip_stats.mib2));
create_ip4_input_fragment(ip_id, 8*200, 200, 1);
fail_unless(lwip_stats.ip_frag.recv == 1);
fail_unless(lwip_stats.ip_frag.err == 0);
fail_unless(lwip_stats.ip_frag.memerr == 0);
fail_unless(lwip_stats.ip_frag.drop == 0);
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
create_ip4_input_fragment(ip_id, 0*200, 200, 0);
fail_unless(lwip_stats.ip_frag.recv == 2);
fail_unless(lwip_stats.ip_frag.err == 0);
fail_unless(lwip_stats.ip_frag.memerr == 0);
fail_unless(lwip_stats.ip_frag.drop == 0);
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
create_ip4_input_fragment(ip_id, 1*200, 200, 0);
fail_unless(lwip_stats.ip_frag.recv == 3);
fail_unless(lwip_stats.ip_frag.err == 0);
fail_unless(lwip_stats.ip_frag.memerr == 0);
fail_unless(lwip_stats.ip_frag.drop == 0);
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
create_ip4_input_fragment(ip_id, 2*200, 200, 0);
fail_unless(lwip_stats.ip_frag.recv == 4);
fail_unless(lwip_stats.ip_frag.err == 0);
fail_unless(lwip_stats.ip_frag.memerr == 0);
fail_unless(lwip_stats.ip_frag.drop == 0);
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
create_ip4_input_fragment(ip_id, 3*200, 200, 0);
fail_unless(lwip_stats.ip_frag.recv == 5);
fail_unless(lwip_stats.ip_frag.err == 0);
fail_unless(lwip_stats.ip_frag.memerr == 0);
fail_unless(lwip_stats.ip_frag.drop == 0);
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
create_ip4_input_fragment(ip_id, 4*200, 200, 0);
fail_unless(lwip_stats.ip_frag.recv == 6);
fail_unless(lwip_stats.ip_frag.err == 0);
fail_unless(lwip_stats.ip_frag.memerr == 0);
fail_unless(lwip_stats.ip_frag.drop == 0);
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
create_ip4_input_fragment(ip_id, 7*200, 200, 0);
fail_unless(lwip_stats.ip_frag.recv == 7);
fail_unless(lwip_stats.ip_frag.err == 0);
fail_unless(lwip_stats.ip_frag.memerr == 0);
fail_unless(lwip_stats.ip_frag.drop == 0);
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
create_ip4_input_fragment(ip_id, 6*200, 200, 0);
fail_unless(lwip_stats.ip_frag.recv == 8);
fail_unless(lwip_stats.ip_frag.err == 0);
fail_unless(lwip_stats.ip_frag.memerr == 0);
fail_unless(lwip_stats.ip_frag.drop == 0);
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
create_ip4_input_fragment(ip_id, 5*200, 200, 0);
fail_unless(lwip_stats.ip_frag.recv == 9);
fail_unless(lwip_stats.ip_frag.err == 0);
fail_unless(lwip_stats.ip_frag.memerr == 0);
fail_unless(lwip_stats.ip_frag.drop == 0);
fail_unless(lwip_stats.mib2.ipreasmoks == 1);
}
END_TEST
/** Create the suite including all tests for this module */
Suite *
ip4_suite(void)
{
testfunc tests[] = {
TESTFUNC(test_ip4_reass),
};
return create_suite("IPv4", tests, sizeof(tests)/sizeof(testfunc), ip4_setup, ip4_teardown);
}

View File

@@ -0,0 +1,8 @@
#ifndef LWIP_HDR_TEST_IP4_H
#define LWIP_HDR_TEST_IP4_H
#include "../lwip_check.h"
Suite* ip4_suite(void);
#endif

View File

@@ -1,5 +1,6 @@
#include "lwip_check.h" #include "lwip_check.h"
#include "ip4/test_ip4.h"
#include "udp/test_udp.h" #include "udp/test_udp.h"
#include "tcp/test_tcp.h" #include "tcp/test_tcp.h"
#include "tcp/test_tcp_oos.h" #include "tcp/test_tcp_oos.h"
@@ -37,6 +38,7 @@ int main(void)
SRunner *sr; SRunner *sr;
size_t i; size_t i;
suite_getter_fn* suites[] = { suite_getter_fn* suites[] = {
ip4_suite,
udp_suite, udp_suite,
tcp_suite, tcp_suite,
tcp_oos_suite, tcp_oos_suite,

View File

@@ -59,4 +59,7 @@
/* Minimal changes to opt.h required for etharp unit tests: */ /* Minimal changes to opt.h required for etharp unit tests: */
#define ETHARP_SUPPORT_STATIC_ENTRIES 1 #define ETHARP_SUPPORT_STATIC_ENTRIES 1
/* MIB2 stats are required to check IPv4 reassembly results */
#define MIB2_STATS 1
#endif /* LWIP_HDR_LWIPOPTS_H */ #endif /* LWIP_HDR_LWIPOPTS_H */