Compare commits
95 Commits
master
...
STABLE-2_0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
92f23d6ca0 | ||
|
|
750c9a750b | ||
|
|
8244fb523c | ||
|
|
a13c488e52 | ||
|
|
e8a3d42e2d | ||
|
|
66120f7d79 | ||
|
|
1d04b06450 | ||
|
|
c51e6fbb12 | ||
|
|
9b19266e3d | ||
|
|
a2ac9b045a | ||
|
|
737ed228c9 | ||
|
|
82e5a18b50 | ||
|
|
ac880ea907 | ||
|
|
32aa50cfbc | ||
|
|
e6fa613633 | ||
|
|
c6b19cad34 | ||
|
|
f389d78f7e | ||
|
|
dced7dad41 | ||
|
|
56a295f0a0 | ||
|
|
aecb1b9eb0 | ||
|
|
dbb3b3a3a1 | ||
|
|
77c12bb124 | ||
|
|
0623dc4038 | ||
|
|
f5438b1b43 | ||
|
|
1cf9fc0d39 | ||
|
|
f9872c519c | ||
|
|
a4017a485c | ||
|
|
2490d034cd | ||
|
|
282e85763b | ||
|
|
c0862d6074 | ||
|
|
ea2f6fb57c | ||
|
|
b307fea1b9 | ||
|
|
c31bd404e2 | ||
|
|
0381849624 | ||
|
|
19d56b4096 | ||
|
|
66db517a28 | ||
|
|
2452bc9336 | ||
|
|
2848b17e80 | ||
|
|
c71c9882c2 | ||
|
|
40fbd6bc24 | ||
|
|
df7485de1c | ||
|
|
fe6e1bd4af | ||
|
|
168fa1c38a | ||
|
|
f0975b3c59 | ||
|
|
563932b888 | ||
|
|
8849a443a4 | ||
|
|
e318688195 | ||
|
|
fa8b6a92b4 | ||
|
|
2ca39c275a | ||
|
|
4d1d567ab7 | ||
|
|
8927cda2f8 | ||
|
|
bc78251f4a | ||
|
|
0a3e4cd10e | ||
|
|
76efa271e6 | ||
|
|
b3293d903e | ||
|
|
5ef8a3cb60 | ||
|
|
01c2e43c5c | ||
|
|
0b7bef5420 | ||
|
|
3c4aec99a4 | ||
|
|
dc38e21a70 | ||
|
|
d471e5f89e | ||
|
|
99ef13f2be | ||
|
|
bb2b2be454 | ||
|
|
faa7a21a83 | ||
|
|
d6e8e05edd | ||
|
|
0b299f96e9 | ||
|
|
777d54f0e4 | ||
|
|
8c6ac8eb59 | ||
|
|
4fc3770278 | ||
|
|
e53c84654e | ||
|
|
d0b0cf983e | ||
|
|
90d68b41df | ||
|
|
e6756387b0 | ||
|
|
4fe1436904 | ||
|
|
1fdbda9700 | ||
|
|
fed15778dd | ||
|
|
bbe91e356f | ||
|
|
0a73e0ff30 | ||
|
|
7ba2633ef0 | ||
|
|
d860dd7655 | ||
|
|
2694486309 | ||
|
|
cb97e27120 | ||
|
|
890c5982a1 | ||
|
|
4deaebae44 | ||
|
|
5fe195c3d3 | ||
|
|
e5071daf45 | ||
|
|
980b219c28 | ||
|
|
76b4365aaa | ||
|
|
a5a4830b16 | ||
|
|
1a2a9a4e96 | ||
|
|
216bf89491 | ||
|
|
a68eddbd47 | ||
|
|
fd096a5769 | ||
|
|
15b75555a6 | ||
|
|
33955c636d |
103
CHANGELOG
103
CHANGELOG
@@ -3,13 +3,110 @@ HISTORY
|
||||
(git master)
|
||||
|
||||
* [Enter new changes just after this line - do not remove this line]
|
||||
|
||||
|
||||
(STABLE-2.0.3)
|
||||
|
||||
++ Bugfixes:
|
||||
|
||||
2017-09-11: Simon Goldschmidt
|
||||
* tcp_in.c: fix bug #51937 (leaking tcp_pcbs on passive close with unacked data)
|
||||
|
||||
2017-08-02: Abroz Bizjak/Simon Goldschmidt
|
||||
* multiple fixes in IPv4 reassembly (leading to corrupted datagrams received)
|
||||
|
||||
2017-03-30: Simon Goldschmidt
|
||||
* dhcp.c: return ERR_VAL instead of asserting on offset-out-of-pbuf
|
||||
|
||||
2017-03-23: Dirk Ziegelmeier
|
||||
* dhcp.h: fix bug #50618 (dhcp_remove_struct() macro does not work)
|
||||
|
||||
(STABLE-2.0.2)
|
||||
|
||||
++ New features:
|
||||
|
||||
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.
|
||||
|
||||
2017-02-10: Simon Goldschmidt
|
||||
* tcp_close does not fail on memory error (instead, FIN is sent from tcp_tmr)
|
||||
|
||||
++ 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:
|
||||
|
||||
2016-12-31: Simon Goldschmidt
|
||||
* tcp.h/.c: added function tcp_listen_with_backlog_and_err() to get the error
|
||||
reason when listening fails (bug #49861)
|
||||
|
||||
2016-12-20: Erik Andersen
|
||||
* Add MQTT client
|
||||
|
||||
2016-12-14: Jan Breuer:
|
||||
* opt.h, ndc.h/.c: add support for RDNSS option (as per RFC 6106)
|
||||
|
||||
@@ -40,7 +137,7 @@ HISTORY
|
||||
|
||||
2016-12-05: Dirk Ziegelmeier
|
||||
* fixed compiling with IPv4 disabled (IPv6 only case)
|
||||
|
||||
|
||||
2016-11-28: Simon Goldschmidt
|
||||
* api_lib.c: fixed bug #49725 (send-timeout: netconn_write() can return
|
||||
ERR_OK without all bytes being written)
|
||||
@@ -69,7 +166,7 @@ HISTORY
|
||||
2016-11-11: Dirk Ziegelmeier
|
||||
* sockets.c: fixed bug #49578 (dropping multicast membership does not work
|
||||
with LWIP_SOCKET_OFFSET)
|
||||
|
||||
|
||||
(STABLE-2.0.0)
|
||||
|
||||
++ New features:
|
||||
|
||||
10
UPGRADING
10
UPGRADING
@@ -8,6 +8,16 @@ with newer versions.
|
||||
|
||||
* [Enter new changes just after this line - do not remove this line]
|
||||
|
||||
(2.0.2)
|
||||
|
||||
++ Application changes:
|
||||
|
||||
* slipif: The way to pass serial port number has changed. netif->num is not
|
||||
supported any more, netif->state is interpreted as an u8_t port number now
|
||||
(it's not a POINTER to an u8_t any more!)
|
||||
|
||||
(2.0.1)
|
||||
|
||||
++ Application changes:
|
||||
|
||||
* UDP does NOT receive multicast traffic from ALL netifs on an UDP PCB bound to a specific
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
void eth_mac_irq()
|
||||
void
|
||||
eth_mac_irq()
|
||||
{
|
||||
/* Service MAC IRQ here */
|
||||
|
||||
@@ -17,7 +18,8 @@ void eth_mac_irq()
|
||||
}
|
||||
}
|
||||
|
||||
static err_t netif_output(struct netif *netif, struct pbuf *p)
|
||||
static err_t
|
||||
netif_output(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
LINK_STATS_INC(link.xmit);
|
||||
|
||||
@@ -38,12 +40,14 @@ static err_t netif_output(struct netif *netif, struct pbuf *p)
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static void netif_status_callback(struct netif *netif)
|
||||
static void
|
||||
netif_status_callback(struct netif *netif)
|
||||
{
|
||||
printf("netif status changed %s\n", ip4addr_ntoa(netif_ip4_addr(netif)));
|
||||
}
|
||||
|
||||
static err_t netif_init(struct netif *netif)
|
||||
static err_t
|
||||
netif_init(struct netif *netif)
|
||||
{
|
||||
netif->linkoutput = netif_output;
|
||||
netif->output = etharp_output;
|
||||
@@ -58,7 +62,8 @@ static err_t netif_init(struct netif *netif)
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void main(void)
|
||||
void
|
||||
main(void)
|
||||
{
|
||||
struct netif netif;
|
||||
|
||||
@@ -74,7 +79,7 @@ void main(void)
|
||||
netif_set_up(&netif);
|
||||
|
||||
/* Start DHCP and HTTPD */
|
||||
dhcp_init();
|
||||
dhcp_start(&netif );
|
||||
httpd_init();
|
||||
|
||||
while(1) {
|
||||
|
||||
@@ -38,7 +38,7 @@ PROJECT_NAME = "lwIP"
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = "2.0.1"
|
||||
PROJECT_NUMBER = "2.0.3"
|
||||
|
||||
# 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
|
||||
|
||||
@@ -26,6 +26,11 @@
|
||||
* @verbinclude "UPGRADING"
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page changelog Changelog
|
||||
* @verbinclude "CHANGELOG"
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page contrib How to contribute to lwIP
|
||||
* @verbinclude "contrib.txt"
|
||||
|
||||
@@ -177,14 +177,20 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
||||
LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL);
|
||||
LWIP_ASSERT("recv_udp must have an argument", arg != NULL);
|
||||
conn = (struct netconn *)arg;
|
||||
|
||||
if (conn == NULL) {
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
|
||||
LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb);
|
||||
|
||||
#if LWIP_SO_RCVBUF
|
||||
SYS_ARCH_GET(conn->recv_avail, recv_avail);
|
||||
if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox) ||
|
||||
if (!sys_mbox_valid(&conn->recvmbox) ||
|
||||
((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) {
|
||||
#else /* LWIP_SO_RCVBUF */
|
||||
if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox)) {
|
||||
if (!sys_mbox_valid(&conn->recvmbox)) {
|
||||
#endif /* LWIP_SO_RCVBUF */
|
||||
pbuf_free(p);
|
||||
return;
|
||||
@@ -471,8 +477,6 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
|
||||
struct netconn *newconn;
|
||||
struct netconn *conn = (struct netconn *)arg;
|
||||
|
||||
LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: newpcb->tate: %s\n", tcp_debug_state_str(newpcb->state)));
|
||||
|
||||
if (conn == NULL) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
@@ -490,6 +494,8 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: newpcb->tate: %s\n", tcp_debug_state_str(newpcb->state)));
|
||||
|
||||
/* We have to set the callback here even though
|
||||
* the new socket is unknown. newconn->socket is marked as -1. */
|
||||
newconn = netconn_alloc(conn->type, conn->callback);
|
||||
@@ -562,6 +568,13 @@ pcb_new(struct api_msg *msg)
|
||||
case NETCONN_RAW:
|
||||
msg->conn->pcb.raw = raw_new_ip_type(iptype, msg->msg.n.proto);
|
||||
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);
|
||||
}
|
||||
break;
|
||||
@@ -1777,25 +1790,28 @@ lwip_netconn_do_close(void *m)
|
||||
#if LWIP_NETCONN_FULLDUPLEX
|
||||
if (msg->msg.sd.shut & NETCONN_SHUT_WR) {
|
||||
/* 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);
|
||||
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 = NULL;
|
||||
msg->conn->write_offset = 0;
|
||||
msg->conn->state = NETCONN_NONE;
|
||||
state = NETCONN_NONE;
|
||||
NETCONN_SET_SAFE_ERR(msg->conn, ERR_CLSD);
|
||||
sys_sem_signal(op_completed_sem);
|
||||
sys_sem_signal(write_completed_sem);
|
||||
} else {
|
||||
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
|
||||
conn->current_msg or conn->state! */
|
||||
msg->err = tcp_shutdown(msg->conn->pcb.tcp, 1, 0);
|
||||
}
|
||||
}
|
||||
if (state == NETCONN_NONE) {
|
||||
#else /* LWIP_NETCONN_FULLDUPLEX */
|
||||
msg->err = ERR_INPROGRESS;
|
||||
#endif /* LWIP_NETCONN_FULLDUPLEX */
|
||||
} else {
|
||||
#endif /* LWIP_NETCONN_FULLDUPLEX */
|
||||
if (msg->msg.sd.shut & NETCONN_SHUT_RD) {
|
||||
/* Drain and delete mboxes */
|
||||
netconn_drain(msg->conn);
|
||||
|
||||
@@ -407,7 +407,7 @@ alloc_socket(struct netconn *newconn, int accepted)
|
||||
for (i = 0; i < NUM_SOCKETS; ++i) {
|
||||
/* Protect socket array */
|
||||
SYS_ARCH_PROTECT(lev);
|
||||
if (!sockets[i].conn) {
|
||||
if (!sockets[i].conn && (sockets[i].select_waiting == 0)) {
|
||||
sockets[i].conn = newconn;
|
||||
/* The socket is not yet known to anyone, so no need to protect
|
||||
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].errevent = 0;
|
||||
sockets[i].err = 0;
|
||||
sockets[i].select_waiting = 0;
|
||||
return i + LWIP_SOCKET_OFFSET;
|
||||
}
|
||||
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));
|
||||
|
||||
#if LWIP_IPV4 && LWIP_IPV6
|
||||
/* Dual-stack: Unmap IPv6 mapped IPv4 addresses */
|
||||
if (IP_IS_V6_VAL(local_addr) && ip6_addr_isipv6mappedipv4(ip_2_ip6(&local_addr))) {
|
||||
unmap_ipv6_mapped_ipv4(ip_2_ip4(&local_addr), ip_2_ip6(&local_addr));
|
||||
/* Dual-stack: Unmap IPv4 mapped IPv6 addresses */
|
||||
if (IP_IS_V6_VAL(local_addr) && ip6_addr_isipv4mappedipv6(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);
|
||||
}
|
||||
#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));
|
||||
|
||||
#if LWIP_IPV4 && LWIP_IPV6
|
||||
/* Dual-stack: Unmap IPv6 mapped IPv4 addresses */
|
||||
if (IP_IS_V6_VAL(remote_addr) && ip6_addr_isipv6mappedipv4(ip_2_ip6(&remote_addr))) {
|
||||
unmap_ipv6_mapped_ipv4(ip_2_ip4(&remote_addr), ip_2_ip6(&remote_addr));
|
||||
/* Dual-stack: Unmap IPv4 mapped IPv6 addresses */
|
||||
if (IP_IS_V6_VAL(remote_addr) && ip6_addr_isipv4mappedipv6(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);
|
||||
}
|
||||
#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
|
||||
/* 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)) {
|
||||
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);
|
||||
}
|
||||
#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);
|
||||
|
||||
for (i = 0; i < msg->msg_iovlen; i++) {
|
||||
u8_t apiflags = write_flags;
|
||||
if (i + 1 < msg->msg_iovlen) {
|
||||
apiflags |= NETCONN_MORE;
|
||||
}
|
||||
written = 0;
|
||||
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) {
|
||||
@@ -1092,9 +1095,9 @@ lwip_sendmsg(int s, const struct msghdr *msg, int flags)
|
||||
|
||||
if (err == ERR_OK) {
|
||||
#if LWIP_IPV4 && LWIP_IPV6
|
||||
/* Dual-stack: Unmap IPv6 mapped IPv4 addresses */
|
||||
if (IP_IS_V6_VAL(chain_buf->addr) && ip6_addr_isipv6mappedipv4(ip_2_ip6(&chain_buf->addr))) {
|
||||
unmap_ipv6_mapped_ipv4(ip_2_ip4(&chain_buf->addr), ip_2_ip6(&chain_buf->addr));
|
||||
/* Dual-stack: Unmap IPv4 mapped IPv6 addresses */
|
||||
if (IP_IS_V6_VAL(chain_buf->addr) && ip6_addr_isipv4mappedipv6(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);
|
||||
}
|
||||
#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 */
|
||||
if (err == ERR_OK) {
|
||||
#if LWIP_IPV4 && LWIP_IPV6
|
||||
/* Dual-stack: Unmap IPv6 mapped IPv4 addresses */
|
||||
if (IP_IS_V6_VAL(buf.addr) && ip6_addr_isipv6mappedipv4(ip_2_ip6(&buf.addr))) {
|
||||
unmap_ipv6_mapped_ipv4(ip_2_ip4(&buf.addr), ip_2_ip6(&buf.addr));
|
||||
/* Dual-stack: Unmap IPv4 mapped IPv6 addresses */
|
||||
if (IP_IS_V6_VAL(buf.addr) && ip6_addr_isipv4mappedipv6(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);
|
||||
}
|
||||
#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);
|
||||
sock = tryget_socket(i);
|
||||
if (sock != NULL) {
|
||||
/* @todo: what if this is a new socket (reallocated?) in this case,
|
||||
select_waiting-- would be wrong (a global 'sockalloc' counter,
|
||||
stored per socket could help) */
|
||||
/* for now, handle select_waiting==0... */
|
||||
LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0);
|
||||
if (sock->select_waiting > 0) {
|
||||
sock->select_waiting--;
|
||||
@@ -1684,8 +1685,7 @@ again:
|
||||
}
|
||||
|
||||
/**
|
||||
* Unimplemented: Close one end of a full-duplex connection.
|
||||
* Currently, the full connection is closed.
|
||||
* Close one end of a full-duplex connection.
|
||||
*/
|
||||
int
|
||||
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
|
||||
/* 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_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);
|
||||
}
|
||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||
@@ -2574,6 +2574,12 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_
|
||||
switch (optname) {
|
||||
#if LWIP_IPV6 && LWIP_RAW
|
||||
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);
|
||||
if (*(const int *)optval < 0) {
|
||||
sock->conn->pcb.raw->chksum_reqd = 0;
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
#include <stdlib.h> /* atoi */
|
||||
#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 */
|
||||
#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
|
||||
running out of memory */
|
||||
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
|
||||
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 */
|
||||
}
|
||||
}
|
||||
#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 */
|
||||
|
||||
#if LWIP_HTTPD_SSI
|
||||
@@ -422,17 +452,7 @@ http_state_alloc(void)
|
||||
#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
|
||||
if (ret != NULL) {
|
||||
http_state_init(ret);
|
||||
#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
|
||||
/* 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 */
|
||||
http_add_connection(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -481,22 +501,7 @@ http_state_free(struct http_state *hs)
|
||||
{
|
||||
if (hs != NULL) {
|
||||
http_state_eof(hs);
|
||||
#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
|
||||
/* 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_remove_connection(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) */
|
||||
#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
|
||||
if (hs->keepalive) {
|
||||
#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
|
||||
struct http_state* next = hs->next;
|
||||
#endif
|
||||
http_remove_connection(hs);
|
||||
|
||||
http_state_eof(hs);
|
||||
http_state_init(hs);
|
||||
/* restore state: */
|
||||
#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
|
||||
hs->next = next;
|
||||
#endif
|
||||
hs->pcb = pcb;
|
||||
hs->keepalive = 1;
|
||||
http_add_connection(hs);
|
||||
/* ensure nagle doesn't interfere with sending all data as fast as possible: */
|
||||
tcp_nagle_disable(pcb);
|
||||
} else
|
||||
@@ -1690,7 +1692,14 @@ http_post_rxpbuf(struct http_state *hs, struct pbuf *p)
|
||||
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);
|
||||
#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND
|
||||
hs->unrecved_bytes--;
|
||||
#endif
|
||||
if (err != ERR_OK) {
|
||||
/* Ignore remaining content in case of application error */
|
||||
hs->post_content_len_left = 0;
|
||||
@@ -1751,8 +1760,8 @@ http_post_request(struct pbuf *inp, struct http_state *hs,
|
||||
if (content_len >= 0) {
|
||||
/* adjust length of HTTP header passed to application */
|
||||
const char *hdr_start_after_uri = uri_end + 1;
|
||||
u16_t hdr_len = 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_len = (u16_t)LWIP_MIN(data_len, crlfcrlf + 4 - data);
|
||||
u16_t hdr_data_len = (u16_t)LWIP_MIN(data_len, crlfcrlf + 4 - hdr_start_after_uri);
|
||||
u8_t post_auto_wnd = 1;
|
||||
http_uri_buf[0] = 0;
|
||||
/* trim http header */
|
||||
@@ -2617,4 +2626,4 @@ http_set_cgi_handlers(const tCGI *cgis, int num_handlers)
|
||||
}
|
||||
#endif /* LWIP_HTTPD_CGI */
|
||||
|
||||
#endif /* LWIP_TCP */
|
||||
#endif /* LWIP_TCP && LWIP_CALLBACK_API */
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
#include <string.h>
|
||||
|
||||
/* 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 */
|
||||
#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 */
|
||||
|
||||
@@ -47,14 +47,16 @@
|
||||
* Erik Andersson <erian747@gmail.com>
|
||||
*
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "lwip/apps/mqtt.h"
|
||||
#include "lwip/timeouts.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/apps/mqtt.h"
|
||||
#include <string.h>
|
||||
|
||||
#if LWIP_TCP && LWIP_CALLBACK_API
|
||||
|
||||
/**
|
||||
* 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;
|
||||
u8_t n;
|
||||
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 */
|
||||
if (r_objs[n].next == &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->arg = arg;
|
||||
r->pkt_id = pkt_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
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;
|
||||
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);
|
||||
|
||||
@@ -357,8 +360,9 @@ mqtt_take_request(struct mqtt_request_t **tail, u16_t pkt_id)
|
||||
static void
|
||||
mqtt_request_time_elapsed(struct mqtt_request_t **tail, u8_t t)
|
||||
{
|
||||
struct mqtt_request_t *r = *tail;
|
||||
struct mqtt_request_t *r;
|
||||
LWIP_ASSERT("mqtt_request_time_elapsed: tail != NULL", tail != NULL);
|
||||
r = *tail;
|
||||
while (t > 0 && r != NULL) {
|
||||
if (t >= r->timeout_diff) {
|
||||
t -= (u8_t)r->timeout_diff;
|
||||
@@ -634,7 +638,7 @@ mqtt_incomming_suback(struct mqtt_request_t *r, u8_t result)
|
||||
* @param remaining_length Remaining length of complete message
|
||||
*/
|
||||
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;
|
||||
|
||||
@@ -680,7 +684,7 @@ mqtt_message_received(mqtt_client_t *client, u8_t fixed_hdr_idx, u16_t length, u
|
||||
topic = var_hdr_payload + 2;
|
||||
after_topic = 2 + topic_len;
|
||||
/* 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"));
|
||||
goto out_disconnect;
|
||||
}
|
||||
@@ -1230,6 +1234,7 @@ mqtt_client_connect(mqtt_client_t *client, const ip_addr_t *ip_addr, u16_t port,
|
||||
}
|
||||
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 must be > 0", len > 0, return ERR_VAL);
|
||||
will_topic_len = (u8_t)len;
|
||||
len = strlen(client_info->will_msg);
|
||||
LWIP_ERROR("mqtt_client_connect: client_info->will_msg length overflow", len <= 0xFF, return ERR_VAL);
|
||||
@@ -1291,7 +1296,7 @@ mqtt_client_connect(mqtt_client_t *client, const ip_addr_t *ip_addr, u16_t port,
|
||||
/* Append client id */
|
||||
mqtt_output_append_string(&client->output, client_info->client_id, client_id_length);
|
||||
/* 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_msg, will_msg_len);
|
||||
}
|
||||
@@ -1333,3 +1338,5 @@ mqtt_client_is_connected(mqtt_client_t *client)
|
||||
LWIP_ASSERT("mqtt_client_is_connected: client != NULL", client);
|
||||
return client->conn_state == MQTT_CONNECTED;
|
||||
}
|
||||
|
||||
#endif /* LWIP_TCP && LWIP_CALLBACK_API */
|
||||
|
||||
@@ -280,6 +280,7 @@ DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static
|
||||
#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
|
||||
|
||||
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 */
|
||||
|
||||
|
||||
@@ -430,6 +431,38 @@ dns_init_local(void)
|
||||
#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
|
||||
* 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 addr the first IP address for the hostname in the local host-list or
|
||||
* 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
|
||||
*/
|
||||
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
|
||||
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!)
|
||||
* @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
|
||||
* - 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_IPV6: try to resolve IPv6 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_IPV6: try to resolve IPv6 only
|
||||
*/
|
||||
err_t
|
||||
dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_callback found,
|
||||
|
||||
@@ -218,9 +218,6 @@ PACK_STRUCT_END
|
||||
#if !LWIP_ETHERNET && (LWIP_ARP || PPPOE_SUPPORT)
|
||||
#error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT"
|
||||
#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
|
||||
#error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too"
|
||||
#endif
|
||||
@@ -340,7 +337,7 @@ void
|
||||
lwip_init(void)
|
||||
{
|
||||
#ifndef LWIP_SKIP_CONST_CHECK
|
||||
int a;
|
||||
int a = 0;
|
||||
LWIP_UNUSED_ARG(a);
|
||||
LWIP_ASSERT("LWIP_CONST_CAST not implemented correctly. Check your lwIP port.", LWIP_CONST_CAST(void*, &a) == &a);
|
||||
#endif
|
||||
|
||||
@@ -736,7 +736,7 @@ dhcp_start(struct netif *netif)
|
||||
|
||||
/* no DHCP client attached yet? */
|
||||
if (dhcp == NULL) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting new DHCP client\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): mallocing new DHCP client\n"));
|
||||
dhcp = (struct dhcp *)mem_malloc(sizeof(struct dhcp));
|
||||
if (dhcp == NULL) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n"));
|
||||
@@ -1500,7 +1500,7 @@ again:
|
||||
offset_max = options_idx_max;
|
||||
options = (u8_t*)q->payload;
|
||||
/* at least 1 byte to read and no end marker, then at least 3 bytes to read? */
|
||||
while ((q != NULL) && (options[offset] != DHCP_OPTION_END) && (offset < offset_max)) {
|
||||
while ((q != NULL) && (offset < offset_max) && (options[offset] != DHCP_OPTION_END)) {
|
||||
u8_t op = options[offset];
|
||||
u8_t len;
|
||||
u8_t decode_len = 0;
|
||||
@@ -1617,7 +1617,7 @@ decode_next:
|
||||
offset_max -= q->len;
|
||||
if ((offset < offset_max) && offset_max) {
|
||||
q = q->next;
|
||||
LWIP_ASSERT("next pbuf was null", q);
|
||||
LWIP_ERROR("next pbuf was null", q != NULL, return ERR_VAL;);
|
||||
options = (u8_t*)q->payload;
|
||||
} else {
|
||||
/* We've run out of bytes, probably no end marker. Don't proceed. */
|
||||
@@ -1832,7 +1832,7 @@ dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type)
|
||||
(dhcp->p_out->len >= sizeof(struct dhcp_msg)));
|
||||
|
||||
/* DHCP_REQUEST should reuse 'xid' from DHCPOFFER */
|
||||
if (message_type != DHCP_REQUEST) {
|
||||
if ((message_type != DHCP_REQUEST) || (dhcp->state == DHCP_STATE_REBOOTING)) {
|
||||
/* reuse transaction identifier in retransmissions */
|
||||
if (dhcp->tries == 0) {
|
||||
#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND)
|
||||
@@ -1942,7 +1942,8 @@ dhcp_supplied_address(const struct netif *netif)
|
||||
{
|
||||
if ((netif != NULL) && (netif_dhcp_data(netif) != NULL)) {
|
||||
struct dhcp* dhcp = netif_dhcp_data(netif);
|
||||
return (dhcp->state == DHCP_STATE_BOUND) || (dhcp->state == DHCP_STATE_RENEWING);
|
||||
return (dhcp->state == DHCP_STATE_BOUND) || (dhcp->state == DHCP_STATE_RENEWING) ||
|
||||
(dhcp->state == DHCP_STATE_REBINDING);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -56,6 +56,10 @@
|
||||
|
||||
#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 */
|
||||
|
||||
/** 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_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
|
||||
/**
|
||||
@@ -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"));
|
||||
/* ARP request for our address? */
|
||||
if (for_us) {
|
||||
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: replying to ARP request for our IP address\n"));
|
||||
/* Re-use pbuf to send ARP reply.
|
||||
Since we are re-using an existing pbuf, we can't call etharp_raw since
|
||||
that would allocate a new pbuf. */
|
||||
hdr->opcode = lwip_htons(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, ðbroadcast, ETHTYPE_ARP);
|
||||
} else
|
||||
#endif /* LWIP_AUTOIP */
|
||||
{
|
||||
ethernet_output(netif, p, &hdr->shwaddr, &hdr->dhwaddr, ETHTYPE_ARP);
|
||||
}
|
||||
|
||||
/* send ARP response */
|
||||
etharp_raw(netif,
|
||||
(struct eth_addr *)netif->hwaddr, &hdr->shwaddr,
|
||||
(struct eth_addr *)netif->hwaddr, netif_ip4_addr(netif),
|
||||
&hdr->shwaddr, &sipaddr,
|
||||
ARP_REPLY);
|
||||
/* we are not configured? */
|
||||
} else if (ip4_addr_isany_val(*netif_ip4_addr(netif))) {
|
||||
/* { for_us == 0 and netif->ip_addr.addr == 0 } */
|
||||
|
||||
@@ -51,6 +51,10 @@
|
||||
|
||||
#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
|
||||
* 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) */
|
||||
|
||||
@@ -240,7 +240,7 @@ igmp_lookfor_group(struct netif *ifp, const ip4_addr_t *addr)
|
||||
* @return a struct igmp_group*,
|
||||
* NULL on memory error.
|
||||
*/
|
||||
struct igmp_group *
|
||||
static struct igmp_group *
|
||||
igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr)
|
||||
{
|
||||
struct igmp_group *group;
|
||||
|
||||
@@ -59,6 +59,10 @@
|
||||
|
||||
#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
|
||||
* generate the IP checksum (in contrast to calculating it on-the-fly). */
|
||||
#ifndef LWIP_INLINE_IP_CHKSUM
|
||||
|
||||
@@ -79,6 +79,10 @@
|
||||
|
||||
#define IP_REASS_FLAG_LASTFRAG 0x01
|
||||
|
||||
#define IP_REASS_VALIDATE_TELEGRAM_FINISHED 1
|
||||
#define IP_REASS_VALIDATE_PBUF_QUEUED 0
|
||||
#define IP_REASS_VALIDATE_PBUF_DROPPED -1
|
||||
|
||||
/** This is a helper struct which holds the starting
|
||||
* offset and the ending offset of this fragment to
|
||||
* easily chain the fragments.
|
||||
@@ -333,10 +337,11 @@ ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev)
|
||||
* fragment was received at least once).
|
||||
* @param ipr points to the reassembly state
|
||||
* @param new_p points to the pbuf for the current fragment
|
||||
* @return 0 if invalid, >0 otherwise
|
||||
* @param is_last is 1 if this pbuf has MF==0 (ipr->flags not updated yet)
|
||||
* @return see IP_REASS_VALIDATE_* defines
|
||||
*/
|
||||
static int
|
||||
ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct pbuf *new_p)
|
||||
ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct pbuf *new_p, int is_last)
|
||||
{
|
||||
struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL;
|
||||
struct pbuf *q;
|
||||
@@ -375,7 +380,18 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
|
||||
}
|
||||
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||
iprh_prev->next_pbuf = new_p;
|
||||
if (iprh_prev->end != iprh->start) {
|
||||
/* There is a fragment missing between the current
|
||||
* and the previous fragment */
|
||||
valid = 0;
|
||||
}
|
||||
} else {
|
||||
#if IP_REASS_CHECK_OVERLAP
|
||||
if (iprh->end > iprh_tmp->start) {
|
||||
/* fragment overlaps with following, throw away */
|
||||
goto freepbuf;
|
||||
}
|
||||
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||
/* fragment with the lowest offset */
|
||||
ipr->p = new_p;
|
||||
}
|
||||
@@ -426,7 +442,7 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
|
||||
|
||||
/* At this point, the validation part begins: */
|
||||
/* If we already received the last fragment */
|
||||
if ((ipr->flags & IP_REASS_FLAG_LASTFRAG) != 0) {
|
||||
if (is_last || ((ipr->flags & IP_REASS_FLAG_LASTFRAG) != 0)) {
|
||||
/* and had no holes so far */
|
||||
if (valid) {
|
||||
/* then check if the rest of the fragments is here */
|
||||
@@ -454,23 +470,21 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
|
||||
((struct ip_reass_helper*)ipr->p->payload) != iprh);
|
||||
LWIP_ASSERT("validate_datagram:next_pbuf!=NULL",
|
||||
iprh->next_pbuf == NULL);
|
||||
LWIP_ASSERT("validate_datagram:datagram end!=datagram len",
|
||||
iprh->end == ipr->datagram_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* If valid is 0 here, there are some fragments missing in the middle
|
||||
* (since MF == 0 has already arrived). Such datagrams simply time out if
|
||||
* no more fragments are received... */
|
||||
return valid;
|
||||
return valid ? IP_REASS_VALIDATE_TELEGRAM_FINISHED : IP_REASS_VALIDATE_PBUF_QUEUED;
|
||||
}
|
||||
/* If we come here, not all fragments were received, yet! */
|
||||
return 0; /* not yet valid! */
|
||||
return IP_REASS_VALIDATE_PBUF_QUEUED; /* not yet valid! */
|
||||
#if IP_REASS_CHECK_OVERLAP
|
||||
freepbuf:
|
||||
ip_reass_pbufcount -= pbuf_clen(new_p);
|
||||
pbuf_free(new_p);
|
||||
return 0;
|
||||
return IP_REASS_VALIDATE_PBUF_DROPPED;
|
||||
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||
}
|
||||
|
||||
@@ -488,6 +502,8 @@ ip4_reass(struct pbuf *p)
|
||||
struct ip_reassdata *ipr;
|
||||
struct ip_reass_helper *iprh;
|
||||
u16_t offset, len, clen;
|
||||
int valid;
|
||||
int is_last;
|
||||
|
||||
IPFRAG_STATS_INC(ip_frag.recv);
|
||||
MIB2_STATS_INC(mib2.ipreasmreqds);
|
||||
@@ -552,24 +568,41 @@ ip4_reass(struct pbuf *p)
|
||||
SMEMCPY(&ipr->iphdr, fraghdr, IP_HLEN);
|
||||
}
|
||||
}
|
||||
/* Track the current number of pbufs current 'in-flight', in order to limit
|
||||
the number of fragments that may be enqueued at any one time */
|
||||
ip_reass_pbufcount += clen;
|
||||
|
||||
/* At this point, we have either created a new entry or pointing
|
||||
* to an existing one */
|
||||
|
||||
/* check for 'no more fragments', and update queue entry*/
|
||||
if ((IPH_OFFSET(fraghdr) & PP_NTOHS(IP_MF)) == 0) {
|
||||
is_last = (IPH_OFFSET(fraghdr) & PP_NTOHS(IP_MF)) == 0;
|
||||
if (is_last) {
|
||||
u16_t datagram_len = (u16_t)(offset + len);
|
||||
if ((datagram_len < offset) || (datagram_len > (0xFFFF - IP_HLEN))) {
|
||||
/* u16_t overflow, cannot handle this */
|
||||
goto nullreturn;
|
||||
}
|
||||
}
|
||||
/* find the right place to insert this pbuf */
|
||||
/* @todo: trim pbufs if fragments are overlapping */
|
||||
valid = ip_reass_chain_frag_into_datagram_and_validate(ipr, p, is_last);
|
||||
if (valid == IP_REASS_VALIDATE_PBUF_DROPPED) {
|
||||
goto nullreturn;
|
||||
}
|
||||
/* if we come here, the pbuf has been enqueued */
|
||||
|
||||
/* Track the current number of pbufs current 'in-flight', in order to limit
|
||||
the number of fragments that may be enqueued at any one time
|
||||
(overflow checked by testing against IP_REASS_MAX_PBUFS) */
|
||||
ip_reass_pbufcount = (u16_t)(ip_reass_pbufcount + clen);
|
||||
if (is_last) {
|
||||
u16_t datagram_len = (u16_t)(offset + len);
|
||||
ipr->datagram_len = datagram_len;
|
||||
ipr->flags |= IP_REASS_FLAG_LASTFRAG;
|
||||
ipr->datagram_len = offset + len;
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("ip4_reass: last fragment seen, total len %"S16_F"\n",
|
||||
ipr->datagram_len));
|
||||
}
|
||||
/* find the right place to insert this pbuf */
|
||||
/* @todo: trim pbufs if fragments are overlapping */
|
||||
if (ip_reass_chain_frag_into_datagram_and_validate(ipr, p)) {
|
||||
|
||||
if (valid == IP_REASS_VALIDATE_TELEGRAM_FINISHED) {
|
||||
struct ip_reassdata *ipr_prev;
|
||||
/* the totally last fragment (flag more fragments = 0) was received at least
|
||||
* once AND all fragments are received */
|
||||
|
||||
@@ -60,6 +60,10 @@
|
||||
#include "lwip/debug.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
|
||||
* 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_src, ip6hdr->src);
|
||||
|
||||
/* Don't accept virtual IPv6 mapped IPv4 addresses */
|
||||
if (ip6_addr_isipv6mappedipv4(ip_2_ip6(&ip_data.current_iphdr_dest)) ||
|
||||
ip6_addr_isipv6mappedipv4(ip_2_ip6(&ip_data.current_iphdr_src)) ) {
|
||||
/* Don't accept virtual IPv4 mapped IPv6 addresses.
|
||||
* Don't accept multicast source addresses. */
|
||||
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.drop);
|
||||
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;
|
||||
if (dest != LWIP_IP_HDRINCL) {
|
||||
if (src != NULL && ip6_addr_isany(src)) {
|
||||
src = ip_2_ip6(ip6_select_source_address(netif, dest));
|
||||
if ((src == NULL) || ip6_addr_isany(src)) {
|
||||
src_used = ip_2_ip6(ip6_select_source_address(netif, dest));
|
||||
if ((src_used == NULL) || ip6_addr_isany(src_used)) {
|
||||
/* 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"));
|
||||
IP6_STATS_INC(ip6.rterr);
|
||||
|
||||
@@ -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. */
|
||||
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. */
|
||||
MLD6_STATS_INC(mld6.xmit);
|
||||
ip6_output_if(p, (ip6_addr_isany(src_addr)) ? NULL : src_addr, &(group->group_address),
|
||||
|
||||
@@ -64,6 +64,10 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef LWIP_HOOK_FILENAME
|
||||
#include LWIP_HOOK_FILENAME
|
||||
#endif
|
||||
|
||||
#if LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK
|
||||
#error LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK
|
||||
#endif
|
||||
|
||||
@@ -75,7 +75,6 @@
|
||||
#include "lwip/ip6_frag.h"
|
||||
#include "lwip/mld6.h"
|
||||
|
||||
|
||||
#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc)
|
||||
#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"
|
||||
};
|
||||
|
||||
#ifdef LWIP_HOOK_FILENAME
|
||||
#include LWIP_HOOK_FILENAME
|
||||
#endif
|
||||
|
||||
#if MEMP_MEM_MALLOC && MEMP_OVERFLOW_CHECK >= 2
|
||||
#undef MEMP_OVERFLOW_CHECK
|
||||
/* MEMP_OVERFLOW_CHECK >= 2 does not work with MEMP_MEM_MALLOC, use 1 instead */
|
||||
|
||||
@@ -849,7 +849,9 @@ netif_loop_output(struct netif *netif, struct pbuf *p)
|
||||
netif_poll(). */
|
||||
|
||||
/* let last point to the last pbuf in chain r */
|
||||
for (last = r; last->next != NULL; last = last->next);
|
||||
for (last = r; last->next != NULL; last = last->next) {
|
||||
/* nothing to do here, just get to the last pbuf */
|
||||
}
|
||||
|
||||
SYS_ARCH_PROTECT(lev);
|
||||
if (netif->loop_first != NULL) {
|
||||
|
||||
@@ -350,8 +350,18 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
|
||||
|
||||
break;
|
||||
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) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -812,6 +822,7 @@ pbuf_ref(struct pbuf *p)
|
||||
/* pbuf given? */
|
||||
if (p != NULL) {
|
||||
SYS_ARCH_INC(p->ref, 1);
|
||||
LWIP_ASSERT("pbuf ref overflow", p->ref > 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -209,7 +209,7 @@ raw_input(struct pbuf *p, struct netif *inp)
|
||||
err_t
|
||||
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;
|
||||
}
|
||||
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
|
||||
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;
|
||||
}
|
||||
ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr);
|
||||
|
||||
@@ -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(("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_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 */
|
||||
|
||||
@@ -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(("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.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 */
|
||||
|
||||
|
||||
@@ -62,6 +62,10 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef LWIP_HOOK_FILENAME
|
||||
#include LWIP_HOOK_FILENAME
|
||||
#endif
|
||||
|
||||
#ifndef TCP_LOCAL_PORT_RANGE_START
|
||||
/* From http://www.iana.org/assignments/port-numbers:
|
||||
"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 u16_t tcp_new_port(void);
|
||||
|
||||
static err_t tcp_close_shutdown_fin(struct tcp_pcb *pcb);
|
||||
|
||||
/**
|
||||
* Initialize this module.
|
||||
*/
|
||||
@@ -258,8 +264,6 @@ tcp_backlog_accepted(struct tcp_pcb* pcb)
|
||||
static err_t
|
||||
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 ((pcb->refused_data != NULL) || (pcb->rcv_wnd != TCP_WND_MAX(pcb))) {
|
||||
/* 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) {
|
||||
case CLOSED:
|
||||
/* 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
|
||||
* is erroneous, but this should never happen as the pcb has in those cases
|
||||
* been freed, and so any remaining handles are bogus. */
|
||||
err = ERR_OK;
|
||||
if (pcb->local_port != 0) {
|
||||
TCP_RMV(&tcp_bound_pcbs, pcb);
|
||||
}
|
||||
memp_free(MEMP_TCP_PCB, pcb);
|
||||
pcb = NULL;
|
||||
break;
|
||||
case LISTEN:
|
||||
err = ERR_OK;
|
||||
tcp_listen_closed(pcb);
|
||||
tcp_pcb_remove(&tcp_listen_pcbs.pcbs, pcb);
|
||||
memp_free(MEMP_TCP_PCB_LISTEN, pcb);
|
||||
pcb = NULL;
|
||||
break;
|
||||
case SYN_SENT:
|
||||
err = ERR_OK;
|
||||
TCP_PCB_REMOVE_ACTIVE(pcb);
|
||||
memp_free(MEMP_TCP_PCB, pcb);
|
||||
pcb = NULL;
|
||||
MIB2_STATS_INC(mib2.tcpattemptfails);
|
||||
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:
|
||||
err = tcp_send_fin(pcb);
|
||||
if (err == ERR_OK) {
|
||||
@@ -344,18 +357,25 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
|
||||
break;
|
||||
default:
|
||||
/* Has already been closed, do nothing. */
|
||||
err = ERR_OK;
|
||||
pcb = NULL;
|
||||
break;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
if (pcb != NULL && err == ERR_OK) {
|
||||
if (err == ERR_OK) {
|
||||
/* To ensure all data has been sent when tcp_close returns, we have
|
||||
to make sure tcp_output doesn't fail.
|
||||
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
|
||||
for the return value of tcp_output for now. */
|
||||
tcp_output(pcb);
|
||||
} else if (err == ERR_MEM) {
|
||||
/* Mark this pcb for closing. Closing is retried from tcp_tmr. */
|
||||
pcb->flags |= TF_CLOSEPEND;
|
||||
/* We have to return ERR_OK from here to indicate to the callers that this
|
||||
pcb should not be used any more as it will be freed soon via tcp_tmr.
|
||||
This is OK here since sending FIN does not guarantee a time frime for
|
||||
actually freeing the pcb, either (it is left in closure states for
|
||||
remote ACK or timeout) */
|
||||
return ERR_OK;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
@@ -393,8 +413,8 @@ tcp_close(struct tcp_pcb *pcb)
|
||||
* @ingroup tcp_raw
|
||||
* Causes all or part of a full-duplex connection of this PCB to be shut down.
|
||||
* This doesn't deallocate the PCB unless shutting down both sides!
|
||||
* Shutting down both sides is the same as calling tcp_close, so if it succeds,
|
||||
* the PCB should not be referenced any more.
|
||||
* Shutting down both sides is the same as calling tcp_close, so if it succeds
|
||||
* (i.e. returns ER_OK), the PCB must not be referenced any more!
|
||||
*
|
||||
* @param pcb PCB to shutdown
|
||||
* @param shut_rx shut down receive side if this is != 0
|
||||
@@ -467,6 +487,7 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
|
||||
} else {
|
||||
int send_rst = 0;
|
||||
u16_t local_port = 0;
|
||||
enum tcp_state last_state;
|
||||
seqno = pcb->snd_nxt;
|
||||
ackno = pcb->rcv_nxt;
|
||||
#if LWIP_CALLBACK_API
|
||||
@@ -499,8 +520,9 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
|
||||
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);
|
||||
}
|
||||
last_state = pcb->state;
|
||||
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 +573,7 @@ tcp_bind(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port)
|
||||
#endif /* LWIP_IPV4 */
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@@ -859,7 +881,7 @@ tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port,
|
||||
u32_t iss;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -931,7 +953,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);
|
||||
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
|
||||
pcb->cwnd = 1;
|
||||
pcb->ssthresh = TCP_WND;
|
||||
#if LWIP_CALLBACK_API
|
||||
pcb->connected = connected;
|
||||
#else /* LWIP_CALLBACK_API */
|
||||
@@ -997,11 +1018,11 @@ tcp_slowtmr_start:
|
||||
pcb_remove = 0;
|
||||
pcb_reset = 0;
|
||||
|
||||
if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) {
|
||||
if (pcb->state == SYN_SENT && pcb->nrtx >= TCP_SYNMAXRTX) {
|
||||
++pcb_remove;
|
||||
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;
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n"));
|
||||
} else {
|
||||
@@ -1035,7 +1056,8 @@ tcp_slowtmr_start:
|
||||
/* Double retransmission time-out unless we are trying to
|
||||
* connect to somebody (i.e., we are in 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. */
|
||||
@@ -1132,6 +1154,7 @@ tcp_slowtmr_start:
|
||||
tcp_err_fn err_fn = pcb->errf;
|
||||
#endif /* LWIP_CALLBACK_API */
|
||||
void *err_arg;
|
||||
enum tcp_state last_state;
|
||||
tcp_pcb_purge(pcb);
|
||||
/* Remove PCB from tcp_active_pcbs list. */
|
||||
if (prev != NULL) {
|
||||
@@ -1149,12 +1172,13 @@ tcp_slowtmr_start:
|
||||
}
|
||||
|
||||
err_arg = pcb->callback_arg;
|
||||
last_state = pcb->state;
|
||||
pcb2 = pcb;
|
||||
pcb = pcb->next;
|
||||
memp_free(MEMP_TCP_PCB, pcb2);
|
||||
|
||||
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) {
|
||||
goto tcp_slowtmr_start;
|
||||
}
|
||||
@@ -1244,6 +1268,12 @@ tcp_fasttmr_start:
|
||||
tcp_output(pcb);
|
||||
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;
|
||||
|
||||
@@ -1590,6 +1620,14 @@ tcp_alloc(u8_t prio)
|
||||
pcb->tmr = tcp_ticks;
|
||||
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
|
||||
pcb->recv = tcp_recv_null;
|
||||
#endif /* LWIP_CALLBACK_API */
|
||||
|
||||
@@ -61,8 +61,6 @@
|
||||
|
||||
/** Initial CWND calculation as defined RFC 2581 */
|
||||
#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
|
||||
processing of TCP segments. They are set by the tcp_input()
|
||||
@@ -91,6 +89,8 @@ static void tcp_parseopt(struct tcp_pcb *pcb);
|
||||
static void tcp_listen_input(struct tcp_pcb_listen *pcb);
|
||||
static void tcp_timewait_input(struct tcp_pcb *pcb);
|
||||
|
||||
static int tcp_input_delayed_close(struct tcp_pcb *pcb);
|
||||
|
||||
/**
|
||||
* The initial input processing of TCP. It verifies the TCP header, demultiplexes
|
||||
* the segment between the PCBs and passes it on to tcp_process(), which implements
|
||||
@@ -378,7 +378,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
end. We then call the error callback to inform the
|
||||
application that the connection is dead before we
|
||||
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);
|
||||
memp_free(MEMP_TCP_PCB, pcb);
|
||||
} else {
|
||||
@@ -406,17 +406,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
}
|
||||
recv_acked = 0;
|
||||
}
|
||||
if (recv_flags & TF_CLOSED) {
|
||||
/* The connection has been closed and we will deallocate the
|
||||
PCB. */
|
||||
if (!(pcb->flags & TF_RXCLOSED)) {
|
||||
/* Connection closed although the application has only shut down the
|
||||
tx side: call the PCB's err callback and indicate the closure to
|
||||
ensure the application doesn't continue using the PCB. */
|
||||
TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_CLSD);
|
||||
}
|
||||
tcp_pcb_remove(&tcp_active_pcbs, pcb);
|
||||
memp_free(MEMP_TCP_PCB, pcb);
|
||||
if (tcp_input_delayed_close(pcb)) {
|
||||
goto aborted;
|
||||
}
|
||||
#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
|
||||
@@ -490,6 +480,9 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
}
|
||||
|
||||
tcp_input_pcb = NULL;
|
||||
if (tcp_input_delayed_close(pcb)) {
|
||||
goto aborted;
|
||||
}
|
||||
/* Try to send something out. */
|
||||
tcp_output(pcb);
|
||||
#if TCP_INPUT_DEBUG
|
||||
@@ -534,6 +527,30 @@ dropped:
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
/** Called from tcp_input to check for TF_CLOSED flag. This results in closing
|
||||
* and deallocating a pcb at the correct place to ensure noone references it
|
||||
* any more.
|
||||
* @returns 1 if the pcb has been closed and deallocated, 0 otherwise
|
||||
*/
|
||||
static int
|
||||
tcp_input_delayed_close(struct tcp_pcb *pcb)
|
||||
{
|
||||
if (recv_flags & TF_CLOSED) {
|
||||
/* The connection has been closed and we will deallocate the
|
||||
PCB. */
|
||||
if (!(pcb->flags & TF_RXCLOSED)) {
|
||||
/* Connection closed although the application has only shut down the
|
||||
tx side: call the PCB's err callback and indicate the closure to
|
||||
ensure the application doesn't continue using the PCB. */
|
||||
TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_CLSD);
|
||||
}
|
||||
tcp_pcb_remove(&tcp_active_pcbs, pcb);
|
||||
memp_free(MEMP_TCP_PCB, pcb);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by tcp_input() when a segment arrives for a listening
|
||||
* connection (from tcp_input()).
|
||||
@@ -615,7 +632,6 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
||||
tcp_parseopt(npcb);
|
||||
npcb->snd_wnd = tcphdr->wnd;
|
||||
npcb->snd_wnd_max = npcb->snd_wnd;
|
||||
npcb->ssthresh = LWIP_TCP_INITIAL_SSTHRESH(npcb);
|
||||
|
||||
#if TCP_CALCULATE_EFF_SEND_MSS
|
||||
npcb->mss = tcp_eff_send_mss(npcb->mss, &npcb->local_ip, &npcb->remote_ip);
|
||||
@@ -771,9 +787,6 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip);
|
||||
#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);
|
||||
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_process (SENT): cwnd %"TCPWNDSIZE_F
|
||||
" ssthresh %"TCPWNDSIZE_F"\n",
|
||||
@@ -816,9 +829,12 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(),
|
||||
ip_current_src_addr(), tcphdr->dest, tcphdr->src);
|
||||
/* Resend SYN immediately (don't wait for rto timeout) to establish
|
||||
connection faster */
|
||||
pcb->rtime = 0;
|
||||
tcp_rexmit_rto(pcb);
|
||||
connection faster, but do not send more SYNs than we otherwise would
|
||||
have, or we might get caught in a loop on loopback interfaces. */
|
||||
if (pcb->nrtx < TCP_SYNMAXRTX) {
|
||||
pcb->rtime = 0;
|
||||
tcp_rexmit_rto(pcb);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SYN_RCVD:
|
||||
@@ -827,14 +843,16 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) {
|
||||
pcb->state = ESTABLISHED;
|
||||
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
|
||||
LWIP_ASSERT("pcb->listener->accept != NULL",
|
||||
(pcb->listener == NULL) || (pcb->listener->accept != NULL));
|
||||
#endif
|
||||
if (pcb->listener == NULL) {
|
||||
/* listen pcb might be closed by now */
|
||||
err = ERR_VAL;
|
||||
} else
|
||||
#endif
|
||||
#endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */
|
||||
{
|
||||
tcp_backlog_accepted(pcb);
|
||||
/* Call the accept function. */
|
||||
@@ -853,11 +871,6 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
* we'd better pass it on to the application as well. */
|
||||
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 */
|
||||
if (recv_acked != 0) {
|
||||
recv_acked--;
|
||||
@@ -925,7 +938,7 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
break;
|
||||
case CLOSING:
|
||||
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));
|
||||
tcp_pcb_purge(pcb);
|
||||
TCP_RMV_ACTIVE(pcb);
|
||||
@@ -935,7 +948,7 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
break;
|
||||
case LAST_ACK:
|
||||
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));
|
||||
/* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */
|
||||
recv_flags |= TF_CLOSED;
|
||||
@@ -1417,7 +1430,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
TCP_SEQ_GEQ(seqno + tcplen,
|
||||
next->tcphdr->seqno + next->len)) {
|
||||
/* 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_SET_FLAG(inseg.tcphdr, TCP_FIN);
|
||||
tcplen = TCP_TCPLEN(&inseg);
|
||||
@@ -1755,11 +1768,11 @@ tcp_parseopt(struct tcp_pcb *pcb)
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
|
||||
return;
|
||||
}
|
||||
/* An WND_SCALE option with the right option length. */
|
||||
data = tcp_getoptbyte();
|
||||
/* If syn was received with wnd scale option,
|
||||
activate wnd scale opt, but only if this is not a retransmission */
|
||||
if ((flags & TCP_SYN) && !(pcb->flags & TF_WND_SCALE)) {
|
||||
/* An WND_SCALE option with the right option length. */
|
||||
data = tcp_getoptbyte();
|
||||
pcb->snd_scale = data;
|
||||
if (pcb->snd_scale > 14U) {
|
||||
pcb->snd_scale = 14U;
|
||||
|
||||
@@ -376,6 +376,9 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
|
||||
#if TCP_OVERSIZE
|
||||
u16_t oversize = 0;
|
||||
u16_t oversize_used = 0;
|
||||
#if TCP_OVERSIZE_DBGCHECK
|
||||
u16_t oversize_add = 0;
|
||||
#endif /* TCP_OVERSIZE_DBGCHECK*/
|
||||
#endif /* TCP_OVERSIZE */
|
||||
u16_t extendlen = 0;
|
||||
#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_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)",
|
||||
pcb->unsent_oversize == last_unsent->oversize_left);
|
||||
#endif /* TCP_OVERSIZE_DBGCHECK */
|
||||
oversize = pcb->unsent_oversize;
|
||||
if (oversize > 0) {
|
||||
LWIP_ASSERT("inconsistent oversize vs. space", oversize_used <= space);
|
||||
LWIP_ASSERT("inconsistent oversize vs. space", oversize <= space);
|
||||
seg = last_unsent;
|
||||
oversize_used = LWIP_MIN(space, LWIP_MIN(oversize, len));
|
||||
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;
|
||||
}
|
||||
/* 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 */
|
||||
|
||||
/*
|
||||
@@ -490,7 +493,7 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
|
||||
* the end.
|
||||
*/
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
#if TCP_OVERSIZE_DBGCHECK
|
||||
last_unsent->oversize_left += oversize;
|
||||
oversize_add = oversize;
|
||||
#endif /* TCP_OVERSIZE_DBGCHECK */
|
||||
TCP_DATA_COPY2(concat_p->payload, (const u8_t*)arg + pos, seglen, &concat_chksum, &concat_chksum_swapped);
|
||||
#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;
|
||||
u16_t left = len - pos;
|
||||
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
|
||||
u16_t chksum = 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
|
||||
* 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
|
||||
@@ -1412,7 +1420,9 @@ tcp_rexmit_rto(struct tcp_pcb *pcb)
|
||||
pcb->unacked = NULL;
|
||||
|
||||
/* increment number of retransmissions */
|
||||
++pcb->nrtx;
|
||||
if (pcb->nrtx < 0xFF) {
|
||||
++pcb->nrtx;
|
||||
}
|
||||
|
||||
/* Don't take any RTT measurements after retransmitting. */
|
||||
pcb->rttest = 0;
|
||||
@@ -1457,7 +1467,9 @@ tcp_rexmit(struct tcp_pcb *pcb)
|
||||
}
|
||||
#endif /* TCP_OVERSIZE */
|
||||
|
||||
++pcb->nrtx;
|
||||
if (pcb->nrtx < 0xFF) {
|
||||
++pcb->nrtx;
|
||||
}
|
||||
|
||||
/* Don't take any rtt measurements after retransmitting. */
|
||||
pcb->rttest = 0;
|
||||
@@ -1488,11 +1500,7 @@ tcp_rexmit_fast(struct tcp_pcb *pcb)
|
||||
|
||||
/* Set ssthresh to half of the minimum of the current
|
||||
* cwnd and the advertised window */
|
||||
if (pcb->cwnd > pcb->snd_wnd) {
|
||||
pcb->ssthresh = pcb->snd_wnd / 2;
|
||||
} else {
|
||||
pcb->ssthresh = pcb->cwnd / 2;
|
||||
}
|
||||
pcb->ssthresh = LWIP_MIN(pcb->cwnd, pcb->snd_wnd) / 2;
|
||||
|
||||
/* The minimum value for ssthresh should be 2 MSS */
|
||||
if (pcb->ssthresh < (2U * pcb->mss)) {
|
||||
|
||||
@@ -176,7 +176,7 @@ void sys_timeouts_init(void)
|
||||
{
|
||||
size_t i;
|
||||
/* tcp_tmr() at index 0 is started on demand */
|
||||
for (i = 1; i < LWIP_ARRAYSIZE(lwip_cyclic_timers); i++) {
|
||||
for (i = (LWIP_TCP ? 1 : 0); i < LWIP_ARRAYSIZE(lwip_cyclic_timers); i++) {
|
||||
/* we have to cast via size_t to get rid of const warning
|
||||
(this is OK as cyclic_timer() casts back to const* */
|
||||
sys_timeout(lwip_cyclic_timers[i].interval_ms, cyclic_timer, LWIP_CONST_CAST(void*, &lwip_cyclic_timers[i]));
|
||||
|
||||
@@ -892,7 +892,7 @@ udp_bind(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port)
|
||||
#endif /* LWIP_IPV4 */
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@@ -982,7 +982,7 @@ udp_connect(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port)
|
||||
{
|
||||
struct udp_pcb *ipcb;
|
||||
|
||||
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) {
|
||||
if ((pcb == NULL) || (ipaddr == NULL)) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,8 +39,9 @@
|
||||
|
||||
#include "lwip/apps/mqtt_opts.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#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,
|
||||
mqtt_request_cb_t cb, void *arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
#endif
|
||||
|
||||
/** Define random number generator function of your system */
|
||||
#ifndef LWIP_RAND
|
||||
#ifdef __DOXYGEN__
|
||||
#define LWIP_RAND() ((u32_t)rand())
|
||||
#endif
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
* systems, this should be defined to something less resource-consuming.
|
||||
*/
|
||||
#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 <stdlib.h>
|
||||
#endif
|
||||
@@ -162,6 +162,19 @@ typedef uintptr_t mem_ptr_t;
|
||||
#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) */
|
||||
#ifndef LWIP_CONST_CAST
|
||||
#define LWIP_CONST_CAST(target_type, val) ((target_type)((ptrdiff_t)val))
|
||||
|
||||
@@ -91,14 +91,6 @@ u32_t lwip_htonl(u32_t x);
|
||||
#endif
|
||||
#define lwip_ntohl(x) lwip_htonl(x)
|
||||
|
||||
/* Provide usual function names as macros for users, but this can be turned off */
|
||||
#ifndef LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS
|
||||
#define htons(x) lwip_htons(x)
|
||||
#define ntohs(x) lwip_ntohs(x)
|
||||
#define htonl(x) lwip_htonl(x)
|
||||
#define ntohl(x) lwip_ntohl(x)
|
||||
#endif
|
||||
|
||||
/* These macros should be calculated by the preprocessor and are used
|
||||
with compile-time constants only (so that there is no little-endian
|
||||
overhead at runtime). */
|
||||
@@ -109,9 +101,16 @@ u32_t lwip_htonl(u32_t x);
|
||||
(((x) & 0x00ff0000UL) >> 8) | \
|
||||
(((x) & 0xff000000UL) >> 24))
|
||||
#define PP_NTOHL(x) PP_HTONL(x)
|
||||
|
||||
#endif /* BYTE_ORDER == BIG_ENDIAN */
|
||||
|
||||
/* Provide usual function names as macros for users, but this can be turned off */
|
||||
#ifndef LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS
|
||||
#define htons(x) lwip_htons(x)
|
||||
#define ntohs(x) lwip_ntohs(x)
|
||||
#define htonl(x) lwip_htonl(x)
|
||||
#define ntohl(x) lwip_ntohl(x)
|
||||
#endif
|
||||
|
||||
/* Functions that are not available as standard implementations.
|
||||
* In cc.h, you can #define these to implementations available on
|
||||
* your platform to save some code bytes if you use these functions
|
||||
|
||||
@@ -108,7 +108,7 @@ struct dhcp
|
||||
|
||||
void dhcp_set_struct(struct netif *netif, struct dhcp *dhcp);
|
||||
/** Remove a struct dhcp previously set to the netif using dhcp_set_struct() */
|
||||
#define dhcp_remove_struct(netif) do { (netif)->dhcp = NULL; } while(0)
|
||||
#define dhcp_remove_struct(netif) netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, NULL)
|
||||
void dhcp_cleanup(struct netif *netif);
|
||||
err_t dhcp_start(struct netif *netif);
|
||||
err_t dhcp_renew(struct netif *netif);
|
||||
|
||||
@@ -76,6 +76,7 @@ struct local_hostlist_entry {
|
||||
ip_addr_t addr;
|
||||
struct local_hostlist_entry *next;
|
||||
};
|
||||
#define DNS_LOCAL_HOSTLIST_ELEM(name, addr_init) {name, addr_init, NULL}
|
||||
#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
|
||||
#ifndef DNS_LOCAL_HOSTLIST_MAX_NAMELEN
|
||||
#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);
|
||||
|
||||
|
||||
#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);
|
||||
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
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ enum icmp_dur_type {
|
||||
|
||||
/** ICMP time exceeded codes */
|
||||
enum icmp_te_type {
|
||||
/* time to live exceeded in transit */
|
||||
/** time to live exceeded in transit */
|
||||
ICMP_TE_TTL = 0,
|
||||
/** fragment reassembly time exceeded */
|
||||
ICMP_TE_FRAG = 1
|
||||
|
||||
@@ -54,11 +54,11 @@ extern "C" {
|
||||
/** x.X.x: Minor version of the stack */
|
||||
#define LWIP_VERSION_MINOR 0
|
||||
/** x.x.X: Revision of the stack */
|
||||
#define LWIP_VERSION_REVISION 1
|
||||
#define LWIP_VERSION_REVISION 3
|
||||
/** For release candidates, this is set to 1..254
|
||||
* For official releases, this is set to 255 (LWIP_RC_RELEASE)
|
||||
* For development versions (Git), this is set to 0 (LWIP_RC_DEVELOPMENT) */
|
||||
#define LWIP_VERSION_RC LWIP_RC_DEVELOPMENT
|
||||
#define LWIP_VERSION_RC LWIP_RC_RELEASE
|
||||
|
||||
/** LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases */
|
||||
#define LWIP_RC_RELEASE 255
|
||||
|
||||
@@ -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_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_multicast_transient_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00100000UL))
|
||||
|
||||
@@ -222,14 +222,14 @@ int ipaddr_aton(const char *cp, ip_addr_t *addr);
|
||||
#define IPADDR_STRLEN_MAX IP6ADDR_STRLEN_MAX
|
||||
|
||||
/** @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[2] = PP_HTONL(0x0000FFFFUL); \
|
||||
(ip6addr)->addr[1] = 0; \
|
||||
(ip6addr)->addr[0] = 0; } while(0);
|
||||
|
||||
/** @ingroup ipaddr */
|
||||
#define unmap_ipv6_mapped_ipv4(ip4addr, ip6addr) \
|
||||
#define unmap_ipv4_mapped_ipv6(ip4addr, ip6addr) \
|
||||
(ip4addr)->addr = (ip6addr)->addr[3];
|
||||
|
||||
#define IP46_ADDR_ANY(type) (((type) == IPADDR_TYPE_V6)? IP6_ADDR_ANY : IP4_ADDR_ANY)
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
#ifndef LWIP_HDR_MEMP_H
|
||||
#define LWIP_HDR_MEMP_H
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
@@ -1047,11 +1047,9 @@
|
||||
#define LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING 2
|
||||
#define LWIP_DNS_SECURE_RAND_SRC_PORT 4
|
||||
|
||||
/** DNS_LOCAL_HOSTLIST: Implements a local host-to-address list. If enabled,
|
||||
* you have to define
|
||||
* \#define DNS_LOCAL_HOSTLIST_INIT {{"host1", 0x123}, {"host2", 0x234}}
|
||||
* (an array of structs name/address, where address is an u32_t in network
|
||||
* byte order).
|
||||
/** DNS_LOCAL_HOSTLIST: Implements a local host-to-address list. If enabled, you have to define an initializer:
|
||||
* \#define DNS_LOCAL_HOSTLIST_INIT {DNS_LOCAL_HOSTLIST_ELEM("host_ip4", IPADDR4_INIT_BYTES(1,2,3,4)), \
|
||||
* DNS_LOCAL_HOSTLIST_ELEM("host_ip6", IPADDR6_INIT_HOST(123, 234, 345, 456)}
|
||||
*
|
||||
* 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)
|
||||
@@ -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:
|
||||
* Hook for generation of the Initial Sequence Number (ISN) for a new TCP
|
||||
|
||||
@@ -170,16 +170,18 @@ err_t tcp_process_refused_data(struct tcp_pcb *pcb);
|
||||
LWIP_EVENT_RECV, NULL, 0, ERR_OK)
|
||||
#define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
||||
LWIP_EVENT_CONNECTED, NULL, 0, (err))
|
||||
#define TCP_EVENT_POLL(pcb,ret) 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, \
|
||||
LWIP_EVENT_ERR, NULL, 0, (err))
|
||||
#define TCP_EVENT_POLL(pcb,ret) do { if ((pcb)->state != SYN_RCVD) { \
|
||||
ret = lwip_tcp_event((pcb)->callback_arg, (pcb), LWIP_EVENT_POLL, NULL, 0, ERR_OK); \
|
||||
} else { \
|
||||
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 */
|
||||
|
||||
#define TCP_EVENT_ACCEPT(lpcb,pcb,arg,err,ret) \
|
||||
do { \
|
||||
if((lpcb != NULL) && ((lpcb)->accept != NULL)) \
|
||||
if((lpcb)->accept != NULL) \
|
||||
(ret) = (lpcb)->accept((arg),(pcb),(err)); \
|
||||
else (ret) = ERR_ARG; \
|
||||
} while (0)
|
||||
@@ -223,8 +225,9 @@ err_t tcp_process_refused_data(struct tcp_pcb *pcb);
|
||||
else (ret) = ERR_OK; \
|
||||
} while (0)
|
||||
|
||||
#define TCP_EVENT_ERR(errf,arg,err) \
|
||||
#define TCP_EVENT_ERR(last_state,errf,arg,err) \
|
||||
do { \
|
||||
LWIP_UNUSED_ARG(last_state); \
|
||||
if((errf) != NULL) \
|
||||
(errf)((arg),(err)); \
|
||||
} while (0)
|
||||
@@ -249,7 +252,7 @@ struct tcp_seg {
|
||||
#if TCP_OVERSIZE_DBGCHECK
|
||||
u16_t oversize_left; /* Extra bytes available at the end of the last
|
||||
pbuf in unsent (used for asserting vs.
|
||||
tcp_pcb.unsent_oversized only) */
|
||||
tcp_pcb.unsent_oversize only) */
|
||||
#endif /* TCP_OVERSIZE_DBGCHECK */
|
||||
#if TCP_CHECKSUM_ON_COPY
|
||||
u16_t chksum;
|
||||
|
||||
@@ -387,9 +387,9 @@ void stats_init(void);
|
||||
|
||||
#if MEM_STATS
|
||||
#define MEM_STATS_AVAIL(x, y) lwip_stats.mem.x = y
|
||||
#define MEM_STATS_INC(x) STATS_INC(mem.x)
|
||||
#define MEM_STATS_INC_USED(x, y) STATS_INC_USED(mem, y)
|
||||
#define MEM_STATS_DEC_USED(x, y) lwip_stats.mem.x -= y
|
||||
#define MEM_STATS_INC(x) SYS_ARCH_INC(lwip_stats.mem.x, 1)
|
||||
#define MEM_STATS_INC_USED(x, y) SYS_ARCH_INC(lwip_stats.mem.x, y)
|
||||
#define MEM_STATS_DEC_USED(x, y) SYS_ARCH_DEC(lwip_stats.mem.x, y)
|
||||
#define MEM_STATS_DISPLAY() stats_display_mem(&lwip_stats.mem, "HEAP")
|
||||
#else
|
||||
#define MEM_STATS_AVAIL(x, y)
|
||||
|
||||
@@ -145,7 +145,7 @@ typedef u32_t tcpwnd_size_t;
|
||||
typedef u16_t tcpwnd_size_t;
|
||||
#endif
|
||||
|
||||
#if LWIP_WND_SCALE || TCP_LISTEN_BACKLOG
|
||||
#if LWIP_WND_SCALE || TCP_LISTEN_BACKLOG || LWIP_TCP_TIMESTAMPS
|
||||
typedef u16_t tcpflags_t;
|
||||
#else
|
||||
typedef u8_t tcpflags_t;
|
||||
@@ -210,7 +210,7 @@ struct tcp_pcb {
|
||||
#define TF_ACK_DELAY 0x01U /* Delayed ACK. */
|
||||
#define TF_ACK_NOW 0x02U /* Immediate ACK. */
|
||||
#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_FIN 0x20U /* Connection was closed locally (FIN segment enqueued). */
|
||||
#define TF_NODELAY 0x40U /* Disable Nagle algorithm */
|
||||
@@ -220,6 +220,9 @@ struct tcp_pcb {
|
||||
#endif
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
#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
|
||||
|
||||
/* 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 */
|
||||
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)
|
||||
#else /* LWIP_TCP_TIMESTAMPS */
|
||||
#define tcp_mss(pcb) ((pcb)->mss)
|
||||
#endif /* LWIP_TCP_TIMESTAMPS */
|
||||
#define tcp_sndbuf(pcb) (TCPWND16((pcb)->snd_buf))
|
||||
#define tcp_sndqueuelen(pcb) ((pcb)->snd_queuelen)
|
||||
/** @ingroup tcp_raw */
|
||||
|
||||
@@ -138,10 +138,10 @@
|
||||
*/
|
||||
struct link_callbacks {
|
||||
/* 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
|
||||
/* 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 */
|
||||
/* End a connection (i.e. initiate disconnect phase) */
|
||||
void (*disconnect) (ppp_pcb *pcb, void *ctx);
|
||||
|
||||
@@ -56,6 +56,10 @@
|
||||
#include "netif/ppp/pppoe.h"
|
||||
#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 ethzero = {{0,0,0,0,0,0}};
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
if (holdoff == 0) {
|
||||
new_phase(pcb, PPP_PHASE_INITIALIZE);
|
||||
return pcb->link_cb->connect(pcb, pcb->link_ctx_cb);
|
||||
ppp_do_connect(pcb);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
new_phase(pcb, PPP_PHASE_HOLDOFF);
|
||||
@@ -302,7 +302,8 @@ err_t ppp_listen(ppp_pcb *pcb) {
|
||||
|
||||
if (pcb->link_cb->listen) {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ LWIP_MEMPOOL_DECLARE(PPPOE_IF, MEMP_NUM_PPPOE_INTERFACES, sizeof(struct pppoe_so
|
||||
/* callbacks called from PPP core */
|
||||
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_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 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) */
|
||||
static err_t
|
||||
static void
|
||||
pppoe_connect(ppp_pcb *ppp, void *ctx)
|
||||
{
|
||||
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));
|
||||
}
|
||||
sys_timeout(PPPOE_DISC_TIMEOUT, pppoe_timeout, sc);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* disconnect */
|
||||
|
||||
@@ -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_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_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 */
|
||||
|
||||
/* 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. */
|
||||
static err_t pppol2tp_connect(ppp_pcb *ppp, void *ctx) {
|
||||
static void pppol2tp_connect(ppp_pcb *ppp, void *ctx) {
|
||||
err_t err;
|
||||
pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx;
|
||||
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));
|
||||
}
|
||||
sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Disconnect */
|
||||
|
||||
@@ -57,9 +57,9 @@ LWIP_MEMPOOL_DECLARE(PPPOS_PCB, MEMP_NUM_PPPOS_INTERFACES, sizeof(pppos_pcb), "P
|
||||
/* callbacks called from PPP core */
|
||||
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_connect(ppp_pcb *ppp, void *ctx);
|
||||
static void pppos_connect(ppp_pcb *ppp, void *ctx);
|
||||
#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 */
|
||||
static void pppos_disconnect(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;
|
||||
}
|
||||
|
||||
static err_t
|
||||
static void
|
||||
pppos_connect(ppp_pcb *ppp, void *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));
|
||||
ppp_start(ppp); /* notify upper layers */
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
#if PPP_SERVER
|
||||
static err_t
|
||||
static void
|
||||
pppos_listen(ppp_pcb *ppp, void *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));
|
||||
ppp_start(ppp); /* notify upper layers */
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif /* PPP_SERVER */
|
||||
|
||||
|
||||
@@ -127,8 +127,6 @@ static enum tcase {
|
||||
static int debug = 0;
|
||||
static void setdebug(int a) {debug = a;}
|
||||
|
||||
#define netif_dhcp_data(netif) ((struct dhcp*)(netif)->client_data[LWIP_NETIF_CLIENT_DATA_INDEX_DHCP])
|
||||
|
||||
static int tick = 0;
|
||||
static void tick_lwip(void)
|
||||
{
|
||||
|
||||
154
test/unit/ip4/test_ip4.c
Normal file
154
test/unit/ip4/test_ip4.c
Normal file
@@ -0,0 +1,154 @@
|
||||
#include "test_ip4.h"
|
||||
|
||||
#include "lwip/ip4.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/prot/ip.h"
|
||||
#include "lwip/prot/ip4.h"
|
||||
|
||||
#if !LWIP_IPV4 || !IP_REASSEMBLY || !MIB2_STATS || !IPFRAG_STATS
|
||||
#error "This tests needs LWIP_IPV4, IP_REASSEMBLY; MIB2- and IPFRAG-statistics enabled"
|
||||
#endif
|
||||
|
||||
/* Helper functions */
|
||||
static void
|
||||
create_ip4_input_fragment(u16_t ip_id, u16_t start, u16_t len, int last)
|
||||
{
|
||||
struct pbuf *p;
|
||||
struct netif *input_netif = netif_list; /* just use any netif */
|
||||
fail_unless((start & 7) == 0);
|
||||
fail_unless(((len & 7) == 0) || last);
|
||||
fail_unless(input_netif != NULL);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, len + sizeof(struct ip_hdr), PBUF_RAM);
|
||||
fail_unless(p != NULL);
|
||||
if (p != NULL) {
|
||||
err_t err;
|
||||
struct ip_hdr *iphdr = (struct ip_hdr *)p->payload;
|
||||
IPH_VHL_SET(iphdr, 4, sizeof(struct ip_hdr) / 4);
|
||||
IPH_TOS_SET(iphdr, 0);
|
||||
IPH_LEN_SET(iphdr, lwip_htons(p->tot_len));
|
||||
IPH_ID_SET(iphdr, lwip_htons(ip_id));
|
||||
if (last) {
|
||||
IPH_OFFSET_SET(iphdr, lwip_htons(start / 8));
|
||||
} else {
|
||||
IPH_OFFSET_SET(iphdr, lwip_htons((start / 8) | IP_MF));
|
||||
}
|
||||
IPH_TTL_SET(iphdr, 5);
|
||||
IPH_PROTO_SET(iphdr, IP_PROTO_UDP);
|
||||
IPH_CHKSUM_SET(iphdr, 0);
|
||||
ip4_addr_copy(iphdr->src, *netif_ip4_addr(input_netif));
|
||||
iphdr->src.addr = lwip_htonl(lwip_htonl(iphdr->src.addr) + 1);
|
||||
ip4_addr_copy(iphdr->dest, *netif_ip4_addr(input_netif));
|
||||
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, sizeof(struct ip_hdr)));
|
||||
|
||||
err = ip4_input(p, input_netif);
|
||||
if (err != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
fail_unless(err == ERR_OK);
|
||||
}
|
||||
}
|
||||
|
||||
/* Setups/teardown functions */
|
||||
|
||||
static void
|
||||
ip4_setup(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
ip4_teardown(void)
|
||||
{
|
||||
if (netif_list->loop_first != NULL) {
|
||||
pbuf_free(netif_list->loop_first);
|
||||
netif_list->loop_first = NULL;
|
||||
}
|
||||
netif_list->loop_last = NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Test functions */
|
||||
|
||||
START_TEST(test_ip4_reass)
|
||||
{
|
||||
const u16_t ip_id = 128;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
memset(&lwip_stats.mib2, 0, sizeof(lwip_stats.mib2));
|
||||
|
||||
create_ip4_input_fragment(ip_id, 8*200, 200, 1);
|
||||
fail_unless(lwip_stats.ip_frag.recv == 1);
|
||||
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
|
||||
|
||||
create_ip4_input_fragment(ip_id, 0*200, 200, 0);
|
||||
fail_unless(lwip_stats.ip_frag.recv == 2);
|
||||
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
|
||||
|
||||
create_ip4_input_fragment(ip_id, 1*200, 200, 0);
|
||||
fail_unless(lwip_stats.ip_frag.recv == 3);
|
||||
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
|
||||
|
||||
create_ip4_input_fragment(ip_id, 2*200, 200, 0);
|
||||
fail_unless(lwip_stats.ip_frag.recv == 4);
|
||||
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
|
||||
|
||||
create_ip4_input_fragment(ip_id, 3*200, 200, 0);
|
||||
fail_unless(lwip_stats.ip_frag.recv == 5);
|
||||
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
|
||||
|
||||
create_ip4_input_fragment(ip_id, 4*200, 200, 0);
|
||||
fail_unless(lwip_stats.ip_frag.recv == 6);
|
||||
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
|
||||
|
||||
create_ip4_input_fragment(ip_id, 7*200, 200, 0);
|
||||
fail_unless(lwip_stats.ip_frag.recv == 7);
|
||||
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
|
||||
|
||||
create_ip4_input_fragment(ip_id, 6*200, 200, 0);
|
||||
fail_unless(lwip_stats.ip_frag.recv == 8);
|
||||
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
|
||||
|
||||
create_ip4_input_fragment(ip_id, 5*200, 200, 0);
|
||||
fail_unless(lwip_stats.ip_frag.recv == 9);
|
||||
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||
fail_unless(lwip_stats.mib2.ipreasmoks == 1);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
/** Create the suite including all tests for this module */
|
||||
Suite *
|
||||
ip4_suite(void)
|
||||
{
|
||||
testfunc tests[] = {
|
||||
TESTFUNC(test_ip4_reass),
|
||||
};
|
||||
return create_suite("IPv4", tests, sizeof(tests)/sizeof(testfunc), ip4_setup, ip4_teardown);
|
||||
}
|
||||
8
test/unit/ip4/test_ip4.h
Normal file
8
test/unit/ip4/test_ip4.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef LWIP_HDR_TEST_IP4_H
|
||||
#define LWIP_HDR_TEST_IP4_H
|
||||
|
||||
#include "../lwip_check.h"
|
||||
|
||||
Suite* ip4_suite(void);
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "lwip_check.h"
|
||||
|
||||
#include "ip4/test_ip4.h"
|
||||
#include "udp/test_udp.h"
|
||||
#include "tcp/test_tcp.h"
|
||||
#include "tcp/test_tcp_oos.h"
|
||||
@@ -37,6 +38,7 @@ int main(void)
|
||||
SRunner *sr;
|
||||
size_t i;
|
||||
suite_getter_fn* suites[] = {
|
||||
ip4_suite,
|
||||
udp_suite,
|
||||
tcp_suite,
|
||||
tcp_oos_suite,
|
||||
|
||||
@@ -59,4 +59,7 @@
|
||||
/* Minimal changes to opt.h required for etharp unit tests: */
|
||||
#define ETHARP_SUPPORT_STATIC_ENTRIES 1
|
||||
|
||||
/* MIB2 stats are required to check IPv4 reassembly results */
|
||||
#define MIB2_STATS 1
|
||||
|
||||
#endif /* LWIP_HDR_LWIPOPTS_H */
|
||||
|
||||
@@ -155,19 +155,19 @@ tcp_set_state(struct tcp_pcb* pcb, enum tcp_state state, ip_addr_t* local_ip,
|
||||
|
||||
if (state == ESTABLISHED) {
|
||||
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->remote_ip.addr = remote_ip->addr;
|
||||
ip_addr_copy(pcb->remote_ip, *remote_ip);
|
||||
pcb->remote_port = remote_port;
|
||||
} else if(state == LISTEN) {
|
||||
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;
|
||||
} else if(state == TIME_WAIT) {
|
||||
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->remote_ip.addr = remote_ip->addr;
|
||||
ip_addr_copy(pcb->remote_ip, *remote_ip);
|
||||
pcb->remote_port = remote_port;
|
||||
} else {
|
||||
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->flags |= NETIF_FLAG_UP | NETIF_FLAG_LINK_UP;
|
||||
ip4_addr_copy(netif->netmask, *ip_2_ip4(netmask));
|
||||
ip4_addr_copy(netif->ip_addr, *ip_2_ip4(ip_addr));
|
||||
ip_addr_copy_from_ip4(netif->netmask, *ip_2_ip4(netmask));
|
||||
ip_addr_copy_from_ip4(netif->ip_addr, *ip_2_ip4(ip_addr));
|
||||
for (n = netif_list; n != NULL; n = n->next) {
|
||||
if (n == netif) {
|
||||
return;
|
||||
|
||||
@@ -46,9 +46,9 @@ tcp_setup(void)
|
||||
static void
|
||||
tcp_teardown(void)
|
||||
{
|
||||
tcp_remove_all();
|
||||
netif_list = NULL;
|
||||
netif_default = NULL;
|
||||
tcp_remove_all();
|
||||
}
|
||||
|
||||
|
||||
@@ -422,6 +422,8 @@ START_TEST(test_tcp_fast_rexmit_wraparound)
|
||||
pcb->mss = TCP_MSS;
|
||||
/* disable initial congestion window (we don't send a SYN here...) */
|
||||
pcb->cwnd = 2*TCP_MSS;
|
||||
/* start in congestion advoidance */
|
||||
pcb->ssthresh = pcb->cwnd;
|
||||
|
||||
/* send 6 mss-sized segments */
|
||||
for (i = 0; i < 6; i++) {
|
||||
@@ -442,7 +444,9 @@ START_TEST(test_tcp_fast_rexmit_wraparound)
|
||||
/* ACK the first segment */
|
||||
p = tcp_create_rx_segment(pcb, NULL, 0, 0, TCP_MSS, TCP_ACK);
|
||||
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_bytes == TCP_MSS + 40U);
|
||||
memset(&txcounters, 0, sizeof(txcounters));
|
||||
|
||||
Reference in New Issue
Block a user