Squashed 'features/FEATURE_LWIP/lwip-interface/lwip/' changes from 10f93f4..7648b58

git-subtree-dir: features/FEATURE_LWIP/lwip-interface/lwip
git-subtree-split: 7648b58d03006bd60b9592f1853c167bf52b0193
pull/4814/head
Mika Leppänen 2017-07-24 13:17:40 +03:00
parent 61a7b15741
commit 7bbc850309
47 changed files with 490 additions and 242 deletions

View File

@ -3,16 +3,91 @@ HISTORY
(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]
(STABLE-2.0.2)
++ New features:
2017-02-10: Dirk Ziegelmeier
* Implement task #14367: Hooks need a better place to be defined:
We now have a #define for a header file name that is #included in every .c
file that provides hooks.
++ Bugfixes:
2017-03-08
* tcp: do not keep sending SYNs when getting ACKs
2017-03-08: Joel Cunningham
* tcp: Initialize ssthresh to TCP_SND_BUF (bug #50476)
2017-03-01: Simon Goldschmidt
* httpd: LWIP_HTTPD_POST_MANUAL_WND: fixed double-free when httpd_post_data_recved
is called nested from httpd_post_receive_data() (bug #50424)
2017-02-28: David van Moolenbroek/Simon Goldschmidt
* tcp: fixed bug #50418: LWIP_EVENT_API: fix invalid calbacks for SYN_RCVD pcb
2017-02-17: Simon Goldschmidt
* dns: Improved DNS_LOCAL_HOSTLIST interface (bug #50325)
2017-02-16: Simon Goldschmidt
* LWIP_NETCONN_FULLDUPLEX: fixed shutdown during write (bug #50274)
2017-02-13: Simon Goldschmidt/Dirk Ziegelmeier
* For tiny targtes, LWIP_RAND is optional (fix compile time checks)
2017-02-10: Simon Goldschmidt
* tcp: Fixed bug #47485 (tcp_close() should not fail on memory error) by retrying
to send FIN from tcp_fasttmr
2017-02-09: Simon Goldschmidt
* sockets: Fixed bug #44032 (LWIP_NETCONN_FULLDUPLEX: select might work on
invalid/reused socket) by not allowing to reallocate a socket that has
"select_waiting != 0"
2017-02-09: Simon Goldschmidt
* httpd: Fixed bug #50059 (httpd LWIP_HTTPD_SUPPORT_11_KEEPALIVE vs.
LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED)
2017-02-08: Dirk Ziegelmeier
* Rename "IPv6 mapped IPv4 addresses" to their correct name from RFC4191:
"IPv4-mapped IPv6 address"
2017-02-08: Luc Revardel
* mld6.c: Fix bug #50220 (mld6_leavegroup does not send ICMP6_TYPE_MLD, even
if last reporter)
2017-02-08: David van Moolenbroek
* ip6.c: Patch #9250: fix source substitution in ip6_output_if()
2017-02-08: Simon Goldschmidt
* tcp_out.c: Fixed bug #50090 (last_unsent->oversize_left can become wrong value
in tcp_write error path)
2017-02-02: Dirk Ziegelmeier
* Fix bug #50206: UDP Netconn bind to IP6_ADDR_ANY fails
2017-01-18: Dirk Ziegelmeier
* Fix zero-copy RX, see bug bug #50064. PBUF_REFs were not supported as ARP requests.
2017-01-15: Axel Lin, Dirk Ziegelmeier
* minor bug fixes in mqtt
2017-01-11: Knut Andre Tidemann
* sockets/netconn: fix broken default ICMPv6 handling of checksums
(STABLE-2.0.1)
++ New features: ++ New features:
2016-12-31: Simon Goldschmidt 2016-12-31: Simon Goldschmidt
* tcp.h/.c: added function tcp_listen_with_backlog_and_err() to get the error * tcp.h/.c: added function tcp_listen_with_backlog_and_err() to get the error
reason when listening fails (bug #49861) reason when listening fails (bug #49861)
2016-12-20: Erik Andersen 2016-12-20: Erik Andersen
* Add MQTT client * Add MQTT client
2016-12-14: Jan Breuer: 2016-12-14: Jan Breuer:
* opt.h, ndc.h/.c: add support for RDNSS option (as per RFC 6106) * opt.h, ndc.h/.c: add support for RDNSS option (as per RFC 6106)
@ -43,7 +118,7 @@ HISTORY
2016-12-05: Dirk Ziegelmeier 2016-12-05: Dirk Ziegelmeier
* fixed compiling with IPv4 disabled (IPv6 only case) * fixed compiling with IPv4 disabled (IPv6 only case)
2016-11-28: Simon Goldschmidt 2016-11-28: Simon Goldschmidt
* api_lib.c: fixed bug #49725 (send-timeout: netconn_write() can return * api_lib.c: fixed bug #49725 (send-timeout: netconn_write() can return
ERR_OK without all bytes being written) ERR_OK without all bytes being written)
@ -72,7 +147,7 @@ HISTORY
2016-11-11: Dirk Ziegelmeier 2016-11-11: Dirk Ziegelmeier
* sockets.c: fixed bug #49578 (dropping multicast membership does not work * sockets.c: fixed bug #49578 (dropping multicast membership does not work
with LWIP_SOCKET_OFFSET) with LWIP_SOCKET_OFFSET)
(STABLE-2.0.0) (STABLE-2.0.0)
++ New features: ++ New features:

View File

@ -38,7 +38,7 @@ PROJECT_NAME = "lwIP"
# could be handy for archiving the generated documentation or if some version # could be handy for archiving the generated documentation or if some version
# control system is used. # control system is used.
PROJECT_NUMBER = "2.0.1" PROJECT_NUMBER = "2.0.2"
# Using the PROJECT_BRIEF tag one can provide an optional one line description # Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a # for a project that appears at the top of each page and should give viewer a

View File

