Upgraded lwIP to 2.0.3
This commit is contained in:
@@ -4,6 +4,22 @@ HISTORY
|
||||
|
||||
* [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)
|
||||
|
||||
++ New features:
|
||||
@@ -13,6 +29,9 @@ HISTORY
|
||||
We now have a #define for a header file name that is #included in every .c
|
||||
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:
|
||||
|
||||
2017-03-08
|
||||
|
||||
@@ -8,6 +8,14 @@ with newer versions.
|
||||
|
||||
* [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)
|
||||
|
||||
++ Application changes:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
void eth_mac_irq()
|
||||
void
|
||||
eth_mac_irq()
|
||||
{
|
||||
/* 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);
|
||||
|
||||
@@ -38,12 +40,14 @@ static err_t netif_output(struct netif *netif, struct pbuf *p)
|
||||
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)));
|
||||
}
|
||||
|
||||
static err_t netif_init(struct netif *netif)
|
||||
static err_t
|
||||
netif_init(struct netif *netif)
|
||||
{
|
||||
netif->linkoutput = netif_output;
|
||||
netif->output = etharp_output;
|
||||
@@ -58,7 +62,8 @@ static err_t netif_init(struct netif *netif)
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void main(void)
|
||||
void
|
||||
main(void)
|
||||
{
|
||||
struct netif netif;
|
||||
|
||||
@@ -74,7 +79,7 @@ void main(void)
|
||||
netif_set_up(&netif);
|
||||
|
||||
/* Start DHCP and HTTPD */
|
||||
dhcp_init();
|
||||
dhcp_start(&netif );
|
||||
httpd_init();
|
||||
|
||||
while(1) {
|
||||
|
||||
@@ -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 an argument", arg != NULL);
|
||||
conn = (struct netconn *)arg;
|
||||
|
||||
if (conn == NULL) {
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
|
||||
LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb);
|
||||
|
||||
#if LWIP_SO_RCVBUF
|
||||
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)) {
|
||||
#else /* LWIP_SO_RCVBUF */
|
||||
if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox)) {
|
||||
if (!sys_mbox_valid(&conn->recvmbox)) {
|
||||
#endif /* LWIP_SO_RCVBUF */
|
||||
pbuf_free(p);
|
||||
return;
|
||||
@@ -471,8 +477,6 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
|
||||
struct netconn *newconn;
|
||||
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) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
@@ -490,6 +494,8 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
|
||||
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
|
||||
* the new socket is unknown. newconn->socket is marked as -1. */
|
||||
newconn = netconn_alloc(conn->type, conn->callback);
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "lwip/sys.h"
|
||||
|
||||
#include <errno.h>
|
||||
//#include "lwip/errno.h"
|
||||
|
||||
#if !NO_SYS
|
||||
/** Table to quickly map an lwIP error (err_t) to a socket error
|
||||
|
||||
@@ -360,8 +360,9 @@ mqtt_take_request(struct mqtt_request_t **tail, u16_t pkt_id)
|
||||
static void
|
||||
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);
|
||||
r = *tail;
|
||||
while (t > 0 && r != NULL) {
|
||||
if (t >= r->timeout_diff) {
|
||||
t -= (u8_t)r->timeout_diff;
|
||||
|
||||
@@ -337,7 +337,7 @@ void
|
||||
lwip_init(void)
|
||||
{
|
||||
#ifndef LWIP_SKIP_CONST_CHECK
|
||||
int a;
|
||||
int a = 0;
|
||||
LWIP_UNUSED_ARG(a);
|
||||
LWIP_ASSERT("LWIP_CONST_CAST not implemented correctly. Check your lwIP port.", LWIP_CONST_CAST(void*, &a) == &a);
|
||||
#endif
|
||||
|
||||
@@ -736,7 +736,7 @@ dhcp_start(struct netif *netif)
|
||||
|
||||
/* no DHCP client attached yet? */
|
||||
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));
|
||||
if (dhcp == NULL) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n"));
|
||||
@@ -1500,7 +1500,7 @@ again:
|
||||
offset_max = options_idx_max;
|
||||
options = (u8_t*)q->payload;
|
||||
/* 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 len;
|
||||
u8_t decode_len = 0;
|
||||
@@ -1617,7 +1617,7 @@ decode_next:
|
||||
offset_max -= q->len;
|
||||
if ((offset < offset_max) && offset_max) {
|
||||
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;
|
||||
} else {
|
||||
/* 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_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 */
|
||||
if (dhcp->tries == 0) {
|
||||
#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)) {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -79,6 +79,10 @@
|
||||
|
||||
#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
|
||||
* offset and the ending offset of this fragment to
|
||||
* 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).
|
||||
* @param ipr points to the reassembly state
|
||||
* @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
|
||||
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 pbuf *q;
|
||||
@@ -375,7 +380,18 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
|
||||
}
|
||||
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||
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 {
|
||||
#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 */
|
||||
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: */
|
||||
/* 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 */
|
||||
if (valid) {
|
||||
/* 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);
|
||||
LWIP_ASSERT("validate_datagram: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
|
||||
* (since MF == 0 has already arrived). Such datagrams simply time out if
|
||||
* 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! */
|
||||
return 0; /* not yet valid! */
|
||||
return IP_REASS_VALIDATE_PBUF_QUEUED; /* not yet valid! */
|
||||
#if IP_REASS_CHECK_OVERLAP
|
||||
freepbuf:
|
||||
ip_reass_pbufcount -= pbuf_clen(new_p);
|
||||
pbuf_free(new_p);
|
||||
return 0;
|
||||
return IP_REASS_VALIDATE_PBUF_DROPPED;
|
||||
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||
}
|
||||
|
||||
@@ -488,6 +502,8 @@ ip4_reass(struct pbuf *p)
|
||||
struct ip_reassdata *ipr;
|
||||
struct ip_reass_helper *iprh;
|
||||
u16_t offset, len, clen;
|
||||
int valid;
|
||||
int is_last;
|
||||
|
||||
IPFRAG_STATS_INC(ip_frag.recv);
|
||||
MIB2_STATS_INC(mib2.ipreasmreqds);
|
||||
@@ -552,24 +568,41 @@ ip4_reass(struct pbuf *p)
|
||||
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
|
||||
* to an existing one */
|
||||
|
||||
/* 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->datagram_len = offset + len;
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("ip4_reass: last fragment seen, total len %"S16_F"\n",
|
||||
ipr->datagram_len));
|
||||
}
|
||||
/* find the right place to insert this pbuf */
|
||||
/* @todo: trim pbufs if fragments are overlapping */
|
||||
if (ip_reass_chain_frag_into_datagram_and_validate(ipr, p)) {
|
||||
|
||||
if (valid == IP_REASS_VALIDATE_TELEGRAM_FINISHED) {
|
||||
struct ip_reassdata *ipr_prev;
|
||||
/* the totally last fragment (flag more fragments = 0) was received at least
|
||||
* once AND all fragments are received */
|
||||
|
||||
@@ -849,7 +849,9 @@ netif_loop_output(struct netif *netif, struct pbuf *p)
|
||||
netif_poll(). */
|
||||
|
||||
/* 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);
|
||||
if (netif->loop_first != NULL) {
|
||||
|
||||
@@ -358,7 +358,6 @@ tcp_close_shutdown_fin(struct tcp_pcb *pcb)
|
||||
default:
|
||||
/* Has already been closed, do nothing. */
|
||||
return ERR_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
if (err == ERR_OK) {
|
||||
@@ -371,6 +370,12 @@ tcp_close_shutdown_fin(struct tcp_pcb *pcb)
|
||||
} else if (err == ERR_MEM) {
|
||||
/* Mark this pcb for closing. Closing is retried from tcp_tmr. */
|
||||
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;
|
||||
}
|
||||
@@ -408,8 +413,8 @@ tcp_close(struct tcp_pcb *pcb)
|
||||
* @ingroup tcp_raw
|
||||
* 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!
|
||||
* Shutting down both sides is the same as calling tcp_close, so if it succeds,
|
||||
* the PCB should not be referenced any more.
|
||||
* Shutting down both sides is the same as calling tcp_close, so if it succeds
|
||||
* (i.e. returns ER_OK), the PCB must not be referenced any more!
|
||||
*
|
||||
* @param pcb PCB to shutdown
|
||||
* @param shut_rx shut down receive side if this is != 0
|
||||
|
||||
@@ -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_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 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;
|
||||
}
|
||||
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);
|
||||
if (tcp_input_delayed_close(pcb)) {
|
||||
goto aborted;
|
||||
}
|
||||
#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
|
||||
@@ -488,6 +480,9 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
}
|
||||
|
||||
tcp_input_pcb = NULL;
|
||||
if (tcp_input_delayed_close(pcb)) {
|
||||
goto aborted;
|
||||
}
|
||||
/* Try to send something out. */
|
||||
tcp_output(pcb);
|
||||
#if TCP_INPUT_DEBUG
|
||||
@@ -532,6 +527,30 @@ dropped:
|
||||
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
|
||||
* connection (from tcp_input()).
|
||||
@@ -1749,11 +1768,11 @@ tcp_parseopt(struct tcp_pcb *pcb)
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
|
||||
return;
|
||||
}
|
||||
/* An WND_SCALE option with the right option length. */
|
||||
data = tcp_getoptbyte();
|
||||
/* If syn was received with wnd scale option,
|
||||
activate wnd scale opt, but only if this is not a retransmission */
|
||||
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;
|
||||
if (pcb->snd_scale > 14U) {
|
||||
pcb->snd_scale = 14U;
|
||||
|
||||
@@ -176,7 +176,7 @@ void sys_timeouts_init(void)
|
||||
{
|
||||
size_t i;
|
||||
/* 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
|
||||
(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]));
|
||||
|
||||
@@ -76,8 +76,7 @@
|
||||
* systems, this should be defined to something less resource-consuming.
|
||||
*/
|
||||
#ifndef LWIP_PLATFORM_DIAG
|
||||
#include "Debug.hpp"
|
||||
#define LWIP_PLATFORM_DIAG(x) printf(x);
|
||||
#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0)
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
@@ -91,14 +91,6 @@ u32_t lwip_htonl(u32_t x);
|
||||
#endif
|
||||
#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
|
||||
with compile-time constants only (so that there is no little-endian
|
||||
overhead at runtime). */
|
||||
@@ -109,9 +101,16 @@ u32_t lwip_htonl(u32_t x);
|
||||
(((x) & 0x00ff0000UL) >> 8) | \
|
||||
(((x) & 0xff000000UL) >> 24))
|
||||
#define PP_NTOHL(x) PP_HTONL(x)
|
||||
|
||||
#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.
|
||||
* In cc.h, you can #define these to implementations available on
|
||||
* your platform to save some code bytes if you use these functions
|
||||
|
||||
@@ -108,7 +108,7 @@ struct dhcp
|
||||
|
||||
void dhcp_set_struct(struct netif *netif, struct dhcp *dhcp);
|
||||
/** 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);
|
||||
err_t dhcp_start(struct netif *netif);
|
||||
err_t dhcp_renew(struct netif *netif);
|
||||
|
||||
@@ -43,8 +43,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define LWIP_PROVIDE_ERRNO 0
|
||||
|
||||
#ifdef LWIP_PROVIDE_ERRNO
|
||||
|
||||
#define EPERM 1 /* Operation not permitted */
|
||||
@@ -176,13 +174,12 @@ extern "C" {
|
||||
#define EMEDIUMTYPE 124 /* Wrong medium type */
|
||||
|
||||
#ifndef errno
|
||||
//extern int errno;
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#else /* LWIP_PROVIDE_ERRNO */
|
||||
|
||||
/* Define LWIP_ERRNO_INCLUDE to <errno.h> to include the error defines here */
|
||||
#define LWIP_ERRNO_INCLUDE <errno.h>
|
||||
#ifdef LWIP_ERRNO_INCLUDE
|
||||
#include LWIP_ERRNO_INCLUDE
|
||||
#endif /* LWIP_ERRNO_INCLUDE */
|
||||
|
||||
@@ -54,7 +54,7 @@ extern "C" {
|
||||
/** x.X.x: Minor version of the stack */
|
||||
#define LWIP_VERSION_MINOR 0
|
||||
/** 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 official releases, this is set to 255 (LWIP_RC_RELEASE)
|
||||
* For development versions (Git), this is set to 0 (LWIP_RC_DEVELOPMENT) */
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
#ifndef LWIP_HDR_MEMP_H
|
||||
#define LWIP_HDR_MEMP_H
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
@@ -387,9 +387,9 @@ void stats_init(void);
|
||||
|
||||
#if MEM_STATS
|
||||
#define MEM_STATS_AVAIL(x, y) lwip_stats.mem.x = y
|
||||
#define MEM_STATS_INC(x) STATS_INC(mem.x)
|
||||
#define MEM_STATS_INC_USED(x, y) STATS_INC_USED(mem, y)
|
||||
#define MEM_STATS_DEC_USED(x, y) lwip_stats.mem.x -= y
|
||||
#define MEM_STATS_INC(x) SYS_ARCH_INC(lwip_stats.mem.x, 1)
|
||||
#define MEM_STATS_INC_USED(x, y) SYS_ARCH_INC(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")
|
||||
#else
|
||||
#define MEM_STATS_AVAIL(x, y)
|
||||
|
||||
154
ext/lwip/test/unit/ip4/test_ip4.c
Executable file
154
ext/lwip/test/unit/ip4/test_ip4.c
Executable 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);
|
||||
}
|
||||
8
ext/lwip/test/unit/ip4/test_ip4.h
Executable file
8
ext/lwip/test/unit/ip4/test_ip4.h
Executable 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
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "lwip_check.h"
|
||||
|
||||
#include "ip4/test_ip4.h"
|
||||
#include "udp/test_udp.h"
|
||||
#include "tcp/test_tcp.h"
|
||||
#include "tcp/test_tcp_oos.h"
|
||||
@@ -37,6 +38,7 @@ int main(void)
|
||||
SRunner *sr;
|
||||
size_t i;
|
||||
suite_getter_fn* suites[] = {
|
||||
ip4_suite,
|
||||
udp_suite,
|
||||
tcp_suite,
|
||||
tcp_oos_suite,
|
||||
|
||||
@@ -59,4 +59,7 @@
|
||||
/* Minimal changes to opt.h required for etharp unit tests: */
|
||||
#define ETHARP_SUPPORT_STATIC_ENTRIES 1
|
||||
|
||||
/* MIB2 stats are required to check IPv4 reassembly results */
|
||||
#define MIB2_STATS 1
|
||||
|
||||
#endif /* LWIP_HDR_LWIPOPTS_H */
|
||||
|
||||
Reference in New Issue
Block a user