@ -26,6 +26,11 @@
* @verbinclude "UPGRADING" * @verbinclude "UPGRADING"
*/ */
/**
* @page changelog Changelog
* @verbinclude "CHANGELOG"
*/
/** /**
* @page contrib How to contribute to lwIP * @page contrib How to contribute to lwIP
* @verbinclude "contrib.txt" * @verbinclude "contrib.txt"

View File

@ -562,6 +562,13 @@ pcb_new(struct api_msg *msg)
case NETCONN_RAW: case NETCONN_RAW:
msg->conn->pcb.raw = raw_new_ip_type(iptype, msg->msg.n.proto); msg->conn->pcb.raw = raw_new_ip_type(iptype, msg->msg.n.proto);
if (msg->conn->pcb.raw != NULL) { if (msg->conn->pcb.raw != NULL) {
#if LWIP_IPV6
/* ICMPv6 packets should always have checksum calculated by the stack as per RFC 3542 chapter 3.1 */
if (NETCONNTYPE_ISIPV6(msg->conn->type) && msg->conn->pcb.raw->protocol == IP6_NEXTH_ICMP6) {
msg->conn->pcb.raw->chksum_reqd = 1;
msg->conn->pcb.raw->chksum_offset = 2;
}
#endif /* LWIP_IPV6 */
raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
} }
break; break;
@ -1777,25 +1784,28 @@ lwip_netconn_do_close(void *m)
#if LWIP_NETCONN_FULLDUPLEX #if LWIP_NETCONN_FULLDUPLEX
if (msg->msg.sd.shut & NETCONN_SHUT_WR) { if (msg->msg.sd.shut & NETCONN_SHUT_WR) {
/* close requested, abort running write */ /* close requested, abort running write */
sys_sem_t* op_completed_sem; sys_sem_t* write_completed_sem;
LWIP_ASSERT("msg->conn->current_msg != NULL", msg->conn->current_msg != NULL); LWIP_ASSERT("msg->conn->current_msg != NULL", msg->conn->current_msg != NULL);
op_completed_sem = LWIP_API_MSG_SEM(msg->conn->current_msg); write_completed_sem = LWIP_API_MSG_SEM(msg->conn->current_msg);
msg->conn->current_msg->err = ERR_CLSD; msg->conn->current_msg->err = ERR_CLSD;
msg->conn->current_msg = NULL; msg->conn->current_msg = NULL;
msg->conn->write_offset = 0; msg->conn->write_offset = 0;
msg->conn->state = NETCONN_NONE; msg->conn->state = NETCONN_NONE;
state = NETCONN_NONE;
NETCONN_SET_SAFE_ERR(msg->conn, ERR_CLSD); NETCONN_SET_SAFE_ERR(msg->conn, ERR_CLSD);
sys_sem_signal(op_completed_sem); sys_sem_signal(write_completed_sem);
} else { } else {
LWIP_ASSERT("msg->msg.sd.shut == NETCONN_SHUT_RD", msg->msg.sd.shut == NETCONN_SHUT_RD); LWIP_ASSERT("msg->msg.sd.shut == NETCONN_SHUT_RD", msg->msg.sd.shut == NETCONN_SHUT_RD);
/* In this case, let the write continue and do not interfere with /* In this case, let the write continue and do not interfere with
conn->current_msg or conn->state! */ conn->current_msg or conn->state! */
msg->err = tcp_shutdown(msg->conn->pcb.tcp, 1, 0); msg->err = tcp_shutdown(msg->conn->pcb.tcp, 1, 0);
} }
}
if (state == NETCONN_NONE) {
#else /* LWIP_NETCONN_FULLDUPLEX */ #else /* LWIP_NETCONN_FULLDUPLEX */
msg->err = ERR_INPROGRESS; msg->err = ERR_INPROGRESS;
#endif /* LWIP_NETCONN_FULLDUPLEX */
} else { } else {
#endif /* LWIP_NETCONN_FULLDUPLEX */
if (msg->msg.sd.shut & NETCONN_SHUT_RD) { if (msg->msg.sd.shut & NETCONN_SHUT_RD) {
/* Drain and delete mboxes */ /* Drain and delete mboxes */
netconn_drain(msg->conn); netconn_drain(msg->conn);

View File

@ -40,7 +40,7 @@
#include "lwip/def.h" #include "lwip/def.h"
#include "lwip/sys.h" #include "lwip/sys.h"
#include "lwip/errno.h" #include "lwip/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

@ -407,7 +407,7 @@ alloc_socket(struct netconn *newconn, int accepted)
for (i = 0; i < NUM_SOCKETS; ++i) { for (i = 0; i < NUM_SOCKETS; ++i) {
/* Protect socket array */ /* Protect socket array */
SYS_ARCH_PROTECT(lev); SYS_ARCH_PROTECT(lev);
if (!sockets[i].conn) { if (!sockets[i].conn && (sockets[i].select_waiting == 0)) {
sockets[i].conn = newconn; sockets[i].conn = newconn;
/* The socket is not yet known to anyone, so no need to protect /* The socket is not yet known to anyone, so no need to protect
after having marked it as used. */ after having marked it as used. */
@ -420,7 +420,6 @@ alloc_socket(struct netconn *newconn, int accepted)
sockets[i].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1); sockets[i].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1);
sockets[i].errevent = 0; sockets[i].errevent = 0;
sockets[i].err = 0; sockets[i].err = 0;
sockets[i].select_waiting = 0;
return i + LWIP_SOCKET_OFFSET; return i + LWIP_SOCKET_OFFSET;
} }
SYS_ARCH_UNPROTECT(lev); SYS_ARCH_UNPROTECT(lev);
@ -585,9 +584,9 @@ lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port)); LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port));
#if LWIP_IPV4 && LWIP_IPV6 #if LWIP_IPV4 && LWIP_IPV6
/* Dual-stack: Unmap IPv6 mapped IPv4 addresses */ /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */
if (IP_IS_V6_VAL(local_addr) && ip6_addr_isipv6mappedipv4(ip_2_ip6(&local_addr))) { if (IP_IS_V6_VAL(local_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&local_addr))) {
unmap_ipv6_mapped_ipv4(ip_2_ip4(&local_addr), ip_2_ip6(&local_addr)); unmap_ipv4_mapped_ipv6(ip_2_ip4(&local_addr), ip_2_ip6(&local_addr));
IP_SET_TYPE_VAL(local_addr, IPADDR_TYPE_V4); IP_SET_TYPE_VAL(local_addr, IPADDR_TYPE_V4);
} }
#endif /* LWIP_IPV4 && LWIP_IPV6 */ #endif /* LWIP_IPV4 && LWIP_IPV6 */
@ -677,9 +676,9 @@ lwip_connect(int s, const struct sockaddr *name, socklen_t namelen)
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", remote_port)); LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", remote_port));
#if LWIP_IPV4 && LWIP_IPV6 #if LWIP_IPV4 && LWIP_IPV6
/* Dual-stack: Unmap IPv6 mapped IPv4 addresses */ /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */
if (IP_IS_V6_VAL(remote_addr) && ip6_addr_isipv6mappedipv4(ip_2_ip6(&remote_addr))) { if (IP_IS_V6_VAL(remote_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&remote_addr))) {
unmap_ipv6_mapped_ipv4(ip_2_ip4(&remote_addr), ip_2_ip6(&remote_addr)); unmap_ipv4_mapped_ipv6(ip_2_ip4(&remote_addr), ip_2_ip6(&remote_addr));
IP_SET_TYPE_VAL(remote_addr, IPADDR_TYPE_V4); IP_SET_TYPE_VAL(remote_addr, IPADDR_TYPE_V4);
} }
#endif /* LWIP_IPV4 && LWIP_IPV6 */ #endif /* LWIP_IPV4 && LWIP_IPV6 */
@ -865,9 +864,9 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
} }
#if LWIP_IPV4 && LWIP_IPV6 #if LWIP_IPV4 && LWIP_IPV6
/* Dual-stack: Map IPv4 addresses to IPv6 mapped IPv4 */ /* Dual-stack: Map IPv4 addresses to IPv4 mapped IPv6 */
if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) && IP_IS_V4(fromaddr)) { if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) && IP_IS_V4(fromaddr)) {
ip4_2_ipv6_mapped_ipv4(ip_2_ip6(fromaddr), ip_2_ip4(fromaddr)); ip4_2_ipv4_mapped_ipv6(ip_2_ip6(fromaddr), ip_2_ip4(fromaddr));
IP_SET_TYPE(fromaddr, IPADDR_TYPE_V6); IP_SET_TYPE(fromaddr, IPADDR_TYPE_V6);
} }
#endif /* LWIP_IPV4 && LWIP_IPV6 */ #endif /* LWIP_IPV4 && LWIP_IPV6 */
@ -995,6 +994,10 @@ lwip_sendmsg(int s, const struct msghdr *msg, int flags)
((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0); ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0);
for (i = 0; i < msg->msg_iovlen; i++) { for (i = 0; i < msg->msg_iovlen; i++) {
u8_t apiflags = write_flags;
if (i + 1 < msg->msg_iovlen) {
apiflags |= NETCONN_MORE;
}
written = 0; written = 0;
err = netconn_write_partly(sock->conn, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len, write_flags, &written); err = netconn_write_partly(sock->conn, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len, write_flags, &written);
if (err == ERR_OK) { if (err == ERR_OK) {
@ -1092,9 +1095,9 @@ lwip_sendmsg(int s, const struct msghdr *msg, int flags)
if (err == ERR_OK) { if (err == ERR_OK) {
#if LWIP_IPV4 && LWIP_IPV6 #if LWIP_IPV4 && LWIP_IPV6
/* Dual-stack: Unmap IPv6 mapped IPv4 addresses */ /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */
if (IP_IS_V6_VAL(chain_buf->addr) && ip6_addr_isipv6mappedipv4(ip_2_ip6(&chain_buf->addr))) { if (IP_IS_V6_VAL(chain_buf->addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&chain_buf->addr))) {
unmap_ipv6_mapped_ipv4(ip_2_ip4(&chain_buf->addr), ip_2_ip6(&chain_buf->addr)); unmap_ipv4_mapped_ipv6(ip_2_ip4(&chain_buf->addr), ip_2_ip6(&chain_buf->addr));
IP_SET_TYPE_VAL(chain_buf->addr, IPADDR_TYPE_V4); IP_SET_TYPE_VAL(chain_buf->addr, IPADDR_TYPE_V4);
} }
#endif /* LWIP_IPV4 && LWIP_IPV6 */ #endif /* LWIP_IPV4 && LWIP_IPV6 */
@ -1190,9 +1193,9 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ #endif /* LWIP_NETIF_TX_SINGLE_PBUF */
if (err == ERR_OK) { if (err == ERR_OK) {
#if LWIP_IPV4 && LWIP_IPV6 #if LWIP_IPV4 && LWIP_IPV6
/* Dual-stack: Unmap IPv6 mapped IPv4 addresses */ /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */
if (IP_IS_V6_VAL(buf.addr) && ip6_addr_isipv6mappedipv4(ip_2_ip6(&buf.addr))) { if (IP_IS_V6_VAL(buf.addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&buf.addr))) {
unmap_ipv6_mapped_ipv4(ip_2_ip4(&buf.addr), ip_2_ip6(&buf.addr)); unmap_ipv4_mapped_ipv6(ip_2_ip4(&buf.addr), ip_2_ip6(&buf.addr));
IP_SET_TYPE_VAL(buf.addr, IPADDR_TYPE_V4); IP_SET_TYPE_VAL(buf.addr, IPADDR_TYPE_V4);
} }
#endif /* LWIP_IPV4 && LWIP_IPV6 */ #endif /* LWIP_IPV4 && LWIP_IPV6 */
@ -1490,9 +1493,7 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
SYS_ARCH_PROTECT(lev); SYS_ARCH_PROTECT(lev);
sock = tryget_socket(i); sock = tryget_socket(i);
if (sock != NULL) { if (sock != NULL) {
/* @todo: what if this is a new socket (reallocated?) in this case, /* for now, handle select_waiting==0... */
select_waiting-- would be wrong (a global 'sockalloc' counter,
stored per socket could help) */
LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0); LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0);
if (sock->select_waiting > 0) { if (sock->select_waiting > 0) {
sock->select_waiting--; sock->select_waiting--;
@ -1684,8 +1685,7 @@ again:
} }
/** /**
* Unimplemented: Close one end of a full-duplex connection. * Close one end of a full-duplex connection.
* Currently, the full connection is closed.
*/ */
int int
lwip_shutdown(int s, int how) lwip_shutdown(int s, int how)
@ -1750,10 +1750,10 @@ lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local)
} }
#if LWIP_IPV4 && LWIP_IPV6 #if LWIP_IPV4 && LWIP_IPV6
/* Dual-stack: Map IPv4 addresses to IPv6 mapped IPv4 */ /* Dual-stack: Map IPv4 addresses to IPv4 mapped IPv6 */
if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) && if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) &&
IP_IS_V4_VAL(naddr)) { IP_IS_V4_VAL(naddr)) {
ip4_2_ipv6_mapped_ipv4(ip_2_ip6(&naddr), ip_2_ip4(&naddr)); ip4_2_ipv4_mapped_ipv6(ip_2_ip6(&naddr), ip_2_ip4(&naddr));
IP_SET_TYPE_VAL(naddr, IPADDR_TYPE_V6); IP_SET_TYPE_VAL(naddr, IPADDR_TYPE_V6);
} }
#endif /* LWIP_IPV4 && LWIP_IPV6 */ #endif /* LWIP_IPV4 && LWIP_IPV6 */
@ -2574,6 +2574,12 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_
switch (optname) { switch (optname) {
#if LWIP_IPV6 && LWIP_RAW #if LWIP_IPV6 && LWIP_RAW
case IPV6_CHECKSUM: case IPV6_CHECKSUM:
/* It should not be possible to disable the checksum generation with ICMPv6
* as per RFC 3542 chapter 3.1 */
if(sock->conn->pcb.raw->protocol == IPPROTO_ICMPV6) {
return EINVAL;
}
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_RAW); LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_RAW);
if (*(const int *)optval < 0) { if (*(const int *)optval < 0) {
sock->conn->pcb.raw->chksum_reqd = 0; sock->conn->pcb.raw->chksum_reqd = 0;

View File

@ -102,7 +102,7 @@
#include <stdlib.h> /* atoi */ #include <stdlib.h> /* atoi */
#include <stdio.h> #include <stdio.h>
#if LWIP_TCP #if LWIP_TCP && LWIP_CALLBACK_API
/** Minimum length for a valid HTTP/0.9 request: "GET /\r\n" -> 7 bytes */ /** Minimum length for a valid HTTP/0.9 request: "GET /\r\n" -> 7 bytes */
#define MIN_REQ_LEN 7 #define MIN_REQ_LEN 7
@ -335,9 +335,34 @@ char *http_cgi_param_vals[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Values for each ext
/** global list of active HTTP connections, use to kill the oldest when /** global list of active HTTP connections, use to kill the oldest when
running out of memory */ running out of memory */
static struct http_state *http_connections; static struct http_state *http_connections;
#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED static void
http_add_connection(struct http_state *hs)
{
/* add the connection to the list */
hs->next = http_connections;
http_connections = hs;
}
static void
http_remove_connection(struct http_state *hs)
{
/* take the connection off the list */
if (http_connections) {
if (http_connections == hs) {
http_connections = hs->next;
} else {
struct http_state *last;
for(last = http_connections; last->next != NULL; last = last->next) {
if (last->next == hs) {
last->next = hs->next;
break;
}
}
}
}
}
static void static void
http_kill_oldest_connection(u8_t ssi_required) http_kill_oldest_connection(u8_t ssi_required)
{ {
@ -366,6 +391,11 @@ http_kill_oldest_connection(u8_t ssi_required)
http_close_or_abort_conn(hs_free_next->next->pcb, hs_free_next->next, 1); /* this also unlinks the http_state from the list */ http_close_or_abort_conn(hs_free_next->next->pcb, hs_free_next->next, 1); /* this also unlinks the http_state from the list */
} }
} }
#else /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
#define http_add_connection(hs)
#define http_remove_connection(hs)
#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ #endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
#if LWIP_HTTPD_SSI #if LWIP_HTTPD_SSI
@ -422,17 +452,7 @@ http_state_alloc(void)
#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ #endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
if (ret != NULL) { if (ret != NULL) {
http_state_init(ret); http_state_init(ret);
#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED http_add_connection(ret);
/* add the connection to the list */
if (http_connections == NULL) {
http_connections = ret;
} else {
struct http_state *last;
for(last = http_connections; last->next != NULL; last = last->next);
LWIP_ASSERT("last != NULL", last != NULL);
last->next = ret;
}
#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
} }
return ret; return ret;
} }
@ -481,22 +501,7 @@ http_state_free(struct http_state *hs)
{ {
if (hs != NULL) { if (hs != NULL) {
http_state_eof(hs); http_state_eof(hs);
#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED http_remove_connection(hs);
/* take the connection off the list */
if (http_connections) {
if (http_connections == hs) {
http_connections = hs->next;
} else {
struct http_state *last;
for(last = http_connections; last->next != NULL; last = last->next) {
if (last->next == hs) {
last->next = hs->next;
break;
}
}
}
}
#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
HTTP_FREE_HTTP_STATE(hs); HTTP_FREE_HTTP_STATE(hs);
} }
} }
@ -638,17 +643,14 @@ http_eof(struct tcp_pcb *pcb, struct http_state *hs)
/* HTTP/1.1 persistent connection? (Not supported for SSI) */ /* HTTP/1.1 persistent connection? (Not supported for SSI) */
#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE #if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
if (hs->keepalive) { if (hs->keepalive) {
#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED http_remove_connection(hs);
struct http_state* next = hs->next;
#endif
http_state_eof(hs); http_state_eof(hs);
http_state_init(hs); http_state_init(hs);
/* restore state: */ /* restore state: */
#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
hs->next = next;
#endif
hs->pcb = pcb; hs->pcb = pcb;
hs->keepalive = 1; hs->keepalive = 1;
http_add_connection(hs);
/* ensure nagle doesn't interfere with sending all data as fast as possible: */ /* ensure nagle doesn't interfere with sending all data as fast as possible: */
tcp_nagle_disable(pcb); tcp_nagle_disable(pcb);
} else } else
@ -1690,7 +1692,14 @@ http_post_rxpbuf(struct http_state *hs, struct pbuf *p)
hs->post_content_len_left -= p->tot_len; hs->post_content_len_left -= p->tot_len;
} }
} }
#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND
/* prevent connection being closed if httpd_post_data_recved() is called nested */
hs->unrecved_bytes++;
#endif
err = httpd_post_receive_data(hs, p); err = httpd_post_receive_data(hs, p);
#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND
hs->unrecved_bytes--;
#endif
if (err != ERR_OK) { if (err != ERR_OK) {
/* Ignore remaining content in case of application error */ /* Ignore remaining content in case of application error */
hs->post_content_len_left = 0; hs->post_content_len_left = 0;
@ -1751,8 +1760,8 @@ http_post_request(struct pbuf *inp, struct http_state *hs,
if (content_len >= 0) { if (content_len >= 0) {
/* adjust length of HTTP header passed to application */ /* adjust length of HTTP header passed to application */
const char *hdr_start_after_uri = uri_end + 1; const char *hdr_start_after_uri = uri_end + 1;
u16_t hdr_len = LWIP_MIN(data_len, crlfcrlf + 4 - data); u16_t hdr_len = (u16_t)LWIP_MIN(data_len, crlfcrlf + 4 - data);
u16_t hdr_data_len = LWIP_MIN(data_len, crlfcrlf + 4 - hdr_start_after_uri); u16_t hdr_data_len = (u16_t)LWIP_MIN(data_len, crlfcrlf + 4 - hdr_start_after_uri);
u8_t post_auto_wnd = 1; u8_t post_auto_wnd = 1;
http_uri_buf[0] = 0; http_uri_buf[0] = 0;
/* trim http header */ /* trim http header */
@ -2617,4 +2626,4 @@ http_set_cgi_handlers(const tCGI *cgis, int num_handlers)
} }
#endif /* LWIP_HTTPD_CGI */ #endif /* LWIP_HTTPD_CGI */
#endif /* LWIP_TCP */ #endif /* LWIP_TCP && LWIP_CALLBACK_API */

View File

@ -53,7 +53,7 @@
#include <string.h> #include <string.h>
/* Currently, only TCP-over-IPv4 is implemented (does iperf support IPv6 anyway?) */ /* Currently, only TCP-over-IPv4 is implemented (does iperf support IPv6 anyway?) */
#if LWIP_IPV4 && LWIP_TCP #if LWIP_IPV4 && LWIP_TCP && LWIP_CALLBACK_API
/** Specify the idle timeout (in seconds) after that the test fails */ /** Specify the idle timeout (in seconds) after that the test fails */
#ifndef LWIPERF_TCP_MAX_IDLE_SEC #ifndef LWIPERF_TCP_MAX_IDLE_SEC
@ -658,4 +658,4 @@ lwiperf_abort(void* lwiperf_session)
} }
} }
#endif /* LWIP_IPV4 && LWIP_TCP */ #endif /* LWIP_IPV4 && LWIP_TCP && LWIP_CALLBACK_API */

View File

@ -47,14 +47,16 @@
* Erik Andersson <erian747@gmail.com> * Erik Andersson <erian747@gmail.com>
* *
*/ */
#include <string.h> #include "lwip/apps/mqtt.h"
#include "lwip/timeouts.h" #include "lwip/timeouts.h"
#include "lwip/ip_addr.h" #include "lwip/ip_addr.h"
#include "lwip/mem.h" #include "lwip/mem.h"
#include "lwip/err.h" #include "lwip/err.h"
#include "lwip/pbuf.h" #include "lwip/pbuf.h"
#include "lwip/tcp.h" #include "lwip/tcp.h"
#include "lwip/apps/mqtt.h" #include <string.h>
#if LWIP_TCP && LWIP_CALLBACK_API
/** /**
* MQTT_DEBUG: Default is off. * MQTT_DEBUG: Default is off.
@ -257,7 +259,7 @@ mqtt_create_request(struct mqtt_request_t *r_objs, u16_t pkt_id, mqtt_request_cb
struct mqtt_request_t *r = NULL; struct mqtt_request_t *r = NULL;
u8_t n; u8_t n;
LWIP_ASSERT("mqtt_create_request: r_objs != NULL", r_objs != NULL); LWIP_ASSERT("mqtt_create_request: r_objs != NULL", r_objs != NULL);
for (n = 0; n < MQTT_REQ_MAX_IN_FLIGHT && r == NULL; n++) { for (n = 0; n < MQTT_REQ_MAX_IN_FLIGHT; n++) {
/* Item point to itself if not in use */ /* Item point to itself if not in use */
if (r_objs[n].next == &r_objs[n]) { if (r_objs[n].next == &r_objs[n]) {
r = &r_objs[n]; r = &r_objs[n];
@ -265,6 +267,7 @@ mqtt_create_request(struct mqtt_request_t *r_objs, u16_t pkt_id, mqtt_request_cb
r->cb = cb; r->cb = cb;
r->arg = arg; r->arg = arg;
r->pkt_id = pkt_id; r->pkt_id = pkt_id;
break;
} }
} }
return r; return r;
@ -281,7 +284,7 @@ mqtt_append_request(struct mqtt_request_t **tail, struct mqtt_request_t *r)
{ {
struct mqtt_request_t *head = NULL; struct mqtt_request_t *head = NULL;
s16_t time_before = 0; s16_t time_before = 0;
struct mqtt_request_t *iter = *tail; struct mqtt_request_t *iter;
LWIP_ASSERT("mqtt_append_request: tail != NULL", tail != NULL); LWIP_ASSERT("mqtt_append_request: tail != NULL", tail != NULL);
@ -634,7 +637,7 @@ mqtt_incomming_suback(struct mqtt_request_t *r, u8_t result)
* @param remaining_length Remaining length of complete message * @param remaining_length Remaining length of complete message
*/ */
static mqtt_connection_status_t static mqtt_connection_status_t
mqtt_message_received(mqtt_client_t *client, u8_t fixed_hdr_idx, u16_t length, u32_t remaining_length) mqtt_message_received(mqtt_client_t *client, u8_t fixed_hdr_idx, u16_t length, u32_t remaining_length)
{ {
mqtt_connection_status_t res = MQTT_CONNECT_ACCEPTED; mqtt_connection_status_t res = MQTT_CONNECT_ACCEPTED;
@ -680,7 +683,7 @@ mqtt_message_received(mqtt_client_t *client, u8_t fixed_hdr_idx, u16_t length, u
topic = var_hdr_payload + 2; topic = var_hdr_payload + 2;
after_topic = 2 + topic_len; after_topic = 2 + topic_len;
/* Check length, add one byte even for QoS 0 so that zero termination will fit */ /* Check length, add one byte even for QoS 0 so that zero termination will fit */
if ((after_topic + qos ? 2 : 1) > length) { if ((after_topic + (qos? 2 : 1)) > length) {
LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_message_received: Receive buffer can not fit topic + pkt_id\n")); LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_message_received: Receive buffer can not fit topic + pkt_id\n"));
goto out_disconnect; goto out_disconnect;
} }
@ -1230,6 +1233,7 @@ mqtt_client_connect(mqtt_client_t *client, const ip_addr_t *ip_addr, u16_t port,
} }
len = strlen(client_info->will_topic); len = strlen(client_info->will_topic);
LWIP_ERROR("mqtt_client_connect: client_info->will_topic length overflow", len <= 0xFF, return ERR_VAL); LWIP_ERROR("mqtt_client_connect: client_info->will_topic length overflow", len <= 0xFF, return ERR_VAL);
LWIP_ERROR("mqtt_client_connect: client_info->will_topic length must be > 0", len > 0, return ERR_VAL);
will_topic_len = (u8_t)len; will_topic_len = (u8_t)len;
len = strlen(client_info->will_msg); len = strlen(client_info->will_msg);
LWIP_ERROR("mqtt_client_connect: client_info->will_msg length overflow", len <= 0xFF, return ERR_VAL); LWIP_ERROR("mqtt_client_connect: client_info->will_msg length overflow", len <= 0xFF, return ERR_VAL);
@ -1291,7 +1295,7 @@ mqtt_client_connect(mqtt_client_t *client, const ip_addr_t *ip_addr, u16_t port,
/* Append client id */ /* Append client id */
mqtt_output_append_string(&client->output, client_info->client_id, client_id_length); mqtt_output_append_string(&client->output, client_info->client_id, client_id_length);
/* Append will message if used */ /* Append will message if used */
if (will_topic_len > 0) { if ((flags & MQTT_CONNECT_FLAG_WILL) != 0) {
mqtt_output_append_string(&client->output, client_info->will_topic, will_topic_len); mqtt_output_append_string(&client->output, client_info->will_topic, will_topic_len);
mqtt_output_append_string(&client->output, client_info->will_msg, will_msg_len); mqtt_output_append_string(&client->output, client_info->will_msg, will_msg_len);
} }
@ -1333,3 +1337,5 @@ mqtt_client_is_connected(mqtt_client_t *client)
LWIP_ASSERT("mqtt_client_is_connected: client != NULL", client); LWIP_ASSERT("mqtt_client_is_connected: client != NULL", client);
return client->conn_state == MQTT_CONNECTED; return client->conn_state == MQTT_CONNECTED;
} }
#endif /* LWIP_TCP && LWIP_CALLBACK_API */

View File

@ -56,6 +56,10 @@
#include <string.h> #include <string.h>
#ifdef LWIP_HOOK_FILENAME
#include LWIP_HOOK_FILENAME
#endif
#if LWIP_IPV4 && LWIP_ARP /* don't build if not configured for use in lwipopts.h */ #if LWIP_IPV4 && LWIP_ARP /* don't build if not configured for use in lwipopts.h */
/** Re-request a used ARP entry 1 minute before it would expire to prevent /** Re-request a used ARP entry 1 minute before it would expire to prevent
@ -128,7 +132,11 @@ static u8_t etharp_cached_entry;
static err_t etharp_request_dst(struct netif *netif, const ip4_addr_t *ipaddr, const struct eth_addr* hw_dst_addr); static err_t etharp_request_dst(struct netif *netif, const ip4_addr_t *ipaddr, const struct eth_addr* hw_dst_addr);
static err_t etharp_raw(struct netif *netif,
const struct eth_addr *ethsrc_addr, const struct eth_addr *ethdst_addr,
const struct eth_addr *hwsrc_addr, const ip4_addr_t *ipsrc_addr,
const struct eth_addr *hwdst_addr, const ip4_addr_t *ipdst_addr,
const u16_t opcode);
#if ARP_QUEUEING #if ARP_QUEUEING
/** /**
@ -695,38 +703,12 @@ etharp_input(struct pbuf *p, struct netif *netif)
LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming ARP request\n")); LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming ARP request\n"));
/* ARP request for our address? */ /* ARP request for our address? */
if (for_us) { if (for_us) {
/* send ARP response */
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: replying to ARP request for our IP address\n")); etharp_raw(netif,
/* Re-use pbuf to send ARP reply. (struct eth_addr *)netif->hwaddr, &hdr->shwaddr,
Since we are re-using an existing pbuf, we can't call etharp_raw since (struct eth_addr *)netif->hwaddr, netif_ip4_addr(netif),
that would allocate a new pbuf. */ &hdr->shwaddr, &sipaddr,
hdr->opcode = lwip_htons(ARP_REPLY); ARP_REPLY);
IPADDR2_COPY(&hdr->dipaddr, &hdr->sipaddr);
IPADDR2_COPY(&hdr->sipaddr, netif_ip4_addr(netif));
LWIP_ASSERT("netif->hwaddr_len must be the same as ETH_HWADDR_LEN for etharp!",
(netif->hwaddr_len == ETH_HWADDR_LEN));
/* hwtype, hwaddr_len, proto, protolen and the type in the ethernet header
are already correct, we tested that before */
ETHADDR16_COPY(&hdr->dhwaddr, &hdr->shwaddr);
ETHADDR16_COPY(&hdr->shwaddr, netif->hwaddr);
/* return ARP reply */
#if LWIP_AUTOIP
/* If we are using Link-Local, all ARP packets that contain a Link-Local
* 'sender IP address' MUST be sent using link-layer broadcast instead of
* link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */
if (ip4_addr_islinklocal(netif_ip4_addr(netif))) {
ethernet_output(netif, p, &hdr->shwaddr, &ethbroadcast, ETHTYPE_ARP);
} else
#endif /* LWIP_AUTOIP */
{
ethernet_output(netif, p, &hdr->shwaddr, &hdr->dhwaddr, ETHTYPE_ARP);
}
/* we are not configured? */ /* we are not configured? */
} else if (ip4_addr_isany_val(*netif_ip4_addr(netif))) { } else if (ip4_addr_isany_val(*netif_ip4_addr(netif))) {
/* { for_us == 0 and netif->ip_addr.addr == 0 } */ /* { for_us == 0 and netif->ip_addr.addr == 0 } */

View File

@ -51,6 +51,10 @@
#include <string.h> #include <string.h>
#ifdef LWIP_HOOK_FILENAME
#include LWIP_HOOK_FILENAME
#endif
/** Small optimization: set to 0 if incoming PBUF_POOL pbuf always can be /** Small optimization: set to 0 if incoming PBUF_POOL pbuf always can be
* used to modify and send a response packet (and to 1 if this is not the case, * used to modify and send a response packet (and to 1 if this is not the case,
* e.g. when link header is stripped of when receiving) */ * e.g. when link header is stripped of when receiving) */

View File

@ -240,7 +240,7 @@ igmp_lookfor_group(struct netif *ifp, const ip4_addr_t *addr)
* @return a struct igmp_group*, * @return a struct igmp_group*,
* NULL on memory error. * NULL on memory error.
*/ */
struct igmp_group * static struct igmp_group *
igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr) igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr)
{ {
struct igmp_group *group; struct igmp_group *group;

View File

@ -59,6 +59,10 @@
#include <string.h> #include <string.h>
#ifdef LWIP_HOOK_FILENAME
#include LWIP_HOOK_FILENAME
#endif
/** Set this to 0 in the rare case of wanting to call an extra function to /** Set this to 0 in the rare case of wanting to call an extra function to
* generate the IP checksum (in contrast to calculating it on-the-fly). */ * generate the IP checksum (in contrast to calculating it on-the-fly). */
#ifndef LWIP_INLINE_IP_CHKSUM #ifndef LWIP_INLINE_IP_CHKSUM

View File

@ -60,6 +60,10 @@
#include "lwip/debug.h" #include "lwip/debug.h"
#include "lwip/stats.h" #include "lwip/stats.h"
#ifdef LWIP_HOOK_FILENAME
#include LWIP_HOOK_FILENAME
#endif
/** /**
* Finds the appropriate network interface for a given IPv6 address. It tries to select * Finds the appropriate network interface for a given IPv6 address. It tries to select
* a netif following a sequence of heuristics: * a netif following a sequence of heuristics:
@ -443,9 +447,11 @@ ip6_input(struct pbuf *p, struct netif *inp)
ip_addr_copy_from_ip6(ip_data.current_iphdr_dest, ip6hdr->dest); ip_addr_copy_from_ip6(ip_data.current_iphdr_dest, ip6hdr->dest);
ip_addr_copy_from_ip6(ip_data.current_iphdr_src, ip6hdr->src); ip_addr_copy_from_ip6(ip_data.current_iphdr_src, ip6hdr->src);
/* Don't accept virtual IPv6 mapped IPv4 addresses */ /* Don't accept virtual IPv4 mapped IPv6 addresses.
if (ip6_addr_isipv6mappedipv4(ip_2_ip6(&ip_data.current_iphdr_dest)) || * Don't accept multicast source addresses. */
ip6_addr_isipv6mappedipv4(ip_2_ip6(&ip_data.current_iphdr_src)) ) { if (ip6_addr_isipv4mappedipv6(ip_2_ip6(&ip_data.current_iphdr_dest)) ||
ip6_addr_isipv4mappedipv6(ip_2_ip6(&ip_data.current_iphdr_src)) ||
ip6_addr_ismulticast(ip_2_ip6(&ip_data.current_iphdr_src))) {
IP6_STATS_INC(ip6.err); IP6_STATS_INC(ip6.err);
IP6_STATS_INC(ip6.drop); IP6_STATS_INC(ip6.drop);
return ERR_OK; return ERR_OK;
@ -815,8 +821,8 @@ ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
const ip6_addr_t *src_used = src; const ip6_addr_t *src_used = src;
if (dest != LWIP_IP_HDRINCL) { if (dest != LWIP_IP_HDRINCL) {
if (src != NULL && ip6_addr_isany(src)) { if (src != NULL && ip6_addr_isany(src)) {
src = ip_2_ip6(ip6_select_source_address(netif, dest)); src_used = ip_2_ip6(ip6_select_source_address(netif, dest));
if ((src == NULL) || ip6_addr_isany(src)) { if ((src_used == NULL) || ip6_addr_isany(src_used)) {
/* No appropriate source address was found for this packet. */ /* No appropriate source address was found for this packet. */
LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: No suitable source address for packet.\n")); LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: No suitable source address for packet.\n"));
IP6_STATS_INC(ip6.rterr); IP6_STATS_INC(ip6.rterr);

View File

@ -573,6 +573,11 @@ mld6_send(struct netif *netif, struct mld_group *group, u8_t type)
/* Add hop-by-hop headers options: router alert with MLD value. */ /* Add hop-by-hop headers options: router alert with MLD value. */
ip6_options_add_hbh_ra(p, IP6_NEXTH_ICMP6, IP6_ROUTER_ALERT_VALUE_MLD); ip6_options_add_hbh_ra(p, IP6_NEXTH_ICMP6, IP6_ROUTER_ALERT_VALUE_MLD);
if (type == ICMP6_TYPE_MLR) {
/* Remember we were the last to report */
group->last_reporter_flag = 1;
}
/* Send the packet out. */ /* Send the packet out. */
MLD6_STATS_INC(mld6.xmit); MLD6_STATS_INC(mld6.xmit);
ip6_output_if(p, (ip6_addr_isany(src_addr)) ? NULL : src_addr, &(group->group_address), ip6_output_if(p, (ip6_addr_isany(src_addr)) ? NULL : src_addr, &(group->group_address),

View File

@ -64,6 +64,10 @@
#include <string.h> #include <string.h>
#ifdef LWIP_HOOK_FILENAME
#include LWIP_HOOK_FILENAME
#endif
#if LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK #if LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK
#error LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK #error LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK
#endif #endif

View File

@ -280,6 +280,7 @@ DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static
#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ #endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
static void dns_init_local(void); static void dns_init_local(void);
static err_t dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype));
#endif /* DNS_LOCAL_HOSTLIST */ #endif /* DNS_LOCAL_HOSTLIST */
@ -430,6 +431,38 @@ dns_init_local(void)
#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) */ #endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) */
} }
/**
* @ingroup dns
* Iterate the local host-list for a hostname.
*
* @param iterator_fn a function that is called for every entry in the local host-list
* @param iterator_arg 3rd argument passed to iterator_fn
* @return the number of entries in the local host-list
*/
size_t
dns_local_iterate(dns_found_callback iterator_fn, void *iterator_arg)
{
size_t i;
#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
struct local_hostlist_entry *entry = local_hostlist_dynamic;
i = 0;
while (entry != NULL) {
if (iterator_fn != NULL) {
iterator_fn(entry->name, &entry->addr, iterator_arg);
}
i++;
entry = entry->next;
}
#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
for (i = 0; i < LWIP_ARRAYSIZE(local_hostlist_static); i++) {
if (iterator_fn != NULL) {
iterator_fn(local_hostlist_static[i].name, &local_hostlist_static[i].addr, iterator_arg);
}
}
#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
return i;
}
/** /**
* @ingroup dns * @ingroup dns
* Scans the local host-list for a hostname. * Scans the local host-list for a hostname.
@ -437,8 +470,20 @@ dns_init_local(void)
* @param hostname Hostname to look for in the local host-list * @param hostname Hostname to look for in the local host-list
* @param addr the first IP address for the hostname in the local host-list or * @param addr the first IP address for the hostname in the local host-list or
* IPADDR_NONE if not found. * IPADDR_NONE if not found.
* @param dns_addrtype - LWIP_DNS_ADDRTYPE_IPV4_IPV6: try to resolve IPv4 (ATTENTION: no fallback here!)
* - LWIP_DNS_ADDRTYPE_IPV6_IPV4: try to resolve IPv6 (ATTENTION: no fallback here!)
* - LWIP_DNS_ADDRTYPE_IPV4: try to resolve IPv4 only
* - LWIP_DNS_ADDRTYPE_IPV6: try to resolve IPv6 only
* @return ERR_OK if found, ERR_ARG if not found * @return ERR_OK if found, ERR_ARG if not found
*/ */
err_t
dns_local_lookup(const char *hostname, ip_addr_t *addr, u8_t dns_addrtype)
{
LWIP_UNUSED_ARG(dns_addrtype);
return dns_lookup_local(hostname, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype));
}
/* Internal implementation for dns_local_lookup and dns_lookup */
static err_t static err_t
dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype)) dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype))
{ {
@ -1436,9 +1481,9 @@ dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback foun
* ERR_INPROGRESS is returned!) * ERR_INPROGRESS is returned!)
* @param callback_arg argument to pass to the callback function * @param callback_arg argument to pass to the callback function
* @param dns_addrtype - LWIP_DNS_ADDRTYPE_IPV4_IPV6: try to resolve IPv4 first, try IPv6 if IPv4 fails only * @param dns_addrtype - LWIP_DNS_ADDRTYPE_IPV4_IPV6: try to resolve IPv4 first, try IPv6 if IPv4 fails only
* - LWIP_DNS_ADDRTYPE_IPV6_IPV4: try to resolve IPv6 first, try IPv4 if IPv6 fails only * - LWIP_DNS_ADDRTYPE_IPV6_IPV4: try to resolve IPv6 first, try IPv4 if IPv6 fails only
* - LWIP_DNS_ADDRTYPE_IPV4: try to resolve IPv4 only * - LWIP_DNS_ADDRTYPE_IPV4: try to resolve IPv4 only
* - LWIP_DNS_ADDRTYPE_IPV6: try to resolve IPv6 only * - LWIP_DNS_ADDRTYPE_IPV6: try to resolve IPv6 only
*/ */
err_t err_t
dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_callback found, dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_callback found,

View File

@ -218,9 +218,6 @@ PACK_STRUCT_END
#if !LWIP_ETHERNET && (LWIP_ARP || PPPOE_SUPPORT) #if !LWIP_ETHERNET && (LWIP_ARP || PPPOE_SUPPORT)
#error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT" #error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT"
#endif #endif
#if (LWIP_IGMP || LWIP_IPV6) && !defined(LWIP_RAND)
#error "When using IGMP or IPv6, LWIP_RAND() needs to be defined to a random-function returning an u32_t random value (in arch/cc.h)"
#endif
#if LWIP_TCPIP_CORE_LOCKING_INPUT && !LWIP_TCPIP_CORE_LOCKING #if LWIP_TCPIP_CORE_LOCKING_INPUT && !LWIP_TCPIP_CORE_LOCKING
#error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too" #error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too"
#endif #endif

View File

@ -75,7 +75,6 @@
#include "lwip/ip6_frag.h" #include "lwip/ip6_frag.h"
#include "lwip/mld6.h" #include "lwip/mld6.h"
#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc) #define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc)
#include "lwip/priv/memp_std.h" #include "lwip/priv/memp_std.h"
@ -84,6 +83,10 @@ const struct memp_desc* const memp_pools[MEMP_MAX] = {
#include "lwip/priv/memp_std.h" #include "lwip/priv/memp_std.h"
}; };
#ifdef LWIP_HOOK_FILENAME
#include LWIP_HOOK_FILENAME
#endif
#if MEMP_MEM_MALLOC && MEMP_OVERFLOW_CHECK >= 2 #if MEMP_MEM_MALLOC && MEMP_OVERFLOW_CHECK >= 2
#undef MEMP_OVERFLOW_CHECK #undef MEMP_OVERFLOW_CHECK
/* MEMP_OVERFLOW_CHECK >= 2 does not work with MEMP_MEM_MALLOC, use 1 instead */ /* MEMP_OVERFLOW_CHECK >= 2 does not work with MEMP_MEM_MALLOC, use 1 instead */

View File

@ -350,8 +350,18 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
break; break;
case PBUF_RAM: case PBUF_RAM:
/* If pbuf is to be allocated in RAM, allocate memory for it. */ {
p = (struct pbuf*)mem_malloc(LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length)); mem_size_t alloc_len = LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length);
/* bug #50040: Check for integer overflow when calculating alloc_len */
if (alloc_len < LWIP_MEM_ALIGN_SIZE(length)) {
return NULL;
}
/* If pbuf is to be allocated in RAM, allocate memory for it. */
p = (struct pbuf*)mem_malloc(alloc_len);
}
if (p == NULL) { if (p == NULL) {
return NULL; return NULL;
} }
@ -812,6 +822,7 @@ pbuf_ref(struct pbuf *p)
/* pbuf given? */ /* pbuf given? */
if (p != NULL) { if (p != NULL) {
SYS_ARCH_INC(p->ref, 1); SYS_ARCH_INC(p->ref, 1);
LWIP_ASSERT("pbuf ref overflow", p->ref > 0);
} }
} }

View File

@ -209,7 +209,7 @@ raw_input(struct pbuf *p, struct netif *inp)
err_t err_t
raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr) raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr)
{ {
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) { if ((pcb == NULL) || (ipaddr == NULL)) {
return ERR_VAL; return ERR_VAL;
} }
ip_addr_set_ipaddr(&pcb->local_ip, ipaddr); ip_addr_set_ipaddr(&pcb->local_ip, ipaddr);
@ -233,7 +233,7 @@ raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr)
err_t err_t
raw_connect(struct raw_pcb *pcb, const ip_addr_t *ipaddr) raw_connect(struct raw_pcb *pcb, const ip_addr_t *ipaddr)
{ {
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) { if ((pcb == NULL) || (ipaddr == NULL)) {
return ERR_VAL; return ERR_VAL;
} }
ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr); ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr);

View File

@ -96,7 +96,7 @@ stats_display_igmp(struct stats_igmp *igmp, const char *name)
LWIP_PLATFORM_DIAG(("rx_report: %"STAT_COUNTER_F"\n\t", igmp->rx_report)); LWIP_PLATFORM_DIAG(("rx_report: %"STAT_COUNTER_F"\n\t", igmp->rx_report));
LWIP_PLATFORM_DIAG(("tx_join: %"STAT_COUNTER_F"\n\t", igmp->tx_join)); LWIP_PLATFORM_DIAG(("tx_join: %"STAT_COUNTER_F"\n\t", igmp->tx_join));
LWIP_PLATFORM_DIAG(("tx_leave: %"STAT_COUNTER_F"\n\t", igmp->tx_leave)); LWIP_PLATFORM_DIAG(("tx_leave: %"STAT_COUNTER_F"\n\t", igmp->tx_leave));
LWIP_PLATFORM_DIAG(("tx_report: %"STAT_COUNTER_F"\n\t", igmp->tx_report)); LWIP_PLATFORM_DIAG(("tx_report: %"STAT_COUNTER_F"\n", igmp->tx_report));
} }
#endif /* IGMP_STATS || MLD6_STATS */ #endif /* IGMP_STATS || MLD6_STATS */
@ -135,7 +135,7 @@ stats_display_sys(struct stats_sys *sys)
LWIP_PLATFORM_DIAG(("mutex.err: %"U32_F"\n\t", (u32_t)sys->mutex.err)); LWIP_PLATFORM_DIAG(("mutex.err: %"U32_F"\n\t", (u32_t)sys->mutex.err));
LWIP_PLATFORM_DIAG(("mbox.used: %"U32_F"\n\t", (u32_t)sys->mbox.used)); LWIP_PLATFORM_DIAG(("mbox.used: %"U32_F"\n\t", (u32_t)sys->mbox.used));
LWIP_PLATFORM_DIAG(("mbox.max: %"U32_F"\n\t", (u32_t)sys->mbox.max)); LWIP_PLATFORM_DIAG(("mbox.max: %"U32_F"\n\t", (u32_t)sys->mbox.max));
LWIP_PLATFORM_DIAG(("mbox.err: %"U32_F"\n\t", (u32_t)sys->mbox.err)); LWIP_PLATFORM_DIAG(("mbox.err: %"U32_F"\n", (u32_t)sys->mbox.err));
} }
#endif /* SYS_STATS */ #endif /* SYS_STATS */

View File

@ -62,6 +62,10 @@
#include <string.h> #include <string.h>
#ifdef LWIP_HOOK_FILENAME
#include LWIP_HOOK_FILENAME
#endif
#ifndef TCP_LOCAL_PORT_RANGE_START #ifndef TCP_LOCAL_PORT_RANGE_START
/* From http://www.iana.org/assignments/port-numbers: /* From http://www.iana.org/assignments/port-numbers:
"The Dynamic and/or Private Ports are those from 49152 through 65535" */ "The Dynamic and/or Private Ports are those from 49152 through 65535" */
@ -132,6 +136,8 @@ static u8_t tcp_timer;
static u8_t tcp_timer_ctr; static u8_t tcp_timer_ctr;
static u16_t tcp_new_port(void); static u16_t tcp_new_port(void);
static err_t tcp_close_shutdown_fin(struct tcp_pcb *pcb);
/** /**
* Initialize this module. * Initialize this module.
*/ */
@ -258,8 +264,6 @@ tcp_backlog_accepted(struct tcp_pcb* pcb)
static err_t static err_t
tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data) tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
{ {
err_t err;
if (rst_on_unacked_data && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) { if (rst_on_unacked_data && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) {
if ((pcb->refused_data != NULL) || (pcb->rcv_wnd != TCP_WND_MAX(pcb))) { if ((pcb->refused_data != NULL) || (pcb->rcv_wnd != TCP_WND_MAX(pcb))) {
/* Not all data received by application, send RST to tell the remote /* Not all data received by application, send RST to tell the remote
@ -290,6 +294,8 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
} }
} }
/* - states which free the pcb are handled here,
- states which send FIN and change state are handled in tcp_close_shutdown_fin() */
switch (pcb->state) { switch (pcb->state) {
case CLOSED: case CLOSED:
/* Closing a pcb in the CLOSED state might seem erroneous, /* Closing a pcb in the CLOSED state might seem erroneous,
@ -299,27 +305,34 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
* or for a pcb that has been used and then entered the CLOSED state * 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 * is erroneous, but this should never happen as the pcb has in those cases
* been freed, and so any remaining handles are bogus. */ * been freed, and so any remaining handles are bogus. */
err = ERR_OK;
if (pcb->local_port != 0) { if (pcb->local_port != 0) {
TCP_RMV(&tcp_bound_pcbs, pcb); TCP_RMV(&tcp_bound_pcbs, pcb);
} }
memp_free(MEMP_TCP_PCB, pcb); memp_free(MEMP_TCP_PCB, pcb);
pcb = NULL;
break; break;
case LISTEN: case LISTEN:
err = ERR_OK;
tcp_listen_closed(pcb); tcp_listen_closed(pcb);
tcp_pcb_remove(&tcp_listen_pcbs.pcbs, pcb); tcp_pcb_remove(&tcp_listen_pcbs.pcbs, pcb);
memp_free(MEMP_TCP_PCB_LISTEN, pcb); memp_free(MEMP_TCP_PCB_LISTEN, pcb);
pcb = NULL;
break; break;
case SYN_SENT: case SYN_SENT:
err = ERR_OK;
TCP_PCB_REMOVE_ACTIVE(pcb); TCP_PCB_REMOVE_ACTIVE(pcb);
memp_free(MEMP_TCP_PCB, pcb); memp_free(MEMP_TCP_PCB, pcb);
pcb = NULL;
MIB2_STATS_INC(mib2.tcpattemptfails); MIB2_STATS_INC(mib2.tcpattemptfails);
break; break;
default:
return tcp_close_shutdown_fin(pcb);
}
return ERR_OK;
}
static err_t
tcp_close_shutdown_fin(struct tcp_pcb *pcb)
{
err_t err;
LWIP_ASSERT("pcb != NULL", pcb != NULL);
switch (pcb->state) {
case SYN_RCVD: case SYN_RCVD:
err = tcp_send_fin(pcb); err = tcp_send_fin(pcb);
if (err == ERR_OK) { if (err == ERR_OK) {
@ -344,18 +357,20 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
break; break;
default: default:
/* Has already been closed, do nothing. */ /* Has already been closed, do nothing. */
err = ERR_OK; return ERR_OK;
pcb = NULL;
break; break;
} }
if (pcb != NULL && err == ERR_OK) { if (err == ERR_OK) {
/* To ensure all data has been sent when tcp_close returns, we have /* To ensure all data has been sent when tcp_close returns, we have
to make sure tcp_output doesn't fail. to make sure tcp_output doesn't fail.
Since we don't really have to ensure all data has been sent when tcp_close Since we don't really have to ensure all data has been sent when tcp_close
returns (unsent data is sent from tcp timer functions, also), we don't care returns (unsent data is sent from tcp timer functions, also), we don't care
for the return value of tcp_output for now. */ for the return value of tcp_output for now. */
tcp_output(pcb); tcp_output(pcb);
} else if (err == ERR_MEM) {
/* Mark this pcb for closing. Closing is retried from tcp_tmr. */
pcb->flags |= TF_CLOSEPEND;
} }
return err; return err;
} }
@ -467,6 +482,7 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
} else { } else {
int send_rst = 0; int send_rst = 0;
u16_t local_port = 0; u16_t local_port = 0;
enum tcp_state last_state;
seqno = pcb->snd_nxt; seqno = pcb->snd_nxt;
ackno = pcb->rcv_nxt; ackno = pcb->rcv_nxt;
#if LWIP_CALLBACK_API #if LWIP_CALLBACK_API
@ -499,8 +515,9 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n")); LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n"));
tcp_rst(seqno, ackno, &pcb->local_ip, &pcb->remote_ip, local_port, pcb->remote_port); tcp_rst(seqno, ackno, &pcb->local_ip, &pcb->remote_ip, local_port, pcb->remote_port);
} }
last_state = pcb->state;
memp_free(MEMP_TCP_PCB, pcb); memp_free(MEMP_TCP_PCB, pcb);
TCP_EVENT_ERR(errf, errf_arg, ERR_ABRT); TCP_EVENT_ERR(last_state, errf, errf_arg, ERR_ABRT);
} }
} }
@ -551,7 +568,7 @@ tcp_bind(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port)
#endif /* LWIP_IPV4 */ #endif /* LWIP_IPV4 */
/* still need to check for ipaddr == NULL in IPv6 only case */ /* still need to check for ipaddr == NULL in IPv6 only case */
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) { if ((pcb == NULL) || (ipaddr == NULL)) {
return ERR_VAL; return ERR_VAL;
} }
@ -859,7 +876,7 @@ tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port,
u32_t iss; u32_t iss;
u16_t old_local_port; u16_t old_local_port;
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) { if ((pcb == NULL) || (ipaddr == NULL)) {
return ERR_VAL; return ERR_VAL;
} }
@ -931,7 +948,6 @@ tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port,
pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip); pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip);
#endif /* TCP_CALCULATE_EFF_SEND_MSS */ #endif /* TCP_CALCULATE_EFF_SEND_MSS */
pcb->cwnd = 1; pcb->cwnd = 1;
pcb->ssthresh = TCP_WND;
#if LWIP_CALLBACK_API #if LWIP_CALLBACK_API
pcb->connected = connected; pcb->connected = connected;
#else /* LWIP_CALLBACK_API */ #else /* LWIP_CALLBACK_API */
@ -997,11 +1013,11 @@ tcp_slowtmr_start:
pcb_remove = 0; pcb_remove = 0;
pcb_reset = 0; pcb_reset = 0;
if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) { if (pcb->state == SYN_SENT && pcb->nrtx >= TCP_SYNMAXRTX) {
++pcb_remove; ++pcb_remove;
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n")); LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n"));
} }
else if (pcb->nrtx == TCP_MAXRTX) { else if (pcb->nrtx >= TCP_MAXRTX) {
++pcb_remove; ++pcb_remove;
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n")); LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n"));
} else { } else {
@ -1035,7 +1051,8 @@ tcp_slowtmr_start:
/* Double retransmission time-out unless we are trying to /* Double retransmission time-out unless we are trying to
* connect to somebody (i.e., we are in SYN_SENT). */ * connect to somebody (i.e., we are in SYN_SENT). */
if (pcb->state != SYN_SENT) { if (pcb->state != SYN_SENT) {
pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx]; u8_t backoff_idx = LWIP_MIN(pcb->nrtx, sizeof(tcp_backoff)-1);
pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[backoff_idx];
} }
/* Reset the retransmission timer. */ /* Reset the retransmission timer. */
@ -1132,6 +1149,7 @@ tcp_slowtmr_start:
tcp_err_fn err_fn = pcb->errf; tcp_err_fn err_fn = pcb->errf;
#endif /* LWIP_CALLBACK_API */ #endif /* LWIP_CALLBACK_API */
void *err_arg; void *err_arg;
enum tcp_state last_state;
tcp_pcb_purge(pcb); tcp_pcb_purge(pcb);
/* Remove PCB from tcp_active_pcbs list. */ /* Remove PCB from tcp_active_pcbs list. */
if (prev != NULL) { if (prev != NULL) {
@ -1149,12 +1167,13 @@ tcp_slowtmr_start:
} }
err_arg = pcb->callback_arg; err_arg = pcb->callback_arg;
last_state = pcb->state;
pcb2 = pcb; pcb2 = pcb;
pcb = pcb->next; pcb = pcb->next;
memp_free(MEMP_TCP_PCB, pcb2); memp_free(MEMP_TCP_PCB, pcb2);
tcp_active_pcbs_changed = 0; tcp_active_pcbs_changed = 0;
TCP_EVENT_ERR(err_fn, err_arg, ERR_ABRT); TCP_EVENT_ERR(last_state, err_fn, err_arg, ERR_ABRT);
if (tcp_active_pcbs_changed) { if (tcp_active_pcbs_changed) {
goto tcp_slowtmr_start; goto tcp_slowtmr_start;
} }
@ -1244,6 +1263,12 @@ tcp_fasttmr_start:
tcp_output(pcb); tcp_output(pcb);
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
} }
/* send pending FIN */
if (pcb->flags & TF_CLOSEPEND) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: pending FIN\n"));
pcb->flags &= ~(TF_CLOSEPEND);
tcp_close_shutdown_fin(pcb);
}
next = pcb->next; next = pcb->next;
@ -1590,6 +1615,14 @@ tcp_alloc(u8_t prio)
pcb->tmr = tcp_ticks; pcb->tmr = tcp_ticks;
pcb->last_timer = tcp_timer_ctr; pcb->last_timer = tcp_timer_ctr;
/* RFC 5681 recommends setting ssthresh abritrarily high and gives an example
of using the largest advertised receive window. We've seen complications with
receiving TCPs that use window scaling and/or window auto-tuning where the
initial advertised window is very small and then grows rapidly once the
connection is established. To avoid these complications, we set ssthresh to the
largest effective cwnd (amount of in-flight data) that the sender can have. */
pcb->ssthresh = TCP_SND_BUF;
#if LWIP_CALLBACK_API #if LWIP_CALLBACK_API
pcb->recv = tcp_recv_null; pcb->recv = tcp_recv_null;
#endif /* LWIP_CALLBACK_API */ #endif /* LWIP_CALLBACK_API */

View File

@ -61,8 +61,6 @@
/** Initial CWND calculation as defined RFC 2581 */ /** Initial CWND calculation as defined RFC 2581 */
#define LWIP_TCP_CALC_INITIAL_CWND(mss) LWIP_MIN((4U * (mss)), LWIP_MAX((2U * (mss)), 4380U)); #define LWIP_TCP_CALC_INITIAL_CWND(mss) LWIP_MIN((4U * (mss)), LWIP_MAX((2U * (mss)), 4380U));
/** Initial slow start threshold value: we use the full window */
#define LWIP_TCP_INITIAL_SSTHRESH(pcb) ((pcb)->snd_wnd)
/* These variables are global to all functions involved in the input /* These variables are global to all functions involved in the input
processing of TCP segments. They are set by the tcp_input() processing of TCP segments. They are set by the tcp_input()
@ -378,7 +376,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
end. We then call the error callback to inform the end. We then call the error callback to inform the
application that the connection is dead before we application that the connection is dead before we
deallocate the PCB. */ deallocate the PCB. */
TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST); TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_RST);
tcp_pcb_remove(&tcp_active_pcbs, pcb); tcp_pcb_remove(&tcp_active_pcbs, pcb);
memp_free(MEMP_TCP_PCB, pcb); memp_free(MEMP_TCP_PCB, pcb);
} else { } else {
@ -413,7 +411,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
/* Connection closed although the application has only shut down the /* Connection closed although the application has only shut down the
tx side: call the PCB's err callback and indicate the closure to tx side: call the PCB's err callback and indicate the closure to
ensure the application doesn't continue using the PCB. */ ensure the application doesn't continue using the PCB. */
TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_CLSD); TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_CLSD);
} }
tcp_pcb_remove(&tcp_active_pcbs, pcb); tcp_pcb_remove(&tcp_active_pcbs, pcb);
memp_free(MEMP_TCP_PCB, pcb); memp_free(MEMP_TCP_PCB, pcb);
@ -615,7 +613,6 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
tcp_parseopt(npcb); tcp_parseopt(npcb);
npcb->snd_wnd = tcphdr->wnd; npcb->snd_wnd = tcphdr->wnd;
npcb->snd_wnd_max = npcb->snd_wnd; npcb->snd_wnd_max = npcb->snd_wnd;
npcb->ssthresh = LWIP_TCP_INITIAL_SSTHRESH(npcb);
#if TCP_CALCULATE_EFF_SEND_MSS #if TCP_CALCULATE_EFF_SEND_MSS
npcb->mss = tcp_eff_send_mss(npcb->mss, &npcb->local_ip, &npcb->remote_ip); npcb->mss = tcp_eff_send_mss(npcb->mss, &npcb->local_ip, &npcb->remote_ip);
@ -771,9 +768,6 @@ tcp_process(struct tcp_pcb *pcb)
pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip); pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip);
#endif /* TCP_CALCULATE_EFF_SEND_MSS */ #endif /* TCP_CALCULATE_EFF_SEND_MSS */
/* Set ssthresh again after changing 'mss' and 'snd_wnd' */
pcb->ssthresh = LWIP_TCP_INITIAL_SSTHRESH(pcb);
pcb->cwnd = LWIP_TCP_CALC_INITIAL_CWND(pcb->mss); pcb->cwnd = LWIP_TCP_CALC_INITIAL_CWND(pcb->mss);
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_process (SENT): cwnd %"TCPWNDSIZE_F LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_process (SENT): cwnd %"TCPWNDSIZE_F
" ssthresh %"TCPWNDSIZE_F"\n", " ssthresh %"TCPWNDSIZE_F"\n",
@ -816,9 +810,12 @@ tcp_process(struct tcp_pcb *pcb)
tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(),
ip_current_src_addr(), tcphdr->dest, tcphdr->src); ip_current_src_addr(), tcphdr->dest, tcphdr->src);
/* Resend SYN immediately (don't wait for rto timeout) to establish /* Resend SYN immediately (don't wait for rto timeout) to establish
connection faster */ connection faster, but do not send more SYNs than we otherwise would
pcb->rtime = 0; have, or we might get caught in a loop on loopback interfaces. */
tcp_rexmit_rto(pcb); if (pcb->nrtx < TCP_SYNMAXRTX) {
pcb->rtime = 0;
tcp_rexmit_rto(pcb);
}
} }
break; break;
case SYN_RCVD: case SYN_RCVD:
@ -827,14 +824,16 @@ tcp_process(struct tcp_pcb *pcb)
if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) { if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) {
pcb->state = ESTABLISHED; pcb->state = ESTABLISHED;
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\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 || TCP_LISTEN_BACKLOG
#if LWIP_CALLBACK_API #if LWIP_CALLBACK_API
LWIP_ASSERT("pcb->listener->accept != NULL", LWIP_ASSERT("pcb->listener->accept != NULL",
(pcb->listener == NULL) || (pcb->listener->accept != NULL)); (pcb->listener == NULL) || (pcb->listener->accept != NULL));
#endif
if (pcb->listener == NULL) { if (pcb->listener == NULL) {
/* listen pcb might be closed by now */ /* listen pcb might be closed by now */
err = ERR_VAL; err = ERR_VAL;
} else } else
#endif #endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */
{ {
tcp_backlog_accepted(pcb); tcp_backlog_accepted(pcb);
/* Call the accept function. */ /* Call the accept function. */
@ -853,11 +852,6 @@ tcp_process(struct tcp_pcb *pcb)
* we'd better pass it on to the application as well. */ * we'd better pass it on to the application as well. */
tcp_receive(pcb); tcp_receive(pcb);
/* passive open: update initial ssthresh now that the correct window is
known: if the remote side supports window scaling, the window sent
with the initial SYN can be smaller than the one used later */
pcb->ssthresh = LWIP_TCP_INITIAL_SSTHRESH(pcb);
/* Prevent ACK for SYN to generate a sent event */ /* Prevent ACK for SYN to generate a sent event */
if (recv_acked != 0) { if (recv_acked != 0) {
recv_acked--; recv_acked--;
@ -925,7 +919,7 @@ tcp_process(struct tcp_pcb *pcb)
break; break;
case CLOSING: case CLOSING:
tcp_receive(pcb); tcp_receive(pcb);
if (flags & TCP_ACK && ackno == pcb->snd_nxt && pcb->unsent == NULL) { if ((flags & TCP_ACK) && ackno == pcb->snd_nxt && pcb->unsent == NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
tcp_pcb_purge(pcb); tcp_pcb_purge(pcb);
TCP_RMV_ACTIVE(pcb); TCP_RMV_ACTIVE(pcb);
@ -935,7 +929,7 @@ tcp_process(struct tcp_pcb *pcb)
break; break;
case LAST_ACK: case LAST_ACK:
tcp_receive(pcb); tcp_receive(pcb);
if (flags & TCP_ACK && ackno == pcb->snd_nxt && pcb->unsent == NULL) { if ((flags & TCP_ACK) && ackno == pcb->snd_nxt && pcb->unsent == NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
/* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */ /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */
recv_flags |= TF_CLOSED; recv_flags |= TF_CLOSED;
@ -1417,7 +1411,7 @@ tcp_receive(struct tcp_pcb *pcb)
TCP_SEQ_GEQ(seqno + tcplen, TCP_SEQ_GEQ(seqno + tcplen,
next->tcphdr->seqno + next->len)) { next->tcphdr->seqno + next->len)) {
/* inseg cannot have FIN here (already processed above) */ /* inseg cannot have FIN here (already processed above) */
if (TCPH_FLAGS(next->tcphdr) & TCP_FIN && if ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0 &&
(TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) { (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) {
TCPH_SET_FLAG(inseg.tcphdr, TCP_FIN); TCPH_SET_FLAG(inseg.tcphdr, TCP_FIN);
tcplen = TCP_TCPLEN(&inseg); tcplen = TCP_TCPLEN(&inseg);

View File

@ -376,6 +376,9 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
#if TCP_OVERSIZE #if TCP_OVERSIZE
u16_t oversize = 0; u16_t oversize = 0;
u16_t oversize_used = 0; u16_t oversize_used = 0;
#if TCP_OVERSIZE_DBGCHECK
u16_t oversize_add = 0;
#endif /* TCP_OVERSIZE_DBGCHECK*/
#endif /* TCP_OVERSIZE */ #endif /* TCP_OVERSIZE */
u16_t extendlen = 0; u16_t extendlen = 0;
#if TCP_CHECKSUM_ON_COPY #if TCP_CHECKSUM_ON_COPY
@ -461,13 +464,13 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
*/ */
#if TCP_OVERSIZE #if TCP_OVERSIZE
#if TCP_OVERSIZE_DBGCHECK #if TCP_OVERSIZE_DBGCHECK
/* check that pcb->unsent_oversize matches last_unsent->unsent_oversize */ /* check that pcb->unsent_oversize matches last_unsent->oversize_left */
LWIP_ASSERT("unsent_oversize mismatch (pcb vs. last_unsent)", LWIP_ASSERT("unsent_oversize mismatch (pcb vs. last_unsent)",
pcb->unsent_oversize == last_unsent->oversize_left); pcb->unsent_oversize == last_unsent->oversize_left);
#endif /* TCP_OVERSIZE_DBGCHECK */ #endif /* TCP_OVERSIZE_DBGCHECK */
oversize = pcb->unsent_oversize; oversize = pcb->unsent_oversize;
if (oversize > 0) { if (oversize > 0) {
LWIP_ASSERT("inconsistent oversize vs. space", oversize_used <= space); LWIP_ASSERT("inconsistent oversize vs. space", oversize <= space);
seg = last_unsent; seg = last_unsent;
oversize_used = LWIP_MIN(space, LWIP_MIN(oversize, len)); oversize_used = LWIP_MIN(space, LWIP_MIN(oversize, len));
pos += oversize_used; pos += oversize_used;
@ -475,7 +478,7 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
space -= oversize_used; space -= oversize_used;
} }
/* now we are either finished or oversize is zero */ /* now we are either finished or oversize is zero */
LWIP_ASSERT("inconsistend oversize vs. len", (oversize == 0) || (pos == len)); LWIP_ASSERT("inconsistent oversize vs. len", (oversize == 0) || (pos == len));
#endif /* TCP_OVERSIZE */ #endif /* TCP_OVERSIZE */
/* /*
@ -490,7 +493,7 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
* the end. * the end.
*/ */
if ((pos < len) && (space > 0) && (last_unsent->len > 0)) { if ((pos < len) && (space > 0) && (last_unsent->len > 0)) {
u16_t seglen = space < len - pos ? space : len - pos; u16_t seglen = LWIP_MIN(space, len - pos);
seg = last_unsent; seg = last_unsent;
/* Create a pbuf with a copy or reference to seglen bytes. We /* Create a pbuf with a copy or reference to seglen bytes. We
@ -505,7 +508,7 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
goto memerr; goto memerr;
} }
#if TCP_OVERSIZE_DBGCHECK #if TCP_OVERSIZE_DBGCHECK
last_unsent->oversize_left += oversize; oversize_add = oversize;
#endif /* TCP_OVERSIZE_DBGCHECK */ #endif /* TCP_OVERSIZE_DBGCHECK */
TCP_DATA_COPY2(concat_p->payload, (const u8_t*)arg + pos, seglen, &concat_chksum, &concat_chksum_swapped); TCP_DATA_COPY2(concat_p->payload, (const u8_t*)arg + pos, seglen, &concat_chksum, &concat_chksum_swapped);
#if TCP_CHECKSUM_ON_COPY #if TCP_CHECKSUM_ON_COPY
@ -557,7 +560,7 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
struct pbuf *p; struct pbuf *p;
u16_t left = len - pos; u16_t left = len - pos;
u16_t max_len = mss_local - optlen; u16_t max_len = mss_local - optlen;
u16_t seglen = left > max_len ? max_len : left; u16_t seglen = LWIP_MIN(left, max_len);
#if TCP_CHECKSUM_ON_COPY #if TCP_CHECKSUM_ON_COPY
u16_t chksum = 0; u16_t chksum = 0;
u8_t chksum_swapped = 0; u8_t chksum_swapped = 0;
@ -656,6 +659,11 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
* All three segmentation phases were successful. We can commit the * All three segmentation phases were successful. We can commit the
* transaction. * transaction.
*/ */
#if TCP_OVERSIZE_DBGCHECK
if ((last_unsent != NULL) && (oversize_add != 0)) {
last_unsent->oversize_left += oversize_add;
}
#endif /* TCP_OVERSIZE_DBGCHECK */
/* /*
* Phase 1: If data has been added to the preallocated tail of * Phase 1: If data has been added to the preallocated tail of
@ -1412,7 +1420,9 @@ tcp_rexmit_rto(struct tcp_pcb *pcb)
pcb->unacked = NULL; pcb->unacked = NULL;
/* increment number of retransmissions */ /* increment number of retransmissions */
++pcb->nrtx; if (pcb->nrtx < 0xFF) {
++pcb->nrtx;
}
/* Don't take any RTT measurements after retransmitting. */ /* Don't take any RTT measurements after retransmitting. */
pcb->rttest = 0; pcb->rttest = 0;
@ -1457,7 +1467,9 @@ tcp_rexmit(struct tcp_pcb *pcb)
} }
#endif /* TCP_OVERSIZE */ #endif /* TCP_OVERSIZE */
++pcb->nrtx; if (pcb->nrtx < 0xFF) {
++pcb->nrtx;
}
/* Don't take any rtt measurements after retransmitting. */ /* Don't take any rtt measurements after retransmitting. */
pcb->rttest = 0; pcb->rttest = 0;
@ -1488,11 +1500,7 @@ tcp_rexmit_fast(struct tcp_pcb *pcb)
/* Set ssthresh to half of the minimum of the current /* Set ssthresh to half of the minimum of the current
* cwnd and the advertised window */ * cwnd and the advertised window */
if (pcb->cwnd > pcb->snd_wnd) { pcb->ssthresh = LWIP_MIN(pcb->cwnd, pcb->snd_wnd) / 2;
pcb->ssthresh = pcb->snd_wnd / 2;
} else {
pcb->ssthresh = pcb->cwnd / 2;
}
/* The minimum value for ssthresh should be 2 MSS */ /* The minimum value for ssthresh should be 2 MSS */
if (pcb->ssthresh < (2U * pcb->mss)) { if (pcb->ssthresh < (2U * pcb->mss)) {

View File

@ -892,7 +892,7 @@ udp_bind(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port)
#endif /* LWIP_IPV4 */ #endif /* LWIP_IPV4 */
/* still need to check for ipaddr == NULL in IPv6 only case */ /* still need to check for ipaddr == NULL in IPv6 only case */
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) { if ((pcb == NULL) || (ipaddr == NULL)) {
return ERR_VAL; return ERR_VAL;
} }
@ -982,7 +982,7 @@ udp_connect(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port)
{ {
struct udp_pcb *ipcb; struct udp_pcb *ipcb;
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) { if ((pcb == NULL) || (ipaddr == NULL)) {
return ERR_VAL; return ERR_VAL;
} }

View File

@ -39,8 +39,9 @@
#include "lwip/apps/mqtt_opts.h" #include "lwip/apps/mqtt_opts.h"
#include "lwip/err.h" #include "lwip/err.h"
#include "lwip/ip_addr.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -236,7 +237,7 @@ err_t mqtt_sub_unsub(mqtt_client_t *client, const char *topic, u8_t qos, mqtt_re
err_t mqtt_publish(mqtt_client_t *client, const char *topic, const void *payload, u16_t payload_length, u8_t qos, u8_t retain, err_t mqtt_publish(mqtt_client_t *client, const char *topic, const void *payload, u16_t payload_length, u8_t qos, u8_t retain,
mqtt_request_cb_t cb, void *arg); mqtt_request_cb_t cb, void *arg);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -66,7 +66,7 @@
#endif #endif
/** Define random number generator function of your system */ /** Define random number generator function of your system */
#ifndef LWIP_RAND #ifdef __DOXYGEN__
#define LWIP_RAND() ((u32_t)rand()) #define LWIP_RAND() ((u32_t)rand())
#endif #endif
@ -76,7 +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
#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0) #define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0)
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#endif #endif
@ -162,6 +162,19 @@ typedef uintptr_t mem_ptr_t;
#endif #endif
#endif #endif
/** Define this to 1 in arch/cc.h of your port if your compiler does not provide
* the limits.h header. You need to define the type limits yourself in this case
* (e.g. INT_MAX).
*/
#ifndef LWIP_NO_LIMITS_H
#define LWIP_NO_LIMITS_H 0
#endif
/* Include limits.h? */
#if !LWIP_NO_LIMITS_H
#include <limits.h>
#endif
/** C++ const_cast<target_type>(val) equivalent to remove constness from a value (GCC -Wcast-qual) */ /** C++ const_cast<target_type>(val) equivalent to remove constness from a value (GCC -Wcast-qual) */
#ifndef LWIP_CONST_CAST #ifndef LWIP_CONST_CAST
#define LWIP_CONST_CAST(target_type, val) ((target_type)((ptrdiff_t)val)) #define LWIP_CONST_CAST(target_type, val) ((target_type)((ptrdiff_t)val))

View File

@ -76,6 +76,7 @@ struct local_hostlist_entry {
ip_addr_t addr; ip_addr_t addr;
struct local_hostlist_entry *next; struct local_hostlist_entry *next;
}; };
#define DNS_LOCAL_HOSTLIST_ELEM(name, addr_init) {name, addr_init, NULL}
#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
#ifndef DNS_LOCAL_HOSTLIST_MAX_NAMELEN #ifndef DNS_LOCAL_HOSTLIST_MAX_NAMELEN
#define DNS_LOCAL_HOSTLIST_MAX_NAMELEN DNS_MAX_NAME_LENGTH #define DNS_LOCAL_HOSTLIST_MAX_NAMELEN DNS_MAX_NAME_LENGTH
@ -111,10 +112,14 @@ err_t dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *add
u8_t dns_addrtype); u8_t dns_addrtype);
#if DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC #if DNS_LOCAL_HOSTLIST
size_t dns_local_iterate(dns_found_callback iterator_fn, void *iterator_arg);
err_t dns_local_lookup(const char *hostname, ip_addr_t *addr, u8_t dns_addrtype);
#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
int dns_local_removehost(const char *hostname, const ip_addr_t *addr); int dns_local_removehost(const char *hostname, const ip_addr_t *addr);
err_t dns_local_addhost(const char *hostname, const ip_addr_t *addr); err_t dns_local_addhost(const char *hostname, const ip_addr_t *addr);
#endif /* DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ #endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
#endif /* DNS_LOCAL_HOSTLIST */
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -69,7 +69,7 @@ enum icmp_dur_type {
/** ICMP time exceeded codes */ /** ICMP time exceeded codes */
enum icmp_te_type { enum icmp_te_type {
/* time to live exceeded in transit */ /** time to live exceeded in transit */
ICMP_TE_TTL = 0, ICMP_TE_TTL = 0,
/** fragment reassembly time exceeded */ /** fragment reassembly time exceeded */
ICMP_TE_FRAG = 1 ICMP_TE_FRAG = 1

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 1 #define LWIP_VERSION_REVISION 2
/** 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

@ -159,7 +159,7 @@ typedef struct ip6_addr ip6_addr_t;
#define ip6_addr_isuniquelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xfe000000UL)) == PP_HTONL(0xfc000000UL)) #define ip6_addr_isuniquelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xfe000000UL)) == PP_HTONL(0xfc000000UL))
#define ip6_addr_isipv6mappedipv4(ip6addr) (((ip6addr)->addr[0] == 0) && ((ip6addr)->addr[1] == 0) && (((ip6addr)->addr[2]) == PP_HTONL(0x0000FFFFUL))) #define ip6_addr_isipv4mappedipv6(ip6addr) (((ip6addr)->addr[0] == 0) && ((ip6addr)->addr[1] == 0) && (((ip6addr)->addr[2]) == PP_HTONL(0x0000FFFFUL)))
#define ip6_addr_ismulticast(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL)) #define ip6_addr_ismulticast(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL))
#define ip6_addr_multicast_transient_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00100000UL)) #define ip6_addr_multicast_transient_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00100000UL))

View File

@ -222,14 +222,14 @@ int ipaddr_aton(const char *cp, ip_addr_t *addr);
#define IPADDR_STRLEN_MAX IP6ADDR_STRLEN_MAX #define IPADDR_STRLEN_MAX IP6ADDR_STRLEN_MAX
/** @ingroup ipaddr */ /** @ingroup ipaddr */
#define ip4_2_ipv6_mapped_ipv4(ip6addr, ip4addr) do { \ #define ip4_2_ipv4_mapped_ipv6(ip6addr, ip4addr) do { \
(ip6addr)->addr[3] = (ip4addr)->addr; \ (ip6addr)->addr[3] = (ip4addr)->addr; \
(ip6addr)->addr[2] = PP_HTONL(0x0000FFFFUL); \ (ip6addr)->addr[2] = PP_HTONL(0x0000FFFFUL); \
(ip6addr)->addr[1] = 0; \ (ip6addr)->addr[1] = 0; \
(ip6addr)->addr[0] = 0; } while(0); (ip6addr)->addr[0] = 0; } while(0);
/** @ingroup ipaddr */ /** @ingroup ipaddr */
#define unmap_ipv6_mapped_ipv4(ip4addr, ip6addr) \ #define unmap_ipv4_mapped_ipv6(ip4addr, ip6addr) \
(ip4addr)->addr = (ip6addr)->addr[3]; (ip4addr)->addr = (ip6addr)->addr[3];
#define IP46_ADDR_ANY(type) (((type) == IPADDR_TYPE_V6)? IP6_ADDR_ANY : IP4_ADDR_ANY) #define IP46_ADDR_ANY(type) (((type) == IPADDR_TYPE_V6)? IP6_ADDR_ANY : IP4_ADDR_ANY)

View File

@ -1047,11 +1047,9 @@
#define LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING 2 #define LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING 2
#define LWIP_DNS_SECURE_RAND_SRC_PORT 4 #define LWIP_DNS_SECURE_RAND_SRC_PORT 4
/** DNS_LOCAL_HOSTLIST: Implements a local host-to-address list. If enabled, /** DNS_LOCAL_HOSTLIST: Implements a local host-to-address list. If enabled, you have to define an initializer:
* you have to define * \#define DNS_LOCAL_HOSTLIST_INIT {DNS_LOCAL_HOSTLIST_ELEM("host_ip4", IPADDR4_INIT_BYTES(1,2,3,4)), \
* \#define DNS_LOCAL_HOSTLIST_INIT {{"host1", 0x123}, {"host2", 0x234}} * DNS_LOCAL_HOSTLIST_ELEM("host_ip6", IPADDR6_INIT_HOST(123, 234, 345, 456)}
* (an array of structs name/address, where address is an u32_t in network
* byte order).
* *
* Instead, you can also use an external function: * Instead, you can also use an external function:
* \#define DNS_LOOKUP_LOCAL_EXTERN(x) extern err_t my_lookup_function(const char *name, ip_addr_t *addr, u8_t dns_addrtype) * \#define DNS_LOOKUP_LOCAL_EXTERN(x) extern err_t my_lookup_function(const char *name, ip_addr_t *addr, u8_t dns_addrtype)
@ -2415,6 +2413,15 @@
* @{ * @{
*/ */
/**
* LWIP_HOOK_FILENAME: Custom filename to #include in files that provide hooks.
* Declare your hook function prototypes in there, you may also #include all headers
* providing data types that are need in this file.
*/
#ifdef __DOXYGEN__
#define LWIP_HOOK_FILENAME "path/to/my/lwip_hooks.h"
#endif
/** /**
* LWIP_HOOK_TCP_ISN: * LWIP_HOOK_TCP_ISN:
* Hook for generation of the Initial Sequence Number (ISN) for a new TCP * Hook for generation of the Initial Sequence Number (ISN) for a new TCP

View File

@ -170,16 +170,18 @@ err_t tcp_process_refused_data(struct tcp_pcb *pcb);
LWIP_EVENT_RECV, NULL, 0, ERR_OK) LWIP_EVENT_RECV, NULL, 0, ERR_OK)
#define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ #define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
LWIP_EVENT_CONNECTED, NULL, 0, (err)) LWIP_EVENT_CONNECTED, NULL, 0, (err))
#define TCP_EVENT_POLL(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ #define TCP_EVENT_POLL(pcb,ret) do { if ((pcb)->state != SYN_RCVD) { \
LWIP_EVENT_POLL, NULL, 0, ERR_OK) ret = lwip_tcp_event((pcb)->callback_arg, (pcb), LWIP_EVENT_POLL, NULL, 0, ERR_OK); \
#define TCP_EVENT_ERR(errf,arg,err) lwip_tcp_event((arg), NULL, \ } else { \
LWIP_EVENT_ERR, NULL, 0, (err)) ret = ERR_ARG; } } while(0)
#define TCP_EVENT_ERR(last_state,errf,arg,err) do { if (last_state != SYN_RCVD) { \
lwip_tcp_event((arg), NULL, LWIP_EVENT_ERR, NULL, 0, (err)); } } while(0)
#else /* LWIP_EVENT_API */ #else /* LWIP_EVENT_API */
#define TCP_EVENT_ACCEPT(lpcb,pcb,arg,err,ret) \ #define TCP_EVENT_ACCEPT(lpcb,pcb,arg,err,ret) \
do { \ do { \
if((lpcb != NULL) && ((lpcb)->accept != NULL)) \ if((lpcb)->accept != NULL) \
(ret) = (lpcb)->accept((arg),(pcb),(err)); \ (ret) = (lpcb)->accept((arg),(pcb),(err)); \
else (ret) = ERR_ARG; \ else (ret) = ERR_ARG; \
} while (0) } while (0)
@ -223,8 +225,9 @@ err_t tcp_process_refused_data(struct tcp_pcb *pcb);
else (ret) = ERR_OK; \ else (ret) = ERR_OK; \
} while (0) } while (0)
#define TCP_EVENT_ERR(errf,arg,err) \ #define TCP_EVENT_ERR(last_state,errf,arg,err) \
do { \ do { \
LWIP_UNUSED_ARG(last_state); \
if((errf) != NULL) \ if((errf) != NULL) \
(errf)((arg),(err)); \ (errf)((arg),(err)); \
} while (0) } while (0)
@ -249,7 +252,7 @@ struct tcp_seg {
#if TCP_OVERSIZE_DBGCHECK #if TCP_OVERSIZE_DBGCHECK
u16_t oversize_left; /* Extra bytes available at the end of the last u16_t oversize_left; /* Extra bytes available at the end of the last
pbuf in unsent (used for asserting vs. pbuf in unsent (used for asserting vs.
tcp_pcb.unsent_oversized only) */ tcp_pcb.unsent_oversize only) */
#endif /* TCP_OVERSIZE_DBGCHECK */ #endif /* TCP_OVERSIZE_DBGCHECK */
#if TCP_CHECKSUM_ON_COPY #if TCP_CHECKSUM_ON_COPY
u16_t chksum; u16_t chksum;

View File

@ -46,7 +46,7 @@
#include "lwip/ip_addr.h" #include "lwip/ip_addr.h"
#include "lwip/err.h" #include "lwip/err.h"
#include "lwip/inet.h" #include "lwip/inet.h"
#include "lwip/errno.h" #include "lwip/lwip_errno.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@ -145,7 +145,7 @@ typedef u32_t tcpwnd_size_t;
typedef u16_t tcpwnd_size_t; typedef u16_t tcpwnd_size_t;
#endif #endif
#if LWIP_WND_SCALE || TCP_LISTEN_BACKLOG #if LWIP_WND_SCALE || TCP_LISTEN_BACKLOG || LWIP_TCP_TIMESTAMPS
typedef u16_t tcpflags_t; typedef u16_t tcpflags_t;
#else #else
typedef u8_t tcpflags_t; typedef u8_t tcpflags_t;
@ -210,7 +210,7 @@ struct tcp_pcb {
#define TF_ACK_DELAY 0x01U /* Delayed ACK. */ #define TF_ACK_DELAY 0x01U /* Delayed ACK. */
#define TF_ACK_NOW 0x02U /* Immediate ACK. */ #define TF_ACK_NOW 0x02U /* Immediate ACK. */
#define TF_INFR 0x04U /* In fast recovery. */ #define TF_INFR 0x04U /* In fast recovery. */
#define TF_TIMESTAMP 0x08U /* Timestamp option enabled */ #define TF_CLOSEPEND 0x08U /* If this is set, tcp_close failed to enqueue the FIN (retried in tcp_tmr) */
#define TF_RXCLOSED 0x10U /* rx closed by tcp_shutdown */ #define TF_RXCLOSED 0x10U /* rx closed by tcp_shutdown */
#define TF_FIN 0x20U /* Connection was closed locally (FIN segment enqueued). */ #define TF_FIN 0x20U /* Connection was closed locally (FIN segment enqueued). */
#define TF_NODELAY 0x40U /* Disable Nagle algorithm */ #define TF_NODELAY 0x40U /* Disable Nagle algorithm */
@ -220,6 +220,9 @@ struct tcp_pcb {
#endif #endif
#if TCP_LISTEN_BACKLOG #if TCP_LISTEN_BACKLOG
#define TF_BACKLOGPEND 0x0200U /* If this is set, a connection pcb has increased the backlog on its listener */ #define TF_BACKLOGPEND 0x0200U /* If this is set, a connection pcb has increased the backlog on its listener */
#endif
#if LWIP_TCP_TIMESTAMPS
#define TF_TIMESTAMP 0x0400U /* Timestamp option enabled */
#endif #endif
/* the rest of the fields are in host byte order /* the rest of the fields are in host byte order
@ -358,7 +361,11 @@ void tcp_accept (struct tcp_pcb *pcb, tcp_accept_fn accept);
#endif /* LWIP_CALLBACK_API */ #endif /* LWIP_CALLBACK_API */
void tcp_poll (struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval); void tcp_poll (struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval);
#if LWIP_TCP_TIMESTAMPS
#define tcp_mss(pcb) (((pcb)->flags & TF_TIMESTAMP) ? ((pcb)->mss - 12) : (pcb)->mss) #define tcp_mss(pcb) (((pcb)->flags & TF_TIMESTAMP) ? ((pcb)->mss - 12) : (pcb)->mss)
#else /* LWIP_TCP_TIMESTAMPS */
#define tcp_mss(pcb) ((pcb)->mss)
#endif /* LWIP_TCP_TIMESTAMPS */
#define tcp_sndbuf(pcb) (TCPWND16((pcb)->snd_buf)) #define tcp_sndbuf(pcb) (TCPWND16((pcb)->snd_buf))
#define tcp_sndqueuelen(pcb) ((pcb)->snd_queuelen) #define tcp_sndqueuelen(pcb) ((pcb)->snd_queuelen)
/** @ingroup tcp_raw */ /** @ingroup tcp_raw */

View File

@ -138,10 +138,10 @@
*/ */
struct link_callbacks { struct link_callbacks {
/* Start a connection (e.g. Initiate discovery phase) */ /* Start a connection (e.g. Initiate discovery phase) */
err_t (*connect) (ppp_pcb *pcb, void *ctx); void (*connect) (ppp_pcb *pcb, void *ctx);
#if PPP_SERVER #if PPP_SERVER
/* Listen for an incoming connection (Passive mode) */ /* Listen for an incoming connection (Passive mode) */
err_t (*listen) (ppp_pcb *pcb, void *ctx); void (*listen) (ppp_pcb *pcb, void *ctx);
#endif /* PPP_SERVER */ #endif /* PPP_SERVER */
/* End a connection (i.e. initiate disconnect phase) */ /* End a connection (i.e. initiate disconnect phase) */
void (*disconnect) (ppp_pcb *pcb, void *ctx); void (*disconnect) (ppp_pcb *pcb, void *ctx);

View File

@ -30,4 +30,4 @@
* *
*/ */
#include "lwip/errno.h" #include "lwip/lwip_errno.h"

View File

@ -56,6 +56,10 @@
#include "netif/ppp/pppoe.h" #include "netif/ppp/pppoe.h"
#endif /* PPPOE_SUPPORT */ #endif /* PPPOE_SUPPORT */
#ifdef LWIP_HOOK_FILENAME
#include LWIP_HOOK_FILENAME
#endif
const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}}; const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
const struct eth_addr ethzero = {{0,0,0,0,0,0}}; const struct eth_addr ethzero = {{0,0,0,0,0,0}};

View File

@ -275,8 +275,8 @@ err_t ppp_connect(ppp_pcb *pcb, u16_t holdoff) {
PPPDEBUG(LOG_DEBUG, ("ppp_connect[%d]: holdoff=%d\n", pcb->netif->num, holdoff)); PPPDEBUG(LOG_DEBUG, ("ppp_connect[%d]: holdoff=%d\n", pcb->netif->num, holdoff));
if (holdoff == 0) { if (holdoff == 0) {
new_phase(pcb, PPP_PHASE_INITIALIZE); ppp_do_connect(pcb);
return pcb->link_cb->connect(pcb, pcb->link_ctx_cb); return ERR_OK;
} }
new_phase(pcb, PPP_PHASE_HOLDOFF); new_phase(pcb, PPP_PHASE_HOLDOFF);
@ -302,7 +302,8 @@ err_t ppp_listen(ppp_pcb *pcb) {
if (pcb->link_cb->listen) { if (pcb->link_cb->listen) {
new_phase(pcb, PPP_PHASE_INITIALIZE); new_phase(pcb, PPP_PHASE_INITIALIZE);
return pcb->link_cb->listen(pcb, pcb->link_ctx_cb); pcb->link_cb->listen(pcb, pcb->link_ctx_cb);
return ERR_OK;
} }
return ERR_IF; return ERR_IF;
} }

View File

@ -119,7 +119,7 @@ LWIP_MEMPOOL_DECLARE(PPPOE_IF, MEMP_NUM_PPPOE_INTERFACES, sizeof(struct pppoe_so
/* callbacks called from PPP core */ /* callbacks called from PPP core */
static err_t pppoe_write(ppp_pcb *ppp, void *ctx, struct pbuf *p); static err_t pppoe_write(ppp_pcb *ppp, void *ctx, struct pbuf *p);
static err_t pppoe_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol); static err_t pppoe_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol);
static err_t pppoe_connect(ppp_pcb *ppp, void *ctx); static void pppoe_connect(ppp_pcb *ppp, void *ctx);
static void pppoe_disconnect(ppp_pcb *ppp, void *ctx); static void pppoe_disconnect(ppp_pcb *ppp, void *ctx);
static err_t pppoe_destroy(ppp_pcb *ppp, void *ctx); static err_t pppoe_destroy(ppp_pcb *ppp, void *ctx);
@ -879,7 +879,7 @@ pppoe_timeout(void *arg)
} }
/* Start a connection (i.e. initiate discovery phase) */ /* Start a connection (i.e. initiate discovery phase) */
static err_t static void
pppoe_connect(ppp_pcb *ppp, void *ctx) pppoe_connect(ppp_pcb *ppp, void *ctx)
{ {
err_t err; err_t err;
@ -934,7 +934,6 @@ pppoe_connect(ppp_pcb *ppp, void *ctx)
PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err));
} }
sys_timeout(PPPOE_DISC_TIMEOUT, pppoe_timeout, sc); sys_timeout(PPPOE_DISC_TIMEOUT, pppoe_timeout, sc);
return err;
} }
/* disconnect */ /* disconnect */

View File

@ -73,7 +73,7 @@ LWIP_MEMPOOL_DECLARE(PPPOL2TP_PCB, MEMP_NUM_PPPOL2TP_INTERFACES, sizeof(pppol2tp
static err_t pppol2tp_write(ppp_pcb *ppp, void *ctx, struct pbuf *p); static err_t pppol2tp_write(ppp_pcb *ppp, void *ctx, struct pbuf *p);
static err_t pppol2tp_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol); static err_t pppol2tp_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol);
static err_t pppol2tp_destroy(ppp_pcb *ppp, void *ctx); /* Destroy a L2TP control block */ static err_t pppol2tp_destroy(ppp_pcb *ppp, void *ctx); /* Destroy a L2TP control block */
static err_t pppol2tp_connect(ppp_pcb *ppp, void *ctx); /* Be a LAC, connect to a LNS. */ static void pppol2tp_connect(ppp_pcb *ppp, void *ctx); /* Be a LAC, connect to a LNS. */
static void pppol2tp_disconnect(ppp_pcb *ppp, void *ctx); /* Disconnect */ static void pppol2tp_disconnect(ppp_pcb *ppp, void *ctx); /* Disconnect */
/* Prototypes for procedures local to this file. */ /* Prototypes for procedures local to this file. */
@ -255,7 +255,7 @@ static err_t pppol2tp_destroy(ppp_pcb *ppp, void *ctx) {
} }
/* Be a LAC, connect to a LNS. */ /* Be a LAC, connect to a LNS. */
static err_t pppol2tp_connect(ppp_pcb *ppp, void *ctx) { static void pppol2tp_connect(ppp_pcb *ppp, void *ctx) {
err_t err; err_t err;
pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx;
lcp_options *lcp_wo; lcp_options *lcp_wo;
@ -326,7 +326,6 @@ static err_t pppol2tp_connect(ppp_pcb *ppp, void *ctx) {
PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCRQ, error=%d\n", err)); PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCRQ, error=%d\n", err));
} }
sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp);
return err;
} }
/* Disconnect */ /* Disconnect */

View File

@ -57,9 +57,9 @@ LWIP_MEMPOOL_DECLARE(PPPOS_PCB, MEMP_NUM_PPPOS_INTERFACES, sizeof(pppos_pcb), "P
/* callbacks called from PPP core */ /* callbacks called from PPP core */
static err_t pppos_write(ppp_pcb *ppp, void *ctx, struct pbuf *p); static err_t pppos_write(ppp_pcb *ppp, void *ctx, struct pbuf *p);
static err_t pppos_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *pb, u16_t protocol); static err_t pppos_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *pb, u16_t protocol);
static err_t pppos_connect(ppp_pcb *ppp, void *ctx); static void pppos_connect(ppp_pcb *ppp, void *ctx);
#if PPP_SERVER #if PPP_SERVER
static err_t pppos_listen(ppp_pcb *ppp, void *ctx); static void pppos_listen(ppp_pcb *ppp, void *ctx);
#endif /* PPP_SERVER */ #endif /* PPP_SERVER */
static void pppos_disconnect(ppp_pcb *ppp, void *ctx); static void pppos_disconnect(ppp_pcb *ppp, void *ctx);
static err_t pppos_destroy(ppp_pcb *ppp, void *ctx); static err_t pppos_destroy(ppp_pcb *ppp, void *ctx);
@ -298,7 +298,7 @@ pppos_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *pb, u16_t protocol)
return err; return err;
} }
static err_t static void
pppos_connect(ppp_pcb *ppp, void *ctx) pppos_connect(ppp_pcb *ppp, void *ctx)
{ {
pppos_pcb *pppos = (pppos_pcb *)ctx; pppos_pcb *pppos = (pppos_pcb *)ctx;
@ -327,11 +327,10 @@ pppos_connect(ppp_pcb *ppp, void *ctx)
*/ */
PPPDEBUG(LOG_INFO, ("pppos_connect: unit %d: connecting\n", ppp->netif->num)); PPPDEBUG(LOG_INFO, ("pppos_connect: unit %d: connecting\n", ppp->netif->num));
ppp_start(ppp); /* notify upper layers */ ppp_start(ppp); /* notify upper layers */
return ERR_OK;
} }
#if PPP_SERVER #if PPP_SERVER
static err_t static void
pppos_listen(ppp_pcb *ppp, void *ctx) pppos_listen(ppp_pcb *ppp, void *ctx)
{ {
pppos_pcb *pppos = (pppos_pcb *)ctx; pppos_pcb *pppos = (pppos_pcb *)ctx;
@ -360,7 +359,6 @@ pppos_listen(ppp_pcb *ppp, void *ctx)
*/ */
PPPDEBUG(LOG_INFO, ("pppos_listen: unit %d: listening\n", ppp->netif->num)); PPPDEBUG(LOG_INFO, ("pppos_listen: unit %d: listening\n", ppp->netif->num));
ppp_start(ppp); /* notify upper layers */ ppp_start(ppp); /* notify upper layers */
return ERR_OK;
} }
#endif /* PPP_SERVER */ #endif /* PPP_SERVER */

View File

@ -155,19 +155,19 @@ tcp_set_state(struct tcp_pcb* pcb, enum tcp_state state, ip_addr_t* local_ip,
if (state == ESTABLISHED) { if (state == ESTABLISHED) {
TCP_REG(&tcp_active_pcbs, pcb); TCP_REG(&tcp_active_pcbs, pcb);
pcb->local_ip.addr = local_ip->addr; ip_addr_copy(pcb->local_ip, *local_ip);
pcb->local_port = local_port; pcb->local_port = local_port;
pcb->remote_ip.addr = remote_ip->addr; ip_addr_copy(pcb->remote_ip, *remote_ip);
pcb->remote_port = remote_port; pcb->remote_port = remote_port;
} else if(state == LISTEN) { } else if(state == LISTEN) {
TCP_REG(&tcp_listen_pcbs.pcbs, pcb); TCP_REG(&tcp_listen_pcbs.pcbs, pcb);
pcb->local_ip.addr = local_ip->addr; ip_addr_copy(pcb->local_ip, *local_ip);
pcb->local_port = local_port; pcb->local_port = local_port;
} else if(state == TIME_WAIT) { } else if(state == TIME_WAIT) {
TCP_REG(&tcp_tw_pcbs, pcb); TCP_REG(&tcp_tw_pcbs, pcb);
pcb->local_ip.addr = local_ip->addr; ip_addr_copy(pcb->local_ip, *local_ip);
pcb->local_port = local_port; pcb->local_port = local_port;
pcb->remote_ip.addr = remote_ip->addr; ip_addr_copy(pcb->remote_ip, *remote_ip);
pcb->remote_port = remote_port; pcb->remote_port = remote_port;
} else { } else {
fail(); fail();
@ -302,8 +302,8 @@ void test_tcp_init_netif(struct netif *netif, struct test_tcp_txcounters *txcoun
} }
netif->output = test_tcp_netif_output; netif->output = test_tcp_netif_output;
netif->flags |= NETIF_FLAG_UP | NETIF_FLAG_LINK_UP; netif->flags |= NETIF_FLAG_UP | NETIF_FLAG_LINK_UP;
ip4_addr_copy(netif->netmask, *ip_2_ip4(netmask)); ip_addr_copy_from_ip4(netif->netmask, *ip_2_ip4(netmask));
ip4_addr_copy(netif->ip_addr, *ip_2_ip4(ip_addr)); ip_addr_copy_from_ip4(netif->ip_addr, *ip_2_ip4(ip_addr));
for (n = netif_list; n != NULL; n = n->next) { for (n = netif_list; n != NULL; n = n->next) {
if (n == netif) { if (n == netif) {
return; return;

View File

@ -46,9 +46,9 @@ tcp_setup(void)
static void static void
tcp_teardown(void) tcp_teardown(void)
{ {
tcp_remove_all();
netif_list = NULL; netif_list = NULL;
netif_default = NULL; netif_default = NULL;
tcp_remove_all();
} }
@ -422,6 +422,8 @@ START_TEST(test_tcp_fast_rexmit_wraparound)
pcb->mss = TCP_MSS; pcb->mss = TCP_MSS;
/* disable initial congestion window (we don't send a SYN here...) */ /* disable initial congestion window (we don't send a SYN here...) */
pcb->cwnd = 2*TCP_MSS; pcb->cwnd = 2*TCP_MSS;
/* start in congestion advoidance */
pcb->ssthresh = pcb->cwnd;
/* send 6 mss-sized segments */ /* send 6 mss-sized segments */
for (i = 0; i < 6; i++) { for (i = 0; i < 6; i++) {
@ -442,7 +444,9 @@ START_TEST(test_tcp_fast_rexmit_wraparound)
/* ACK the first segment */ /* ACK the first segment */
p = tcp_create_rx_segment(pcb, NULL, 0, 0, TCP_MSS, TCP_ACK); p = tcp_create_rx_segment(pcb, NULL, 0, 0, TCP_MSS, TCP_ACK);
test_tcp_input(p, &netif); test_tcp_input(p, &netif);
/* ensure this didn't trigger a retransmission */ /* ensure this didn't trigger a retransmission. Only one
segment should be transmitted because cwnd opened up by
TCP_MSS and a fraction since we are in congestion avoidance */
EXPECT(txcounters.num_tx_calls == 1); EXPECT(txcounters.num_tx_calls == 1);
EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U); EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U);
memset(&txcounters, 0, sizeof(txcounters)); memset(&txcounters, 0, sizeof(txcounters));