mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2025-01-18 10:03:30 +08:00
update lwip to 1.3.2
git-svn-id: https://rt-thread.googlecode.com/svn/trunk@297 bbd45198-f89e-11dd-88c7-29a3b14d5316
This commit is contained in:
parent
ce10330d80
commit
a27f7c67bd
@ -19,9 +19,180 @@ HISTORY
|
||||
|
||||
++ New features:
|
||||
|
||||
|
||||
++ Bugfixes:
|
||||
|
||||
|
||||
(STABLE-1.3.2)
|
||||
|
||||
++ New features:
|
||||
|
||||
2009-10-27 Simon Goldschmidt/Stephan Lesage
|
||||
* netifapi.c/.h: Added netifapi_netif_set_addr()
|
||||
|
||||
2009-10-07 Simon Goldschmidt/Fabian Koch
|
||||
* api_msg.c, netbuf.c/.h, opt.h: patch #6888: Patch for UDP Netbufs to
|
||||
support dest-addr and dest-port (optional: LWIP_NETBUF_RECVINFO)
|
||||
|
||||
2009-08-26 Simon Goldschmidt/Simon Kallweit
|
||||
* slipif.c/.h: bug #26397: SLIP polling support
|
||||
|
||||
2009-08-25 Simon Goldschmidt
|
||||
* opt.h, etharp.h/.c: task #9033: Support IEEE 802.1q tagged frame (VLAN),
|
||||
New configuration options ETHARP_SUPPORT_VLAN and ETHARP_VLAN_CHECK.
|
||||
|
||||
2009-08-25 Simon Goldschmidt
|
||||
* ip_addr.h, netdb.c: patch #6900: added define ip_ntoa(struct ip_addr*)
|
||||
|
||||
2009-08-24 Jakob Stoklund Olesen
|
||||
* autoip.c, dhcp.c, netif.c: patch #6725: Teach AutoIP and DHCP to respond
|
||||
to netif_set_link_up().
|
||||
|
||||
2009-08-23 Simon Goldschmidt
|
||||
* tcp.h/.c: Added function tcp_debug_state_str() to convert a tcp state
|
||||
to a human-readable string.
|
||||
|
||||
++ Bugfixes:
|
||||
|
||||
2009-12-24: Kieran Mansley
|
||||
* tcp_in.c Apply patches from Oleg Tyshev to improve OOS processing
|
||||
(BUG#28241)
|
||||
|
||||
2009-12-06: Simon Goldschmidt
|
||||
* ppp.h/.c: Fixed bug #27079 (Yet another leak in PPP): outpacket_buf can
|
||||
be statically allocated (like in ucip)
|
||||
|
||||
2009-12-04: Simon Goldschmidt (patch by Ioardan Neshev)
|
||||
* pap.c: patch #6969: PPP: missing PAP authentication UNTIMEOUT
|
||||
|
||||
2009-12-03: Simon Goldschmidt
|
||||
* tcp.h, tcp_in.c, tcp_out.c: Fixed bug #28106: dup ack for fast retransmit
|
||||
could have non-zero length
|
||||
|
||||
2009-12-02: Simon Goldschmidt
|
||||
* tcp_in.c: Fixed bug #27904: TCP sends too many ACKs: delay resetting
|
||||
tcp_input_pcb until after calling the pcb's callbacks
|
||||
|
||||
2009-11-29: Simon Goldschmidt
|
||||
* tcp_in.c: Fixed bug #28054: Two segments with FIN flag on the out-of-
|
||||
sequence queue, also fixed PBUF_POOL leak in the out-of-sequence code
|
||||
|
||||
2009-11-29: Simon Goldschmidt
|
||||
* pbuf.c: Fixed bug #28064: pbuf_alloc(PBUF_POOL) is not thread-safe by
|
||||
queueing a call into tcpip_thread to free ooseq-bufs if the pool is empty
|
||||
|
||||
2009-11-26: Simon Goldschmidt
|
||||
* tcp.h: Fixed bug #28098: Nagle can prevent fast retransmit from sending
|
||||
segment
|
||||
|
||||
2009-11-26: Simon Goldschmidt
|
||||
* tcp.h, sockets.c: Fixed bug #28099: API required to disable Nagle
|
||||
algorithm at PCB level
|
||||
|
||||
2009-11-22: Simon Goldschmidt
|
||||
* tcp_out.c: Fixed bug #27905: FIN isn't combined with data on unsent
|
||||
|
||||
2009-11-22: Simon Goldschmidt (suggested by Bill Auerbach)
|
||||
* tcp.c: tcp_alloc: prevent increasing stats.err for MEMP_TCP_PCB when
|
||||
reusing time-wait pcb
|
||||
|
||||
2009-11-20: Simon Goldschmidt (patch by Albert Bartel)
|
||||
* sockets.c: Fixed bug #28062: Data received directly after accepting
|
||||
does not wake up select
|
||||
|
||||
2009-11-11: Simon Goldschmidt
|
||||
* netdb.h: Fixed bug #27994: incorrect define for freeaddrinfo(addrinfo)
|
||||
|
||||
2009-10-30: Simon Goldschmidt
|
||||
* opt.h: Increased default value for TCP_MSS to 536, updated default
|
||||
value for TCP_WND to 4*TCP_MSS to keep delayed ACK working.
|
||||
|
||||
2009-10-28: Kieran Mansley
|
||||
* tcp_in.c, tcp_out.c, tcp.h: re-work the fast retransmission code
|
||||
to follow algorithm from TCP/IP Illustrated
|
||||
|
||||
2009-10-27: Kieran Mansley
|
||||
* tcp_in.c: fix BUG#27445: grow cwnd with every duplicate ACK
|
||||
|
||||
2009-10-25: Simon Goldschmidt
|
||||
* tcp.h: bug-fix in the TCP_EVENT_RECV macro (has to call tcp_recved if
|
||||
pcb->recv is NULL to keep rcv_wnd correct)
|
||||
|
||||
2009-10-25: Simon Goldschmidt
|
||||
* tcp_in.c: Fixed bug #26251: RST process in TIME_WAIT TCP state
|
||||
|
||||
2009-10-23: Simon Goldschmidt (David Empson)
|
||||
* tcp.c: Fixed bug #27783: Silly window avoidance for small window sizes
|
||||
|
||||
2009-10-21: Simon Goldschmidt
|
||||
* tcp_in.c: Fixed bug #27215: TCP sent() callback gives leading and
|
||||
trailing 1 byte len (SYN/FIN)
|
||||
|
||||
2009-10-21: Simon Goldschmidt
|
||||
* tcp_out.c: Fixed bug #27315: zero window probe and FIN
|
||||
|
||||
2009-10-19: Simon Goldschmidt
|
||||
* dhcp.c/.h: Minor code simplification (don't store received pbuf, change
|
||||
conditional code to assert where applicable), check pbuf length before
|
||||
testing for valid reply
|
||||
|
||||
2009-10-19: Simon Goldschmidt
|
||||
* dhcp.c: Removed most calls to udp_connect since they aren't necessary
|
||||
when using udp_sendto_if() - always stay connected to IP_ADDR_ANY.
|
||||
|
||||
2009-10-16: Simon Goldschmidt
|
||||
* ip.c: Fixed bug #27390: Source IP check in ip_input() causes it to drop
|
||||
valid DHCP packets -> allow 0.0.0.0 as source address when LWIP_DHCP is
|
||||
enabled
|
||||
|
||||
2009-10-15: Simon Goldschmidt (Oleg Tyshev)
|
||||
* tcp_in.c: Fixed bug #27329: dupacks by unidirectional data transmit
|
||||
|
||||
2009-10-15: Simon Goldschmidt
|
||||
* api_lib.c: Fixed bug #27709: conn->err race condition on netconn_recv()
|
||||
timeout
|
||||
|
||||
2009-10-15: Simon Goldschmidt
|
||||
* autoip.c: Fixed bug #27704: autoip starts with wrong address
|
||||
LWIP_AUTOIP_CREATE_SEED_ADDR() returned address in host byte order instead
|
||||
of network byte order
|
||||
|
||||
2009-10-11 Simon Goldschmidt (Jörg Kesten)
|
||||
* tcp_out.c: Fixed bug #27504: tcp_enqueue wrongly concatenates segments
|
||||
which are not consecutive when retransmitting unacked segments
|
||||
|
||||
2009-10-09 Simon Goldschmidt
|
||||
* opt.h: Fixed default values of some stats to only be enabled if used
|
||||
Fixes bug #27338: sys_stats is defined when NO_SYS = 1
|
||||
|
||||
2009-08-30 Simon Goldschmidt
|
||||
* ip.c: Fixed bug bug #27345: "ip_frag() does not use the LWIP_NETIF_LOOPBACK
|
||||
function" by checking for loopback before calling ip_frag
|
||||
|
||||
2009-08-25 Simon Goldschmidt
|
||||
* dhcp.c: fixed invalid dependency to etharp_query if DHCP_DOES_ARP_CHECK==0
|
||||
|
||||
2009-08-23 Simon Goldschmidt
|
||||
* ppp.c: bug #27078: Possible memory leak in pppInit()
|
||||
|
||||
2009-08-23 Simon Goldschmidt
|
||||
* netdb.c, dns.c: bug #26657: DNS, if host name is "localhost", result
|
||||
is error.
|
||||
|
||||
2009-08-23 Simon Goldschmidt
|
||||
* opt.h, init.c: bug #26649: TCP fails when TCP_MSS > TCP_SND_BUF
|
||||
Fixed wrong parenthesis, added check in init.c
|
||||
|
||||
2009-08-23 Simon Goldschmidt
|
||||
* ppp.c: bug #27266: wait-state debug message in pppMain occurs every ms
|
||||
|
||||
2009-08-23 Simon Goldschmidt
|
||||
* many ppp files: bug #27267: Added include to string.h where needed
|
||||
|
||||
2009-08-23 Simon Goldschmidt
|
||||
* tcp.h: patch #6843: tcp.h macro optimization patch (for little endian)
|
||||
|
||||
|
||||
(STABLE-1.3.1)
|
||||
|
||||
++ New features:
|
||||
|
@ -72,7 +72,7 @@ current CVS sources and is available from this web page:
|
||||
http://www.nongnu.org/lwip/
|
||||
|
||||
There is now a constantly growin wiki about lwIP at
|
||||
http://lwip.scribblewiki.com/
|
||||
http://lwip.wikia.com/wiki/LwIP_Wiki
|
||||
|
||||
Also, there are mailing lists you can subscribe at
|
||||
http://savannah.nongnu.org/mail/?group=lwip
|
||||
|
@ -16,7 +16,7 @@ src/arch/sys_arch_init.c
|
||||
src/core/dhcp.c
|
||||
src/core/dns.c
|
||||
src/core/init.c
|
||||
src/core/memp_tiny.c
|
||||
src/core/memp.c
|
||||
src/core/netif.c
|
||||
src/core/pbuf.c
|
||||
src/core/raw.c
|
||||
|
@ -327,8 +327,9 @@ netconn_recv(struct netconn *conn)
|
||||
|
||||
#if LWIP_SO_RCVTIMEO
|
||||
if (sys_arch_mbox_fetch(conn->recvmbox, (void *)&p, conn->recv_timeout)==SYS_ARCH_TIMEOUT) {
|
||||
memp_free(MEMP_NETBUF, buf);
|
||||
conn->err = ERR_TIMEOUT;
|
||||
p = NULL;
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
sys_arch_mbox_fetch(conn->recvmbox, (void *)&p, 0);
|
||||
|
@ -168,6 +168,15 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
||||
buf->ptr = p;
|
||||
buf->addr = addr;
|
||||
buf->port = port;
|
||||
#if LWIP_NETBUF_RECVINFO
|
||||
{
|
||||
const struct ip_hdr* iphdr = ip_current_header();
|
||||
/* get the UDP header - always in the first pbuf, ensured by udp_input */
|
||||
const struct udp_hdr* udphdr = (void*)(((char*)iphdr) + IPH_LEN(iphdr));
|
||||
buf->toaddr = (struct ip_addr*)&iphdr->dest;
|
||||
buf->toport = udphdr->dest;
|
||||
}
|
||||
#endif /* LWIP_NETBUF_RECVINFO */
|
||||
}
|
||||
|
||||
if (sys_mbox_trypost(conn->recvmbox, buf) != ERR_OK) {
|
||||
@ -807,6 +816,8 @@ do_connect(struct api_msg_msg *msg)
|
||||
break;
|
||||
#endif /* LWIP_TCP */
|
||||
default:
|
||||
LWIP_ERROR("Invalid netconn type", 0, do{ msg->conn->err = ERR_VAL;
|
||||
sys_sem_signal(msg->conn->op_completed); }while(0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1149,7 +1160,7 @@ do_close(struct api_msg_msg *msg)
|
||||
#endif /* LWIP_TCP */
|
||||
{
|
||||
msg->conn->err = ERR_VAL;
|
||||
TCPIP_APIMSG_ACK(msg);
|
||||
sys_sem_signal(msg->conn->op_completed);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,6 +62,11 @@ netbuf *netbuf_new(void)
|
||||
buf->p = NULL;
|
||||
buf->ptr = NULL;
|
||||
buf->addr = NULL;
|
||||
buf->port = 0;
|
||||
#if LWIP_NETBUF_RECVINFO
|
||||
buf->toaddr = NULL;
|
||||
buf->toport = 0;
|
||||
#endif /* LWIP_NETBUF_RECVINFO */
|
||||
return buf;
|
||||
} else {
|
||||
return NULL;
|
||||
|
@ -116,7 +116,7 @@ lwip_gethostbyname(const char *name)
|
||||
u8_t idx;
|
||||
for ( idx=0; s_hostent.h_aliases[idx]; idx++) {
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases[%i]-> == %p\n", idx, s_hostent.h_aliases[idx]));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases[%i]-> == %s\n", idx, s_hostent.h_aliases[idx]));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases[%i]-> == %s\n", idx, s_hostent.h_aliases[idx]));
|
||||
}
|
||||
}
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addrtype == %d\n", s_hostent.h_addrtype));
|
||||
@ -126,7 +126,7 @@ lwip_gethostbyname(const char *name)
|
||||
u8_t idx;
|
||||
for ( idx=0; s_hostent.h_addr_list[idx]; idx++) {
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i] == %p\n", idx, s_hostent.h_addr_list[idx]));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, inet_ntoa(*((struct in_addr*)(s_hostent.h_addr_list[idx])))));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ip_ntoa(s_hostent.h_addr_list[idx])));
|
||||
}
|
||||
}
|
||||
#endif /* DNS_DEBUG */
|
||||
@ -234,12 +234,6 @@ lwip_freeaddrinfo(struct addrinfo *ai)
|
||||
struct addrinfo *next;
|
||||
|
||||
while (ai != NULL) {
|
||||
if (ai->ai_addr != NULL) {
|
||||
mem_free(ai->ai_addr);
|
||||
}
|
||||
if (ai->ai_canonname != NULL) {
|
||||
mem_free(ai->ai_canonname);
|
||||
}
|
||||
next = ai->ai_next;
|
||||
mem_free(ai);
|
||||
ai = next;
|
||||
@ -274,6 +268,8 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
|
||||
struct addrinfo *ai;
|
||||
struct sockaddr_in *sa = NULL;
|
||||
int port_nr = 0;
|
||||
size_t total_size;
|
||||
size_t namelen = 0;
|
||||
|
||||
if (res == NULL) {
|
||||
return EAI_FAIL;
|
||||
@ -300,19 +296,21 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
|
||||
}
|
||||
} else {
|
||||
/* service location specified, use loopback address */
|
||||
addr.addr = INADDR_LOOPBACK;
|
||||
addr.addr = htonl(INADDR_LOOPBACK);
|
||||
}
|
||||
|
||||
ai = mem_malloc(sizeof(struct addrinfo));
|
||||
total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_in);
|
||||
if (nodename != NULL) {
|
||||
namelen = strlen(nodename);
|
||||
LWIP_ASSERT("namelen is too long", (namelen + 1) <= (mem_size_t)-1);
|
||||
total_size += namelen + 1;
|
||||
}
|
||||
ai = mem_malloc(total_size);
|
||||
if (ai == NULL) {
|
||||
goto memerr;
|
||||
}
|
||||
memset(ai, 0, sizeof(struct addrinfo));
|
||||
sa = mem_malloc(sizeof(struct sockaddr_in));
|
||||
if (sa == NULL) {
|
||||
goto memerr;
|
||||
}
|
||||
memset(sa, 0, sizeof(struct sockaddr_in));
|
||||
memset(ai, 0, total_size);
|
||||
sa = (struct sockaddr_in*)((u8_t*)ai + sizeof(struct addrinfo));
|
||||
/* set up sockaddr */
|
||||
sa->sin_addr.s_addr = addr.addr;
|
||||
sa->sin_family = AF_INET;
|
||||
@ -328,12 +326,7 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
|
||||
}
|
||||
if (nodename != NULL) {
|
||||
/* copy nodename to canonname if specified */
|
||||
size_t namelen = strlen(nodename);
|
||||
LWIP_ASSERT("namelen is too long", (namelen + 1) <= (mem_size_t)-1);
|
||||
ai->ai_canonname = mem_malloc((mem_size_t)(namelen + 1));
|
||||
if (ai->ai_canonname == NULL) {
|
||||
goto memerr;
|
||||
}
|
||||
ai->ai_canonname = ((char*)ai + sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
|
||||
MEMCPY(ai->ai_canonname, nodename, namelen);
|
||||
ai->ai_canonname[namelen] = 0;
|
||||
}
|
||||
@ -347,9 +340,6 @@ memerr:
|
||||
if (ai != NULL) {
|
||||
mem_free(ai);
|
||||
}
|
||||
if (sa != NULL) {
|
||||
mem_free(sa);
|
||||
}
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
|
||||
|
@ -58,6 +58,20 @@ do_netifapi_netif_add( struct netifapi_msg_msg *msg)
|
||||
TCPIP_NETIFAPI_ACK(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call netif_set_addr() inside the tcpip_thread context.
|
||||
*/
|
||||
void
|
||||
do_netifapi_netif_set_addr( struct netifapi_msg_msg *msg)
|
||||
{
|
||||
netif_set_addr( msg->netif,
|
||||
msg->msg.add.ipaddr,
|
||||
msg->msg.add.netmask,
|
||||
msg->msg.add.gw);
|
||||
msg->err = ERR_OK;
|
||||
TCPIP_NETIFAPI_ACK(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the
|
||||
* tcpip_thread context.
|
||||
@ -103,6 +117,28 @@ netifapi_netif_add(struct netif *netif,
|
||||
return msg.msg.err;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call netif_set_addr() in a thread-safe way by running that function inside the
|
||||
* tcpip_thread context.
|
||||
*
|
||||
* @note for params @see netif_set_addr()
|
||||
*/
|
||||
err_t
|
||||
netifapi_netif_set_addr(struct netif *netif,
|
||||
struct ip_addr *ipaddr,
|
||||
struct ip_addr *netmask,
|
||||
struct ip_addr *gw)
|
||||
{
|
||||
struct netifapi_msg msg;
|
||||
msg.function = do_netifapi_netif_set_addr;
|
||||
msg.msg.netif = netif;
|
||||
msg.msg.msg.add.ipaddr = ipaddr;
|
||||
msg.msg.msg.add.netmask = netmask;
|
||||
msg.msg.msg.add.gw = gw;
|
||||
TCPIP_NETIFAPI(&msg);
|
||||
return msg.msg.err;
|
||||
}
|
||||
|
||||
/**
|
||||
* call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) in a thread-safe
|
||||
* way by running that function inside the tcpip_thread context.
|
||||
|
@ -494,7 +494,7 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
|
||||
buf = sock->lastdata;
|
||||
} else {
|
||||
/* If this is non-blocking call, then check first */
|
||||
if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK)) &&
|
||||
if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK)) &&
|
||||
(sock->rcvevent <= 0)) {
|
||||
if (off > 0) {
|
||||
/* already received data, return that */
|
||||
@ -546,9 +546,9 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
|
||||
if (netconn_type(sock->conn) == NETCONN_TCP) {
|
||||
LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen);
|
||||
len -= copylen;
|
||||
if ( (len <= 0) ||
|
||||
(buf->p->flags & PBUF_FLAG_PUSH) ||
|
||||
(sock->rcvevent <= 0) ||
|
||||
if ( (len <= 0) ||
|
||||
(buf->p->flags & PBUF_FLAG_PUSH) ||
|
||||
(sock->rcvevent <= 0) ||
|
||||
((flags & MSG_PEEK)!=0)) {
|
||||
done = 1;
|
||||
}
|
||||
@ -702,16 +702,16 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
|
||||
#if LWIP_TCPIP_CORE_LOCKING
|
||||
/* Should only be consider like a sample or a simple way to experiment this option (no check of "to" field...) */
|
||||
{ struct pbuf* p;
|
||||
|
||||
|
||||
p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
|
||||
if (p == NULL) {
|
||||
err = ERR_MEM;
|
||||
} else {
|
||||
p->payload = (void*)data;
|
||||
p->len = p->tot_len = short_size;
|
||||
|
||||
|
||||
remote_addr.addr = ((const struct sockaddr_in *)to)->sin_addr.s_addr;
|
||||
|
||||
|
||||
LOCK_TCPIP_CORE();
|
||||
if (sock->conn->type==NETCONN_RAW) {
|
||||
err = sock->conn->err = raw_sendto(sock->conn->pcb.raw, p, &remote_addr);
|
||||
@ -719,7 +719,7 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
|
||||
err = sock->conn->err = udp_sendto(sock->conn->pcb.udp, p, &remote_addr, ntohs(((const struct sockaddr_in *)to)->sin_port));
|
||||
}
|
||||
UNLOCK_TCPIP_CORE();
|
||||
|
||||
|
||||
pbuf_free(p);
|
||||
}
|
||||
}
|
||||
@ -845,11 +845,11 @@ lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
|
||||
int i, nready = 0;
|
||||
fd_set lreadset, lwriteset, lexceptset;
|
||||
struct lwip_socket *p_sock;
|
||||
|
||||
|
||||
FD_ZERO(&lreadset);
|
||||
FD_ZERO(&lwriteset);
|
||||
FD_ZERO(&lexceptset);
|
||||
|
||||
|
||||
/* Go through each socket in each list to count number of sockets which
|
||||
currently match */
|
||||
for(i = 0; i < maxfdp1; i++) {
|
||||
@ -875,7 +875,7 @@ lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
|
||||
*readset = lreadset;
|
||||
*writeset = lwriteset;
|
||||
FD_ZERO(exceptset);
|
||||
|
||||
|
||||
return nready;
|
||||
}
|
||||
|
||||
@ -935,27 +935,27 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
|
||||
FD_ZERO(writeset);
|
||||
if (exceptset)
|
||||
FD_ZERO(exceptset);
|
||||
|
||||
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n"));
|
||||
set_errno(0);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* add our semaphore to list */
|
||||
/* We don't actually need any dynamic memory. Our entry on the
|
||||
* list is only valid while we are in this function, so it's ok
|
||||
* to use local variables */
|
||||
|
||||
|
||||
select_cb.sem = sys_sem_new(0);
|
||||
/* Note that we are still protected */
|
||||
/* Put this select_cb on top of list */
|
||||
select_cb.next = select_cb_list;
|
||||
select_cb_list = &select_cb;
|
||||
|
||||
|
||||
/* Now we can safely unprotect */
|
||||
sys_sem_signal(selectsem);
|
||||
|
||||
|
||||
/* Now just wait to be woken */
|
||||
if (timeout == 0)
|
||||
/* Wait forever */
|
||||
@ -965,7 +965,7 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
|
||||
if(msectimeout == 0)
|
||||
msectimeout = 1;
|
||||
}
|
||||
|
||||
|
||||
if (sys_arch_timeouts() == NULL){
|
||||
/* it's not a lwip thread, use os semaphore with timeout to handle it */
|
||||
i = sys_arch_sem_wait(select_cb.sem, msectimeout);
|
||||
@ -976,7 +976,7 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
|
||||
/* it's a lwip thread, use os semaphore with timeout to handle it */
|
||||
i = sys_sem_wait_timeout(select_cb.sem, msectimeout);
|
||||
}
|
||||
|
||||
|
||||
/* Take us off the list */
|
||||
sys_sem_wait(selectsem);
|
||||
if (select_cb_list == &select_cb)
|
||||
@ -988,9 +988,9 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sys_sem_signal(selectsem);
|
||||
|
||||
|
||||
sys_sem_free(select_cb.sem);
|
||||
if (i == 0) {
|
||||
/* Timeout */
|
||||
@ -1000,13 +1000,13 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
|
||||
FD_ZERO(writeset);
|
||||
if (exceptset)
|
||||
FD_ZERO(exceptset);
|
||||
|
||||
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n"));
|
||||
set_errno(0);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (readset)
|
||||
lreadset = *readset;
|
||||
else
|
||||
@ -1019,22 +1019,22 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
|
||||
lexceptset = *exceptset;
|
||||
else
|
||||
FD_ZERO(&lexceptset);
|
||||
|
||||
|
||||
/* See what's set */
|
||||
nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset);
|
||||
} else
|
||||
sys_sem_signal(selectsem);
|
||||
|
||||
|
||||
if (readset)
|
||||
*readset = lreadset;
|
||||
if (writeset)
|
||||
*writeset = lwriteset;
|
||||
if (exceptset)
|
||||
*exceptset = lexceptset;
|
||||
|
||||
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready));
|
||||
set_errno(0);
|
||||
|
||||
|
||||
return nready;
|
||||
}
|
||||
|
||||
@ -1068,6 +1068,7 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
|
||||
sys_sem_signal(socksem);
|
||||
return;
|
||||
}
|
||||
s = conn->socket;
|
||||
sys_sem_signal(socksem);
|
||||
}
|
||||
|
||||
@ -1205,11 +1206,11 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
|
||||
|
||||
/* Do length and type checks for the various options first, to keep it readable. */
|
||||
switch (level) {
|
||||
|
||||
|
||||
/* Level: SOL_SOCKET */
|
||||
case SOL_SOCKET:
|
||||
switch (optname) {
|
||||
|
||||
|
||||
case SO_ACCEPTCONN:
|
||||
case SO_BROADCAST:
|
||||
/* UNIMPL case SO_DEBUG: */
|
||||
@ -1258,7 +1259,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
|
||||
err = ENOPROTOOPT;
|
||||
} /* switch (optname) */
|
||||
break;
|
||||
|
||||
|
||||
/* Level: IPPROTO_IP */
|
||||
case IPPROTO_IP:
|
||||
switch (optname) {
|
||||
@ -1290,7 +1291,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
|
||||
err = ENOPROTOOPT;
|
||||
} /* switch (optname) */
|
||||
break;
|
||||
|
||||
|
||||
#if LWIP_TCP
|
||||
/* Level: IPPROTO_TCP */
|
||||
case IPPROTO_TCP:
|
||||
@ -1298,7 +1299,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
|
||||
err = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* If this is no TCP socket, ignore any options. */
|
||||
if (sock->conn->type != NETCONN_TCP)
|
||||
return 0;
|
||||
@ -1312,7 +1313,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
|
||||
case TCP_KEEPCNT:
|
||||
#endif /* LWIP_TCP_KEEPALIVE */
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
|
||||
s, optname));
|
||||
@ -1327,7 +1328,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
|
||||
err = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* If this is no UDP lite socket, ignore any options. */
|
||||
if (sock->conn->type != NETCONN_UDPLITE)
|
||||
return 0;
|
||||
@ -1336,7 +1337,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
|
||||
case UDPLITE_SEND_CSCOV:
|
||||
case UDPLITE_RECV_CSCOV:
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
|
||||
s, optname));
|
||||
@ -1351,7 +1352,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
|
||||
err = ENOPROTOOPT;
|
||||
} /* switch */
|
||||
|
||||
|
||||
|
||||
if (err != ERR_OK) {
|
||||
sock_set_errno(sock, err);
|
||||
return -1;
|
||||
@ -1396,7 +1397,7 @@ lwip_getsockopt_internal(void *arg)
|
||||
optval = data->optval;
|
||||
|
||||
switch (level) {
|
||||
|
||||
|
||||
/* Level: SOL_SOCKET */
|
||||
case SOL_SOCKET:
|
||||
switch (optname) {
|
||||
@ -1442,7 +1443,7 @@ lwip_getsockopt_internal(void *arg)
|
||||
case SO_ERROR:
|
||||
if (sock->err == 0) {
|
||||
sock_set_errno(sock, err_to_errno(sock->conn->err));
|
||||
}
|
||||
}
|
||||
*(int *)optval = sock->err;
|
||||
sock->err = 0;
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n",
|
||||
@ -1500,7 +1501,7 @@ lwip_getsockopt_internal(void *arg)
|
||||
case IPPROTO_TCP:
|
||||
switch (optname) {
|
||||
case TCP_NODELAY:
|
||||
*(int*)optval = (sock->conn->pcb.tcp->flags & TF_NODELAY);
|
||||
*(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n",
|
||||
s, (*(int*)optval)?"on":"off") );
|
||||
break;
|
||||
@ -1861,9 +1862,9 @@ lwip_setsockopt_internal(void *arg)
|
||||
switch (optname) {
|
||||
case TCP_NODELAY:
|
||||
if (*(int*)optval) {
|
||||
sock->conn->pcb.tcp->flags |= TF_NODELAY;
|
||||
tcp_nagle_disable(sock->conn->pcb.tcp);
|
||||
} else {
|
||||
sock->conn->pcb.tcp->flags &= ~TF_NODELAY;
|
||||
tcp_nagle_enable(sock->conn->pcb.tcp);
|
||||
}
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n",
|
||||
s, (*(int *)optval)?"on":"off") );
|
||||
|
@ -99,6 +99,10 @@
|
||||
* MTU is checked to be big enough in dhcp_start */
|
||||
#define DHCP_MAX_MSG_LEN(netif) (netif->mtu)
|
||||
#define DHCP_MAX_MSG_LEN_MIN_REQUIRED 576
|
||||
/** Minimum length for reply before packet is parsed */
|
||||
#define DHCP_MIN_REPLY_LEN 44
|
||||
|
||||
#define REBOOT_TRIES 2
|
||||
|
||||
/* DHCP client state machine functions */
|
||||
static void dhcp_handle_ack(struct netif *netif);
|
||||
@ -107,17 +111,18 @@ static void dhcp_handle_offer(struct netif *netif);
|
||||
|
||||
static err_t dhcp_discover(struct netif *netif);
|
||||
static err_t dhcp_select(struct netif *netif);
|
||||
static void dhcp_check(struct netif *netif);
|
||||
static void dhcp_bind(struct netif *netif);
|
||||
#if DHCP_DOES_ARP_CHECK
|
||||
static void dhcp_check(struct netif *netif);
|
||||
static err_t dhcp_decline(struct netif *netif);
|
||||
#endif /* DHCP_DOES_ARP_CHECK */
|
||||
static err_t dhcp_rebind(struct netif *netif);
|
||||
static err_t dhcp_reboot(struct netif *netif);
|
||||
static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state);
|
||||
|
||||
/* receive, unfold, parse and free incoming messages */
|
||||
static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port);
|
||||
static err_t dhcp_unfold_reply(struct dhcp *dhcp);
|
||||
static err_t dhcp_unfold_reply(struct dhcp *dhcp, struct pbuf *p);
|
||||
static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type);
|
||||
static u8_t dhcp_get_option_byte(u8_t *ptr);
|
||||
#if 0
|
||||
@ -161,7 +166,7 @@ static void
|
||||
dhcp_handle_nak(struct netif *netif)
|
||||
{
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n",
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n",
|
||||
(void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
|
||||
/* Set the interface down since the address must no longer be used, as per RFC2131 */
|
||||
netif_set_down(netif);
|
||||
@ -175,6 +180,7 @@ dhcp_handle_nak(struct netif *netif)
|
||||
dhcp_discover(netif);
|
||||
}
|
||||
|
||||
#if DHCP_DOES_ARP_CHECK
|
||||
/**
|
||||
* Checks if the offered IP address is already in use.
|
||||
*
|
||||
@ -190,20 +196,21 @@ dhcp_check(struct netif *netif)
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
err_t result;
|
||||
u16_t msecs;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0],
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0],
|
||||
(s16_t)netif->name[1]));
|
||||
dhcp_set_state(dhcp, DHCP_CHECKING);
|
||||
/* create an ARP query for the offered IP address, expecting that no host
|
||||
responds, as the IP address should not be in use. */
|
||||
result = etharp_query(netif, &dhcp->offered_ip_addr, NULL);
|
||||
if (result != ERR_OK) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_check: could not perform ARP query\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_check: could not perform ARP query\n"));
|
||||
}
|
||||
dhcp->tries++;
|
||||
msecs = 500;
|
||||
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_check(): set request timeout %"U16_F" msecs\n", msecs));
|
||||
}
|
||||
#endif /* DHCP_DOES_ARP_CHECK */
|
||||
|
||||
/**
|
||||
* Remember the configuration offered by a DHCP server.
|
||||
@ -216,7 +223,7 @@ dhcp_handle_offer(struct netif *netif)
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
/* obtain the server address */
|
||||
u8_t *option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_SERVER_ID);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n",
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n",
|
||||
(void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
|
||||
if (option_ptr != NULL) {
|
||||
dhcp->server_ip_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
|
||||
@ -247,7 +254,7 @@ dhcp_select(struct netif *netif)
|
||||
const char *p;
|
||||
#endif /* LWIP_NETIF_HOSTNAME */
|
||||
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_select(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_select(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
|
||||
dhcp_set_state(dhcp, DHCP_REQUESTING);
|
||||
|
||||
/* create and initialize the DHCP message header */
|
||||
@ -286,16 +293,12 @@ dhcp_select(struct netif *netif)
|
||||
/* shrink the pbuf to the actual content length */
|
||||
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
|
||||
|
||||
/* TODO: we really should bind to a specific local interface here
|
||||
but we cannot specify an unconfigured netif as it is addressless */
|
||||
/* send broadcast to any DHCP server */
|
||||
udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
|
||||
/* reconnect to any (or to server here?!) */
|
||||
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
|
||||
dhcp_delete_request(netif);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n"));
|
||||
} else {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_select: could not allocate DHCP request\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_select: could not allocate DHCP request\n"));
|
||||
}
|
||||
dhcp->tries++;
|
||||
msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000;
|
||||
@ -378,7 +381,7 @@ static void
|
||||
dhcp_timeout(struct netif *netif)
|
||||
{
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_timeout()\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout()\n"));
|
||||
/* back-off period has passed, or server selection timed out */
|
||||
if ((dhcp->state == DHCP_BACKING_OFF) || (dhcp->state == DHCP_SELECTING)) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout(): restarting discovery\n"));
|
||||
@ -393,6 +396,7 @@ dhcp_timeout(struct netif *netif)
|
||||
dhcp_release(netif);
|
||||
dhcp_discover(netif);
|
||||
}
|
||||
#if DHCP_DOES_ARP_CHECK
|
||||
/* received no ARP reply for the offered address (which is good) */
|
||||
} else if (dhcp->state == DHCP_CHECKING) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): CHECKING, ARP request timed out\n"));
|
||||
@ -404,6 +408,7 @@ dhcp_timeout(struct netif *netif)
|
||||
/* bind the interface to the offered address */
|
||||
dhcp_bind(netif);
|
||||
}
|
||||
#endif /* DHCP_DOES_ARP_CHECK */
|
||||
}
|
||||
/* did not get response to renew request? */
|
||||
else if (dhcp->state == DHCP_RENEWING) {
|
||||
@ -421,6 +426,12 @@ dhcp_timeout(struct netif *netif)
|
||||
dhcp_release(netif);
|
||||
dhcp_discover(netif);
|
||||
}
|
||||
} else if (dhcp->state == DHCP_REBOOTING) {
|
||||
if (dhcp->tries < REBOOT_TRIES) {
|
||||
dhcp_reboot(netif);
|
||||
} else {
|
||||
dhcp_discover(netif);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -600,13 +611,13 @@ dhcp_start(struct netif *netif)
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): allocated dhcp"));
|
||||
/* already has DHCP client attached */
|
||||
} else {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 3, ("dhcp_start(): restarting DHCP configuration\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(): restarting DHCP configuration\n"));
|
||||
if (dhcp->pcb != NULL) {
|
||||
udp_remove(dhcp->pcb);
|
||||
}
|
||||
if (dhcp->p != NULL) {
|
||||
pbuf_free(dhcp->p);
|
||||
}
|
||||
LWIP_ASSERT("pbuf p_out wasn't freed", dhcp->p_out == NULL);
|
||||
LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL &&
|
||||
dhcp->options_in == NULL && dhcp->options_in_len == 0);
|
||||
}
|
||||
|
||||
/* clear data structure */
|
||||
@ -652,23 +663,23 @@ dhcp_start(struct netif *netif)
|
||||
void
|
||||
dhcp_inform(struct netif *netif)
|
||||
{
|
||||
struct dhcp *dhcp, *old_dhcp = netif->dhcp;
|
||||
struct dhcp *dhcp, *old_dhcp;
|
||||
err_t result = ERR_OK;
|
||||
dhcp = mem_malloc(sizeof(struct dhcp));
|
||||
if (dhcp == NULL) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_inform(): could not allocate dhcp\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform(): could not allocate dhcp\n"));
|
||||
return;
|
||||
}
|
||||
netif->dhcp = dhcp;
|
||||
memset(dhcp, 0, sizeof(struct dhcp));
|
||||
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): allocated dhcp\n"));
|
||||
dhcp->pcb = udp_new();
|
||||
if (dhcp->pcb == NULL) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_inform(): could not obtain pcb"));
|
||||
mem_free((void *)dhcp);
|
||||
return;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform(): could not obtain pcb"));
|
||||
goto free_dhcp_and_return;
|
||||
}
|
||||
old_dhcp = netif->dhcp;
|
||||
netif->dhcp = dhcp;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): created new udp pcb\n"));
|
||||
/* create and initialize the DHCP message header */
|
||||
result = dhcp_create_request(netif);
|
||||
@ -688,21 +699,48 @@ dhcp_inform(struct netif *netif)
|
||||
dhcp->pcb->so_options|=SOF_BROADCAST;
|
||||
#endif /* IP_SOF_BROADCAST */
|
||||
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
|
||||
udp_connect(dhcp->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_inform: INFORMING\n"));
|
||||
udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
|
||||
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
|
||||
dhcp_delete_request(netif);
|
||||
} else {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_inform: could not allocate DHCP request\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform: could not allocate DHCP request\n"));
|
||||
}
|
||||
|
||||
if (dhcp->pcb != NULL) {
|
||||
udp_remove(dhcp->pcb);
|
||||
}
|
||||
udp_remove(dhcp->pcb);
|
||||
dhcp->pcb = NULL;
|
||||
mem_free((void *)dhcp);
|
||||
netif->dhcp = old_dhcp;
|
||||
free_dhcp_and_return:
|
||||
mem_free((void *)dhcp);
|
||||
}
|
||||
|
||||
/** Handle a possible change in the network configuration.
|
||||
*
|
||||
* This enters the REBOOTING state to verify that the currently bound
|
||||
* address is still valid.
|
||||
*/
|
||||
void
|
||||
dhcp_network_changed(struct netif *netif)
|
||||
{
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
if (!dhcp)
|
||||
return;
|
||||
switch (dhcp->state) {
|
||||
case DHCP_REBINDING:
|
||||
case DHCP_RENEWING:
|
||||
case DHCP_BOUND:
|
||||
case DHCP_REBOOTING:
|
||||
netif_set_down(netif);
|
||||
dhcp->tries = 0;
|
||||
dhcp_reboot(netif);
|
||||
break;
|
||||
case DHCP_OFF:
|
||||
/* stay off */
|
||||
break;
|
||||
default:
|
||||
dhcp->tries = 0;
|
||||
dhcp_discover(netif);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if DHCP_DOES_ARP_CHECK
|
||||
@ -715,7 +753,7 @@ dhcp_inform(struct netif *netif)
|
||||
void dhcp_arp_reply(struct netif *netif, struct ip_addr *addr)
|
||||
{
|
||||
LWIP_ERROR("netif != NULL", (netif != NULL), return;);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_arp_reply()\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_arp_reply()\n"));
|
||||
/* is a DHCP client doing an ARP check? */
|
||||
if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_CHECKING)) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n", addr->addr));
|
||||
@ -723,7 +761,8 @@ void dhcp_arp_reply(struct netif *netif, struct ip_addr *addr)
|
||||
were offered by the DHCP server? */
|
||||
if (ip_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) {
|
||||
/* we will not accept the offered address */
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 1, ("dhcp_arp_reply(): arp reply matched with offered address, declining\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
|
||||
("dhcp_arp_reply(): arp reply matched with offered address, declining\n"));
|
||||
dhcp_decline(netif);
|
||||
}
|
||||
}
|
||||
@ -744,7 +783,7 @@ dhcp_decline(struct netif *netif)
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
err_t result = ERR_OK;
|
||||
u16_t msecs;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_decline()\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline()\n"));
|
||||
dhcp_set_state(dhcp, DHCP_BACKING_OFF);
|
||||
/* create and initialize the DHCP message header */
|
||||
result = dhcp_create_request(netif);
|
||||
@ -759,14 +798,13 @@ dhcp_decline(struct netif *netif)
|
||||
/* resize pbuf to reflect true size of options */
|
||||
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
|
||||
|
||||
/* @todo: should we really connect here? we are performing sendto() */
|
||||
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
|
||||
/* per section 4.4.4, broadcast DECLINE messages */
|
||||
udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
|
||||
dhcp_delete_request(netif);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n"));
|
||||
} else {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_decline: could not allocate DHCP request\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("dhcp_decline: could not allocate DHCP request\n"));
|
||||
}
|
||||
dhcp->tries++;
|
||||
msecs = 10*1000;
|
||||
@ -788,7 +826,7 @@ dhcp_discover(struct netif *netif)
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
err_t result = ERR_OK;
|
||||
u16_t msecs;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_discover()\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover()\n"));
|
||||
ip_addr_set(&dhcp->offered_ip_addr, IP_ADDR_ANY);
|
||||
dhcp_set_state(dhcp, DHCP_SELECTING);
|
||||
/* create and initialize the DHCP message header */
|
||||
@ -812,14 +850,13 @@ dhcp_discover(struct netif *netif)
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: realloc()ing\n"));
|
||||
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
|
||||
|
||||
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n"));
|
||||
udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n"));
|
||||
dhcp_delete_request(netif);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n"));
|
||||
} else {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_discover: could not allocate DHCP request\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_discover: could not allocate DHCP request\n"));
|
||||
}
|
||||
dhcp->tries++;
|
||||
#if LWIP_DHCP_AUTOIP_COOP
|
||||
@ -849,7 +886,7 @@ dhcp_bind(struct netif *netif)
|
||||
LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;);
|
||||
dhcp = netif->dhcp;
|
||||
LWIP_ERROR("dhcp_bind: dhcp != NULL", (dhcp != NULL), return;);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_bind(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
|
||||
|
||||
/* temporary DHCP lease? */
|
||||
if (dhcp->offered_t1_renew != 0xffffffffUL) {
|
||||
@ -937,7 +974,7 @@ dhcp_renew(struct netif *netif)
|
||||
#if LWIP_NETIF_HOSTNAME
|
||||
const char *p;
|
||||
#endif /* LWIP_NETIF_HOSTNAME */
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_renew()\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_renew()\n"));
|
||||
dhcp_set_state(dhcp, DHCP_RENEWING);
|
||||
|
||||
/* create and initialize the DHCP message header */
|
||||
@ -974,13 +1011,12 @@ dhcp_renew(struct netif *netif)
|
||||
|
||||
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
|
||||
|
||||
udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT);
|
||||
udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif);
|
||||
dhcp_delete_request(netif);
|
||||
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew: RENEWING\n"));
|
||||
} else {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_renew: could not allocate DHCP request\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_renew: could not allocate DHCP request\n"));
|
||||
}
|
||||
dhcp->tries++;
|
||||
/* back-off on retries, but to a maximum of 20 seconds */
|
||||
@ -1040,12 +1076,11 @@ dhcp_rebind(struct netif *netif)
|
||||
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
|
||||
|
||||
/* broadcast to server */
|
||||
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
|
||||
udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
|
||||
dhcp_delete_request(netif);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind: REBINDING\n"));
|
||||
} else {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_rebind: could not allocate DHCP request\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_rebind: could not allocate DHCP request\n"));
|
||||
}
|
||||
dhcp->tries++;
|
||||
msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
|
||||
@ -1054,6 +1089,52 @@ dhcp_rebind(struct netif *netif)
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enter REBOOTING state to verify an existing lease
|
||||
*
|
||||
* @param netif network interface which must reboot
|
||||
*/
|
||||
static err_t
|
||||
dhcp_reboot(struct netif *netif)
|
||||
{
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
err_t result;
|
||||
u16_t msecs;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot()\n"));
|
||||
dhcp_set_state(dhcp, DHCP_REBOOTING);
|
||||
|
||||
/* create and initialize the DHCP message header */
|
||||
result = dhcp_create_request(netif);
|
||||
if (result == ERR_OK) {
|
||||
|
||||
dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
|
||||
dhcp_option_byte(dhcp, DHCP_REQUEST);
|
||||
|
||||
dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
|
||||
dhcp_option_short(dhcp, 576);
|
||||
|
||||
dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
|
||||
dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
|
||||
|
||||
dhcp_option_trailer(dhcp);
|
||||
|
||||
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
|
||||
|
||||
/* broadcast to server */
|
||||
udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
|
||||
dhcp_delete_request(netif);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot: REBOOTING\n"));
|
||||
} else {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_reboot: could not allocate DHCP request\n"));
|
||||
}
|
||||
dhcp->tries++;
|
||||
msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
|
||||
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot(): set request timeout %"U16_F" msecs\n", msecs));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Release a DHCP lease.
|
||||
*
|
||||
@ -1065,7 +1146,7 @@ dhcp_release(struct netif *netif)
|
||||
struct dhcp *dhcp = netif->dhcp;
|
||||
err_t result;
|
||||
u16_t msecs;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_release()\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release()\n"));
|
||||
|
||||
/* idle DHCP client */
|
||||
dhcp_set_state(dhcp, DHCP_OFF);
|
||||
@ -1086,12 +1167,11 @@ dhcp_release(struct netif *netif)
|
||||
|
||||
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
|
||||
|
||||
udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT);
|
||||
udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif);
|
||||
dhcp_delete_request(netif);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_OFF\n"));
|
||||
} else {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_release: could not allocate DHCP request\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n"));
|
||||
}
|
||||
dhcp->tries++;
|
||||
msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
|
||||
@ -1121,7 +1201,7 @@ dhcp_stop(struct netif *netif)
|
||||
/* Remove the flag that says this netif is handled by DHCP. */
|
||||
netif->flags &= ~NETIF_FLAG_DHCP;
|
||||
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_stop()\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_stop()\n"));
|
||||
/* netif is DHCP configured? */
|
||||
if (dhcp != NULL) {
|
||||
#if LWIP_DHCP_AUTOIP_COOP
|
||||
@ -1135,12 +1215,8 @@ dhcp_stop(struct netif *netif)
|
||||
udp_remove(dhcp->pcb);
|
||||
dhcp->pcb = NULL;
|
||||
}
|
||||
if (dhcp->p != NULL) {
|
||||
pbuf_free(dhcp->p);
|
||||
dhcp->p = NULL;
|
||||
}
|
||||
/* free unfolded reply */
|
||||
dhcp_free_reply(dhcp);
|
||||
LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL &&
|
||||
dhcp->options_in == NULL && dhcp->options_in_len == 0);
|
||||
mem_free((void *)dhcp);
|
||||
netif->dhcp = NULL;
|
||||
}
|
||||
@ -1214,39 +1290,44 @@ dhcp_option_long(struct dhcp *dhcp, u32_t value)
|
||||
*
|
||||
*/
|
||||
static err_t
|
||||
dhcp_unfold_reply(struct dhcp *dhcp)
|
||||
dhcp_unfold_reply(struct dhcp *dhcp, struct pbuf *p)
|
||||
{
|
||||
u16_t ret;
|
||||
LWIP_ERROR("dhcp != NULL", (dhcp != NULL), return ERR_ARG;);
|
||||
LWIP_ERROR("dhcp->p != NULL", (dhcp->p != NULL), return ERR_VAL;);
|
||||
/* free any left-overs from previous unfolds */
|
||||
dhcp_free_reply(dhcp);
|
||||
/* options present? */
|
||||
if (dhcp->p->tot_len > (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN)) {
|
||||
dhcp->options_in_len = dhcp->p->tot_len - (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
|
||||
if (p->tot_len > (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN)) {
|
||||
dhcp->options_in_len = p->tot_len - (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
|
||||
dhcp->options_in = mem_malloc(dhcp->options_in_len);
|
||||
if (dhcp->options_in == NULL) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_unfold_reply(): could not allocate dhcp->options\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("dhcp_unfold_reply(): could not allocate dhcp->options\n"));
|
||||
dhcp->options_in_len = 0;
|
||||
return ERR_MEM;
|
||||
}
|
||||
}
|
||||
dhcp->msg_in = mem_malloc(sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
|
||||
if (dhcp->msg_in == NULL) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_unfold_reply(): could not allocate dhcp->msg_in\n"));
|
||||
mem_free((void *)dhcp->options_in);
|
||||
dhcp->options_in = NULL;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("dhcp_unfold_reply(): could not allocate dhcp->msg_in\n"));
|
||||
if (dhcp->options_in != NULL) {
|
||||
mem_free(dhcp->options_in);
|
||||
dhcp->options_in = NULL;
|
||||
dhcp->options_in_len = 0;
|
||||
}
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
/** copy the DHCP message without options */
|
||||
ret = pbuf_copy_partial(dhcp->p, dhcp->msg_in, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN, 0);
|
||||
ret = pbuf_copy_partial(p, dhcp->msg_in, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN, 0);
|
||||
LWIP_ASSERT("ret == sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN", ret == sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_unfold_reply(): copied %"U16_F" bytes into dhcp->msg_in[]\n",
|
||||
sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN));
|
||||
|
||||
if (dhcp->options_in != NULL) {
|
||||
/** copy the DHCP options */
|
||||
ret = pbuf_copy_partial(dhcp->p, dhcp->options_in, dhcp->options_in_len, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
|
||||
ret = pbuf_copy_partial(p, dhcp->options_in, dhcp->options_in_len, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
|
||||
LWIP_ASSERT("ret == dhcp->options_in_len", ret == dhcp->options_in_len);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_unfold_reply(): copied %"U16_F" bytes to dhcp->options_in[]\n",
|
||||
dhcp->options_in_len));
|
||||
@ -1258,7 +1339,6 @@ dhcp_unfold_reply(struct dhcp *dhcp)
|
||||
/**
|
||||
* Free the incoming DHCP message including contiguous copy of
|
||||
* its DHCP options.
|
||||
*
|
||||
*/
|
||||
static void dhcp_free_reply(struct dhcp *dhcp)
|
||||
{
|
||||
@ -1267,14 +1347,13 @@ static void dhcp_free_reply(struct dhcp *dhcp)
|
||||
dhcp->msg_in = NULL;
|
||||
}
|
||||
if (dhcp->options_in) {
|
||||
mem_free((void *)dhcp->options_in);
|
||||
mem_free(dhcp->options_in);
|
||||
dhcp->options_in = NULL;
|
||||
dhcp->options_in_len = 0;
|
||||
}
|
||||
LWIP_DEBUGF(DHCP_DEBUG, ("dhcp_free_reply(): free'd\n"));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If an incoming DHCP message is in response to us, then trigger the state machine
|
||||
*/
|
||||
@ -1286,7 +1365,7 @@ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_
|
||||
u8_t *options_ptr;
|
||||
u8_t msg_type;
|
||||
u8_t i;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p,
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p,
|
||||
(u16_t)(ntohl(addr->addr) >> 24 & 0xff), (u16_t)(ntohl(addr->addr) >> 16 & 0xff),
|
||||
(u16_t)(ntohl(addr->addr) >> 8 & 0xff), (u16_t)(ntohl(addr->addr) & 0xff), port));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len));
|
||||
@ -1295,28 +1374,38 @@ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_
|
||||
LWIP_UNUSED_ARG(pcb);
|
||||
LWIP_UNUSED_ARG(addr);
|
||||
LWIP_UNUSED_ARG(port);
|
||||
dhcp->p = p;
|
||||
/* TODO: check packet length before reading them */
|
||||
|
||||
LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL &&
|
||||
dhcp->options_in == NULL && dhcp->options_in_len == 0);
|
||||
|
||||
if (p->len < DHCP_MIN_REPLY_LEN) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP reply message too short\n"));
|
||||
goto free_pbuf_and_return;
|
||||
}
|
||||
|
||||
if (reply_msg->op != DHCP_BOOTREPLY) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1, ("not a DHCP reply message, but type %"U16_F"\n", (u16_t)reply_msg->op));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("not a DHCP reply message, but type %"U16_F"\n", (u16_t)reply_msg->op));
|
||||
goto free_pbuf_and_return;
|
||||
}
|
||||
/* iterate through hardware address and match against DHCP message */
|
||||
for (i = 0; i < netif->hwaddr_len; i++) {
|
||||
if (netif->hwaddr[i] != reply_msg->chaddr[i]) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n",
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
|
||||
("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n",
|
||||
(u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i]));
|
||||
goto free_pbuf_and_return;
|
||||
}
|
||||
}
|
||||
/* match transaction ID against what we expected */
|
||||
if (ntohl(reply_msg->xid) != dhcp->xid) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",ntohl(reply_msg->xid),dhcp->xid));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
|
||||
("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",ntohl(reply_msg->xid),dhcp->xid));
|
||||
goto free_pbuf_and_return;
|
||||
}
|
||||
/* option fields could be unfold? */
|
||||
if (dhcp_unfold_reply(dhcp) != ERR_OK) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("problem unfolding DHCP message - too short on memory?\n"));
|
||||
if (dhcp_unfold_reply(dhcp, p) != ERR_OK) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("problem unfolding DHCP message - too short on memory?\n"));
|
||||
goto free_pbuf_and_return;
|
||||
}
|
||||
|
||||
@ -1324,7 +1413,7 @@ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_
|
||||
/* obtain pointer to DHCP message type */
|
||||
options_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_MESSAGE_TYPE);
|
||||
if (options_ptr == NULL) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1, ("DHCP_OPTION_MESSAGE_TYPE option not found\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP_OPTION_MESSAGE_TYPE option not found\n"));
|
||||
goto free_pbuf_and_return;
|
||||
}
|
||||
|
||||
@ -1332,7 +1421,7 @@ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_
|
||||
msg_type = dhcp_get_option_byte(options_ptr + 2);
|
||||
/* message type is DHCP ACK? */
|
||||
if (msg_type == DHCP_ACK) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1, ("DHCP_ACK received\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_ACK received\n"));
|
||||
/* in requesting state? */
|
||||
if (dhcp->state == DHCP_REQUESTING) {
|
||||
dhcp_handle_ack(netif);
|
||||
@ -1355,13 +1444,13 @@ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_
|
||||
else if ((msg_type == DHCP_NAK) &&
|
||||
((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REQUESTING) ||
|
||||
(dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING ))) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1, ("DHCP_NAK received\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_NAK received\n"));
|
||||
dhcp->request_timeout = 0;
|
||||
dhcp_handle_nak(netif);
|
||||
}
|
||||
/* received a DHCP_OFFER in DHCP_SELECTING state? */
|
||||
else if ((msg_type == DHCP_OFFER) && (dhcp->state == DHCP_SELECTING)) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1, ("DHCP_OFFER received in DHCP_SELECTING state\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_OFFER received in DHCP_SELECTING state\n"));
|
||||
dhcp->request_timeout = 0;
|
||||
/* remember offered lease */
|
||||
dhcp_handle_offer(netif);
|
||||
@ -1369,7 +1458,6 @@ static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_
|
||||
free_pbuf_and_return:
|
||||
dhcp_free_reply(dhcp);
|
||||
pbuf_free(p);
|
||||
dhcp->p = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1403,7 +1491,8 @@ dhcp_create_request(struct netif *netif)
|
||||
LWIP_ASSERT("dhcp_create_request: dhcp->msg_out == NULL", dhcp->msg_out == NULL);
|
||||
dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM);
|
||||
if (dhcp->p_out == NULL) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_create_request(): could not allocate pbuf\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("dhcp_create_request(): could not allocate pbuf\n"));
|
||||
return ERR_MEM;
|
||||
}
|
||||
LWIP_ASSERT("dhcp_create_request: check that first pbuf can hold struct dhcp_msg",
|
||||
@ -1413,7 +1502,7 @@ dhcp_create_request(struct netif *netif)
|
||||
if (dhcp->tries==0)
|
||||
xid++;
|
||||
dhcp->xid = xid;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2,
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
|
||||
("transaction id xid(%"X32_F")\n", xid));
|
||||
|
||||
dhcp->msg_out = (struct dhcp_msg *)dhcp->p_out->payload;
|
||||
@ -1521,7 +1610,7 @@ static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type)
|
||||
/* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */
|
||||
/* are the sname and/or file field overloaded with options? */
|
||||
if (options[offset] == DHCP_OPTION_OVERLOAD) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("overloaded message detected\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded message detected\n"));
|
||||
/* skip option type and length */
|
||||
offset += 2;
|
||||
overload = options[offset++];
|
||||
@ -1543,16 +1632,16 @@ static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type)
|
||||
if (overload != DHCP_OVERLOAD_NONE) {
|
||||
u16_t field_len;
|
||||
if (overload == DHCP_OVERLOAD_FILE) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1, ("overloaded file field\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded file field\n"));
|
||||
options = (u8_t *)&dhcp->msg_in->file;
|
||||
field_len = DHCP_FILE_LEN;
|
||||
} else if (overload == DHCP_OVERLOAD_SNAME) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1, ("overloaded sname field\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname field\n"));
|
||||
options = (u8_t *)&dhcp->msg_in->sname;
|
||||
field_len = DHCP_SNAME_LEN;
|
||||
/* TODO: check if else if () is necessary */
|
||||
} else {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1, ("overloaded sname and file field\n"));
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname and file field\n"));
|
||||
options = (u8_t *)&dhcp->msg_in->sname;
|
||||
field_len = DHCP_FILE_LEN + DHCP_SNAME_LEN;
|
||||
}
|
||||
|
@ -961,7 +961,7 @@ dns_gethostbyname(const char *hostname, struct ip_addr *addr, dns_found_callback
|
||||
|
||||
#if LWIP_HAVE_LOOPIF
|
||||
if (strcmp(hostname,"localhost")==0) {
|
||||
addr->addr = INADDR_LOOPBACK;
|
||||
addr->addr = htonl(INADDR_LOOPBACK);
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif /* LWIP_HAVE_LOOPIF */
|
||||
|
@ -168,6 +168,9 @@
|
||||
#if (DNS_LOCAL_HOSTLIST && !DNS_LOCAL_HOSTLIST_IS_DYNAMIC && !(defined(DNS_LOCAL_HOSTLIST_INIT)))
|
||||
#error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST"
|
||||
#endif
|
||||
#if PPP_SUPPORT && !PPPOS_SUPPORT & !PPPOE_SUPPORT
|
||||
#error "PPP_SUPPORT needs either PPPOS_SUPPORT or PPPOE_SUPPORT turned on"
|
||||
#endif
|
||||
|
||||
|
||||
/* Compile-time checks for deprecated options.
|
||||
@ -208,6 +211,8 @@ lwip_sanity_check(void)
|
||||
#if LWIP_TCP
|
||||
if (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN)
|
||||
LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN\n"));
|
||||
if (TCP_SND_BUF < 2 * TCP_MSS)
|
||||
LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly\n"));
|
||||
if (TCP_SND_QUEUELEN < (2 * (TCP_SND_BUF/TCP_MSS)))
|
||||
LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work\n"));
|
||||
if (TCP_SNDLOWAT > TCP_SND_BUF)
|
||||
|
@ -100,7 +100,7 @@
|
||||
*/
|
||||
#ifndef LWIP_AUTOIP_CREATE_SEED_ADDR
|
||||
#define LWIP_AUTOIP_CREATE_SEED_ADDR(netif) \
|
||||
(AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \
|
||||
htonl(AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \
|
||||
((u32_t)((u8_t)(netif->hwaddr[5]))) << 8)))
|
||||
#endif /* LWIP_AUTOIP_CREATE_SEED_ADDR */
|
||||
|
||||
@ -108,7 +108,10 @@
|
||||
static void autoip_handle_arp_conflict(struct netif *netif);
|
||||
|
||||
/* creates a pseudo random LL IP-Address for a network interface */
|
||||
static void autoip_create_addr(struct netif *netif, struct ip_addr *IPAddr);
|
||||
static void autoip_create_addr(struct netif *netif, struct ip_addr *ipaddr);
|
||||
|
||||
/* sends an ARP probe */
|
||||
static err_t autoip_arp_probe(struct netif *netif);
|
||||
|
||||
/* sends an ARP announce */
|
||||
static err_t autoip_arp_announce(struct netif *netif);
|
||||
@ -116,13 +119,16 @@ static err_t autoip_arp_announce(struct netif *netif);
|
||||
/* configure interface for use with current LL IP-Address */
|
||||
static err_t autoip_bind(struct netif *netif);
|
||||
|
||||
/* start sending probes for llipaddr */
|
||||
static void autoip_start_probing(struct netif *netif);
|
||||
|
||||
/**
|
||||
* Initialize this module
|
||||
*/
|
||||
void
|
||||
autoip_init(void)
|
||||
{
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | 3, ("autoip_init()\n"));
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_init()\n"));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -139,19 +145,19 @@ autoip_handle_arp_conflict(struct netif *netif)
|
||||
/* retreat, there was a conflicting ARP in the last
|
||||
* DEFEND_INTERVAL seconds
|
||||
*/
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 1,
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
||||
("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n"));
|
||||
|
||||
/* TODO: close all TCP sessions */
|
||||
autoip_start(netif);
|
||||
} else {
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 1,
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
||||
("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n"));
|
||||
autoip_arp_announce(netif);
|
||||
netif->autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND;
|
||||
}
|
||||
} else {
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 1,
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
||||
("autoip_handle_arp_conflict(): we do not defend, retreating\n"));
|
||||
/* TODO: close all TCP sessions */
|
||||
autoip_start(netif);
|
||||
@ -162,10 +168,10 @@ autoip_handle_arp_conflict(struct netif *netif)
|
||||
* Create an IP-Address out of range 169.254.1.0 to 169.254.254.255
|
||||
*
|
||||
* @param netif network interface on which create the IP-Address
|
||||
* @param IPAddr ip address to initialize
|
||||
* @param ipaddr ip address to initialize
|
||||
*/
|
||||
static void
|
||||
autoip_create_addr(struct netif *netif, struct ip_addr *IPAddr)
|
||||
autoip_create_addr(struct netif *netif, struct ip_addr *ipaddr)
|
||||
{
|
||||
/* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255
|
||||
* compliant to RFC 3927 Section 2.1
|
||||
@ -183,12 +189,25 @@ autoip_create_addr(struct netif *netif, struct ip_addr *IPAddr)
|
||||
addr -= AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1;
|
||||
}
|
||||
LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) &&
|
||||
(addr <= AUTOIP_RANGE_END));
|
||||
IPAddr->addr = htonl(addr);
|
||||
(addr <= AUTOIP_RANGE_END));
|
||||
ipaddr->addr = htonl(addr);
|
||||
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 1,
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
||||
("autoip_create_addr(): tried_llipaddr=%"U16_F", 0x%08"X32_F"\n",
|
||||
(u16_t)(netif->autoip->tried_llipaddr), (u32_t)(IPAddr->addr)));
|
||||
(u16_t)(netif->autoip->tried_llipaddr), (u32_t)(ipaddr->addr)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an ARP probe from a network interface
|
||||
*
|
||||
* @param netif network interface used to send the probe
|
||||
*/
|
||||
static err_t
|
||||
autoip_arp_probe(struct netif *netif)
|
||||
{
|
||||
return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast,
|
||||
(struct eth_addr *)netif->hwaddr, IP_ADDR_ANY, ðzero,
|
||||
&netif->autoip->llipaddr, ARP_REQUEST);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -215,7 +234,7 @@ autoip_bind(struct netif *netif)
|
||||
struct autoip *autoip = netif->autoip;
|
||||
struct ip_addr sn_mask, gw_addr;
|
||||
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | 3,
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
|
||||
("autoip_bind(netif=%p) %c%c%"U16_F" 0x%08"X32_F"\n",
|
||||
(void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num, autoip->llipaddr.addr));
|
||||
|
||||
@ -281,6 +300,16 @@ autoip_start(struct netif *netif)
|
||||
|
||||
autoip_create_addr(netif, &(autoip->llipaddr));
|
||||
autoip->tried_llipaddr++;
|
||||
autoip_start_probing(netif);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
autoip_start_probing(struct netif *netif)
|
||||
{
|
||||
struct autoip *autoip = netif->autoip;
|
||||
|
||||
autoip->state = AUTOIP_STATE_PROBING;
|
||||
autoip->sent_num = 0;
|
||||
|
||||
@ -295,12 +324,24 @@ autoip_start(struct netif *netif)
|
||||
* accquiring and probing address
|
||||
* compliant to RFC 3927 Section 2.2.1
|
||||
*/
|
||||
|
||||
if(autoip->tried_llipaddr > MAX_CONFLICTS) {
|
||||
autoip->ttw = RATE_LIMIT_INTERVAL * AUTOIP_TICKS_PER_SECOND;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
/**
|
||||
* Handle a possible change in the network configuration.
|
||||
*
|
||||
* If there is an AutoIP address configured, take the interface down
|
||||
* and begin probing with the same address.
|
||||
*/
|
||||
void
|
||||
autoip_network_changed(struct netif *netif)
|
||||
{
|
||||
if (netif->autoip && netif->autoip->state != AUTOIP_STATE_OFF) {
|
||||
netif_set_down(netif);
|
||||
autoip_start_probing(netif);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -340,13 +381,13 @@ autoip_tmr()
|
||||
if(netif->autoip->ttw > 0) {
|
||||
netif->autoip->ttw--;
|
||||
} else {
|
||||
if(netif->autoip->sent_num == PROBE_NUM) {
|
||||
if(netif->autoip->sent_num >= PROBE_NUM) {
|
||||
netif->autoip->state = AUTOIP_STATE_ANNOUNCING;
|
||||
netif->autoip->sent_num = 0;
|
||||
netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND;
|
||||
} else {
|
||||
etharp_request(netif, &(netif->autoip->llipaddr));
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | 3,
|
||||
autoip_arp_probe(netif);
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
|
||||
("autoip_tmr() PROBING Sent Probe\n"));
|
||||
netif->autoip->sent_num++;
|
||||
/* calculate time to wait to next probe */
|
||||
@ -363,21 +404,24 @@ autoip_tmr()
|
||||
} else {
|
||||
if(netif->autoip->sent_num == 0) {
|
||||
/* We are here the first time, so we waited ANNOUNCE_WAIT seconds
|
||||
* Now we can bind to an IP address and use it
|
||||
* Now we can bind to an IP address and use it.
|
||||
*
|
||||
* autoip_bind calls netif_set_up. This triggers a gratuitous ARP
|
||||
* which counts as an announcement.
|
||||
*/
|
||||
autoip_bind(netif);
|
||||
}
|
||||
|
||||
if(netif->autoip->sent_num == ANNOUNCE_NUM) {
|
||||
netif->autoip->state = AUTOIP_STATE_BOUND;
|
||||
netif->autoip->sent_num = 0;
|
||||
netif->autoip->ttw = 0;
|
||||
} else {
|
||||
autoip_arp_announce(netif);
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | 3,
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
|
||||
("autoip_tmr() ANNOUNCING Sent Announce\n"));
|
||||
netif->autoip->sent_num++;
|
||||
netif->autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND;
|
||||
}
|
||||
netif->autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND;
|
||||
netif->autoip->sent_num++;
|
||||
|
||||
if(netif->autoip->sent_num >= ANNOUNCE_NUM) {
|
||||
netif->autoip->state = AUTOIP_STATE_BOUND;
|
||||
netif->autoip->sent_num = 0;
|
||||
netif->autoip->ttw = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -397,7 +441,7 @@ autoip_tmr()
|
||||
void
|
||||
autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
|
||||
{
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | 3, ("autoip_arp_reply()\n"));
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_arp_reply()\n"));
|
||||
if ((netif->autoip != NULL) && (netif->autoip->state != AUTOIP_STATE_OFF)) {
|
||||
/* when ip.src == llipaddr && hw.src != netif->hwaddr
|
||||
*
|
||||
@ -431,7 +475,7 @@ autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
|
||||
if ((ip_addr_cmp(&sipaddr, &netif->autoip->llipaddr)) ||
|
||||
(ip_addr_cmp(&dipaddr, &netif->autoip->llipaddr) &&
|
||||
!eth_addr_cmp(&netifaddr, &hdr->shwaddr))) {
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 1,
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
|
||||
("autoip_arp_reply(): Probe Conflict detected\n"));
|
||||
autoip_start(netif);
|
||||
}
|
||||
@ -442,7 +486,7 @@ autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
|
||||
*/
|
||||
if (ip_addr_cmp(&sipaddr, &netif->autoip->llipaddr) &&
|
||||
!eth_addr_cmp(&netifaddr, &hdr->shwaddr)) {
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 1,
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
|
||||
("autoip_arp_reply(): Conflicting ARP-Packet detected\n"));
|
||||
autoip_handle_arp_conflict(netif);
|
||||
}
|
||||
|
@ -62,40 +62,12 @@
|
||||
* The interface that provided the packet for the current callback
|
||||
* invocation.
|
||||
*/
|
||||
static struct netif *current_netif;
|
||||
struct netif *current_netif;
|
||||
|
||||
/**
|
||||
* Header of the input packet currently being processed.
|
||||
*/
|
||||
static const struct ip_hdr *current_header;
|
||||
|
||||
/**
|
||||
* Get the interface that received the current packet.
|
||||
*
|
||||
* This function must only be called from a receive callback (udp_recv,
|
||||
* raw_recv, tcp_accept). It will return NULL otherwise.
|
||||
*
|
||||
* @param pcb Pointer to the pcb receiving a packet.
|
||||
*/
|
||||
struct netif *
|
||||
ip_current_netif(void)
|
||||
{
|
||||
return current_netif;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the IP header of the current packet.
|
||||
*
|
||||
* This function must only be called from a receive callback (udp_recv,
|
||||
* raw_recv, tcp_accept). It will return NULL otherwise.
|
||||
*
|
||||
* @param pcb Pointer to the pcb receiving a packet.
|
||||
*/
|
||||
const struct ip_hdr *
|
||||
ip_current_header(void)
|
||||
{
|
||||
return current_header;
|
||||
}
|
||||
const struct ip_hdr *current_header;
|
||||
|
||||
/**
|
||||
* Finds the appropriate network interface for a given IP address. It
|
||||
@ -122,7 +94,7 @@ ip_route(struct ip_addr *dest)
|
||||
}
|
||||
}
|
||||
if ((netif_default == NULL) || (!netif_is_up(netif_default))) {
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_route: No route to 0x%"X32_F"\n", dest->addr));
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_route: No route to 0x%"X32_F"\n", dest->addr));
|
||||
IP_STATS_INC(ip.rterr);
|
||||
snmp_inc_ipoutnoroutes();
|
||||
return NULL;
|
||||
@ -230,7 +202,7 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
/* identify the IP header */
|
||||
iphdr = p->payload;
|
||||
if (IPH_V(iphdr) != 4) {
|
||||
LWIP_DEBUGF(IP_DEBUG | 1, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr)));
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr)));
|
||||
ip_debug_print(p);
|
||||
pbuf_free(p);
|
||||
IP_STATS_INC(ip.err);
|
||||
@ -248,13 +220,16 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
|
||||
/* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */
|
||||
if ((iphdr_hlen > p->len) || (iphdr_len > p->tot_len)) {
|
||||
if (iphdr_hlen > p->len)
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n",
|
||||
iphdr_hlen, p->len));
|
||||
if (iphdr_len > p->tot_len)
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("IP (len %"U16_F") is longer than pbuf (len %"U16_F"), "
|
||||
"IP packet dropped.\n",
|
||||
iphdr_len, p->tot_len));
|
||||
if (iphdr_hlen > p->len) {
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n",
|
||||
iphdr_hlen, p->len));
|
||||
}
|
||||
if (iphdr_len > p->tot_len) {
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("IP (len %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n",
|
||||
iphdr_len, p->tot_len));
|
||||
}
|
||||
/* free (drop) packet pbufs */
|
||||
pbuf_free(p);
|
||||
IP_STATS_INC(ip.lenerr);
|
||||
@ -267,7 +242,8 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
#if CHECKSUM_CHECK_IP
|
||||
if (inet_chksum(iphdr, iphdr_hlen) != 0) {
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen)));
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen)));
|
||||
ip_debug_print(p);
|
||||
pbuf_free(p);
|
||||
IP_STATS_INC(ip.chkerr);
|
||||
@ -336,10 +312,10 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
if (netif == NULL) {
|
||||
/* remote port is DHCP server? */
|
||||
if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | 1, ("ip_input: UDP packet to DHCP client port %"U16_F"\n",
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: UDP packet to DHCP client port %"U16_F"\n",
|
||||
ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen))->dest)));
|
||||
if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen))->dest) == DHCP_CLIENT_PORT) {
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | 1, ("ip_input: DHCP packet accepted.\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: DHCP packet accepted.\n"));
|
||||
netif = inp;
|
||||
check_ip_src = 0;
|
||||
}
|
||||
@ -349,12 +325,13 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
|
||||
/* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */
|
||||
#if LWIP_DHCP
|
||||
if (check_ip_src)
|
||||
/* DHCP servers need 0.0.0.0 to be allowed as source address (RFC 1.1.2.2: 3.2.1.3/a) */
|
||||
if (check_ip_src && (iphdr->src.addr != 0))
|
||||
#endif /* LWIP_DHCP */
|
||||
{ if ((ip_addr_isbroadcast(&(iphdr->src), inp)) ||
|
||||
(ip_addr_ismulticast(&(iphdr->src)))) {
|
||||
/* packet source is not valid */
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | 1, ("ip_input: packet source is not valid.\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ip_input: packet source is not valid.\n"));
|
||||
/* free (drop) packet pbufs */
|
||||
pbuf_free(p);
|
||||
IP_STATS_INC(ip.drop);
|
||||
@ -367,7 +344,7 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
/* packet not for us? */
|
||||
if (netif == NULL) {
|
||||
/* packet not for us, route or discard */
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | 1, ("ip_input: packet not for us.\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: packet not for us.\n"));
|
||||
#if IP_FORWARD
|
||||
/* non-broadcast packet? */
|
||||
if (!ip_addr_isbroadcast(&(iphdr->dest), inp)) {
|
||||
@ -396,7 +373,7 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
iphdr = p->payload;
|
||||
#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */
|
||||
pbuf_free(p);
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n",
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n",
|
||||
ntohs(IPH_OFFSET(iphdr))));
|
||||
IP_STATS_INC(ip.opterr);
|
||||
IP_STATS_INC(ip.drop);
|
||||
@ -414,7 +391,7 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
#else
|
||||
if (iphdr_hlen > IP_HLEN) {
|
||||
#endif /* LWIP_IGMP */
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n"));
|
||||
pbuf_free(p);
|
||||
IP_STATS_INC(ip.opterr);
|
||||
IP_STATS_INC(ip.drop);
|
||||
@ -476,7 +453,7 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
#endif /* LWIP_ICMP */
|
||||
pbuf_free(p);
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr)));
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr)));
|
||||
|
||||
IP_STATS_INC(ip.proterr);
|
||||
IP_STATS_INC(ip.drop);
|
||||
@ -551,7 +528,7 @@ err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest
|
||||
ip_hlen += optlen_aligned;
|
||||
/* First write in the IP options */
|
||||
if (pbuf_header(p, optlen_aligned)) {
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output_if_opt: not enough room for IP options in pbuf\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output_if_opt: not enough room for IP options in pbuf\n"));
|
||||
IP_STATS_INC(ip.err);
|
||||
snmp_inc_ipoutdiscards();
|
||||
return ERR_BUF;
|
||||
@ -565,7 +542,7 @@ err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest
|
||||
#endif /* IP_OPTIONS_SEND */
|
||||
/* generate IP header */
|
||||
if (pbuf_header(p, IP_HLEN)) {
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: not enough room for IP header in pbuf\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output: not enough room for IP header in pbuf\n"));
|
||||
|
||||
IP_STATS_INC(ip.err);
|
||||
snmp_inc_ipoutdiscards();
|
||||
@ -603,30 +580,27 @@ err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest
|
||||
dest = &(iphdr->dest);
|
||||
}
|
||||
|
||||
#if IP_FRAG
|
||||
/* don't fragment if interface has mtu set to 0 [loopif] */
|
||||
if (netif->mtu && (p->tot_len > netif->mtu))
|
||||
return ip_frag(p,netif,dest);
|
||||
#endif
|
||||
|
||||
IP_STATS_INC(ip.xmit);
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num));
|
||||
ip_debug_print(p);
|
||||
|
||||
#if (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF)
|
||||
#if ENABLE_LOOPBACK
|
||||
if (ip_addr_cmp(dest, &netif->ip_addr)) {
|
||||
/* Packet to self, enqueue it for loopback */
|
||||
LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()"));
|
||||
|
||||
return netif_loop_output(netif, p, dest);
|
||||
} else
|
||||
#endif /* (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) */
|
||||
{
|
||||
LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
|
||||
|
||||
return netif->output(netif, p, dest);
|
||||
}
|
||||
#endif /* ENABLE_LOOPBACK */
|
||||
#if IP_FRAG
|
||||
/* don't fragment if interface has mtu set to 0 [loopif] */
|
||||
if (netif->mtu && (p->tot_len > netif->mtu)) {
|
||||
return ip_frag(p,netif,dest);
|
||||
}
|
||||
#endif
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
|
||||
return netif->output(netif, p, dest);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -300,7 +300,7 @@ mem_free(void *rmem)
|
||||
LWIP_MEM_FREE_DECL_PROTECT();
|
||||
|
||||
if (rmem == NULL) {
|
||||
LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | 2, ("mem_free(p == NULL) was called.\n"));
|
||||
LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("mem_free(p == NULL) was called.\n"));
|
||||
return;
|
||||
}
|
||||
LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0);
|
||||
@ -310,7 +310,7 @@ mem_free(void *rmem)
|
||||
|
||||
if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
|
||||
SYS_ARCH_DECL_PROTECT(lev);
|
||||
LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_free: illegal memory\n"));
|
||||
LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_free: illegal memory\n"));
|
||||
/* protect mem stats from concurrent access */
|
||||
SYS_ARCH_PROTECT(lev);
|
||||
MEM_STATS_INC(illegal);
|
||||
@ -380,7 +380,7 @@ mem_realloc(void *rmem, mem_size_t newsize)
|
||||
|
||||
if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
|
||||
SYS_ARCH_DECL_PROTECT(lev);
|
||||
LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_realloc: illegal memory\n"));
|
||||
LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_realloc: illegal memory\n"));
|
||||
/* protect mem stats from concurrent access */
|
||||
SYS_ARCH_PROTECT(lev);
|
||||
MEM_STATS_INC(illegal);
|
||||
@ -599,7 +599,7 @@ mem_malloc(mem_size_t size)
|
||||
/* if we got interrupted by a mem_free, try again */
|
||||
} while(local_mem_free_count != 0);
|
||||
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
|
||||
LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size));
|
||||
LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size));
|
||||
MEM_STATS_INC(err);
|
||||
LWIP_MEM_ALLOC_UNPROTECT();
|
||||
sys_sem_signal(mem_sem);
|
||||
|
@ -289,7 +289,11 @@ memp_init(void)
|
||||
/* check everything a first time to see if it worked */
|
||||
memp_overflow_check_all();
|
||||
#endif /* MEMP_OVERFLOW_CHECK */
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* fix time-wait tcp pcb issue */
|
||||
static rt_uint16_t tcp_pcbs = 0;
|
||||
#endif /* MEMP_MEM_MALLOC */
|
||||
|
||||
/**
|
||||
* Get an element from a specific pool.
|
||||
@ -308,7 +312,8 @@ memp_malloc(memp_t type)
|
||||
#else
|
||||
memp_malloc_fn(memp_t type, const char* file, const int line)
|
||||
#endif
|
||||
{
|
||||
{
|
||||
#if !MEMP_MEM_MALLOC
|
||||
struct memp *memp;
|
||||
SYS_ARCH_DECL_PROTECT(old_level);
|
||||
|
||||
@ -333,13 +338,41 @@ memp_malloc_fn(memp_t type, const char* file, const int line)
|
||||
((mem_ptr_t)memp % MEM_ALIGNMENT) == 0);
|
||||
memp = (struct memp*)((u8_t*)memp + MEMP_SIZE);
|
||||
} else {
|
||||
LWIP_DEBUGF(MEMP_DEBUG | 2, ("memp_malloc: out of memory in pool %s\n", memp_desc[type]));
|
||||
LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", memp_desc[type]));
|
||||
MEMP_STATS_INC(err, type);
|
||||
}
|
||||
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
|
||||
return memp;
|
||||
#else
|
||||
void* ptr;
|
||||
rt_uint32_t size;
|
||||
SYS_ARCH_DECL_PROTECT(old_level);
|
||||
|
||||
size = memp_sizes[type];
|
||||
LWIP_DEBUGF(MEMP_DEBUG, ("memp malloc %s, size %d, ", memp_desc[type], memp_sizes[type]));
|
||||
|
||||
SYS_ARCH_PROTECT(old_level);
|
||||
if (type == MEMP_TCP_PCB)
|
||||
{
|
||||
if (tcp_pcbs >= MEMP_NUM_TCP_PCB)
|
||||
{
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* increased tcp pcb allocated number */
|
||||
tcp_pcbs ++;
|
||||
}
|
||||
}
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
|
||||
ptr = mem_malloc(size);
|
||||
LWIP_DEBUGF(MEMP_DEBUG, ("mem 0x%x\n", ptr));
|
||||
|
||||
return ptr;
|
||||
#endif /* MEMP_MEM_MALLOC */
|
||||
}
|
||||
|
||||
/**
|
||||
@ -351,6 +384,7 @@ memp_malloc_fn(memp_t type, const char* file, const int line)
|
||||
void
|
||||
memp_free(memp_t type, void *mem)
|
||||
{
|
||||
#if !MEMP_MEM_MALLOC
|
||||
struct memp *memp;
|
||||
SYS_ARCH_DECL_PROTECT(old_level);
|
||||
|
||||
@ -381,6 +415,19 @@ memp_free(memp_t type, void *mem)
|
||||
#endif /* MEMP_SANITY_CHECK */
|
||||
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
}
|
||||
|
||||
#else
|
||||
SYS_ARCH_DECL_PROTECT(old_level);
|
||||
|
||||
SYS_ARCH_PROTECT(old_level);
|
||||
if (type == MEMP_TCP_PCB && mem)
|
||||
{
|
||||
tcp_pcbs --;
|
||||
}
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
|
||||
LWIP_DEBUGF(MEMP_DEBUG, ("memp free %s, mem 0x%x\n", memp_desc[type], mem));
|
||||
/* release this memory */
|
||||
mem_free(mem);
|
||||
#endif /* MEMP_MEM_MALLOC */
|
||||
}
|
||||
|
||||
|
@ -1,116 +0,0 @@
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/raw.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/igmp.h"
|
||||
#include "lwip/api.h"
|
||||
#include "lwip/api_msg.h"
|
||||
#include "lwip/tcpip.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "netif/etharp.h"
|
||||
#include "lwip/ip_frag.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x))
|
||||
|
||||
/** This array holds the element sizes of each pool. */
|
||||
static const u16_t memp_sizes[MEMP_MAX] = {
|
||||
#define LWIP_MEMPOOL(name,num,size,desc) MEMP_ALIGN_SIZE(size),
|
||||
#include "lwip/memp_std.h"
|
||||
};
|
||||
|
||||
/** This array holds a textual description of each pool. */
|
||||
#ifdef LWIP_DEBUG
|
||||
static const char *memp_desc[MEMP_MAX] = {
|
||||
#define LWIP_MEMPOOL(name,num,size,desc) (desc),
|
||||
#include "lwip/memp_std.h"
|
||||
};
|
||||
#endif /* LWIP_DEBUG */
|
||||
|
||||
/* fix time-wait tcp pcb issue */
|
||||
static rt_uint32_t tcp_pcbs = 0;
|
||||
|
||||
/**
|
||||
* Initialize this module.
|
||||
*
|
||||
* Carves out memp_memory into linked lists for each pool-type.
|
||||
*/
|
||||
void
|
||||
memp_init(void)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an element from a specific pool.
|
||||
*
|
||||
* @param type the pool to get an element from
|
||||
*
|
||||
* the debug version has two more parameters:
|
||||
* @param file file name calling this function
|
||||
* @param line number of line where this function is called
|
||||
*
|
||||
* @return a pointer to the allocated memory or a NULL pointer on error
|
||||
*/
|
||||
void *
|
||||
#if !MEMP_OVERFLOW_CHECK
|
||||
memp_malloc(memp_t type)
|
||||
#else
|
||||
memp_malloc_fn(memp_t type, const char* file, const int line)
|
||||
#endif
|
||||
{
|
||||
void* ptr;
|
||||
rt_uint32_t size, level;
|
||||
|
||||
size = memp_sizes[type];
|
||||
LWIP_DEBUGF(MEMP_DEBUG, ("memp malloc %s, size %d, ", memp_desc[type], memp_sizes[type]));
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
if (type == MEMP_TCP_PCB)
|
||||
{
|
||||
if (tcp_pcbs >= MEMP_NUM_TCP_PCB)
|
||||
{
|
||||
rt_hw_interrupt_enable(level);
|
||||
return RT_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* increased tcp pcb allocated number */
|
||||
tcp_pcbs ++;
|
||||
}
|
||||
}
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
||||
ptr = rt_malloc(size);
|
||||
LWIP_DEBUGF(MEMP_DEBUG, ("mem 0x%x\n", ptr));
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put an element back into its pool.
|
||||
*
|
||||
* @param type the pool where to put mem
|
||||
* @param mem the memp element to free
|
||||
*/
|
||||
void
|
||||
memp_free(memp_t type, void *mem)
|
||||
{
|
||||
rt_uint32_t level;
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
if (type == MEMP_TCP_PCB && mem)
|
||||
{
|
||||
tcp_pcbs --;
|
||||
}
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
||||
LWIP_DEBUGF(MEMP_DEBUG, ("memp free %s, mem 0x%x\n", memp_desc[type], mem));
|
||||
/* release this memory */
|
||||
rt_free(mem);
|
||||
}
|
@ -52,6 +52,13 @@
|
||||
#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
||||
#endif /* ENABLE_LOOPBACK */
|
||||
|
||||
#if LWIP_AUTOIP
|
||||
#include "lwip/autoip.h"
|
||||
#endif /* LWIP_AUTOIP */
|
||||
#if LWIP_DHCP
|
||||
#include "lwip/dhcp.h"
|
||||
#endif /* LWIP_DHCP */
|
||||
|
||||
#if LWIP_NETIF_STATUS_CALLBACK
|
||||
#define NETIF_STATUS_CALLBACK(n) { if (n->status_callback) (n->status_callback)(n); }
|
||||
#else
|
||||
@ -271,14 +278,14 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
|
||||
if ((ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0)
|
||||
{
|
||||
/* extern struct tcp_pcb *tcp_active_pcbs; defined by tcp.h */
|
||||
LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: netif address being changed\n"));
|
||||
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n"));
|
||||
pcb = tcp_active_pcbs;
|
||||
while (pcb != NULL) {
|
||||
/* PCB bound to current local interface address? */
|
||||
if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) {
|
||||
/* this connection must be aborted */
|
||||
struct tcp_pcb *next = pcb->next;
|
||||
LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb));
|
||||
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb));
|
||||
tcp_abort(pcb);
|
||||
pcb = next;
|
||||
} else {
|
||||
@ -303,7 +310,7 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
|
||||
snmp_insert_ipaddridx_tree(netif);
|
||||
snmp_insert_iprteidx_tree(0,netif);
|
||||
|
||||
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 3, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
netif->name[0], netif->name[1],
|
||||
ip4_addr1(&netif->ip_addr),
|
||||
ip4_addr2(&netif->ip_addr),
|
||||
@ -323,7 +330,7 @@ void
|
||||
netif_set_gw(struct netif *netif, struct ip_addr *gw)
|
||||
{
|
||||
ip_addr_set(&(netif->gw), gw);
|
||||
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 3, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
netif->name[0], netif->name[1],
|
||||
ip4_addr1(&netif->gw),
|
||||
ip4_addr2(&netif->gw),
|
||||
@ -347,7 +354,7 @@ netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
|
||||
/* set new netmask to netif */
|
||||
ip_addr_set(&(netif->netmask), netmask);
|
||||
snmp_insert_iprteidx_tree(0, netif);
|
||||
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 3, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
netif->name[0], netif->name[1],
|
||||
ip4_addr1(&netif->netmask),
|
||||
ip4_addr2(&netif->netmask),
|
||||
@ -406,7 +413,13 @@ void netif_set_up(struct netif *netif)
|
||||
etharp_gratuitous(netif);
|
||||
}
|
||||
#endif /* LWIP_ARP */
|
||||
|
||||
|
||||
#if LWIP_IGMP
|
||||
/* resend IGMP memberships */
|
||||
if (netif->flags & NETIF_FLAG_IGMP) {
|
||||
igmp_report_groups( netif);
|
||||
}
|
||||
#endif /* LWIP_IGMP */
|
||||
}
|
||||
}
|
||||
|
||||
@ -459,6 +472,19 @@ void netif_set_link_up(struct netif *netif )
|
||||
{
|
||||
netif->flags |= NETIF_FLAG_LINK_UP;
|
||||
|
||||
#if LWIP_DHCP
|
||||
if (netif->dhcp) {
|
||||
dhcp_network_changed(netif);
|
||||
}
|
||||
#endif /* LWIP_DHCP */
|
||||
|
||||
#if LWIP_AUTOIP
|
||||
if (netif->autoip) {
|
||||
autoip_network_changed(netif);
|
||||
}
|
||||
#endif /* LWIP_AUTOIP */
|
||||
|
||||
if (netif->flags & NETIF_FLAG_UP) {
|
||||
#if LWIP_ARP
|
||||
/* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */
|
||||
if (netif->flags & NETIF_FLAG_ETHARP) {
|
||||
@ -467,12 +493,12 @@ void netif_set_link_up(struct netif *netif )
|
||||
#endif /* LWIP_ARP */
|
||||
|
||||
#if LWIP_IGMP
|
||||
/* resend IGMP memberships */
|
||||
if (netif->flags & NETIF_FLAG_IGMP) {
|
||||
igmp_report_groups( netif);
|
||||
}
|
||||
/* resend IGMP memberships */
|
||||
if (netif->flags & NETIF_FLAG_IGMP) {
|
||||
igmp_report_groups( netif);
|
||||
}
|
||||
#endif /* LWIP_IGMP */
|
||||
|
||||
}
|
||||
NETIF_LINK_CALLBACK(netif);
|
||||
}
|
||||
|
||||
|
@ -81,41 +81,71 @@
|
||||
aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */
|
||||
#define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE)
|
||||
|
||||
#if TCP_QUEUE_OOSEQ
|
||||
#define ALLOC_POOL_PBUF(p) do { (p) = alloc_pool_pbuf(); } while (0)
|
||||
#else
|
||||
#define ALLOC_POOL_PBUF(p) do { (p) = memp_malloc(MEMP_PBUF_POOL); } while (0)
|
||||
#endif
|
||||
#if !TCP_QUEUE_OOSEQ || NO_SYS
|
||||
#define PBUF_POOL_IS_EMPTY()
|
||||
#else /* !TCP_QUEUE_OOSEQ || NO_SYS */
|
||||
/** Define this to 0 to prevent freeing ooseq pbufs when the PBUF_POOL is empty */
|
||||
#ifndef PBUF_POOL_FREE_OOSEQ
|
||||
#define PBUF_POOL_FREE_OOSEQ 1
|
||||
#endif /* PBUF_POOL_FREE_OOSEQ */
|
||||
|
||||
|
||||
#if TCP_QUEUE_OOSEQ
|
||||
#if PBUF_POOL_FREE_OOSEQ
|
||||
#include "lwip/tcpip.h"
|
||||
#define PBUF_POOL_IS_EMPTY() pbuf_pool_is_empty()
|
||||
static u8_t pbuf_free_ooseq_queued;
|
||||
/**
|
||||
* Attempt to reclaim some memory from queued out-of-sequence TCP segments
|
||||
* if we run out of pool pbufs. It's better to give priority to new packets
|
||||
* if we're running out.
|
||||
*
|
||||
* @return the allocated pbuf.
|
||||
* This must be done in the correct thread context therefore this function
|
||||
* can only be used with NO_SYS=0 and through tcpip_callback.
|
||||
*/
|
||||
static struct pbuf *
|
||||
alloc_pool_pbuf(void)
|
||||
static void
|
||||
pbuf_free_ooseq(void* arg)
|
||||
{
|
||||
struct tcp_pcb *pcb;
|
||||
struct pbuf *p;
|
||||
struct tcp_pcb* pcb;
|
||||
SYS_ARCH_DECL_PROTECT(old_level);
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
|
||||
retry:
|
||||
p = memp_malloc(MEMP_PBUF_POOL);
|
||||
if (NULL == p) {
|
||||
for (pcb=tcp_active_pcbs; NULL != pcb; pcb = pcb->next) {
|
||||
if (NULL != pcb->ooseq) {
|
||||
tcp_segs_free(pcb->ooseq);
|
||||
pcb->ooseq = NULL;
|
||||
goto retry;
|
||||
}
|
||||
SYS_ARCH_PROTECT(old_level);
|
||||
pbuf_free_ooseq_queued = 0;
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
|
||||
for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) {
|
||||
if (NULL != pcb->ooseq) {
|
||||
/** Free the ooseq pbufs of one PCB only */
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free_ooseq: freeing out-of-sequence pbufs\n"));
|
||||
tcp_segs_free(pcb->ooseq);
|
||||
pcb->ooseq = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
#endif /* TCP_QUEUE_OOSEQ */
|
||||
|
||||
/** Queue a call to pbuf_free_ooseq if not already queued. */
|
||||
static void
|
||||
pbuf_pool_is_empty(void)
|
||||
{
|
||||
u8_t queued;
|
||||
SYS_ARCH_DECL_PROTECT(old_level);
|
||||
|
||||
SYS_ARCH_PROTECT(old_level);
|
||||
queued = pbuf_free_ooseq_queued;
|
||||
pbuf_free_ooseq_queued = 1;
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
|
||||
if(!queued) {
|
||||
/* queue a call to pbuf_free_ooseq if not already queued */
|
||||
if(tcpip_callback_with_block(pbuf_free_ooseq, NULL, 0) != ERR_OK) {
|
||||
SYS_ARCH_PROTECT(old_level);
|
||||
pbuf_free_ooseq_queued = 0;
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* PBUF_POOL_FREE_OOSEQ */
|
||||
#endif /* !TCP_QUEUE_OOSEQ || NO_SYS */
|
||||
|
||||
/**
|
||||
* Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type).
|
||||
@ -154,7 +184,7 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
|
||||
struct pbuf *p, *q, *r;
|
||||
u16_t offset;
|
||||
s32_t rem_len; /* remaining length */
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE | 3, ("pbuf_alloc(length=%"U16_F")\n", length));
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F")\n", length));
|
||||
|
||||
/* determine header offset */
|
||||
offset = 0;
|
||||
@ -181,9 +211,10 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
|
||||
switch (type) {
|
||||
case PBUF_POOL:
|
||||
/* allocate head of pbuf chain into p */
|
||||
ALLOC_POOL_PBUF(p);
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE | 3, ("pbuf_alloc: allocated pbuf %p\n", (void *)p));
|
||||
p = memp_malloc(MEMP_PBUF_POOL);
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc: allocated pbuf %p\n", (void *)p));
|
||||
if (p == NULL) {
|
||||
PBUF_POOL_IS_EMPTY();
|
||||
return NULL;
|
||||
}
|
||||
p->type = type;
|
||||
@ -213,8 +244,9 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
|
||||
rem_len = length - p->len;
|
||||
/* any remaining pbufs to be allocated? */
|
||||
while (rem_len > 0) {
|
||||
ALLOC_POOL_PBUF(q);
|
||||
q = memp_malloc(MEMP_PBUF_POOL);
|
||||
if (q == NULL) {
|
||||
PBUF_POOL_IS_EMPTY();
|
||||
/* free chain so far allocated */
|
||||
pbuf_free(p);
|
||||
/* bail out unsuccesfully */
|
||||
@ -268,7 +300,8 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
|
||||
/* only allocate memory for the pbuf structure */
|
||||
p = memp_malloc(MEMP_PBUF);
|
||||
if (p == NULL) {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE | 2, ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n",
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n",
|
||||
(type == PBUF_ROM) ? "ROM" : "REF"));
|
||||
return NULL;
|
||||
}
|
||||
@ -286,7 +319,7 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
|
||||
p->ref = 1;
|
||||
/* set flags */
|
||||
p->flags = 0;
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE | 3, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p));
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p));
|
||||
return p;
|
||||
}
|
||||
|
||||
@ -426,9 +459,9 @@ pbuf_header(struct pbuf *p, s16_t header_size_increment)
|
||||
p->payload = (u8_t *)p->payload - header_size_increment;
|
||||
/* boundary check fails? */
|
||||
if ((u8_t *)p->payload < (u8_t *)p + SIZEOF_STRUCT_PBUF) {
|
||||
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_header: failed as %p < %p (not enough space for new header size)\n",
|
||||
(void *)p->payload,
|
||||
(void *)(p + 1)));\
|
||||
LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("pbuf_header: failed as %p < %p (not enough space for new header size)\n",
|
||||
(void *)p->payload, (void *)(p + 1)));
|
||||
/* restore old payload pointer */
|
||||
p->payload = payload;
|
||||
/* bail out unsuccesfully */
|
||||
@ -455,7 +488,7 @@ pbuf_header(struct pbuf *p, s16_t header_size_increment)
|
||||
p->len += header_size_increment;
|
||||
p->tot_len += header_size_increment;
|
||||
|
||||
LWIP_DEBUGF(PBUF_DEBUG, ("pbuf_header: old %p new %p (%"S16_F")\n",
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_header: old %p new %p (%"S16_F")\n",
|
||||
(void *)payload, (void *)p->payload, header_size_increment));
|
||||
|
||||
return 0;
|
||||
@ -504,10 +537,11 @@ pbuf_free(struct pbuf *p)
|
||||
if (p == NULL) {
|
||||
LWIP_ASSERT("p != NULL", p != NULL);
|
||||
/* if assertions are disabled, proceed with debug output */
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE | 2, ("pbuf_free(p == NULL) was called.\n"));
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("pbuf_free(p == NULL) was called.\n"));
|
||||
return 0;
|
||||
}
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE | 3, ("pbuf_free(%p)\n", (void *)p));
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free(%p)\n", (void *)p));
|
||||
|
||||
PERF_START;
|
||||
|
||||
@ -534,7 +568,7 @@ pbuf_free(struct pbuf *p)
|
||||
if (ref == 0) {
|
||||
/* remember next pbuf in chain for next iteration */
|
||||
q = p->next;
|
||||
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: deallocating %p\n", (void *)p));
|
||||
LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: deallocating %p\n", (void *)p));
|
||||
type = p->type;
|
||||
/* is this a pbuf from the pool? */
|
||||
if (type == PBUF_POOL) {
|
||||
@ -552,7 +586,7 @@ pbuf_free(struct pbuf *p)
|
||||
/* p->ref > 0, this pbuf is still referenced to */
|
||||
/* (and so the remaining pbufs in chain as well) */
|
||||
} else {
|
||||
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, ref));
|
||||
LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, ref));
|
||||
/* stop walking through the chain */
|
||||
p = NULL;
|
||||
}
|
||||
@ -657,7 +691,7 @@ pbuf_chain(struct pbuf *h, struct pbuf *t)
|
||||
pbuf_cat(h, t);
|
||||
/* t is now referenced by h */
|
||||
pbuf_ref(t);
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_FRESH | 2, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t));
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -686,10 +720,10 @@ pbuf_dechain(struct pbuf *p)
|
||||
/* total length of pbuf p is its own length only */
|
||||
p->tot_len = p->len;
|
||||
/* q is no longer referenced by p, free it */
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_STATE, ("pbuf_dechain: unreferencing %p\n", (void *)q));
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_dechain: unreferencing %p\n", (void *)q));
|
||||
tail_gone = pbuf_free(q);
|
||||
if (tail_gone > 0) {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_STATE,
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE,
|
||||
("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q));
|
||||
}
|
||||
/* return remaining tail or NULL if deallocated */
|
||||
@ -722,7 +756,7 @@ pbuf_copy(struct pbuf *p_to, struct pbuf *p_from)
|
||||
{
|
||||
u16_t offset_to=0, offset_from=0, len;
|
||||
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE | 3, ("pbuf_copy(%p, %p)\n",
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n",
|
||||
(void*)p_to, (void*)p_from));
|
||||
|
||||
/* is the target big enough to hold the source? */
|
||||
@ -768,7 +802,7 @@ pbuf_copy(struct pbuf *p_to, struct pbuf *p_from)
|
||||
(p_to->next == NULL), return ERR_VAL;);
|
||||
}
|
||||
} while (p_from);
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE | 1, ("pbuf_copy: end of chain reached.\n"));
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy: end of chain reached.\n"));
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
@ -210,7 +210,7 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
|
||||
struct ip_addr *src_ip;
|
||||
struct pbuf *q; /* q will be sent down the stack */
|
||||
|
||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | 3, ("raw_sendto\n"));
|
||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n"));
|
||||
|
||||
/* not enough space to add an IP header to first pbuf in given p chain? */
|
||||
if (pbuf_header(p, IP_HLEN)) {
|
||||
@ -218,7 +218,7 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
|
||||
q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM);
|
||||
/* new header pbuf could not be allocated? */
|
||||
if (q == NULL) {
|
||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | 2, ("raw_sendto: could not allocate header\n"));
|
||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: could not allocate header\n"));
|
||||
return ERR_MEM;
|
||||
}
|
||||
/* chain header q in front of given pbuf p */
|
||||
@ -235,7 +235,7 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
|
||||
}
|
||||
|
||||
if ((netif = ip_route(ipaddr)) == NULL) {
|
||||
LWIP_DEBUGF(RAW_DEBUG | 1, ("raw_sendto: No route to 0x%"X32_F"\n", ipaddr->addr));
|
||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to 0x%"X32_F"\n", ipaddr->addr));
|
||||
/* free any temporary header pbuf allocated by pbuf_header() */
|
||||
if (q != p) {
|
||||
pbuf_free(q);
|
||||
@ -246,7 +246,7 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
|
||||
#if IP_SOF_BROADCAST
|
||||
/* broadcast filter? */
|
||||
if ( ((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(ipaddr, netif) ) {
|
||||
LWIP_DEBUGF(RAW_DEBUG | 1, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
|
||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
|
||||
/* free any temporary header pbuf allocated by pbuf_header() */
|
||||
if (q != p) {
|
||||
pbuf_free(q);
|
||||
@ -335,7 +335,7 @@ struct raw_pcb *
|
||||
raw_new(u8_t proto) {
|
||||
struct raw_pcb *pcb;
|
||||
|
||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | 3, ("raw_new\n"));
|
||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_new\n"));
|
||||
|
||||
pcb = memp_malloc(MEMP_RAW_PCB);
|
||||
/* could allocate RAW PCB? */
|
||||
|
@ -2077,25 +2077,25 @@ void snmp_get_snmpenableauthentraps(u8_t *value)
|
||||
void
|
||||
noleafs_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
|
||||
{
|
||||
if (ident_len){}
|
||||
if (ident){}
|
||||
LWIP_UNUSED_ARG(ident_len);
|
||||
LWIP_UNUSED_ARG(ident);
|
||||
od->instance = MIB_OBJECT_NONE;
|
||||
}
|
||||
|
||||
void
|
||||
noleafs_get_value(struct obj_def *od, u16_t len, void *value)
|
||||
{
|
||||
if (od){}
|
||||
if (len){}
|
||||
if (value){}
|
||||
LWIP_UNUSED_ARG(od);
|
||||
LWIP_UNUSED_ARG(len);
|
||||
LWIP_UNUSED_ARG(value);
|
||||
}
|
||||
|
||||
u8_t
|
||||
noleafs_set_test(struct obj_def *od, u16_t len, void *value)
|
||||
{
|
||||
if (od){}
|
||||
if (len){}
|
||||
if (value){}
|
||||
LWIP_UNUSED_ARG(od);
|
||||
LWIP_UNUSED_ARG(len);
|
||||
LWIP_UNUSED_ARG(value);
|
||||
/* can't set */
|
||||
return 0;
|
||||
}
|
||||
@ -2103,9 +2103,9 @@ noleafs_set_test(struct obj_def *od, u16_t len, void *value)
|
||||
void
|
||||
noleafs_set_value(struct obj_def *od, u16_t len, void *value)
|
||||
{
|
||||
if (od){}
|
||||
if (len){}
|
||||
if (value){}
|
||||
LWIP_UNUSED_ARG(od);
|
||||
LWIP_UNUSED_ARG(len);
|
||||
LWIP_UNUSED_ARG(value);
|
||||
}
|
||||
|
||||
|
||||
@ -2238,7 +2238,7 @@ system_set_test(struct obj_def *od, u16_t len, void *value)
|
||||
{
|
||||
u8_t id, set_ok;
|
||||
|
||||
if (value) {}
|
||||
LWIP_UNUSED_ARG(value);
|
||||
set_ok = 0;
|
||||
id = od->id_inst_ptr[0];
|
||||
switch (id)
|
||||
@ -2332,7 +2332,7 @@ interfaces_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
|
||||
static void
|
||||
interfaces_get_value(struct obj_def *od, u16_t len, void *value)
|
||||
{
|
||||
if (len){}
|
||||
LWIP_UNUSED_ARG(len);
|
||||
if (od->id_inst_ptr[0] == 1)
|
||||
{
|
||||
s32_t *sint_ptr = value;
|
||||
@ -2724,7 +2724,8 @@ atentry_get_value(struct obj_def *od, u16_t len, void *value)
|
||||
struct ip_addr ip;
|
||||
struct netif *netif;
|
||||
|
||||
if (len) {}
|
||||
LWIP_UNUSED_ARG(len);
|
||||
LWIP_UNUSED_ARG(value);/* if !LWIP_ARP */
|
||||
|
||||
snmp_ifindextonetif(od->id_inst_ptr[1], &netif);
|
||||
snmp_oidtoip(&od->id_inst_ptr[2], &ip);
|
||||
@ -2831,7 +2832,7 @@ ip_get_value(struct obj_def *od, u16_t len, void *value)
|
||||
{
|
||||
u8_t id;
|
||||
|
||||
if (len) {}
|
||||
LWIP_UNUSED_ARG(len);
|
||||
id = od->id_inst_ptr[0];
|
||||
switch (id)
|
||||
{
|
||||
@ -2985,7 +2986,7 @@ ip_set_test(struct obj_def *od, u16_t len, void *value)
|
||||
u8_t id, set_ok;
|
||||
s32_t *sint_ptr = value;
|
||||
|
||||
if (len) {}
|
||||
LWIP_UNUSED_ARG(len);
|
||||
set_ok = 0;
|
||||
id = od->id_inst_ptr[0];
|
||||
switch (id)
|
||||
@ -3065,7 +3066,7 @@ ip_addrentry_get_value(struct obj_def *od, u16_t len, void *value)
|
||||
struct ip_addr ip;
|
||||
struct netif *netif = netif_list;
|
||||
|
||||
if (len) {}
|
||||
LWIP_UNUSED_ARG(len);
|
||||
snmp_oidtoip(&od->id_inst_ptr[1], &ip);
|
||||
ip.addr = htonl(ip.addr);
|
||||
ifidx = 0;
|
||||
@ -3408,7 +3409,8 @@ ip_ntomentry_get_value(struct obj_def *od, u16_t len, void *value)
|
||||
struct ip_addr ip;
|
||||
struct netif *netif;
|
||||
|
||||
if (len) {}
|
||||
LWIP_UNUSED_ARG(len);
|
||||
LWIP_UNUSED_ARG(value);/* if !LWIP_ARP */
|
||||
|
||||
snmp_ifindextonetif(od->id_inst_ptr[1], &netif);
|
||||
snmp_oidtoip(&od->id_inst_ptr[2], &ip);
|
||||
@ -3482,7 +3484,7 @@ icmp_get_value(struct obj_def *od, u16_t len, void *value)
|
||||
u32_t *uint_ptr = value;
|
||||
u8_t id;
|
||||
|
||||
if (len){}
|
||||
LWIP_UNUSED_ARG(len);
|
||||
id = od->id_inst_ptr[0];
|
||||
switch (id)
|
||||
{
|
||||
@ -3636,7 +3638,7 @@ tcp_get_value(struct obj_def *od, u16_t len, void *value)
|
||||
s32_t *sint_ptr = value;
|
||||
u8_t id;
|
||||
|
||||
if (len){}
|
||||
LWIP_UNUSED_ARG(len);
|
||||
id = od->id_inst_ptr[0];
|
||||
switch (id)
|
||||
{
|
||||
@ -3804,7 +3806,7 @@ udp_get_value(struct obj_def *od, u16_t len, void *value)
|
||||
u32_t *uint_ptr = value;
|
||||
u8_t id;
|
||||
|
||||
if (len){}
|
||||
LWIP_UNUSED_ARG(len);
|
||||
id = od->id_inst_ptr[0];
|
||||
switch (id)
|
||||
{
|
||||
@ -3870,7 +3872,7 @@ udpentry_get_value(struct obj_def *od, u16_t len, void *value)
|
||||
struct ip_addr ip;
|
||||
u16_t port;
|
||||
|
||||
if (len){}
|
||||
LWIP_UNUSED_ARG(len);
|
||||
snmp_oidtoip(&od->id_inst_ptr[1], &ip);
|
||||
ip.addr = htonl(ip.addr);
|
||||
port = od->id_inst_ptr[5];
|
||||
@ -3977,7 +3979,7 @@ snmp_get_value(struct obj_def *od, u16_t len, void *value)
|
||||
u32_t *uint_ptr = value;
|
||||
u8_t id;
|
||||
|
||||
if (len){}
|
||||
LWIP_UNUSED_ARG(len);
|
||||
id = od->id_inst_ptr[0];
|
||||
switch (id)
|
||||
{
|
||||
@ -4080,7 +4082,7 @@ snmp_set_test(struct obj_def *od, u16_t len, void *value)
|
||||
{
|
||||
u8_t id, set_ok;
|
||||
|
||||
if (len) {}
|
||||
LWIP_UNUSED_ARG(len);
|
||||
set_ok = 0;
|
||||
id = od->id_inst_ptr[0];
|
||||
if (id == 30)
|
||||
@ -4113,7 +4115,7 @@ snmp_set_value(struct obj_def *od, u16_t len, void *value)
|
||||
{
|
||||
u8_t id;
|
||||
|
||||
if (len) {}
|
||||
LWIP_UNUSED_ARG(len);
|
||||
id = od->id_inst_ptr[0];
|
||||
if (id == 30)
|
||||
{
|
||||
|
@ -118,7 +118,7 @@ snmp_netiftoifindex(struct netif *netif, s32_t *ifidx)
|
||||
u16_t i;
|
||||
|
||||
i = 0;
|
||||
while (nif != netif)
|
||||
while ((nif != NULL) && (nif != netif))
|
||||
{
|
||||
nif = nif->next;
|
||||
i++;
|
||||
|
@ -97,7 +97,7 @@ sys_mbox_fetch(sys_mbox_t mbox, void **msg)
|
||||
arg = tmptimeout->arg;
|
||||
memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
|
||||
if (h != NULL) {
|
||||
LWIP_DEBUGF(SYS_DEBUG, ("smf calling h=%p(%p)\n", (void*)&h, arg));
|
||||
LWIP_DEBUGF(SYS_DEBUG, ("smf calling h=%p(%p)\n", *(void**)&h, arg));
|
||||
h(arg);
|
||||
}
|
||||
|
||||
@ -154,7 +154,7 @@ sys_sem_wait(sys_sem_t sem)
|
||||
arg = tmptimeout->arg;
|
||||
memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
|
||||
if (h != NULL) {
|
||||
LWIP_DEBUGF(SYS_DEBUG, ("ssw h=%p(%p)\n", (void*)&h, (void *)arg));
|
||||
LWIP_DEBUGF(SYS_DEBUG, ("ssw h=%p(%p)\n", *(void**)&h, (void *)arg));
|
||||
h(arg);
|
||||
}
|
||||
|
||||
@ -203,7 +203,7 @@ sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
|
||||
timeouts = sys_arch_timeouts();
|
||||
|
||||
LWIP_DEBUGF(SYS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" h=%p arg=%p\n",
|
||||
(void *)timeout, msecs, (void*)&h, (void *)arg));
|
||||
(void *)timeout, msecs, *(void**)&h, (void *)arg));
|
||||
|
||||
if (timeouts == NULL) {
|
||||
LWIP_ASSERT("sys_timeout: timeouts != NULL", timeouts != NULL);
|
||||
@ -264,13 +264,15 @@ sys_untimeout(sys_timeout_handler h, void *arg)
|
||||
if ((t->h == h) && (t->arg == arg)) {
|
||||
/* We have a match */
|
||||
/* Unlink from previous in list */
|
||||
if (prev_t == NULL)
|
||||
if (prev_t == NULL) {
|
||||
timeouts->next = t->next;
|
||||
else
|
||||
} else {
|
||||
prev_t->next = t->next;
|
||||
}
|
||||
/* If not the last one, add time of this one back to next */
|
||||
if (t->next != NULL)
|
||||
if (t->next != NULL) {
|
||||
t->next->time += t->time;
|
||||
}
|
||||
memp_free(MEMP_SYS_TIMEOUT, t);
|
||||
return;
|
||||
}
|
||||
|
@ -50,9 +50,24 @@
|
||||
#include "lwip/snmp.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/debug.h"
|
||||
#include "lwip/stats.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
const char *tcp_state_str[] = {
|
||||
"CLOSED",
|
||||
"LISTEN",
|
||||
"SYN_SENT",
|
||||
"SYN_RCVD",
|
||||
"ESTABLISHED",
|
||||
"FIN_WAIT_1",
|
||||
"FIN_WAIT_2",
|
||||
"CLOSE_WAIT",
|
||||
"CLOSING",
|
||||
"LAST_ACK",
|
||||
"TIME_WAIT"
|
||||
};
|
||||
|
||||
/* Incremented every coarse grained timer shot (typically every 500 ms). */
|
||||
u32_t tcp_ticks;
|
||||
const u8_t tcp_backoff[13] =
|
||||
@ -394,7 +409,7 @@ u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb)
|
||||
{
|
||||
u32_t new_right_edge = pcb->rcv_nxt + pcb->rcv_wnd;
|
||||
|
||||
if (TCP_SEQ_GEQ(new_right_edge, pcb->rcv_ann_right_edge + pcb->mss)) {
|
||||
if (TCP_SEQ_GEQ(new_right_edge, pcb->rcv_ann_right_edge + LWIP_MIN((TCP_WND / 2), pcb->mss))) {
|
||||
/* we can advertise more window */
|
||||
pcb->rcv_ann_wnd = pcb->rcv_wnd;
|
||||
return new_right_edge - pcb->rcv_ann_right_edge;
|
||||
@ -564,6 +579,7 @@ tcp_slowtmr(void)
|
||||
struct tcp_pcb *pcb, *pcb2, *prev;
|
||||
u16_t eff_wnd;
|
||||
u8_t pcb_remove; /* flag if a PCB should be removed */
|
||||
u8_t pcb_reset; /* flag if a RST should be sent when removing */
|
||||
err_t err;
|
||||
|
||||
err = ERR_OK;
|
||||
@ -583,6 +599,7 @@ tcp_slowtmr(void)
|
||||
LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT);
|
||||
|
||||
pcb_remove = 0;
|
||||
pcb_reset = 0;
|
||||
|
||||
if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) {
|
||||
++pcb_remove;
|
||||
@ -666,7 +683,8 @@ tcp_slowtmr(void)
|
||||
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
|
||||
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
|
||||
|
||||
tcp_abort(pcb);
|
||||
++pcb_remove;
|
||||
++pcb_reset;
|
||||
}
|
||||
#if LWIP_TCP_KEEPALIVE
|
||||
else if((u32_t)(tcp_ticks - pcb->tmr) >
|
||||
@ -726,6 +744,10 @@ tcp_slowtmr(void)
|
||||
}
|
||||
|
||||
TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_ABRT);
|
||||
if (pcb_reset) {
|
||||
tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
|
||||
pcb->local_port, pcb->remote_port);
|
||||
}
|
||||
|
||||
pcb2 = pcb->next;
|
||||
memp_free(MEMP_TCP_PCB, pcb);
|
||||
@ -899,11 +921,12 @@ tcp_seg_copy(struct tcp_seg *seg)
|
||||
* Default receive callback that is called if the user didn't register
|
||||
* a recv callback for the pcb.
|
||||
*/
|
||||
static err_t
|
||||
err_t
|
||||
tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
|
||||
{
|
||||
arg = arg;
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
if (p != NULL) {
|
||||
tcp_recved(pcb, p->tot_len);
|
||||
pbuf_free(p);
|
||||
} else if (err == ERR_OK) {
|
||||
return tcp_close(pcb);
|
||||
@ -993,9 +1016,18 @@ tcp_alloc(u8_t prio)
|
||||
pcb = memp_malloc(MEMP_TCP_PCB);
|
||||
if (pcb == NULL) {
|
||||
/* Try killing active connections with lower priority than the new one. */
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing connection with prio lower than %d\n", prio));
|
||||
tcp_kill_prio(prio);
|
||||
/* Try to allocate a tcp_pcb again. */
|
||||
pcb = memp_malloc(MEMP_TCP_PCB);
|
||||
if (pcb != NULL) {
|
||||
/* adjust err stats: memp_malloc failed twice before */
|
||||
MEMP_STATS_DEC(err, MEMP_TCP_PCB);
|
||||
}
|
||||
}
|
||||
if (pcb != NULL) {
|
||||
/* adjust err stats: timewait PCB was freed above */
|
||||
MEMP_STATS_DEC(err, MEMP_TCP_PCB);
|
||||
}
|
||||
}
|
||||
if (pcb != NULL) {
|
||||
@ -1218,7 +1250,7 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
|
||||
* Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first.
|
||||
*
|
||||
* @param pcblist PCB list to purge.
|
||||
* @param pcb tcp_pcb to purge. The pcb itself is also deallocated!
|
||||
* @param pcb tcp_pcb to purge. The pcb itself is NOT deallocated!
|
||||
*/
|
||||
void
|
||||
tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)
|
||||
@ -1288,6 +1320,12 @@ tcp_eff_send_mss(u16_t sendmss, struct ip_addr *addr)
|
||||
}
|
||||
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
|
||||
|
||||
const char*
|
||||
tcp_debug_state_str(enum tcp_state s)
|
||||
{
|
||||
return tcp_state_str[s];
|
||||
}
|
||||
|
||||
#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
|
||||
/**
|
||||
* Print a tcp header for debugging purposes.
|
||||
@ -1333,42 +1371,7 @@ tcp_debug_print(struct tcp_hdr *tcphdr)
|
||||
void
|
||||
tcp_debug_print_state(enum tcp_state s)
|
||||
{
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("State: "));
|
||||
switch (s) {
|
||||
case CLOSED:
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("CLOSED\n"));
|
||||
break;
|
||||
case LISTEN:
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("LISTEN\n"));
|
||||
break;
|
||||
case SYN_SENT:
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("SYN_SENT\n"));
|
||||
break;
|
||||
case SYN_RCVD:
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("SYN_RCVD\n"));
|
||||
break;
|
||||
case ESTABLISHED:
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("ESTABLISHED\n"));
|
||||
break;
|
||||
case FIN_WAIT_1:
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("FIN_WAIT_1\n"));
|
||||
break;
|
||||
case FIN_WAIT_2:
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("FIN_WAIT_2\n"));
|
||||
break;
|
||||
case CLOSE_WAIT:
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("CLOSE_WAIT\n"));
|
||||
break;
|
||||
case CLOSING:
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("CLOSING\n"));
|
||||
break;
|
||||
case LAST_ACK:
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("LAST_ACK\n"));
|
||||
break;
|
||||
case TIME_WAIT:
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TIME_WAIT\n"));
|
||||
break;
|
||||
}
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("State: %s\n", tcp_state_str[s]));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -74,7 +74,7 @@ struct tcp_pcb *tcp_input_pcb;
|
||||
|
||||
/* Forward declarations. */
|
||||
static err_t tcp_process(struct tcp_pcb *pcb);
|
||||
static u8_t tcp_receive(struct tcp_pcb *pcb);
|
||||
static void tcp_receive(struct tcp_pcb *pcb);
|
||||
static void tcp_parseopt(struct tcp_pcb *pcb);
|
||||
|
||||
static err_t tcp_listen_input(struct tcp_pcb_listen *pcb);
|
||||
@ -288,10 +288,8 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
tcp_input_pcb = pcb;
|
||||
err = tcp_process(pcb);
|
||||
tcp_input_pcb = NULL;
|
||||
/* A return value of ERR_ABRT means that tcp_abort() was called
|
||||
and that the pcb has been freed. If so, we don't do anything. */
|
||||
if (err != ERR_ABRT) {
|
||||
@ -338,12 +336,17 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
TCP_EVENT_RECV(pcb, NULL, ERR_OK, err);
|
||||
}
|
||||
|
||||
/* If there were no errors, we try to send something out. */
|
||||
if (err == ERR_OK) {
|
||||
tcp_output(pcb);
|
||||
}
|
||||
tcp_input_pcb = NULL;
|
||||
/* Try to send something out. */
|
||||
tcp_output(pcb);
|
||||
#if TCP_INPUT_DEBUG
|
||||
#if TCP_DEBUG
|
||||
tcp_debug_print_state(pcb->state);
|
||||
#endif /* TCP_DEBUG */
|
||||
#endif /* TCP_INPUT_DEBUG */
|
||||
}
|
||||
}
|
||||
tcp_input_pcb = NULL;
|
||||
|
||||
|
||||
/* give up our reference to inseg.p */
|
||||
@ -352,12 +355,6 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
pbuf_free(inseg.p);
|
||||
inseg.p = NULL;
|
||||
}
|
||||
#if TCP_INPUT_DEBUG
|
||||
#if TCP_DEBUG
|
||||
tcp_debug_print_state(pcb->state);
|
||||
#endif /* TCP_DEBUG */
|
||||
#endif /* TCP_INPUT_DEBUG */
|
||||
|
||||
} else {
|
||||
|
||||
/* If no matching PCB was found, send a TCP RST (reset) to the
|
||||
@ -481,13 +478,36 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
||||
static err_t
|
||||
tcp_timewait_input(struct tcp_pcb *pcb)
|
||||
{
|
||||
if (TCP_SEQ_GT(seqno + tcplen, pcb->rcv_nxt)) {
|
||||
pcb->rcv_nxt = seqno + tcplen;
|
||||
/* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */
|
||||
/* RFC 793 3.9 Event Processing - Segment Arrives:
|
||||
* - first check sequence number - we skip that one in TIME_WAIT (always
|
||||
* acceptable since we only send ACKs)
|
||||
* - second check the RST bit (... return) */
|
||||
if (flags & TCP_RST) {
|
||||
return ERR_OK;
|
||||
}
|
||||
if (tcplen > 0) {
|
||||
tcp_ack_now(pcb);
|
||||
/* - fourth, check the SYN bit, */
|
||||
if (flags & TCP_SYN) {
|
||||
/* If an incoming segment is not acceptable, an acknowledgment
|
||||
should be sent in reply */
|
||||
if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) {
|
||||
/* If the SYN is in the window it is an error, send a reset */
|
||||
tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
return ERR_OK;
|
||||
}
|
||||
} else if (flags & TCP_FIN) {
|
||||
/* - eighth, check the FIN bit: Remain in the TIME-WAIT state.
|
||||
Restart the 2 MSL time-wait timeout.*/
|
||||
pcb->tmr = tcp_ticks;
|
||||
}
|
||||
return tcp_output(pcb);
|
||||
|
||||
if ((tcplen > 0)) {
|
||||
/* Acknowledge data, FIN or out-of-window SYN */
|
||||
pcb->flags |= TF_ACK_NOW;
|
||||
return tcp_output(pcb);
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -628,6 +648,11 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
* we'd better pass it on to the application as well. */
|
||||
tcp_receive(pcb);
|
||||
|
||||
/* Prevent ACK for SYN to generate a sent event */
|
||||
if (pcb->acked != 0) {
|
||||
pcb->acked--;
|
||||
}
|
||||
|
||||
pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
|
||||
|
||||
if (recv_flags & TF_GOT_FIN) {
|
||||
@ -660,7 +685,7 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
if (recv_flags & TF_GOT_FIN) {
|
||||
if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
|
||||
LWIP_DEBUGF(TCP_DEBUG,
|
||||
("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
||||
("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
||||
tcp_ack_now(pcb);
|
||||
tcp_pcb_purge(pcb);
|
||||
TCP_RMV(&tcp_active_pcbs, pcb);
|
||||
@ -677,7 +702,7 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
case FIN_WAIT_2:
|
||||
tcp_receive(pcb);
|
||||
if (recv_flags & TF_GOT_FIN) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
||||
tcp_ack_now(pcb);
|
||||
tcp_pcb_purge(pcb);
|
||||
TCP_RMV(&tcp_active_pcbs, pcb);
|
||||
@ -688,7 +713,7 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
case CLOSING:
|
||||
tcp_receive(pcb);
|
||||
if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
||||
tcp_pcb_purge(pcb);
|
||||
TCP_RMV(&tcp_active_pcbs, pcb);
|
||||
pcb->state = TIME_WAIT;
|
||||
@ -698,7 +723,7 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
case LAST_ACK:
|
||||
tcp_receive(pcb);
|
||||
if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
||||
/* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */
|
||||
recv_flags |= TF_CLOSED;
|
||||
}
|
||||
@ -709,6 +734,47 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
#if TCP_QUEUE_OOSEQ
|
||||
/**
|
||||
* Insert segment into the list (segments covered with new one will be deleted)
|
||||
*
|
||||
* Called from tcp_receive()
|
||||
*/
|
||||
static void
|
||||
tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next)
|
||||
{
|
||||
struct tcp_seg *old_seg;
|
||||
|
||||
if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
|
||||
/* received segment overlaps all following segments */
|
||||
tcp_segs_free(next);
|
||||
next = NULL;
|
||||
}
|
||||
else {
|
||||
/* delete some following segments
|
||||
oos queue may have segments with FIN flag */
|
||||
while (next &&
|
||||
TCP_SEQ_GEQ((seqno + cseg->len),
|
||||
(next->tcphdr->seqno + next->len))) {
|
||||
/* cseg with FIN already processed */
|
||||
if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
|
||||
TCPH_FLAGS_SET(cseg->tcphdr, TCPH_FLAGS(cseg->tcphdr) | TCP_FIN);
|
||||
}
|
||||
old_seg = next;
|
||||
next = next->next;
|
||||
tcp_seg_free(old_seg);
|
||||
}
|
||||
if (next &&
|
||||
TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) {
|
||||
/* We need to trim the incoming segment. */
|
||||
cseg->len = (u16_t)(next->tcphdr->seqno - seqno);
|
||||
pbuf_realloc(cseg->p, cseg->len);
|
||||
}
|
||||
}
|
||||
cseg->next = next;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Called by tcp_process. Checks if the given segment is an ACK for outstanding
|
||||
* data, and if so frees the memory of the buffered data. Next, is places the
|
||||
@ -720,10 +786,8 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
* estimation, the RTT is estimated here as well.
|
||||
*
|
||||
* Called from tcp_process().
|
||||
*
|
||||
* @return 1 if the incoming segment is the next in sequence, 0 if not
|
||||
*/
|
||||
static u8_t
|
||||
static void
|
||||
tcp_receive(struct tcp_pcb *pcb)
|
||||
{
|
||||
struct tcp_seg *next;
|
||||
@ -735,7 +799,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
s16_t m;
|
||||
u32_t right_wnd_edge;
|
||||
u16_t new_tot_len;
|
||||
u8_t accepted_inseq = 0;
|
||||
int found_dupack = 0;
|
||||
|
||||
if (flags & TCP_ACK) {
|
||||
right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2;
|
||||
@ -762,51 +826,62 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
#endif /* TCP_WND_DEBUG */
|
||||
}
|
||||
|
||||
if (pcb->lastack == ackno) {
|
||||
/* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a
|
||||
* duplicate ack if:
|
||||
* 1) It doesn't ACK new data
|
||||
* 2) length of received packet is zero (i.e. no payload)
|
||||
* 3) the advertised window hasn't changed
|
||||
* 4) There is outstanding unacknowledged data (retransmission timer running)
|
||||
* 5) The ACK is == biggest ACK sequence number so far seen (snd_una)
|
||||
*
|
||||
* If it passes all five, should process as a dupack:
|
||||
* a) dupacks < 3: do nothing
|
||||
* b) dupacks == 3: fast retransmit
|
||||
* c) dupacks > 3: increase cwnd
|
||||
*
|
||||
* If it only passes 1-3, should reset dupack counter (and add to
|
||||
* stats, which we don't do in lwIP)
|
||||
*
|
||||
* If it only passes 1, should reset dupack counter
|
||||
*
|
||||
*/
|
||||
|
||||
/* Clause 1 */
|
||||
if (TCP_SEQ_LEQ(ackno, pcb->lastack)) {
|
||||
pcb->acked = 0;
|
||||
|
||||
if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge){
|
||||
++pcb->dupacks;
|
||||
if (pcb->dupacks >= 3 && pcb->unacked != NULL) {
|
||||
if (!(pcb->flags & TF_INFR)) {
|
||||
/* This is fast retransmit. Retransmit the first unacked segment. */
|
||||
LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupacks %"U16_F" (%"U32_F"), fast retransmit %"U32_F"\n",
|
||||
(u16_t)pcb->dupacks, pcb->lastack,
|
||||
ntohl(pcb->unacked->tcphdr->seqno)));
|
||||
tcp_rexmit(pcb);
|
||||
/* Set ssthresh to max (FlightSize / 2, 2*SMSS) */
|
||||
/*pcb->ssthresh = LWIP_MAX((pcb->snd_max -
|
||||
pcb->lastack) / 2,
|
||||
2 * pcb->mss);*/
|
||||
/* Set ssthresh to half of the minimum of the current cwnd and the advertised window */
|
||||
if (pcb->cwnd > pcb->snd_wnd)
|
||||
pcb->ssthresh = pcb->snd_wnd / 2;
|
||||
else
|
||||
pcb->ssthresh = pcb->cwnd / 2;
|
||||
|
||||
/* The minimum value for ssthresh should be 2 MSS */
|
||||
if (pcb->ssthresh < 2*pcb->mss) {
|
||||
LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: The minimum value for ssthresh %"U16_F" should be min 2 mss %"U16_F"...\n", pcb->ssthresh, 2*pcb->mss));
|
||||
pcb->ssthresh = 2*pcb->mss;
|
||||
}
|
||||
|
||||
pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
|
||||
pcb->flags |= TF_INFR;
|
||||
} else {
|
||||
/* Inflate the congestion window, but not if it means that
|
||||
the value overflows. */
|
||||
if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
|
||||
pcb->cwnd += pcb->mss;
|
||||
/* Clause 2 */
|
||||
if (tcplen == 0) {
|
||||
/* Clause 3 */
|
||||
if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge){
|
||||
/* Clause 4 */
|
||||
if (pcb->rtime >= 0) {
|
||||
/* Clause 5 */
|
||||
if (pcb->lastack == ackno) {
|
||||
found_dupack = 1;
|
||||
if (pcb->dupacks + 1 > pcb->dupacks)
|
||||
++pcb->dupacks;
|
||||
if (pcb->dupacks > 3) {
|
||||
/* Inflate the congestion window, but not if it means that
|
||||
the value overflows. */
|
||||
if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
|
||||
pcb->cwnd += pcb->mss;
|
||||
}
|
||||
} else if (pcb->dupacks == 3) {
|
||||
/* Do fast retransmit */
|
||||
tcp_rexmit_fast(pcb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupack averted %"U32_F" %"U32_F"\n",
|
||||
pcb->snd_wl2 + pcb->snd_wnd, right_wnd_edge));
|
||||
}
|
||||
/* If Clause (1) or more is true, but not a duplicate ack, reset
|
||||
* count of consecutive duplicate acks */
|
||||
if (!found_dupack) {
|
||||
pcb->dupacks = 0;
|
||||
}
|
||||
} else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){
|
||||
/* We come here when the ACK acknowledges new data. */
|
||||
|
||||
|
||||
/* Reset the "IN Fast Retransmit" flag, since we are no longer
|
||||
in fast retransmit. Also reset the congestion window to the
|
||||
slow start threshold. */
|
||||
@ -868,6 +943,11 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
|
||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
|
||||
LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
|
||||
/* Prevent ACK for FIN to generate a sent event */
|
||||
if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) {
|
||||
pcb->acked--;
|
||||
}
|
||||
|
||||
pcb->snd_queuelen -= pbuf_clen(next->p);
|
||||
tcp_seg_free(next);
|
||||
|
||||
@ -908,6 +988,10 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
pcb->unsent = pcb->unsent->next;
|
||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
|
||||
LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
|
||||
/* Prevent ACK for FIN to generate a sent event */
|
||||
if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) {
|
||||
pcb->acked--;
|
||||
}
|
||||
pcb->snd_queuelen -= pbuf_clen(next->p);
|
||||
tcp_seg_free(next);
|
||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen));
|
||||
@ -1051,7 +1135,6 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
|
||||
pcb->rcv_nxt + pcb->rcv_wnd - 1)){
|
||||
if (pcb->rcv_nxt == seqno) {
|
||||
accepted_inseq = 1;
|
||||
/* The incoming segment is the next in sequence. We check if
|
||||
we have to trim the end of the segment and update rcv_nxt
|
||||
and pass the data to the application. */
|
||||
@ -1084,17 +1167,45 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
("tcp_receive: received in-order FIN, binning ooseq queue\n"));
|
||||
/* Received in-order FIN means anything that was received
|
||||
* out of order must now have been received in-order, so
|
||||
* bin the ooseq queue */
|
||||
* bin the ooseq queue
|
||||
* rcv_nxt
|
||||
* . |--ooseq--|
|
||||
* .==seg============|FIN
|
||||
*/
|
||||
while (pcb->ooseq != NULL) {
|
||||
struct tcp_seg *old_ooseq = pcb->ooseq;
|
||||
pcb->ooseq = pcb->ooseq->next;
|
||||
memp_free(MEMP_TCP_SEG, old_ooseq);
|
||||
tcp_seg_free(old_ooseq);
|
||||
}
|
||||
} else if (TCP_SEQ_LEQ(pcb->ooseq->tcphdr->seqno, seqno + tcplen)) {
|
||||
if (pcb->ooseq->len > 0) {
|
||||
/* We have to trim the second edge of the incoming segment. */
|
||||
LWIP_ASSERT("tcp_receive: trimmed segment would have zero length\n",
|
||||
TCP_SEQ_GT(pcb->ooseq->tcphdr->seqno, seqno));
|
||||
}
|
||||
else {
|
||||
struct tcp_seg* next = pcb->ooseq;
|
||||
struct tcp_seg *old_seg;
|
||||
/* rcv_nxt
|
||||
* . |--ooseq--|
|
||||
* .==seg============|
|
||||
*/
|
||||
while (next &&
|
||||
TCP_SEQ_GEQ(seqno + tcplen,
|
||||
next->tcphdr->seqno + next->len)) {
|
||||
/* inseg doesn't have FIN (already processed) */
|
||||
if (TCPH_FLAGS(next->tcphdr) & TCP_FIN &&
|
||||
(TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) {
|
||||
TCPH_FLAGS_SET(inseg.tcphdr,
|
||||
TCPH_FLAGS(inseg.tcphdr) | TCP_FIN);
|
||||
tcplen = TCP_TCPLEN(&inseg);
|
||||
}
|
||||
old_seg = next;
|
||||
next = next->next;
|
||||
tcp_seg_free(old_seg);
|
||||
}
|
||||
/* rcv_nxt
|
||||
* . |--ooseq--|
|
||||
* .==seg============|
|
||||
*/
|
||||
if (next &&
|
||||
TCP_SEQ_GT(seqno + tcplen,
|
||||
next->tcphdr->seqno)) {
|
||||
/* FIN in inseg already handled by dropping whole ooseq queue */
|
||||
inseg.len = (u16_t)(pcb->ooseq->tcphdr->seqno - seqno);
|
||||
if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
|
||||
@ -1104,15 +1215,8 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
tcplen = TCP_TCPLEN(&inseg);
|
||||
LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n",
|
||||
(seqno + tcplen) == pcb->ooseq->tcphdr->seqno);
|
||||
} else {
|
||||
/* does the ooseq segment contain only flags that are in inseg also? */
|
||||
if ((TCPH_FLAGS(inseg.tcphdr) & (TCP_FIN|TCP_SYN)) ==
|
||||
(TCPH_FLAGS(pcb->ooseq->tcphdr) & (TCP_FIN|TCP_SYN))) {
|
||||
struct tcp_seg *old_ooseq = pcb->ooseq;
|
||||
pcb->ooseq = pcb->ooseq->next;
|
||||
memp_free(MEMP_TCP_SEG, old_ooseq);
|
||||
}
|
||||
}
|
||||
pcb->ooseq = next;
|
||||
}
|
||||
}
|
||||
#endif /* TCP_QUEUE_OOSEQ */
|
||||
@ -1180,7 +1284,6 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pcb->ooseq = cseg->next;
|
||||
tcp_seg_free(cseg);
|
||||
}
|
||||
@ -1192,7 +1295,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
|
||||
} else {
|
||||
/* We get here if the incoming segment is out-of-sequence. */
|
||||
tcp_ack_now(pcb);
|
||||
tcp_send_empty_ack(pcb);
|
||||
#if TCP_QUEUE_OOSEQ
|
||||
/* We queue the segment on the ->ooseq queue. */
|
||||
if (pcb->ooseq == NULL) {
|
||||
@ -1219,25 +1322,16 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
discard. */
|
||||
if (inseg.len > next->len) {
|
||||
/* The incoming segment is larger than the old
|
||||
segment. We replace the old segment with the new
|
||||
segment. We replace some segments with the new
|
||||
one. */
|
||||
cseg = tcp_seg_copy(&inseg);
|
||||
if (cseg != NULL) {
|
||||
cseg->next = next->next;
|
||||
if (prev != NULL) {
|
||||
prev->next = cseg;
|
||||
} else {
|
||||
pcb->ooseq = cseg;
|
||||
}
|
||||
tcp_seg_free(next);
|
||||
if (cseg->next != NULL) {
|
||||
next = cseg->next;
|
||||
if (TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) {
|
||||
/* We need to trim the incoming segment. */
|
||||
cseg->len = (u16_t)(next->tcphdr->seqno - seqno);
|
||||
pbuf_realloc(cseg->p, cseg->len);
|
||||
}
|
||||
}
|
||||
tcp_oos_insert_segment(cseg, next);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
@ -1253,51 +1347,44 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
than the sequence number of the first segment on the
|
||||
queue. We put the incoming segment first on the
|
||||
queue. */
|
||||
|
||||
if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) {
|
||||
/* We need to trim the incoming segment. */
|
||||
inseg.len = (u16_t)(next->tcphdr->seqno - seqno);
|
||||
pbuf_realloc(inseg.p, inseg.len);
|
||||
}
|
||||
cseg = tcp_seg_copy(&inseg);
|
||||
if (cseg != NULL) {
|
||||
cseg->next = next;
|
||||
pcb->ooseq = cseg;
|
||||
tcp_oos_insert_segment(cseg, next);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
/*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) &&
|
||||
TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/
|
||||
if(TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)){
|
||||
/* The sequence number of the incoming segment is in
|
||||
between the sequence numbers of the previous and
|
||||
the next segment on ->ooseq. We trim and insert the
|
||||
incoming segment and trim the previous segment, if
|
||||
needed. */
|
||||
if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) {
|
||||
/* We need to trim the incoming segment. */
|
||||
inseg.len = (u16_t)(next->tcphdr->seqno - seqno);
|
||||
pbuf_realloc(inseg.p, inseg.len);
|
||||
}
|
||||
|
||||
cseg = tcp_seg_copy(&inseg);
|
||||
if (cseg != NULL) {
|
||||
cseg->next = next;
|
||||
prev->next = cseg;
|
||||
if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) {
|
||||
/* We need to trim the prev segment. */
|
||||
prev->len = (u16_t)(seqno - prev->tcphdr->seqno);
|
||||
pbuf_realloc(prev->p, prev->len);
|
||||
if (TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)) {
|
||||
/* The sequence number of the incoming segment is in
|
||||
between the sequence numbers of the previous and
|
||||
the next segment on ->ooseq. We trim trim the previous
|
||||
segment, delete next segments that included in received segment
|
||||
and trim received, if needed. */
|
||||
cseg = tcp_seg_copy(&inseg);
|
||||
if (cseg != NULL) {
|
||||
if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) {
|
||||
/* We need to trim the prev segment. */
|
||||
prev->len = (u16_t)(seqno - prev->tcphdr->seqno);
|
||||
pbuf_realloc(prev->p, prev->len);
|
||||
}
|
||||
prev->next = cseg;
|
||||
tcp_oos_insert_segment(cseg, next);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* If the "next" segment is the last segment on the
|
||||
ooseq queue, we add the incoming segment to the end
|
||||
of the list. */
|
||||
if (next->next == NULL &&
|
||||
TCP_SEQ_GT(seqno, next->tcphdr->seqno)) {
|
||||
if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
|
||||
/* segment "next" already contains all data */
|
||||
break;
|
||||
}
|
||||
next->next = tcp_seg_copy(&inseg);
|
||||
if (next->next != NULL) {
|
||||
if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) {
|
||||
@ -1316,7 +1403,8 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
|
||||
}
|
||||
} else {
|
||||
tcp_ack_now(pcb);
|
||||
/* The incoming segment is not withing the window. */
|
||||
tcp_send_empty_ack(pcb);
|
||||
}
|
||||
} else {
|
||||
/* Segments with length 0 is taken care of here. Segments that
|
||||
@ -1327,7 +1415,6 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
tcp_ack_now(pcb);
|
||||
}
|
||||
}
|
||||
return accepted_inseq;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -132,7 +132,7 @@ tcp_write(struct tcp_pcb *pcb, const void *data, u16_t len, u8_t apiflags)
|
||||
}
|
||||
return ERR_OK;
|
||||
} else {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | 3, ("tcp_write() called in invalid state\n"));
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n"));
|
||||
return ERR_CONN;
|
||||
}
|
||||
}
|
||||
@ -174,7 +174,8 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
||||
|
||||
/* fail on too much data */
|
||||
if (len > pcb->snd_buf) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", len, pcb->snd_buf));
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_WARNING,
|
||||
("tcp_enqueue: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", len, pcb->snd_buf));
|
||||
pcb->flags |= TF_NAGLEMEMERR;
|
||||
return ERR_MEM;
|
||||
}
|
||||
@ -194,7 +195,8 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
||||
queuelen = pcb->snd_queuelen;
|
||||
/* check for configured max queuelen and possible overflow */
|
||||
if ((queuelen >= TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too long queue %"U16_F" (max %"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_WARNING,
|
||||
("tcp_enqueue: too long queue %"U16_F" (max %"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
|
||||
TCP_STATS_INC(tcp.memerr);
|
||||
pcb->flags |= TF_NAGLEMEMERR;
|
||||
return ERR_MEM;
|
||||
@ -218,7 +220,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
||||
/* Allocate memory for tcp_seg, and fill in fields. */
|
||||
seg = memp_malloc(MEMP_TCP_SEG);
|
||||
if (seg == NULL) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2,
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("tcp_enqueue: could not allocate memory for tcp_seg\n"));
|
||||
goto memerr;
|
||||
}
|
||||
@ -243,7 +245,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
||||
* ROM or other static memory, and need not be copied. */
|
||||
if (apiflags & TCP_WRITE_FLAG_COPY) {
|
||||
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen + optlen, PBUF_RAM)) == NULL) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2,
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("tcp_enqueue : could not allocate memory for pbuf copy size %"U16_F"\n", seglen));
|
||||
goto memerr;
|
||||
}
|
||||
@ -259,7 +261,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
||||
else {
|
||||
/* First, allocate a pbuf for the headers. */
|
||||
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2,
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("tcp_enqueue: could not allocate memory for header pbuf\n"));
|
||||
goto memerr;
|
||||
}
|
||||
@ -275,7 +277,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
||||
/* If allocation fails, we have to deallocate the header pbuf as well. */
|
||||
pbuf_free(seg->p);
|
||||
seg->p = NULL;
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2,
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("tcp_enqueue: could not allocate memory for zero-copy pbuf\n"));
|
||||
goto memerr;
|
||||
}
|
||||
@ -293,7 +295,8 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
||||
/* Now that there are more segments queued, we check again if the
|
||||
length of the queue exceeds the configured maximum or overflows. */
|
||||
if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("tcp_enqueue: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
|
||||
goto memerr;
|
||||
}
|
||||
|
||||
@ -301,7 +304,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
||||
|
||||
/* build TCP header */
|
||||
if (pbuf_header(seg->p, TCP_HLEN)) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
|
||||
TCP_STATS_INC(tcp.err);
|
||||
goto memerr;
|
||||
}
|
||||
@ -343,11 +346,13 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
||||
if (useg != NULL &&
|
||||
TCP_TCPLEN(useg) != 0 &&
|
||||
!(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
|
||||
!(flags & (TCP_SYN | TCP_FIN)) &&
|
||||
(!(flags & (TCP_SYN | TCP_FIN)) || (flags == TCP_FIN)) &&
|
||||
/* fit within max seg size */
|
||||
(useg->len + queue->len <= pcb->mss) &&
|
||||
/* only concatenate segments with the same options */
|
||||
(useg->flags == queue->flags)) {
|
||||
(useg->flags == queue->flags) &&
|
||||
/* segments are consecutive */
|
||||
(ntohl(useg->tcphdr->seqno) + useg->len == ntohl(queue->tcphdr->seqno)) ) {
|
||||
/* Remove TCP header from first segment of our to-be-queued list */
|
||||
if(pbuf_header(queue->p, -(TCP_HLEN + optlen))) {
|
||||
/* Can we cope with this failing? Just assert for now */
|
||||
@ -363,10 +368,16 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
||||
queuelen--;
|
||||
pbuf_free(old_q);
|
||||
}
|
||||
LWIP_ASSERT("zero-length pbuf", (queue->p != NULL) && (queue->p->len > 0));
|
||||
pbuf_cat(useg->p, queue->p);
|
||||
useg->len += queue->len;
|
||||
useg->next = queue->next;
|
||||
if (flags & TCP_FIN) {
|
||||
/* the new segment contains only FIN, no data -> put the FIN into the last segment */
|
||||
LWIP_ASSERT("FIN enqueued together with data", queue->p == NULL && queue->len == 0);
|
||||
TCPH_SET_FLAG(useg->tcphdr, TCP_FIN);
|
||||
} else {
|
||||
LWIP_ASSERT("zero-length pbuf", (queue->p != NULL) && (queue->p->len > 0));
|
||||
pbuf_cat(useg->p, queue->p);
|
||||
useg->len += queue->len;
|
||||
useg->next = queue->next;
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("tcp_enqueue: chaining segments, new len %"U16_F"\n", useg->len));
|
||||
if (seg == queue) {
|
||||
@ -443,6 +454,58 @@ tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts)
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Send an ACK without data.
|
||||
*
|
||||
* @param pcb Protocol control block for the TCP connection to send the ACK
|
||||
*/
|
||||
err_t
|
||||
tcp_send_empty_ack(struct tcp_pcb *pcb)
|
||||
{
|
||||
struct pbuf *p;
|
||||
struct tcp_hdr *tcphdr;
|
||||
u8_t optlen = 0;
|
||||
|
||||
#if LWIP_TCP_TIMESTAMPS
|
||||
if (pcb->flags & TF_TIMESTAMP) {
|
||||
optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
|
||||
}
|
||||
#endif
|
||||
p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen, PBUF_RAM);
|
||||
if (p == NULL) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
|
||||
return ERR_BUF;
|
||||
}
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG,
|
||||
("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt));
|
||||
/* remove ACK flags from the PCB, as we send an empty ACK now */
|
||||
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
|
||||
|
||||
tcphdr = tcp_output_set_header(pcb, p, optlen, htonl(pcb->snd_nxt));
|
||||
|
||||
/* NB. MSS option is only sent on SYNs, so ignore it here */
|
||||
#if LWIP_TCP_TIMESTAMPS
|
||||
pcb->ts_lastacksent = pcb->rcv_nxt;
|
||||
|
||||
if (pcb->flags & TF_TIMESTAMP) {
|
||||
tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CHECKSUM_GEN_TCP
|
||||
tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
|
||||
IP_PROTO_TCP, p->tot_len);
|
||||
#endif
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
ip_output_hinted(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP, &(pcb->addr_hint));
|
||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||
ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
pbuf_free(p);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find out what we can send and send it
|
||||
@ -454,14 +517,11 @@ tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts)
|
||||
err_t
|
||||
tcp_output(struct tcp_pcb *pcb)
|
||||
{
|
||||
struct pbuf *p;
|
||||
struct tcp_hdr *tcphdr;
|
||||
struct tcp_seg *seg, *useg;
|
||||
u32_t wnd, snd_nxt;
|
||||
#if TCP_CWND_DEBUG
|
||||
s16_t i = 0;
|
||||
#endif /* TCP_CWND_DEBUG */
|
||||
u8_t optlen = 0;
|
||||
|
||||
/* First, check if we are invoked by the TCP input processing
|
||||
code. If so, we do not output anything. Instead, we rely on the
|
||||
@ -475,12 +535,6 @@ tcp_output(struct tcp_pcb *pcb)
|
||||
|
||||
seg = pcb->unsent;
|
||||
|
||||
/* useg should point to last segment on unacked queue */
|
||||
useg = pcb->unacked;
|
||||
if (useg != NULL) {
|
||||
for (; useg->next != NULL; useg = useg->next);
|
||||
}
|
||||
|
||||
/* If the TF_ACK_NOW flag is set and no data will be sent (either
|
||||
* because the ->unsent queue is empty or because the window does
|
||||
* not allow it), construct an empty ACK segment and send it.
|
||||
@ -490,44 +544,13 @@ tcp_output(struct tcp_pcb *pcb)
|
||||
if (pcb->flags & TF_ACK_NOW &&
|
||||
(seg == NULL ||
|
||||
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
|
||||
#if LWIP_TCP_TIMESTAMPS
|
||||
if (pcb->flags & TF_TIMESTAMP)
|
||||
optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
|
||||
#endif
|
||||
p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen, PBUF_RAM);
|
||||
if (p == NULL) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
|
||||
return ERR_BUF;
|
||||
}
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG,
|
||||
("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt));
|
||||
/* remove ACK flags from the PCB, as we send an empty ACK now */
|
||||
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
|
||||
return tcp_send_empty_ack(pcb);
|
||||
}
|
||||
|
||||
tcphdr = tcp_output_set_header(pcb, p, optlen, htonl(pcb->snd_nxt));
|
||||
|
||||
/* NB. MSS option is only sent on SYNs, so ignore it here */
|
||||
#if LWIP_TCP_TIMESTAMPS
|
||||
pcb->ts_lastacksent = pcb->rcv_nxt;
|
||||
|
||||
if (pcb->flags & TF_TIMESTAMP)
|
||||
tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1));
|
||||
#endif
|
||||
|
||||
#if CHECKSUM_GEN_TCP
|
||||
tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
|
||||
IP_PROTO_TCP, p->tot_len);
|
||||
#endif
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
ip_output_hinted(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP, &(pcb->addr_hint));
|
||||
#else /* LWIP_NETIF_HWADDRHINT*/
|
||||
ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
pbuf_free(p);
|
||||
|
||||
return ERR_OK;
|
||||
/* useg should point to last segment on unacked queue */
|
||||
useg = pcb->unacked;
|
||||
if (useg != NULL) {
|
||||
for (; useg->next != NULL; useg = useg->next);
|
||||
}
|
||||
|
||||
#if TCP_OUTPUT_DEBUG
|
||||
@ -853,9 +876,50 @@ tcp_rexmit(struct tcp_pcb *pcb)
|
||||
|
||||
/* Do the actual retransmission. */
|
||||
snmp_inc_tcpretranssegs();
|
||||
tcp_output(pcb);
|
||||
/* No need to call tcp_output: we are always called from tcp_input()
|
||||
and thus tcp_output directly returns. */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle retransmission after three dupacks received
|
||||
*
|
||||
* @param pcb the tcp_pcb for which to retransmit the first unacked segment
|
||||
*/
|
||||
void
|
||||
tcp_rexmit_fast(struct tcp_pcb *pcb)
|
||||
{
|
||||
if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) {
|
||||
/* This is fast retransmit. Retransmit the first unacked segment. */
|
||||
LWIP_DEBUGF(TCP_FR_DEBUG,
|
||||
("tcp_receive: dupacks %"U16_F" (%"U32_F
|
||||
"), fast retransmit %"U32_F"\n",
|
||||
(u16_t)pcb->dupacks, pcb->lastack,
|
||||
ntohl(pcb->unacked->tcphdr->seqno)));
|
||||
tcp_rexmit(pcb);
|
||||
|
||||
/* Set ssthresh to 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;
|
||||
|
||||
/* The minimum value for ssthresh should be 2 MSS */
|
||||
if (pcb->ssthresh < 2*pcb->mss) {
|
||||
LWIP_DEBUGF(TCP_FR_DEBUG,
|
||||
("tcp_receive: The minimum value for ssthresh %"U16_F
|
||||
" should be min 2 mss %"U16_F"...\n",
|
||||
pcb->ssthresh, 2*pcb->mss));
|
||||
pcb->ssthresh = 2*pcb->mss;
|
||||
}
|
||||
|
||||
pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
|
||||
pcb->flags |= TF_INFR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send keepalive packets to keep a connection active although
|
||||
* no data is sent over it.
|
||||
@ -924,6 +988,8 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
|
||||
struct pbuf *p;
|
||||
struct tcp_hdr *tcphdr;
|
||||
struct tcp_seg *seg;
|
||||
u16_t len;
|
||||
u8_t is_fin;
|
||||
|
||||
LWIP_DEBUGF(TCP_DEBUG,
|
||||
("tcp_zero_window_probe: sending ZERO WINDOW probe to %"
|
||||
@ -944,8 +1010,10 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
|
||||
if(seg == NULL)
|
||||
return;
|
||||
|
||||
p = pbuf_alloc(PBUF_IP, TCP_HLEN + 1, PBUF_RAM);
|
||||
|
||||
is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0);
|
||||
len = is_fin ? TCP_HLEN : TCP_HLEN + 1;
|
||||
|
||||
p = pbuf_alloc(PBUF_IP, len, PBUF_RAM);
|
||||
if(p == NULL) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n"));
|
||||
return;
|
||||
@ -955,8 +1023,13 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
|
||||
|
||||
tcphdr = tcp_output_set_header(pcb, p, 0, seg->tcphdr->seqno);
|
||||
|
||||
/* Copy in one byte from the head of the unacked queue */
|
||||
*((char *)p->payload + sizeof(struct tcp_hdr)) = *(char *)seg->dataptr;
|
||||
if (is_fin) {
|
||||
/* FIN segment, no data */
|
||||
TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN);
|
||||
} else {
|
||||
/* Data segment, copy in one byte from the head of the unacked queue */
|
||||
*((char *)p->payload + sizeof(struct tcp_hdr)) = *(char *)seg->dataptr;
|
||||
}
|
||||
|
||||
#if CHECKSUM_GEN_TCP
|
||||
tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip,
|
||||
|
@ -241,8 +241,8 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
if (inet_chksum_pseudo_partial(p, (struct ip_addr *)&(iphdr->src),
|
||||
(struct ip_addr *)&(iphdr->dest),
|
||||
IP_PROTO_UDPLITE, p->tot_len, chklen) != 0) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | 2,
|
||||
("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
|
||||
UDP_STATS_INC(udp.chkerr);
|
||||
UDP_STATS_INC(udp.drop);
|
||||
snmp_inc_udpinerrors();
|
||||
@ -258,7 +258,7 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
|
||||
(struct ip_addr *)&(iphdr->dest),
|
||||
IP_PROTO_UDP, p->tot_len) != 0) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | 2,
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("udp_input: UDP datagram discarded due to failing checksum\n"));
|
||||
UDP_STATS_INC(udp.chkerr);
|
||||
UDP_STATS_INC(udp.drop);
|
||||
@ -282,7 +282,7 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
/* callback */
|
||||
if (pcb->recv != NULL) {
|
||||
/* now the recv function is responsible for freeing p */
|
||||
pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src);
|
||||
pcb->recv(pcb->recv_arg, pcb, p, &iphdr->src, src);
|
||||
} else {
|
||||
/* no recv function registered? then we have to free the pbuf! */
|
||||
pbuf_free(p);
|
||||
@ -362,7 +362,7 @@ udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
|
||||
{
|
||||
struct netif *netif;
|
||||
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | 3, ("udp_send\n"));
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n"));
|
||||
|
||||
/* find the outgoing network interface for this packet */
|
||||
#if LWIP_IGMP
|
||||
@ -373,7 +373,7 @@ udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
|
||||
|
||||
/* no outgoing network interface could be found? */
|
||||
if (netif == NULL) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | 1, ("udp_send: No route to 0x%"X32_F"\n", dst_ip->addr));
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: No route to 0x%"X32_F"\n", dst_ip->addr));
|
||||
UDP_STATS_INC(udp.rterr);
|
||||
return ERR_RTE;
|
||||
}
|
||||
@ -411,17 +411,18 @@ udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
|
||||
#if IP_SOF_BROADCAST
|
||||
/* broadcast filter? */
|
||||
if ( ((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(dst_ip, netif) ) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | 1, ("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
|
||||
return ERR_VAL;
|
||||
}
|
||||
#endif /* IP_SOF_BROADCAST */
|
||||
|
||||
/* if the PCB is not yet bound to a port, bind it here */
|
||||
if (pcb->local_port == 0) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | 2, ("udp_send: not yet bound to a port, binding now\n"));
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send: not yet bound to a port, binding now\n"));
|
||||
err = udp_bind(pcb, &pcb->local_ip, pcb->local_port);
|
||||
if (err != ERR_OK) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | 2, ("udp_send: forced port bind failed\n"));
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: forced port bind failed\n"));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
@ -432,7 +433,7 @@ udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
|
||||
q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM);
|
||||
/* new header pbuf could not be allocated? */
|
||||
if (q == NULL) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | 2, ("udp_send: could not allocate header\n"));
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: could not allocate header\n"));
|
||||
return ERR_MEM;
|
||||
}
|
||||
/* chain header q in front of given pbuf p */
|
||||
@ -580,9 +581,9 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
||||
struct udp_pcb *ipcb;
|
||||
u8_t rebind;
|
||||
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | 3, ("udp_bind(ipaddr = "));
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_bind(ipaddr = "));
|
||||
ip_addr_debug_print(UDP_DEBUG, ipaddr);
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | 3, (", port = %"U16_F")\n", port));
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, (", port = %"U16_F")\n", port));
|
||||
|
||||
rebind = 0;
|
||||
/* Check for double bind and rebind of the same pcb */
|
||||
|
@ -52,6 +52,10 @@
|
||||
#include "lwip/udp.h"
|
||||
#include "netif/etharp.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* AutoIP Timing */
|
||||
#define AUTOIP_TMR_INTERVAL 100
|
||||
#define AUTOIP_TICKS_PER_SECOND (1000 / AUTOIP_TMR_INTERVAL)
|
||||
@ -100,6 +104,13 @@ void autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr);
|
||||
/** Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds */
|
||||
void autoip_tmr(void);
|
||||
|
||||
/** Handle a possible change in the network configuration */
|
||||
void autoip_network_changed(struct netif *netif);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_AUTOIP */
|
||||
|
||||
#endif /* __LWIP_AUTOIP_H__ */
|
||||
|
@ -33,9 +33,6 @@
|
||||
#define __LWIP_ICMP_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
@ -70,11 +67,6 @@ enum icmp_te_type {
|
||||
ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */
|
||||
};
|
||||
|
||||
void icmp_input(struct pbuf *p, struct netif *inp);
|
||||
|
||||
void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t);
|
||||
void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t);
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
@ -103,10 +95,17 @@ PACK_STRUCT_END
|
||||
#define ICMPH_TYPE_SET(hdr, t) ((hdr)->type = (t))
|
||||
#define ICMPH_CODE_SET(hdr, c) ((hdr)->code = (c))
|
||||
|
||||
|
||||
#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
void icmp_input(struct pbuf *p, struct netif *inp);
|
||||
void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t);
|
||||
void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t);
|
||||
|
||||
#endif /* LWIP_ICMP */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_ICMP */
|
||||
|
||||
#endif /* __LWIP_ICMP_H__ */
|
||||
|
@ -153,6 +153,11 @@ PACK_STRUCT_END
|
||||
#define IPH_PROTO_SET(hdr, proto) (hdr)->_ttl_proto = (htons((proto) | (IPH_TTL(hdr) << 8)))
|
||||
#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum)
|
||||
|
||||
/** The interface that provided the packet for the current callback invocation. */
|
||||
extern struct netif *current_netif;
|
||||
/** Header of the input packet currently being processed. */
|
||||
extern const struct ip_hdr *current_header;
|
||||
|
||||
#define ip_init() /* Compatibility define, not init needed. */
|
||||
struct netif *ip_route(struct ip_addr *dest);
|
||||
err_t ip_input(struct pbuf *p, struct netif *inp);
|
||||
@ -170,8 +175,14 @@ err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest
|
||||
u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options,
|
||||
u16_t optlen);
|
||||
#endif /* IP_OPTIONS_SEND */
|
||||
struct netif *ip_current_netif(void);
|
||||
const struct ip_hdr *ip_current_header(void);
|
||||
/** Get the interface that received the current packet.
|
||||
* This function must only be called from a receive callback (udp_recv,
|
||||
* raw_recv, tcp_accept). It will return NULL otherwise. */
|
||||
#define ip_current_netif() (current_netif)
|
||||
/** Get the IP header of the current packet.
|
||||
* This function must only be called from a receive callback (udp_recv,
|
||||
* raw_recv, tcp_accept). It will return NULL otherwise. */
|
||||
#define ip_current_header() (current_header)
|
||||
#if IP_DEBUG
|
||||
void ip_debug_print(struct pbuf *p);
|
||||
#else
|
||||
|
@ -161,6 +161,11 @@ u8_t ip_addr_isbroadcast(struct ip_addr *, struct netif *);
|
||||
#define ip4_addr3(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff)
|
||||
#define ip4_addr4(ipaddr) ((u16_t)(ntohl((ipaddr)->addr)) & 0xff)
|
||||
|
||||
/**
|
||||
* Same as inet_ntoa() but takes a struct ip_addr*
|
||||
*/
|
||||
#define ip_ntoa(addr) ((addr != NULL) ? inet_ntoa(*((struct in_addr*)(addr))) : "NULL")
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -83,7 +83,7 @@ struct api_msg_msg {
|
||||
size_t len;
|
||||
u8_t apiflags;
|
||||
} w;
|
||||
/** used ofr do_recv */
|
||||
/** used for do_recv */
|
||||
struct {
|
||||
u16_t len;
|
||||
} r;
|
||||
|
@ -35,12 +35,13 @@
|
||||
#include "lwip/arch.h"
|
||||
|
||||
/** lower two bits indicate debug level
|
||||
* - 0 off
|
||||
* - 0 all
|
||||
* - 1 warning
|
||||
* - 2 serious
|
||||
* - 3 severe
|
||||
*/
|
||||
#define LWIP_DBG_LEVEL_OFF 0x00
|
||||
#define LWIP_DBG_LEVEL_ALL 0x00
|
||||
#define LWIP_DBG_LEVEL_OFF LWIP_DBG_LEVEL_ALL /* compatibility define only */
|
||||
#define LWIP_DBG_LEVEL_WARNING 0x01 /* bad checksums, dropped packets, ... */
|
||||
#define LWIP_DBG_LEVEL_SERIOUS 0x02 /* memory allocation failures, ... */
|
||||
#define LWIP_DBG_LEVEL_SEVERE 0x03
|
||||
|
@ -24,22 +24,20 @@ extern "C" {
|
||||
|
||||
struct dhcp
|
||||
{
|
||||
/** current DHCP state machine state */
|
||||
u8_t state;
|
||||
/** retries of current request */
|
||||
u8_t tries;
|
||||
/** transaction identifier of last sent request */
|
||||
u32_t xid;
|
||||
/** our connection to the DHCP server */
|
||||
struct udp_pcb *pcb;
|
||||
/** (first) pbuf of incoming msg */
|
||||
struct pbuf *p;
|
||||
/** incoming msg */
|
||||
struct dhcp_msg *msg_in;
|
||||
/** incoming msg options */
|
||||
struct dhcp_msg *options_in;
|
||||
void *options_in;
|
||||
/** ingoing msg options length */
|
||||
u16_t options_in_len;
|
||||
/** current DHCP state machine state */
|
||||
u8_t state;
|
||||
/** retries of current request */
|
||||
u8_t tries;
|
||||
|
||||
struct pbuf *p_out; /* pbuf of outcoming msg */
|
||||
struct dhcp_msg *msg_out; /* outgoing msg */
|
||||
@ -124,6 +122,8 @@ err_t dhcp_release(struct netif *netif);
|
||||
void dhcp_stop(struct netif *netif);
|
||||
/** inform server of our manual IP address */
|
||||
void dhcp_inform(struct netif *netif);
|
||||
/** Handle a possible change in the network configuration */
|
||||
void dhcp_network_changed(struct netif *netif);
|
||||
|
||||
/** if enabled, check whether the offered IP address is not in use, using ARP */
|
||||
#if DHCP_DOES_ARP_CHECK
|
||||
|
@ -43,7 +43,7 @@ extern "C" {
|
||||
/** x.X.x: Minor version of the stack */
|
||||
#define LWIP_VERSION_MINOR 3U
|
||||
/** x.x.X: Revision of the stack */
|
||||
#define LWIP_VERSION_REVISION 1U
|
||||
#define LWIP_VERSION_REVISION 2U
|
||||
/** For release candidates, this is set to 1..254
|
||||
* For official releases, this is set to 255 (LWIP_RC_RELEASE)
|
||||
* For development versions (CVS), this is set to 0 (LWIP_RC_DEVELOPMENT) */
|
||||
|
@ -84,8 +84,6 @@ extern const u16_t memp_sizes[MEMP_MAX];
|
||||
#include "mem.h"
|
||||
|
||||
#define memp_init()
|
||||
#define memp_malloc(type) mem_malloc(memp_sizes[type])
|
||||
#define memp_free(type, mem) mem_free(mem)
|
||||
|
||||
#else /* MEMP_MEM_MALLOC */
|
||||
|
||||
@ -98,6 +96,7 @@ struct memp_malloc_helper
|
||||
#endif /* MEM_USE_POOLS */
|
||||
|
||||
void memp_init(void);
|
||||
#endif /* MEMP_MEM_MALLOC */
|
||||
|
||||
#if MEMP_OVERFLOW_CHECK
|
||||
void *memp_malloc_fn(memp_t type, const char* file, const int line);
|
||||
@ -107,8 +106,6 @@ void *memp_malloc(memp_t type);
|
||||
#endif
|
||||
void memp_free(memp_t type, void *mem);
|
||||
|
||||
#endif /* MEMP_MEM_MALLOC */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -34,6 +34,7 @@
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -43,6 +44,10 @@ struct netbuf {
|
||||
struct pbuf *p, *ptr;
|
||||
struct ip_addr *addr;
|
||||
u16_t port;
|
||||
#if LWIP_NETBUF_RECVINFO
|
||||
struct ip_addr *toaddr;
|
||||
u16_t toport;
|
||||
#endif /* LWIP_NETBUF_RECVINFO */
|
||||
};
|
||||
|
||||
/* Network buffer functions: */
|
||||
@ -69,6 +74,10 @@ void netbuf_first (struct netbuf *buf);
|
||||
#define netbuf_len(buf) ((buf)->p->tot_len)
|
||||
#define netbuf_fromaddr(buf) ((buf)->addr)
|
||||
#define netbuf_fromport(buf) ((buf)->port)
|
||||
#if LWIP_NETBUF_RECVINFO
|
||||
#define netbuf_destaddr(buf) ((buf)->toaddr)
|
||||
#define netbuf_destport(buf) ((buf)->toport)
|
||||
#endif /* LWIP_NETBUF_RECVINFO */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ int lwip_getaddrinfo(const char *nodename,
|
||||
#define gethostbyname(name) lwip_gethostbyname(name)
|
||||
#define gethostbyname_r(name, ret, buf, buflen, result, h_errnop) \
|
||||
lwip_gethostbyname_r(name, ret, buf, buflen, result, h_errnop)
|
||||
#define freeaddrinfo(addrinfo) lwip_freeaddrinfo(a)
|
||||
#define freeaddrinfo(addrinfo) lwip_freeaddrinfo(addrinfo)
|
||||
#define getaddrinfo(nodname, servname, hints, res) \
|
||||
lwip_getaddrinfo(nodname, servname, hints, res)
|
||||
#endif /* LWIP_COMPAT_SOCKETS */
|
||||
|
@ -131,12 +131,12 @@ struct netif {
|
||||
/* the hostname for this netif, NULL is a valid value */
|
||||
char* hostname;
|
||||
#endif /* LWIP_NETIF_HOSTNAME */
|
||||
/** maximum transfer unit (in bytes) */
|
||||
u16_t mtu;
|
||||
/** number of bytes used in hwaddr */
|
||||
u8_t hwaddr_len;
|
||||
/** link level hardware address of this interface */
|
||||
u8_t hwaddr[NETIF_MAX_HWADDR_LEN];
|
||||
/** maximum transfer unit (in bytes) */
|
||||
u16_t mtu;
|
||||
/** flags (see NETIF_FLAG_ above) */
|
||||
u8_t flags;
|
||||
/** descriptive abbreviation */
|
||||
|
@ -78,6 +78,11 @@ err_t netifapi_netif_add ( struct netif *netif,
|
||||
err_t (* init)(struct netif *netif),
|
||||
err_t (* input)(struct pbuf *p, struct netif *netif) );
|
||||
|
||||
err_t netifapi_netif_set_addr ( struct netif *netif,
|
||||
struct ip_addr *ipaddr,
|
||||
struct ip_addr *netmask,
|
||||
struct ip_addr *gw );
|
||||
|
||||
err_t netifapi_netif_common ( struct netif *netif,
|
||||
void (* voidfunc)(struct netif *netif),
|
||||
err_t (* errtfunc)(struct netif *netif) );
|
||||
|
@ -366,6 +366,16 @@
|
||||
#define ETHARP_TRUST_IP_MAC 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ETHARP_SUPPORT_VLAN==1: support receiving ethernet packets with VLAN header.
|
||||
* Additionally, you can define ETHARP_VLAN_CHECK to an u16_t VLAN ID to check.
|
||||
* If ETHARP_VLAN_CHECK is defined, only VLAN-traffic for this VLAN is accepted.
|
||||
* If ETHARP_VLAN_CHECK is not defined, all traffic is accepted.
|
||||
*/
|
||||
#ifndef ETHARP_SUPPORT_VLAN
|
||||
#define ETHARP_SUPPORT_VLAN 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
--------------------------------
|
||||
---------- IP options ----------
|
||||
@ -718,6 +728,13 @@
|
||||
#define UDP_TTL (IP_DEFAULT_TTL)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_NETBUF_RECVINFO==1: append destination addr and port to every netbuf.
|
||||
*/
|
||||
#ifndef LWIP_NETBUF_RECVINFO
|
||||
#define LWIP_NETBUF_RECVINFO 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
---------------------------------
|
||||
---------- TCP options ----------
|
||||
@ -742,7 +759,7 @@
|
||||
* (2 * TCP_MSS) for things to work well
|
||||
*/
|
||||
#ifndef TCP_WND
|
||||
#define TCP_WND 2048
|
||||
#define TCP_WND (4 * TCP_MSS)
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -768,14 +785,14 @@
|
||||
#endif
|
||||
|
||||
/**
|
||||
* TCP_MSS: TCP Maximum segment size. (default is 128, a *very*
|
||||
* conservative default.)
|
||||
* TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default,
|
||||
* you might want to increase this.)
|
||||
* For the receive side, this MSS is advertised to the remote side
|
||||
* when opening a connection. For the transmit size, this MSS sets
|
||||
* an upper limit on the MSS advertised by the remote host.
|
||||
*/
|
||||
#ifndef TCP_MSS
|
||||
#define TCP_MSS 128
|
||||
#define TCP_MSS 536
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -803,7 +820,7 @@
|
||||
* as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work.
|
||||
*/
|
||||
#ifndef TCP_SND_QUEUELEN
|
||||
#define TCP_SND_QUEUELEN (4 * (TCP_SND_BUF/TCP_MSS))
|
||||
#define TCP_SND_QUEUELEN (4 * (TCP_SND_BUF)/(TCP_MSS))
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -812,7 +829,7 @@
|
||||
* TCP snd_buf for select to return writable.
|
||||
*/
|
||||
#ifndef TCP_SNDLOWAT
|
||||
#define TCP_SNDLOWAT (TCP_SND_BUF/2)
|
||||
#define TCP_SNDLOWAT ((TCP_SND_BUF)/2)
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -1322,21 +1339,21 @@
|
||||
* MEM_STATS==1: Enable mem.c stats.
|
||||
*/
|
||||
#ifndef MEM_STATS
|
||||
#define MEM_STATS 1
|
||||
#define MEM_STATS ((MEM_LIBC_MALLOC == 0) && (MEM_USE_POOLS == 0))
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MEMP_STATS==1: Enable memp.c pool stats.
|
||||
*/
|
||||
#ifndef MEMP_STATS
|
||||
#define MEMP_STATS 1
|
||||
#define MEMP_STATS (MEMP_MEM_MALLOC == 0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SYS_STATS==1: Enable system stats (sem and mbox counts, etc).
|
||||
*/
|
||||
#ifndef SYS_STATS
|
||||
#define SYS_STATS 1
|
||||
#define SYS_STATS (NO_SYS == 0)
|
||||
#endif
|
||||
|
||||
#else
|
||||
@ -1510,9 +1527,12 @@
|
||||
#endif
|
||||
#define PPP_MINMRU 128 /* No MRUs below this */
|
||||
|
||||
|
||||
#ifndef MAXNAMELEN
|
||||
#define MAXNAMELEN 256 /* max length of hostname or name for auth */
|
||||
#endif
|
||||
#ifndef MAXSECRETLEN
|
||||
#define MAXSECRETLEN 256 /* max length of password or secret */
|
||||
#endif
|
||||
|
||||
#endif /* PPP_SUPPORT */
|
||||
|
||||
@ -1574,7 +1594,7 @@
|
||||
* messages are written.
|
||||
*/
|
||||
#ifndef LWIP_DBG_MIN_LEVEL
|
||||
#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_OFF
|
||||
#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -51,27 +51,87 @@ typedef void * sio_fd_t;
|
||||
or be implemented in your custom sio.c file. */
|
||||
|
||||
#ifndef sio_open
|
||||
sio_fd_t sio_open(u8_t);
|
||||
/**
|
||||
* Opens a serial device for communication.
|
||||
*
|
||||
* @param devnum device number
|
||||
* @return handle to serial device if successful, NULL otherwise
|
||||
*/
|
||||
sio_fd_t sio_open(u8_t devnum);
|
||||
#endif
|
||||
|
||||
#ifndef sio_send
|
||||
void sio_send(u8_t, sio_fd_t);
|
||||
/**
|
||||
* Sends a single character to the serial device.
|
||||
*
|
||||
* @param c character to send
|
||||
* @param fd serial device handle
|
||||
*
|
||||
* @note This function will block until the character can be sent.
|
||||
*/
|
||||
void sio_send(u8_t c, sio_fd_t fd);
|
||||
#endif
|
||||
|
||||
#ifndef sio_recv
|
||||
u8_t sio_recv(sio_fd_t);
|
||||
/**
|
||||
* Receives a single character from the serial device.
|
||||
*
|
||||
* @param fd serial device handle
|
||||
*
|
||||
* @note This function will block until a character is received.
|
||||
*/
|
||||
u8_t sio_recv(sio_fd_t fd);
|
||||
#endif
|
||||
|
||||
#ifndef sio_read
|
||||
u32_t sio_read(sio_fd_t, u8_t *, u32_t);
|
||||
/**
|
||||
* Reads from the serial device.
|
||||
*
|
||||
* @param fd serial device handle
|
||||
* @param data pointer to data buffer for receiving
|
||||
* @param len maximum length (in bytes) of data to receive
|
||||
* @return number of bytes actually received - may be 0 if aborted by sio_read_abort
|
||||
*
|
||||
* @note This function will block until data can be received. The blocking
|
||||
* can be cancelled by calling sio_read_abort().
|
||||
*/
|
||||
u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len);
|
||||
#endif
|
||||
|
||||
#ifndef sio_tryread
|
||||
/**
|
||||
* Tries to read from the serial device. Same as sio_read but returns
|
||||
* immediately if no data is available and never blocks.
|
||||
*
|
||||
* @param fd serial device handle
|
||||
* @param data pointer to data buffer for receiving
|
||||
* @param len maximum length (in bytes) of data to receive
|
||||
* @return number of bytes actually received
|
||||
*/
|
||||
u32_t sio_tryread(sio_fd_t fd, u8_t *data, u32_t len);
|
||||
#endif
|
||||
|
||||
#ifndef sio_write
|
||||
u32_t sio_write(sio_fd_t, u8_t *, u32_t);
|
||||
/**
|
||||
* Writes to the serial device.
|
||||
*
|
||||
* @param fd serial device handle
|
||||
* @param data pointer to data to send
|
||||
* @param len length (in bytes) of data to send
|
||||
* @return number of bytes actually sent
|
||||
*
|
||||
* @note This function will block until all data can be sent.
|
||||
*/
|
||||
u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len);
|
||||
#endif
|
||||
|
||||
#ifndef sio_read_abort
|
||||
void sio_read_abort(sio_fd_t);
|
||||
/**
|
||||
* Aborts a blocking sio_read() call.
|
||||
*
|
||||
* @param fd serial device handle
|
||||
*/
|
||||
void sio_read_abort(sio_fd_t fd);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -78,6 +78,9 @@ void tcp_err (struct tcp_pcb *pcb,
|
||||
|
||||
#define tcp_mss(pcb) ((pcb)->mss)
|
||||
#define tcp_sndbuf(pcb) ((pcb)->snd_buf)
|
||||
#define tcp_nagle_disable(pcb) ((pcb)->flags |= TF_NODELAY)
|
||||
#define tcp_nagle_enable(pcb) ((pcb)->flags &= ~TF_NODELAY)
|
||||
#define tcp_nagle_disabled(pcb) (((pcb)->flags & TF_NODELAY) != 0)
|
||||
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
#define tcp_accepted(pcb) (((struct tcp_pcb_listen *)(pcb))->accepts_pending--)
|
||||
@ -122,9 +125,11 @@ void tcp_fasttmr (void);
|
||||
/* Only used by IP to pass a TCP segment to TCP: */
|
||||
void tcp_input (struct pbuf *p, struct netif *inp);
|
||||
/* Used within the TCP code only: */
|
||||
err_t tcp_send_empty_ack(struct tcp_pcb *pcb);
|
||||
err_t tcp_output (struct tcp_pcb *pcb);
|
||||
void tcp_rexmit (struct tcp_pcb *pcb);
|
||||
void tcp_rexmit_rto (struct tcp_pcb *pcb);
|
||||
void tcp_rexmit_fast (struct tcp_pcb *pcb);
|
||||
u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb);
|
||||
|
||||
/**
|
||||
@ -134,9 +139,10 @@ u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb);
|
||||
* - the TF_NODELAY flag is set (nagle algorithm turned off for this pcb) or
|
||||
* - the only unsent segment is at least pcb->mss bytes long (or there is more
|
||||
* than one unsent segment - with lwIP, this can happen although unsent->len < mss)
|
||||
* - or if we are in fast-retransmit (TF_INFR)
|
||||
*/
|
||||
#define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \
|
||||
((tpcb)->flags & TF_NODELAY) || \
|
||||
((tpcb)->flags & (TF_NODELAY | TF_INFR)) || \
|
||||
(((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \
|
||||
((tpcb)->unsent->len >= (tpcb)->mss))) \
|
||||
) ? 1 : 0)
|
||||
@ -230,12 +236,11 @@ PACK_STRUCT_END
|
||||
|
||||
#define TCPH_OFFSET_SET(phdr, offset) (phdr)->_hdrlen_rsvd_flags = htons(((offset) << 8) | TCPH_FLAGS(phdr))
|
||||
#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr))
|
||||
#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons((ntohs((phdr)->_hdrlen_rsvd_flags) & ~TCP_FLAGS) | (flags))
|
||||
#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (flags))
|
||||
#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & htons((u16_t)(~(u16_t)(TCP_FLAGS)))) | htons(flags))
|
||||
#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | htons(flags))
|
||||
#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) )
|
||||
|
||||
#define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & TCP_FIN || \
|
||||
TCPH_FLAGS((seg)->tcphdr) & TCP_SYN)? 1: 0))
|
||||
#define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0))
|
||||
|
||||
enum tcp_state {
|
||||
CLOSED = 0,
|
||||
@ -489,9 +494,7 @@ err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
|
||||
if((pcb)->recv != NULL) { \
|
||||
(ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); \
|
||||
} else { \
|
||||
(ret) = ERR_OK; \
|
||||
if (p != NULL) \
|
||||
pbuf_free(p); \
|
||||
(ret) = tcp_recv_null(NULL, (pcb), (p), (err)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
@ -585,9 +588,14 @@ void tcp_zero_window_probe(struct tcp_pcb *pcb);
|
||||
u16_t tcp_eff_send_mss(u16_t sendmss, struct ip_addr *addr);
|
||||
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
|
||||
|
||||
#if LWIP_CALLBACK_API
|
||||
err_t tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
|
||||
#endif /* LWIP_CALLBACK_API */
|
||||
|
||||
extern struct tcp_pcb *tcp_input_pcb;
|
||||
extern u32_t tcp_ticks;
|
||||
|
||||
const char* tcp_debug_state_str(enum tcp_state s);
|
||||
#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
|
||||
void tcp_debug_print(struct tcp_hdr *tcphdr);
|
||||
void tcp_debug_print_flags(u8_t flags);
|
||||
@ -651,7 +659,7 @@ extern struct tcp_pcb *tcp_tmp_pcb; /* Only used for temporary storage. */
|
||||
if(*pcbs == npcb) { \
|
||||
*pcbs = (*pcbs)->next; \
|
||||
} else for(tcp_tmp_pcb = *pcbs; tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \
|
||||
if(tcp_tmp_pcb->next != NULL && tcp_tmp_pcb->next == npcb) { \
|
||||
if(tcp_tmp_pcb->next == npcb) { \
|
||||
tcp_tmp_pcb->next = npcb->next; \
|
||||
break; \
|
||||
} \
|
||||
@ -679,7 +687,7 @@ extern struct tcp_pcb *tcp_tmp_pcb; /* Only used for temporary storage. */
|
||||
for(tcp_tmp_pcb = *pcbs; \
|
||||
tcp_tmp_pcb != NULL; \
|
||||
tcp_tmp_pcb = tcp_tmp_pcb->next) { \
|
||||
if(tcp_tmp_pcb->next != NULL && tcp_tmp_pcb->next == npcb) { \
|
||||
if(tcp_tmp_pcb->next == npcb) { \
|
||||
tcp_tmp_pcb->next = npcb->next; \
|
||||
break; \
|
||||
} \
|
||||
|
@ -94,6 +94,9 @@ struct udp_pcb {
|
||||
* The callback is responsible for freeing the pbuf
|
||||
* if it's not used any more.
|
||||
*
|
||||
* ATTENTION: Be aware that 'addr' points into the pbuf 'p' so freeing this pbuf
|
||||
* makes 'addr' invalid, too.
|
||||
*
|
||||
* @param arg user supplied argument (udp_pcb.recv_arg)
|
||||
* @param pcb the udp_pcb which received data
|
||||
* @param p the packet buffer that was received
|
||||
|
@ -85,13 +85,34 @@ PACK_STRUCT_END
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#define SIZEOF_ETH_HDR (14 + ETH_PAD_SIZE)
|
||||
|
||||
#if ETHARP_SUPPORT_VLAN
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct eth_vlan_hdr {
|
||||
PACK_STRUCT_FIELD(u16_t tpid);
|
||||
PACK_STRUCT_FIELD(u16_t prio_vid);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#define SIZEOF_VLAN_HDR 4
|
||||
#define VLAN_ID(vlan_hdr) (htons((vlan_hdr)->prio_vid) & 0xFFF)
|
||||
|
||||
#endif /* ETHARP_SUPPORT_VLAN */
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
/** the ARP message */
|
||||
struct etharp_hdr {
|
||||
PACK_STRUCT_FIELD(struct eth_hdr ethhdr);
|
||||
PACK_STRUCT_FIELD(u16_t hwtype);
|
||||
PACK_STRUCT_FIELD(u16_t proto);
|
||||
PACK_STRUCT_FIELD(u16_t _hwlen_protolen);
|
||||
@ -106,24 +127,15 @@ PACK_STRUCT_END
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct ethip_hdr {
|
||||
PACK_STRUCT_FIELD(struct eth_hdr eth);
|
||||
PACK_STRUCT_FIELD(struct ip_hdr ip);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
#define SIZEOF_ETHARP_HDR 28
|
||||
#define SIZEOF_ETHARP_PACKET (SIZEOF_ETH_HDR + SIZEOF_ETHARP_HDR)
|
||||
|
||||
/** 5 seconds period */
|
||||
#define ARP_TMR_INTERVAL 5000
|
||||
|
||||
#define ETHTYPE_ARP 0x0806
|
||||
#define ETHTYPE_IP 0x0800
|
||||
#define ETHTYPE_VLAN 0x8100
|
||||
#define ETHTYPE_PPPOEDISC 0x8863 /* PPP Over Ethernet Discovery Stage */
|
||||
#define ETHTYPE_PPPOE 0x8864 /* PPP Over Ethernet Session Stage */
|
||||
|
||||
|
@ -41,6 +41,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
err_t slipif_init(struct netif * netif);
|
||||
void slipif_poll(struct netif *netif);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -89,7 +89,13 @@
|
||||
#define MEM_LIBC_MALLOC 1
|
||||
#define mem_malloc rt_malloc
|
||||
#define mem_free rt_free
|
||||
#define mem_calloc rt_calloc
|
||||
#define mem_calloc rt_calloc
|
||||
|
||||
#ifdef RT_LWIP_USING_RT_MEM
|
||||
#define MEMP_MEM_MALLOC 1
|
||||
#else
|
||||
#define MEMP_MEM_MALLOC 0
|
||||
#endif
|
||||
|
||||
/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
|
||||
sends a lot of data out of ROM (or other static memory), this
|
||||
|
@ -23,3 +23,7 @@ slipif.c
|
||||
protocol. It requires a sio (serial I/O) module to work.
|
||||
|
||||
ppp/ Point-to-Point Protocol stack
|
||||
The PPP stack has been ported from ucip (http://ucip.sourceforge.net).
|
||||
It matches quite well to pppd 2.3.1 (http://ppp.samba.org), although
|
||||
compared to that, it has some modifications for embedded systems and
|
||||
the source code has been reordered a bit.
|
@ -468,7 +468,7 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e
|
||||
{
|
||||
s8_t i;
|
||||
u8_t k;
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | 3, ("update_arp_entry()\n"));
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry()\n"));
|
||||
LWIP_ASSERT("netif->hwaddr_len == ETHARP_HWADDR_LEN", netif->hwaddr_len == ETHARP_HWADDR_LEN);
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n",
|
||||
ip4_addr1(ipaddr), ip4_addr2(ipaddr), ip4_addr3(ipaddr), ip4_addr4(ipaddr),
|
||||
@ -579,13 +579,21 @@ etharp_find_addr(struct netif *netif, struct ip_addr *ipaddr,
|
||||
void
|
||||
etharp_ip_input(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
struct ethip_hdr *hdr;
|
||||
struct eth_hdr *ethhdr;
|
||||
struct ip_hdr *iphdr;
|
||||
LWIP_ERROR("netif != NULL", (netif != NULL), return;);
|
||||
/* Only insert an entry if the source IP address of the
|
||||
incoming IP packet comes from a host on the local network. */
|
||||
hdr = p->payload;
|
||||
ethhdr = p->payload;
|
||||
iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
|
||||
#if ETHARP_SUPPORT_VLAN
|
||||
if (ethhdr->type == ETHTYPE_VLAN) {
|
||||
iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
|
||||
}
|
||||
#endif /* ETHARP_SUPPORT_VLAN */
|
||||
|
||||
/* source is not on the local network? */
|
||||
if (!ip_addr_netcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) {
|
||||
if (!ip_addr_netcmp(&(iphdr->src), &(netif->ip_addr), &(netif->netmask))) {
|
||||
/* do nothing */
|
||||
return;
|
||||
}
|
||||
@ -594,7 +602,7 @@ etharp_ip_input(struct netif *netif, struct pbuf *p)
|
||||
/* update ARP table */
|
||||
/* @todo We could use ETHARP_TRY_HARD if we think we are going to talk
|
||||
* back soon (for example, if the destination IP address is ours. */
|
||||
update_arp_entry(netif, &(hdr->ip.src), &(hdr->eth.src), 0);
|
||||
update_arp_entry(netif, &(iphdr->src), &(ethhdr->src), 0);
|
||||
}
|
||||
|
||||
|
||||
@ -617,6 +625,7 @@ void
|
||||
etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
|
||||
{
|
||||
struct etharp_hdr *hdr;
|
||||
struct eth_hdr *ethhdr;
|
||||
/* these are aligned properly, whereas the ARP header fields might not be */
|
||||
struct ip_addr sipaddr, dipaddr;
|
||||
u8_t i;
|
||||
@ -629,24 +638,32 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
|
||||
|
||||
/* drop short ARP packets: we have to check for p->len instead of p->tot_len here
|
||||
since a struct etharp_hdr is pointed to p->payload, so it musn't be chained! */
|
||||
if (p->len < sizeof(struct etharp_hdr)) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | 1, ("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len, (s16_t)sizeof(struct etharp_hdr)));
|
||||
if (p->len < SIZEOF_ETHARP_PACKET) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
|
||||
("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len,
|
||||
(s16_t)SIZEOF_ETHARP_PACKET));
|
||||
ETHARP_STATS_INC(etharp.lenerr);
|
||||
ETHARP_STATS_INC(etharp.drop);
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
|
||||
hdr = p->payload;
|
||||
ethhdr = p->payload;
|
||||
hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
|
||||
#if ETHARP_SUPPORT_VLAN
|
||||
if (ethhdr->type == ETHTYPE_VLAN) {
|
||||
hdr = (struct etharp_hdr *)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
|
||||
}
|
||||
#endif /* ETHARP_SUPPORT_VLAN */
|
||||
|
||||
/* RFC 826 "Packet Reception": */
|
||||
if ((hdr->hwtype != htons(HWTYPE_ETHERNET)) ||
|
||||
(hdr->_hwlen_protolen != htons((ETHARP_HWADDR_LEN << 8) | sizeof(struct ip_addr))) ||
|
||||
(hdr->proto != htons(ETHTYPE_IP)) ||
|
||||
(hdr->ethhdr.type != htons(ETHTYPE_ARP))) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | 1,
|
||||
(ethhdr->type != htons(ETHTYPE_ARP))) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
|
||||
("etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
|
||||
hdr->hwtype, ARPH_HWLEN(hdr), hdr->proto, ARPH_PROTOLEN(hdr), hdr->ethhdr.type));
|
||||
hdr->hwtype, ARPH_HWLEN(hdr), hdr->proto, ARPH_PROTOLEN(hdr), ethhdr->type));
|
||||
ETHARP_STATS_INC(etharp.proterr);
|
||||
ETHARP_STATS_INC(etharp.drop);
|
||||
pbuf_free(p);
|
||||
@ -719,12 +736,12 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
|
||||
i--;
|
||||
hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i];
|
||||
#if LWIP_AUTOIP
|
||||
hdr->ethhdr.dest.addr[i] = ethdst_hwaddr[i];
|
||||
ethhdr->dest.addr[i] = ethdst_hwaddr[i];
|
||||
#else /* LWIP_AUTOIP */
|
||||
hdr->ethhdr.dest.addr[i] = hdr->shwaddr.addr[i];
|
||||
ethhdr->dest.addr[i] = hdr->shwaddr.addr[i];
|
||||
#endif /* LWIP_AUTOIP */
|
||||
hdr->shwaddr.addr[i] = ethaddr->addr[i];
|
||||
hdr->ethhdr.src.addr[i] = ethaddr->addr[i];
|
||||
ethhdr->src.addr[i] = ethaddr->addr[i];
|
||||
}
|
||||
|
||||
/* hwtype, hwaddr_len, proto, protolen and the type in the ethernet header
|
||||
@ -788,7 +805,8 @@ etharp_output(struct netif *netif, struct pbuf *q, struct ip_addr *ipaddr)
|
||||
/* make room for Ethernet header - should not fail */
|
||||
if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
|
||||
/* bail out */
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | 2, ("etharp_output: could not allocate room for header.\n"));
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("etharp_output: could not allocate room for header.\n"));
|
||||
LINK_STATS_INC(link.lenerr);
|
||||
return ERR_BUF;
|
||||
}
|
||||
@ -1034,23 +1052,26 @@ etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
|
||||
struct pbuf *p;
|
||||
err_t result = ERR_OK;
|
||||
u8_t k; /* ARP entry index */
|
||||
struct eth_hdr *ethhdr;
|
||||
struct etharp_hdr *hdr;
|
||||
#if LWIP_AUTOIP
|
||||
const u8_t * ethdst_hwaddr;
|
||||
#endif /* LWIP_AUTOIP */
|
||||
|
||||
/* allocate a pbuf for the outgoing ARP request packet */
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(struct etharp_hdr), PBUF_RAM);
|
||||
p = pbuf_alloc(PBUF_RAW, SIZEOF_ETHARP_PACKET, PBUF_RAM);
|
||||
/* could allocate a pbuf for an ARP request? */
|
||||
if (p == NULL) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | 2, ("etharp_raw: could not allocate pbuf for ARP request.\n"));
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("etharp_raw: could not allocate pbuf for ARP request.\n"));
|
||||
ETHARP_STATS_INC(etharp.memerr);
|
||||
return ERR_MEM;
|
||||
}
|
||||
LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr",
|
||||
(p->len >= sizeof(struct etharp_hdr)));
|
||||
(p->len >= SIZEOF_ETHARP_PACKET));
|
||||
|
||||
hdr = p->payload;
|
||||
ethhdr = p->payload;
|
||||
hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n"));
|
||||
hdr->opcode = htons(opcode);
|
||||
|
||||
@ -1070,11 +1091,11 @@ etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
|
||||
hdr->dhwaddr.addr[k] = hwdst_addr->addr[k];
|
||||
/* Write the Ethernet MAC-Addresses */
|
||||
#if LWIP_AUTOIP
|
||||
hdr->ethhdr.dest.addr[k] = ethdst_hwaddr[k];
|
||||
ethhdr->dest.addr[k] = ethdst_hwaddr[k];
|
||||
#else /* LWIP_AUTOIP */
|
||||
hdr->ethhdr.dest.addr[k] = ethdst_addr->addr[k];
|
||||
ethhdr->dest.addr[k] = ethdst_addr->addr[k];
|
||||
#endif /* LWIP_AUTOIP */
|
||||
hdr->ethhdr.src.addr[k] = ethsrc_addr->addr[k];
|
||||
ethhdr->src.addr[k] = ethsrc_addr->addr[k];
|
||||
}
|
||||
hdr->sipaddr = *(struct ip_addr2 *)ipsrc_addr;
|
||||
hdr->dipaddr = *(struct ip_addr2 *)ipdst_addr;
|
||||
@ -1084,7 +1105,7 @@ etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
|
||||
/* set hwlen and protolen together */
|
||||
hdr->_hwlen_protolen = htons((ETHARP_HWADDR_LEN << 8) | sizeof(struct ip_addr));
|
||||
|
||||
hdr->ethhdr.type = htons(ETHTYPE_ARP);
|
||||
ethhdr->type = htons(ETHTYPE_ARP);
|
||||
/* send ARP query */
|
||||
result = netif->linkoutput(netif, p);
|
||||
ETHARP_STATS_INC(etharp.xmit);
|
||||
@ -1126,6 +1147,7 @@ err_t
|
||||
ethernet_input(struct pbuf *p, struct netif *netif)
|
||||
{
|
||||
struct eth_hdr* ethhdr;
|
||||
u16_t type;
|
||||
|
||||
/* points to packet payload, which starts with an Ethernet header */
|
||||
ethhdr = p->payload;
|
||||
@ -1137,7 +1159,22 @@ ethernet_input(struct pbuf *p, struct netif *netif)
|
||||
(unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5],
|
||||
(unsigned)htons(ethhdr->type)));
|
||||
|
||||
switch (htons(ethhdr->type)) {
|
||||
type = htons(ethhdr->type);
|
||||
#if ETHARP_SUPPORT_VLAN
|
||||
if (type == ETHTYPE_VLAN) {
|
||||
struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR);
|
||||
#ifdef ETHARP_VLAN_CHECK /* if not, allow all VLANs */
|
||||
if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) {
|
||||
/* silently ignore this packet: not for our VLAN */
|
||||
pbuf_free(p);
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif /* ETHARP_VLAN_CHECK */
|
||||
type = htons(vlan->tpid);
|
||||
}
|
||||
#endif /* ETHARP_SUPPORT_VLAN */
|
||||
|
||||
switch (type) {
|
||||
/* IP packet? */
|
||||
case ETHTYPE_IP:
|
||||
#if ETHARP_TRUST_IP_MAC
|
||||
@ -1145,7 +1182,7 @@ ethernet_input(struct pbuf *p, struct netif *netif)
|
||||
etharp_ip_input(netif, p);
|
||||
#endif /* ETHARP_TRUST_IP_MAC */
|
||||
/* skip Ethernet header */
|
||||
if(pbuf_header(p, -(s16_t)sizeof(struct eth_hdr))) {
|
||||
if(pbuf_header(p, -(s16_t)SIZEOF_ETH_HDR)) {
|
||||
LWIP_ASSERT("Can't move over header in packet", 0);
|
||||
pbuf_free(p);
|
||||
p = NULL;
|
||||
|
@ -301,26 +301,18 @@ FINSH_FUNCTION_EXPORT(set_dns, set DNS server address);
|
||||
|
||||
void list_if()
|
||||
{
|
||||
struct ip_addr ip_addr;
|
||||
struct _ip_addr
|
||||
{
|
||||
rt_uint8_t addr0, addr1, addr2, addr3;
|
||||
} *addr;
|
||||
|
||||
rt_kprintf("Default network interface: %c%c\n", netif_default->name[0], netif_default->name[1]);
|
||||
addr = (struct _ip_addr*)&netif_default->ip_addr.addr;
|
||||
rt_kprintf("ip address: %d.%d.%d.%d\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3);
|
||||
|
||||
addr = (struct _ip_addr*)&netif_default->gw.addr;
|
||||
rt_kprintf("gw address: %d.%d.%d.%d\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3);
|
||||
|
||||
addr = (struct _ip_addr*)&netif_default->netmask.addr;
|
||||
rt_kprintf("net mask : %d.%d.%d.%d\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3);
|
||||
rt_kprintf("ip address: %s\n", ip_ntoa(&(netif_default->ip_addr.addr)));
|
||||
rt_kprintf("gw address: %s\n", ip_ntoa(&(netif_default->ip_addr.addr)));
|
||||
rt_kprintf("net mask : %s\n", ip_ntoa(&(netif_default->ip_addr.addr)));
|
||||
|
||||
#if LWIP_DNS
|
||||
ip_addr = dns_getserver(0);
|
||||
addr = (struct _ip_addr*)&ip_addr;
|
||||
rt_kprintf("dns server: %d.%d.%d.%d\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3);
|
||||
{
|
||||
struct ip_addr ip_addr;
|
||||
|
||||
ip_addr = dns_getserver(0);
|
||||
rt_kprintf("dns server: %d.%d.%d.%d\n", ip_ntoa(&ip_addr));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
FINSH_FUNCTION_EXPORT(list_if, list network interface information);
|
||||
|
@ -82,6 +82,8 @@
|
||||
#include "cbcp.h"
|
||||
#endif /* CBCP_SUPPORT */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/*************************/
|
||||
/*** LOCAL DEFINITIONS ***/
|
||||
/*************************/
|
||||
|
@ -82,6 +82,7 @@
|
||||
#include "chap.h"
|
||||
#include "chpms.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/*************************/
|
||||
/*** LOCAL DEFINITIONS ***/
|
||||
|
@ -1,4 +1,7 @@
|
||||
/*** WARNING - THIS CODE HAS NOT BEEN FINISHED! ***/
|
||||
/*** The original PPPD code is written in a way to require either the UNIX DES
|
||||
encryption functions encrypt(3) and setkey(3) or the DES library libdes.
|
||||
Since both is not included in lwIP, MSCHAP currently does not work! */
|
||||
/*****************************************************************************
|
||||
* chpms.c - Network MicroSoft Challenge Handshake Authentication Protocol program file.
|
||||
*
|
||||
|
@ -64,6 +64,8 @@
|
||||
|
||||
#include "fsm.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/*************************/
|
||||
/*** LOCAL DEFINITIONS ***/
|
||||
@ -551,7 +553,7 @@ fsm_timeout(void *arg)
|
||||
break;
|
||||
|
||||
default:
|
||||
FSMDEBUG((LOG_INFO, "%s: Timeout event in state %d (%s)!\n",
|
||||
FSMDEBUG((LOG_INFO, "%s: UNHANDLED timeout event in state %d (%s)!\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
}
|
||||
}
|
||||
|
@ -183,20 +183,7 @@ static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
|
||||
/*** LOCAL FUNCTION DEFINITIONS ***/
|
||||
/**********************************/
|
||||
|
||||
/*
|
||||
* Non-standard inet_ntoa left here for compat with original ppp
|
||||
* sources. Assumes u32_t instead of struct in_addr.
|
||||
*/
|
||||
|
||||
char *
|
||||
_inet_ntoa(u32_t n)
|
||||
{
|
||||
struct in_addr ia;
|
||||
ia.s_addr = n;
|
||||
return inet_ntoa(ia);
|
||||
}
|
||||
|
||||
#define inet_ntoa _inet_ntoa
|
||||
#define inet_ntoa(addr) ip_ntoa(((struct ip_addr*)&(addr)))
|
||||
|
||||
/*
|
||||
* ipcp_init - Initialize IPCP.
|
||||
|
@ -42,6 +42,8 @@
|
||||
|
||||
#include "md5.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
***********************************************************************
|
||||
** Message-digest routines: **
|
||||
|
@ -61,6 +61,8 @@
|
||||
#include "auth.h"
|
||||
#include "pap.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/***********************************/
|
||||
/*** LOCAL FUNCTION DECLARATIONS ***/
|
||||
/***********************************/
|
||||
@ -490,6 +492,7 @@ upap_rauthack(upap_state *u, u_char *inp, int id, int len)
|
||||
msg = (char *) inp;
|
||||
PRINTMSG(msg, msglen);
|
||||
|
||||
UNTIMEOUT(upap_timeout, u); /* Cancel timeout */
|
||||
u->us_clientstate = UPAPCS_OPEN;
|
||||
|
||||
auth_withpeer_success(u->us_unit, PPP_PAP);
|
||||
|
@ -166,7 +166,7 @@ typedef struct PPPControl_s {
|
||||
ext_accm outACCM; /* Async-Ctl-Char-Map for output. */
|
||||
#if PPPOS_SUPPORT && VJ_SUPPORT
|
||||
int vjEnabled; /* Flag indicating VJ compression enabled. */
|
||||
struct vjcompress vjComp; /* Van Jabobsen compression header. */
|
||||
struct vjcompress vjComp; /* Van Jacobson compression header. */
|
||||
#endif /* PPPOS_SUPPORT && VJ_SUPPORT */
|
||||
|
||||
struct netif netif;
|
||||
@ -235,7 +235,7 @@ struct protent *ppp_protocols[] = {
|
||||
* Buffers for outgoing packets. This must be accessed only from the appropriate
|
||||
* PPP task so that it doesn't need to be protected to avoid collisions.
|
||||
*/
|
||||
u_char *outpacket_buf[NUM_PPP];
|
||||
u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN];
|
||||
|
||||
|
||||
/*****************************/
|
||||
@ -306,13 +306,11 @@ pppMainWakeup(int pd)
|
||||
void
|
||||
pppLinkTerminated(int pd)
|
||||
{
|
||||
PPPControl *pc = &pppControl[pd];
|
||||
|
||||
PPPDEBUG((LOG_DEBUG, "pppLinkTerminated: unit %d\n", pd));
|
||||
|
||||
#if PPPOE_SUPPORT
|
||||
if(pc->ethif) {
|
||||
pppoe_disconnect(pc->pppoe_sc);
|
||||
if(pppControl[pd].ethif) {
|
||||
pppoe_disconnect(pppControl[pd].pppoe_sc);
|
||||
} else
|
||||
#endif /* PPPOE_SUPPORT */
|
||||
{
|
||||
@ -325,13 +323,11 @@ pppLinkTerminated(int pd)
|
||||
void
|
||||
pppLinkDown(int pd)
|
||||
{
|
||||
PPPControl *pc = &pppControl[pd];
|
||||
|
||||
PPPDEBUG((LOG_DEBUG, "pppLinkDown: unit %d\n", pd));
|
||||
|
||||
#if PPPOE_SUPPORT
|
||||
if(pc->ethif) {
|
||||
pppoe_disconnect(pc->pppoe_sc);
|
||||
if(pppControl[pd].ethif) {
|
||||
pppoe_disconnect(pppControl[pd].pppoe_sc);
|
||||
} else
|
||||
#endif /* PPPOE_SUPPORT */
|
||||
{
|
||||
@ -383,7 +379,7 @@ pppHupCB(void *arg)
|
||||
|
||||
struct ppp_settings ppp_settings;
|
||||
|
||||
err_t
|
||||
void
|
||||
pppInit(void)
|
||||
{
|
||||
struct protent *protp;
|
||||
@ -395,16 +391,11 @@ pppInit(void)
|
||||
|
||||
magicInit();
|
||||
|
||||
subnetMask = htonl(0xffffff00);
|
||||
|
||||
for (i = 0; i < NUM_PPP; i++) {
|
||||
pppControl[i].openFlag = 0;
|
||||
|
||||
subnetMask = htonl(0xffffff00);
|
||||
|
||||
outpacket_buf[i] = (u_char *)mem_malloc(PPP_MRU+PPP_HDRLEN);
|
||||
if(!outpacket_buf[i]) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize to the standard option set.
|
||||
*/
|
||||
@ -413,17 +404,9 @@ pppInit(void)
|
||||
}
|
||||
}
|
||||
|
||||
#if LINK_STATS
|
||||
/** @todo already done in stats_init (in fact, zeroed at boot). So, remove it? */
|
||||
/* Clear the statistics. */
|
||||
memset(&lwip_stats.link, 0, sizeof(lwip_stats.link));
|
||||
#endif /* LINK_STATS */
|
||||
|
||||
#if PPPOE_SUPPORT
|
||||
pppoe_init();
|
||||
#endif /* PPPOE_SUPPORT */
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void
|
||||
@ -601,7 +584,7 @@ int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const cha
|
||||
pppControl[pd].openFlag = !0;
|
||||
}
|
||||
|
||||
/* Launch a deamon thread. */
|
||||
/* PPP session descriptor found, start PPPoE */
|
||||
if (pd >= 0) {
|
||||
|
||||
pppControl[pd].openFlag = 1;
|
||||
@ -824,9 +807,9 @@ static err_t
|
||||
pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr)
|
||||
{
|
||||
int pd = (int)netif->state;
|
||||
u_short protocol = PPP_IP;
|
||||
PPPControl *pc = &pppControl[pd];
|
||||
#if PPPOS_SUPPORT
|
||||
u_short protocol = PPP_IP;
|
||||
u_int fcsOut = PPP_INITFCS;
|
||||
struct pbuf *headMB = NULL, *tailMB = NULL, *p;
|
||||
u_char c;
|
||||
@ -839,7 +822,7 @@ pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr)
|
||||
* and the peer will just drop it if it's not accepting it. */
|
||||
if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !pb) {
|
||||
PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad parms prot=%d pb=%p\n",
|
||||
pd, protocol, pb));
|
||||
pd, PPP_IP, pb));
|
||||
LINK_STATS_INC(link.opterr);
|
||||
LINK_STATS_INC(link.drop);
|
||||
return ERR_ARG;
|
||||
@ -1294,7 +1277,7 @@ GetMask(u32_t addr)
|
||||
* sifvjcomp - config tcp header compression
|
||||
*/
|
||||
int
|
||||
sifvjcomp( int pd, int vjcomp, int cidcomp, int maxcid)
|
||||
sifvjcomp(int pd, int vjcomp, int cidcomp, int maxcid)
|
||||
{
|
||||
#if PPPOS_SUPPORT && VJ_SUPPORT
|
||||
PPPControl *pc = &pppControl[pd];
|
||||
@ -1304,6 +1287,11 @@ sifvjcomp( int pd, int vjcomp, int cidcomp, int maxcid)
|
||||
pc->vjComp.maxSlotIndex = maxcid;
|
||||
PPPDEBUG((LOG_INFO, "sifvjcomp: VJ compress enable=%d slot=%d max slot=%d\n",
|
||||
vjcomp, cidcomp, maxcid));
|
||||
#else /* PPPOS_SUPPORT && VJ_SUPPORT */
|
||||
LWIP_UNUSED_ARG(pd);
|
||||
LWIP_UNUSED_ARG(vjcomp);
|
||||
LWIP_UNUSED_ARG(cidcomp);
|
||||
LWIP_UNUSED_ARG(maxcid);
|
||||
#endif /* PPPOS_SUPPORT && VJ_SUPPORT */
|
||||
|
||||
return 0;
|
||||
@ -1381,6 +1369,8 @@ sifdown(int pd)
|
||||
PPPDEBUG((LOG_WARNING, "sifdown[%d]: bad parms\n", pd));
|
||||
} else {
|
||||
pc->if_up = 0;
|
||||
/* make sure the netif status callback is called */
|
||||
netif_set_down(&pc->netif);
|
||||
netif_remove(&pc->netif);
|
||||
PPPDEBUG((LOG_DEBUG, "sifdown: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
|
||||
if(pc->linkStatusCB) {
|
||||
@ -1537,8 +1527,8 @@ pppMain(void *arg)
|
||||
if(c > 0) {
|
||||
pppInProc(pd, p->payload, c);
|
||||
} else {
|
||||
PPPDEBUG((LOG_DEBUG, "pppMain: unit %d sio_read len=%d returned %d\n", pd, p->len, c));
|
||||
sys_msleep(1); /* give other tasks a chance to run */
|
||||
/* nothing received, give other tasks a chance to run */
|
||||
sys_msleep(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1658,7 +1648,7 @@ pppInput(void *arg)
|
||||
|
||||
switch(protocol) {
|
||||
case PPP_VJC_COMP: /* VJ compressed TCP */
|
||||
#if VJ_SUPPORT
|
||||
#if PPPOS_SUPPORT && VJ_SUPPORT
|
||||
PPPDEBUG((LOG_INFO, "pppInput[%d]: vj_comp in pbuf len=%d\n", pd, nb->len));
|
||||
/*
|
||||
* Clip off the VJ header and prepend the rebuilt TCP/IP header and
|
||||
@ -1670,14 +1660,14 @@ pppInput(void *arg)
|
||||
}
|
||||
/* Something's wrong so drop it. */
|
||||
PPPDEBUG((LOG_WARNING, "pppInput[%d]: Dropping VJ compressed\n", pd));
|
||||
#else /* VJ_SUPPORT */
|
||||
#else /* PPPOS_SUPPORT && VJ_SUPPORT */
|
||||
/* No handler for this protocol so drop the packet. */
|
||||
PPPDEBUG((LOG_INFO, "pppInput[%d]: drop VJ Comp in %d:%s\n", pd, nb->len, nb->payload));
|
||||
#endif /* VJ_SUPPORT */
|
||||
#endif /* PPPOS_SUPPORT && VJ_SUPPORT */
|
||||
break;
|
||||
|
||||
case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */
|
||||
#if VJ_SUPPORT
|
||||
#if PPPOS_SUPPORT && VJ_SUPPORT
|
||||
PPPDEBUG((LOG_INFO, "pppInput[%d]: vj_un in pbuf len=%d\n", pd, nb->len));
|
||||
/*
|
||||
* Process the TCP/IP header for VJ header compression and then pass
|
||||
@ -1689,12 +1679,12 @@ pppInput(void *arg)
|
||||
}
|
||||
/* Something's wrong so drop it. */
|
||||
PPPDEBUG((LOG_WARNING, "pppInput[%d]: Dropping VJ uncompressed\n", pd));
|
||||
#else /* VJ_SUPPORT */
|
||||
#else /* PPPOS_SUPPORT && VJ_SUPPORT */
|
||||
/* No handler for this protocol so drop the packet. */
|
||||
PPPDEBUG((LOG_INFO,
|
||||
"pppInput[%d]: drop VJ UnComp in %d:.*H\n",
|
||||
pd, nb->len, LWIP_MIN(nb->len * 2, 40), nb->payload));
|
||||
#endif /* VJ_SUPPORT */
|
||||
#endif /* PPPOS_SUPPORT && VJ_SUPPORT */
|
||||
break;
|
||||
|
||||
case PPP_IP: /* Internet Protocol */
|
||||
|
@ -333,7 +333,7 @@ struct ppp_addrs {
|
||||
*****************************/
|
||||
|
||||
/* Buffers for outgoing packets. */
|
||||
extern u_char *outpacket_buf[NUM_PPP];
|
||||
extern u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN];
|
||||
|
||||
extern struct ppp_settings ppp_settings;
|
||||
|
||||
@ -345,7 +345,7 @@ extern struct protent *ppp_protocols[]; /* Table of pointers to supported protoc
|
||||
***********************/
|
||||
|
||||
/* Initialize the PPP subsystem. */
|
||||
err_t pppInit(void);
|
||||
void pppInit(void);
|
||||
|
||||
/* Warning: Using PPPAUTHTYPE_ANY might have security consequences.
|
||||
* RFC 1994 says:
|
||||
|
@ -398,7 +398,7 @@ pppoe_dispatch_disc_pkt(struct netif *netif, struct pbuf *pb)
|
||||
#endif
|
||||
struct pppoehdr *ph;
|
||||
struct pppoetag pt;
|
||||
int off = 0, err, errortag;
|
||||
int off, err, errortag;
|
||||
struct eth_hdr *ethhdr;
|
||||
|
||||
pb = pppSingleBuf(pb);
|
||||
@ -410,7 +410,7 @@ pppoe_dispatch_disc_pkt(struct netif *netif, struct pbuf *pb)
|
||||
goto done;
|
||||
}
|
||||
ethhdr = (struct eth_hdr *)pb->payload;
|
||||
off += sizeof(*ethhdr);
|
||||
off = sizeof(*ethhdr);
|
||||
|
||||
ac_cookie = NULL;
|
||||
ac_cookie_len = 0;
|
||||
@ -419,7 +419,7 @@ pppoe_dispatch_disc_pkt(struct netif *netif, struct pbuf *pb)
|
||||
hunique_len = 0;
|
||||
#endif
|
||||
session = 0;
|
||||
if (pb->len - off <= PPPOE_HEADERLEN) {
|
||||
if (pb->len - off < PPPOE_HEADERLEN) {
|
||||
printf("pppoe: packet too short: %d\n", pb->len);
|
||||
goto done;
|
||||
}
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "ppp.h"
|
||||
#include "pppdebug.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if MD5_SUPPORT /* this module depends on MD5 */
|
||||
#define RANDPOOLSZ 16 /* Bytes stored in the pool of randomness. */
|
||||
|
@ -136,7 +136,7 @@ vj_compress_init(struct vjcompress *comp)
|
||||
}
|
||||
|
||||
/*
|
||||
* vj_compress_tcp - Attempt to do Van Jacobsen header compression on a
|
||||
* vj_compress_tcp - Attempt to do Van Jacobson header compression on a
|
||||
* packet. This assumes that nb and comp are not null and that the first
|
||||
* buffer of the chain contains a valid IP header.
|
||||
* Return the VJ type code indicating whether or not the packet was
|
||||
|
@ -39,7 +39,7 @@
|
||||
|
||||
/*
|
||||
* This is an arch independent SLIP netif. The specific serial hooks must be
|
||||
* provided by another file. They are sio_open, sio_recv and sio_send
|
||||
* provided by another file. They are sio_open, sio_read/sio_tryread and sio_send
|
||||
*/
|
||||
|
||||
#include "netif/slipif.h"
|
||||
@ -54,12 +54,28 @@
|
||||
#include "lwip/snmp.h"
|
||||
#include "lwip/sio.h"
|
||||
|
||||
#define SLIP_BLOCK 1
|
||||
#define SLIP_DONTBLOCK 0
|
||||
|
||||
#define SLIP_END 0300 /* 0xC0 */
|
||||
#define SLIP_ESC 0333 /* 0xDB */
|
||||
#define SLIP_ESC_END 0334 /* 0xDC */
|
||||
#define SLIP_ESC_ESC 0335 /* 0xDD */
|
||||
|
||||
#define MAX_SIZE 1500
|
||||
#define SLIP_MAX_SIZE 1500
|
||||
|
||||
enum slipif_recv_state {
|
||||
SLIP_RECV_NORMAL,
|
||||
SLIP_RECV_ESCAPE,
|
||||
};
|
||||
|
||||
struct slipif_priv {
|
||||
sio_fd_t sd;
|
||||
/* q is the whole pbuf chain for a packet, p is the current pbuf in the chain */
|
||||
struct pbuf *p, *q;
|
||||
enum slipif_recv_state state;
|
||||
u16_t i, recved;
|
||||
};
|
||||
|
||||
/**
|
||||
* Send a pbuf doing the necessary SLIP encapsulation
|
||||
@ -74,6 +90,7 @@
|
||||
err_t
|
||||
slipif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
|
||||
{
|
||||
struct slipif_priv *priv;
|
||||
struct pbuf *q;
|
||||
u16_t i;
|
||||
u8_t c;
|
||||
@ -84,73 +101,101 @@ slipif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
|
||||
|
||||
LWIP_UNUSED_ARG(ipaddr);
|
||||
|
||||
priv = netif->state;
|
||||
|
||||
/* Send pbuf out on the serial I/O device. */
|
||||
sio_send(SLIP_END, netif->state);
|
||||
sio_send(SLIP_END, priv->sd);
|
||||
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
for (i = 0; i < q->len; i++) {
|
||||
c = ((u8_t *)q->payload)[i];
|
||||
switch (c) {
|
||||
case SLIP_END:
|
||||
sio_send(SLIP_ESC, netif->state);
|
||||
sio_send(SLIP_ESC_END, netif->state);
|
||||
sio_send(SLIP_ESC, priv->sd);
|
||||
sio_send(SLIP_ESC_END, priv->sd);
|
||||
break;
|
||||
case SLIP_ESC:
|
||||
sio_send(SLIP_ESC, netif->state);
|
||||
sio_send(SLIP_ESC_ESC, netif->state);
|
||||
sio_send(SLIP_ESC, priv->sd);
|
||||
sio_send(SLIP_ESC_ESC, priv->sd);
|
||||
break;
|
||||
default:
|
||||
sio_send(c, netif->state);
|
||||
sio_send(c, priv->sd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
sio_send(SLIP_END, netif->state);
|
||||
sio_send(SLIP_END, priv->sd);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Static function for easy use of blockig or non-blocking
|
||||
* sio_read
|
||||
*
|
||||
* @param fd serial device handle
|
||||
* @param data pointer to data buffer for receiving
|
||||
* @param len maximum length (in bytes) of data to receive
|
||||
* @param block if 1, call sio_read; if 0, call sio_tryread
|
||||
* @return return value of sio_read of sio_tryread
|
||||
*/
|
||||
static u32_t
|
||||
slip_sio_read(sio_fd_t fd, u8_t* data, u32_t len, u8_t block)
|
||||
{
|
||||
if (block) {
|
||||
return sio_read(fd, data, len);
|
||||
} else {
|
||||
return sio_tryread(fd, data, len);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the incoming SLIP stream character by character
|
||||
*
|
||||
* Poll the serial layer by calling sio_recv()
|
||||
* Poll the serial layer by calling sio_read() or sio_tryread().
|
||||
*
|
||||
* @param netif the lwip network interface structure for this slipif
|
||||
* @return The IP packet when SLIP_END is received
|
||||
* @param block if 1, block until data is received; if 0, return when all data
|
||||
* from the buffer is received (multiple calls to this function will
|
||||
* return a complete packet, NULL is returned before - used for polling)
|
||||
* @return The IP packet when SLIP_END is received
|
||||
*/
|
||||
static struct pbuf *
|
||||
slipif_input(struct netif *netif)
|
||||
slipif_input(struct netif *netif, u8_t block)
|
||||
{
|
||||
struct slipif_priv *priv;
|
||||
u8_t c;
|
||||
/* q is the whole pbuf chain for a packet, p is the current pbuf in the chain */
|
||||
struct pbuf *p, *q;
|
||||
u16_t recved;
|
||||
u16_t i;
|
||||
struct pbuf *t;
|
||||
|
||||
LWIP_ASSERT("netif != NULL", (netif != NULL));
|
||||
LWIP_ASSERT("netif->state != NULL", (netif->state != NULL));
|
||||
|
||||
q = p = NULL;
|
||||
recved = i = 0;
|
||||
c = 0;
|
||||
priv = netif->state;
|
||||
|
||||
while (1) {
|
||||
c = sio_recv(netif->state);
|
||||
switch (c) {
|
||||
case SLIP_END:
|
||||
if (recved > 0) {
|
||||
/* Received whole packet. */
|
||||
/* Trim the pbuf to the size of the received packet. */
|
||||
pbuf_realloc(q, recved);
|
||||
|
||||
LINK_STATS_INC(link.recv);
|
||||
|
||||
LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n"));
|
||||
return q;
|
||||
while (slip_sio_read(priv->sd, &c, 1, block) > 0) {
|
||||
switch (priv->state) {
|
||||
case SLIP_RECV_NORMAL:
|
||||
switch (c) {
|
||||
case SLIP_END:
|
||||
if (priv->recved > 0) {
|
||||
/* Received whole packet. */
|
||||
/* Trim the pbuf to the size of the received packet. */
|
||||
pbuf_realloc(priv->q, priv->recved);
|
||||
|
||||
LINK_STATS_INC(link.recv);
|
||||
|
||||
LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n"));
|
||||
t = priv->q;
|
||||
priv->p = priv->q = NULL;
|
||||
priv->i = priv->recved = 0;
|
||||
return t;
|
||||
}
|
||||
continue;
|
||||
case SLIP_ESC:
|
||||
priv->state = SLIP_RECV_ESCAPE;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
case SLIP_ESC:
|
||||
c = sio_recv(netif->state);
|
||||
case SLIP_RECV_ESCAPE:
|
||||
switch (c) {
|
||||
case SLIP_ESC_END:
|
||||
c = SLIP_END;
|
||||
@ -159,52 +204,52 @@ slipif_input(struct netif *netif)
|
||||
c = SLIP_ESC;
|
||||
break;
|
||||
}
|
||||
priv->state = SLIP_RECV_NORMAL;
|
||||
/* FALLTHROUGH */
|
||||
}
|
||||
|
||||
default:
|
||||
/* byte received, packet not yet completely received */
|
||||
if (p == NULL) {
|
||||
/* allocate a new pbuf */
|
||||
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n"));
|
||||
p = pbuf_alloc(PBUF_LINK, PBUF_POOL_BUFSIZE, PBUF_POOL);
|
||||
/* byte received, packet not yet completely received */
|
||||
if (priv->p == NULL) {
|
||||
/* allocate a new pbuf */
|
||||
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n"));
|
||||
priv->p = pbuf_alloc(PBUF_LINK, (PBUF_POOL_BUFSIZE - PBUF_LINK_HLEN), PBUF_POOL);
|
||||
|
||||
if (p == NULL) {
|
||||
LINK_STATS_INC(link.drop);
|
||||
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n"));
|
||||
/* don't process any further since we got no pbuf to receive to */
|
||||
break;
|
||||
}
|
||||
if (priv->p == NULL) {
|
||||
LINK_STATS_INC(link.drop);
|
||||
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n"));
|
||||
/* don't process any further since we got no pbuf to receive to */
|
||||
break;
|
||||
}
|
||||
|
||||
if (q != NULL) {
|
||||
/* 'chain' the pbuf to the existing chain */
|
||||
pbuf_cat(q, p);
|
||||
if (priv->q != NULL) {
|
||||
/* 'chain' the pbuf to the existing chain */
|
||||
pbuf_cat(priv->q, priv->p);
|
||||
} else {
|
||||
/* p is the first pbuf in the chain */
|
||||
priv->q = priv->p;
|
||||
}
|
||||
}
|
||||
|
||||
/* this automatically drops bytes if > SLIP_MAX_SIZE */
|
||||
if ((priv->p != NULL) && (priv->recved <= SLIP_MAX_SIZE)) {
|
||||
((u8_t *)priv->p->payload)[priv->i] = c;
|
||||
priv->recved++;
|
||||
priv->i++;
|
||||
if (priv->i >= priv->p->len) {
|
||||
/* on to the next pbuf */
|
||||
priv->i = 0;
|
||||
if (priv->p->next != NULL && priv->p->next->len > 0) {
|
||||
/* p is a chain, on to the next in the chain */
|
||||
priv->p = priv->p->next;
|
||||
} else {
|
||||
/* p is the first pbuf in the chain */
|
||||
q = p;
|
||||
/* p is a single pbuf, set it to NULL so next time a new
|
||||
* pbuf is allocated */
|
||||
priv->p = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* this automatically drops bytes if > MAX_SIZE */
|
||||
if ((p != NULL) && (recved <= MAX_SIZE)) {
|
||||
((u8_t *)p->payload)[i] = c;
|
||||
recved++;
|
||||
i++;
|
||||
if (i >= p->len) {
|
||||
/* on to the next pbuf */
|
||||
i = 0;
|
||||
if (p->next != NULL && p->next->len > 0) {
|
||||
/* p is a chain, on to the next in the chain */
|
||||
p = p->next;
|
||||
} else {
|
||||
/* p is a single pbuf, set it to NULL so next time a new
|
||||
* pbuf is allocated */
|
||||
p = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -217,13 +262,13 @@ slipif_input(struct netif *netif)
|
||||
* @param nf the lwip network interface structure for this slipif
|
||||
*/
|
||||
static void
|
||||
slipif_loop(void *nf)
|
||||
slipif_loop_thread(void *nf)
|
||||
{
|
||||
struct pbuf *p;
|
||||
struct netif *netif = (struct netif *)nf;
|
||||
|
||||
while (1) {
|
||||
p = slipif_input(netif);
|
||||
p = slipif_input(netif, SLIP_BLOCK);
|
||||
if (p != NULL) {
|
||||
if (netif->input(p, netif) != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
@ -242,6 +287,7 @@ slipif_loop(void *nf)
|
||||
*
|
||||
* @param netif the lwip network interface structure for this slipif
|
||||
* @return ERR_OK if serial line could be opened,
|
||||
* ERR_MEM if no memory could be allocated,
|
||||
* ERR_IF is serial line couldn't be opened
|
||||
*
|
||||
* @note netif->num must contain the number of the serial port to open
|
||||
@ -250,22 +296,39 @@ slipif_loop(void *nf)
|
||||
err_t
|
||||
slipif_init(struct netif *netif)
|
||||
{
|
||||
struct slipif_priv *priv;
|
||||
|
||||
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%"U16_F"\n", (u16_t)netif->num));
|
||||
|
||||
/* Allocate private data */
|
||||
priv = mem_malloc(sizeof(struct slipif_priv));
|
||||
if (!priv) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
netif->name[0] = 's';
|
||||
netif->name[1] = 'l';
|
||||
netif->output = slipif_output;
|
||||
netif->mtu = MAX_SIZE;
|
||||
netif->flags = NETIF_FLAG_POINTTOPOINT;
|
||||
netif->mtu = SLIP_MAX_SIZE;
|
||||
netif->flags |= NETIF_FLAG_POINTTOPOINT;
|
||||
|
||||
/* Try to open the serial port (netif->num contains the port number). */
|
||||
netif->state = sio_open(netif->num);
|
||||
if (!netif->state) {
|
||||
priv->sd = sio_open(netif->num);
|
||||
if (!priv->sd) {
|
||||
/* Opening the serial port failed. */
|
||||
mem_free(priv);
|
||||
return ERR_IF;
|
||||
}
|
||||
|
||||
/* Initialize private data */
|
||||
priv->p = NULL;
|
||||
priv->q = NULL;
|
||||
priv->state = SLIP_RECV_NORMAL;
|
||||
priv->i = 0;
|
||||
priv->recved = 0;
|
||||
|
||||
netif->state = priv;
|
||||
|
||||
/* initialize the snmp variables and counters inside the struct netif
|
||||
* ifSpeed: no assumption can be made without knowing more about the
|
||||
* serial line!
|
||||
@ -273,7 +336,32 @@ slipif_init(struct netif *netif)
|
||||
NETIF_INIT_SNMP(netif, snmp_ifType_slip, 0);
|
||||
|
||||
/* Create a thread to poll the serial line. */
|
||||
sys_thread_new(SLIPIF_THREAD_NAME, slipif_loop, netif, SLIPIF_THREAD_STACKSIZE, SLIPIF_THREAD_PRIO);
|
||||
sys_thread_new(SLIPIF_THREAD_NAME, slipif_loop_thread, netif,
|
||||
SLIPIF_THREAD_STACKSIZE, SLIPIF_THREAD_PRIO);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Polls the serial device and feeds the IP layer with incoming packets.
|
||||
*
|
||||
* @param netif The lwip network interface structure for this slipif
|
||||
*/
|
||||
void
|
||||
slipif_poll(struct netif *netif)
|
||||
{
|
||||
struct pbuf *p;
|
||||
struct slipif_priv *priv;
|
||||
|
||||
LWIP_ASSERT("netif != NULL", (netif != NULL));
|
||||
LWIP_ASSERT("netif->state != NULL", (netif->state != NULL));
|
||||
|
||||
priv = netif->state;
|
||||
|
||||
while ((p = slipif_input(netif, SLIP_DONTBLOCK)) != NULL) {
|
||||
if (netif->input(p, netif) != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* LWIP_HAVE_SLIPIF */
|
||||
|
37
net/lwip/test/unit/lwip_check.h
Normal file
37
net/lwip/test/unit/lwip_check.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef __LWIP_CHECK_H__
|
||||
#define __LWIP_CHECK_H__
|
||||
|
||||
/* Common header file for lwIP unit tests using the check framework */
|
||||
|
||||
#include <config.h>
|
||||
#include <check.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define FAIL_RET() do { fail(); return; } while(0)
|
||||
#define EXPECT(x) fail_unless(x)
|
||||
#define EXPECT_RET(x) do { fail_unless(x); if(!(x)) { return; }} while(0)
|
||||
#define EXPECT_RETX(x, y) do { fail_unless(x); if(!(x)) { return y; }} while(0)
|
||||
#define EXPECT_RETNULL(x) EXPECT_RETX(x, NULL)
|
||||
|
||||
/** typedef for a function returning a test suite */
|
||||
typedef Suite* (suite_getter_fn)(void);
|
||||
|
||||
/** Create a test suite */
|
||||
static Suite* create_suite(const char* name, TFun *tests, size_t num_tests, SFun setup, SFun teardown)
|
||||
{
|
||||
size_t i;
|
||||
Suite *s = suite_create(name);
|
||||
|
||||
for(i = 0; i < num_tests; i++) {
|
||||
// Core test case
|
||||
TCase *tc_core = tcase_create("Core");
|
||||
if ((setup != NULL) || (teardown != NULL)) {
|
||||
tcase_add_checked_fixture(tc_core, setup, teardown);
|
||||
}
|
||||
tcase_add_test(tc_core, tests[i]);
|
||||
suite_add_tcase(s, tc_core);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif /* __LWIP_CHECK_H__ */
|
42
net/lwip/test/unit/lwip_unittests.c
Normal file
42
net/lwip/test/unit/lwip_unittests.c
Normal file
@ -0,0 +1,42 @@
|
||||
#include "lwip_check.h"
|
||||
|
||||
#include "udp/test_udp.h"
|
||||
#include "tcp/test_tcp.h"
|
||||
#include "tcp/test_tcp_oos.h"
|
||||
|
||||
#include "lwip/init.h"
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
int number_failed;
|
||||
SRunner *sr;
|
||||
size_t i;
|
||||
suite_getter_fn* suites[] = {
|
||||
udp_suite,
|
||||
tcp_suite,
|
||||
tcp_oos_suite,
|
||||
};
|
||||
size_t num = sizeof(suites)/sizeof(void*);
|
||||
LWIP_ASSERT("No suites defined", num > 0);
|
||||
|
||||
lwip_init();
|
||||
|
||||
sr = srunner_create((suites[0])());
|
||||
for(i = 1; i < num; i++) {
|
||||
srunner_add_suite(sr, ((suite_getter_fn*)suites[i])());
|
||||
}
|
||||
|
||||
#ifdef LWIP_UNITTESTS_NOFORK
|
||||
srunner_set_fork_status(sr, CK_NOFORK);
|
||||
#endif
|
||||
#ifdef LWIP_UNITTESTS_FORK
|
||||
srunner_set_fork_status(sr, CK_FORK);
|
||||
#endif
|
||||
|
||||
srunner_run_all(sr, CK_NORMAL);
|
||||
number_failed = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
196
net/lwip/test/unit/tcp/tcp_helper.c
Normal file
196
net/lwip/test/unit/tcp/tcp_helper.c
Normal file
@ -0,0 +1,196 @@
|
||||
#include "tcp_helper.h"
|
||||
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
|
||||
#if !LWIP_STATS || !TCP_STATS || !MEMP_STATS
|
||||
#error "This tests needs TCP- and MEMP-statistics enabled"
|
||||
#endif
|
||||
|
||||
/** Remove all pcbs on the given list. */
|
||||
static void
|
||||
tcp_remove(struct tcp_pcb* pcb_list)
|
||||
{
|
||||
struct tcp_pcb *pcb = pcb_list;
|
||||
struct tcp_pcb *pcb2;
|
||||
|
||||
while(pcb != NULL) {
|
||||
pcb2 = pcb;
|
||||
pcb = pcb->next;
|
||||
tcp_abort(pcb2);
|
||||
}
|
||||
}
|
||||
|
||||
/** Remove all pcbs on listen-, active- and time-wait-list (bound- isn't exported). */
|
||||
void
|
||||
tcp_remove_all(void)
|
||||
{
|
||||
//tcp_remove(tcp_bound_pcbs);
|
||||
tcp_remove(tcp_listen_pcbs.pcbs);
|
||||
tcp_remove(tcp_active_pcbs);
|
||||
tcp_remove(tcp_tw_pcbs);
|
||||
fail_unless(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
|
||||
fail_unless(lwip_stats.memp[MEMP_TCP_PCB_LISTEN].used == 0);
|
||||
fail_unless(lwip_stats.memp[MEMP_TCP_SEG].used == 0);
|
||||
fail_unless(lwip_stats.memp[MEMP_PBUF_POOL].used == 0);
|
||||
}
|
||||
|
||||
/** Create a TCP segment usable for passing to tcp_input
|
||||
* - IP-addresses, ports, seqno and ackno are taken from pcb
|
||||
* - seqno and ackno can be altered with an offset
|
||||
*/
|
||||
struct pbuf*
|
||||
tcp_create_rx_segment(struct tcp_pcb* pcb, void* data, size_t data_len, u32_t seqno_offset,
|
||||
u32_t ackno_offset, u8_t headerflags)
|
||||
{
|
||||
return tcp_create_segment(&pcb->remote_ip, &pcb->local_ip, pcb->remote_port, pcb->local_port,
|
||||
data, data_len, pcb->rcv_nxt + seqno_offset, pcb->snd_nxt + ackno_offset, headerflags);
|
||||
}
|
||||
|
||||
/** Create a TCP segment usable for passing to tcp_input */
|
||||
struct pbuf*
|
||||
tcp_create_segment(struct ip_addr* src_ip, struct ip_addr* dst_ip,
|
||||
u16_t src_port, u16_t dst_port, void* data, size_t data_len,
|
||||
u32_t seqno, u32_t ackno, u8_t headerflags)
|
||||
{
|
||||
struct pbuf* p;
|
||||
struct ip_hdr* iphdr;
|
||||
struct tcp_hdr* tcphdr;
|
||||
u16_t pbuf_len = sizeof(struct ip_hdr) + sizeof(struct tcp_hdr) + data_len;
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, pbuf_len, PBUF_POOL);
|
||||
EXPECT_RETNULL(p != NULL);
|
||||
EXPECT_RETNULL(p->next == NULL);
|
||||
|
||||
memset(p->payload, 0, p->len);
|
||||
|
||||
iphdr = p->payload;
|
||||
/* fill IP header */
|
||||
iphdr->dest.addr = dst_ip->addr;
|
||||
iphdr->src.addr = src_ip->addr;
|
||||
IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, 0);
|
||||
IPH_LEN_SET(iphdr, htons(p->tot_len));
|
||||
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
|
||||
|
||||
pbuf_header(p, -(s16_t)sizeof(struct ip_hdr));
|
||||
|
||||
tcphdr = p->payload;
|
||||
tcphdr->src = htons(src_port);
|
||||
tcphdr->dest = htons(dst_port);
|
||||
tcphdr->seqno = htonl(seqno);
|
||||
tcphdr->ackno = htonl(ackno);
|
||||
TCPH_HDRLEN_SET(tcphdr, sizeof(struct tcp_hdr)/4);
|
||||
TCPH_FLAGS_SET(tcphdr, headerflags);
|
||||
tcphdr->wnd = htonl(TCP_WND);
|
||||
|
||||
/* copy data */
|
||||
memcpy((char*)tcphdr + sizeof(struct tcp_hdr), data, data_len);
|
||||
|
||||
/* calculate checksum */
|
||||
tcphdr->chksum = inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest),
|
||||
IP_PROTO_TCP, p->tot_len);
|
||||
|
||||
pbuf_header(p, sizeof(struct ip_hdr));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/** Safely bring a tcp_pcb into the requested state */
|
||||
void
|
||||
tcp_set_state(struct tcp_pcb* pcb, enum tcp_state state, struct ip_addr* local_ip,
|
||||
struct ip_addr* remote_ip, u16_t local_port, u16_t remote_port)
|
||||
{
|
||||
/* @todo: are these all states? */
|
||||
/* @todo: remove from previous list */
|
||||
pcb->state = state;
|
||||
if (state == ESTABLISHED) {
|
||||
TCP_REG(&tcp_active_pcbs, pcb);
|
||||
pcb->local_ip.addr = local_ip->addr;
|
||||
pcb->local_port = local_port;
|
||||
pcb->remote_ip.addr = remote_ip->addr;
|
||||
pcb->remote_port = remote_port;
|
||||
} else if(state == LISTEN) {
|
||||
TCP_REG(&tcp_listen_pcbs.pcbs, pcb);
|
||||
pcb->local_ip.addr = local_ip->addr;
|
||||
pcb->local_port = local_port;
|
||||
} else if(state == TIME_WAIT) {
|
||||
TCP_REG(&tcp_tw_pcbs, pcb);
|
||||
pcb->local_ip.addr = local_ip->addr;
|
||||
pcb->local_port = local_port;
|
||||
pcb->remote_ip.addr = remote_ip->addr;
|
||||
pcb->remote_port = remote_port;
|
||||
} else {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_tcp_counters_err(void* arg, err_t err)
|
||||
{
|
||||
struct test_tcp_counters* counters = arg;
|
||||
EXPECT_RET(arg != NULL);
|
||||
counters->err_calls++;
|
||||
counters->last_err = err;
|
||||
}
|
||||
|
||||
static void
|
||||
test_tcp_counters_check_rxdata(struct test_tcp_counters* counters, struct pbuf* p)
|
||||
{
|
||||
struct pbuf* q;
|
||||
u32_t i, received;
|
||||
if(counters->expected_data == NULL) {
|
||||
/* no data to compare */
|
||||
return;
|
||||
}
|
||||
EXPECT_RET(counters->recved_bytes + p->tot_len <= counters->expected_data_len);
|
||||
received = counters->recved_bytes;
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
char *data = q->payload;
|
||||
for(i = 0; i < q->len; i++) {
|
||||
EXPECT_RET(data[i] == counters->expected_data[received]);
|
||||
received++;
|
||||
}
|
||||
}
|
||||
EXPECT(received == counters->recved_bytes + p->tot_len);
|
||||
}
|
||||
|
||||
err_t
|
||||
test_tcp_counters_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err)
|
||||
{
|
||||
struct test_tcp_counters* counters = arg;
|
||||
EXPECT_RETX(arg != NULL, ERR_OK);
|
||||
EXPECT_RETX(pcb != NULL, ERR_OK);
|
||||
EXPECT_RETX(err == ERR_OK, ERR_OK);
|
||||
|
||||
if (p != NULL) {
|
||||
if (counters->close_calls == 0) {
|
||||
counters->recv_calls++;
|
||||
test_tcp_counters_check_rxdata(counters, p);
|
||||
counters->recved_bytes += p->tot_len;
|
||||
} else {
|
||||
counters->recv_calls_after_close++;
|
||||
counters->recved_bytes_after_close += p->tot_len;
|
||||
}
|
||||
pbuf_free(p);
|
||||
} else {
|
||||
counters->close_calls++;
|
||||
}
|
||||
EXPECT(counters->recv_calls_after_close == 0 && counters->recved_bytes_after_close == 0);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/** Allocate a pcb and set up the test_tcp_counters_* callbacks */
|
||||
struct tcp_pcb*
|
||||
test_tcp_new_counters_pcb(struct test_tcp_counters* counters)
|
||||
{
|
||||
struct tcp_pcb* pcb = tcp_new();
|
||||
if (pcb != NULL) {
|
||||
/* set up args and callbacks */
|
||||
tcp_arg(pcb, counters);
|
||||
tcp_recv(pcb, test_tcp_counters_recv);
|
||||
tcp_err(pcb, test_tcp_counters_err);
|
||||
}
|
||||
return pcb;
|
||||
}
|
36
net/lwip/test/unit/tcp/tcp_helper.h
Normal file
36
net/lwip/test/unit/tcp/tcp_helper.h
Normal file
@ -0,0 +1,36 @@
|
||||
#ifndef __TCP_HELPER_H__
|
||||
#define __TCP_HELPER_H__
|
||||
|
||||
#include "../lwip_check.h"
|
||||
#include "lwip/arch.h"
|
||||
#include "lwip/tcp.h"
|
||||
|
||||
/* counters used for test_tcp_counters_* callback functions */
|
||||
struct test_tcp_counters {
|
||||
u32_t recv_calls;
|
||||
u32_t recved_bytes;
|
||||
u32_t recv_calls_after_close;
|
||||
u32_t recved_bytes_after_close;
|
||||
u32_t close_calls;
|
||||
u32_t err_calls;
|
||||
err_t last_err;
|
||||
char* expected_data;
|
||||
u32_t expected_data_len;
|
||||
};
|
||||
|
||||
/* Helper functions */
|
||||
void tcp_remove_all(void);
|
||||
|
||||
struct pbuf* tcp_create_segment(struct ip_addr* src_ip, struct ip_addr* dst_ip,
|
||||
u16_t src_port, u16_t dst_port, void* data, size_t data_len,
|
||||
u32_t seqno, u32_t ackno, u8_t headerflags);
|
||||
struct pbuf* tcp_create_rx_segment(struct tcp_pcb* pcb, void* data, size_t data_len,
|
||||
u32_t seqno_offset, u32_t ackno_offset, u8_t headerflags);
|
||||
void tcp_set_state(struct tcp_pcb* pcb, enum tcp_state state, struct ip_addr* local_ip,
|
||||
struct ip_addr* remote_ip, u16_t local_port, u16_t remote_port);
|
||||
void test_tcp_counters_err(void* arg, err_t err);
|
||||
err_t test_tcp_counters_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err);
|
||||
|
||||
struct tcp_pcb* test_tcp_new_counters_pcb(struct test_tcp_counters* counters);
|
||||
|
||||
#endif
|
104
net/lwip/test/unit/tcp/test_tcp.c
Normal file
104
net/lwip/test/unit/tcp/test_tcp.c
Normal file
@ -0,0 +1,104 @@
|
||||
#include "test_tcp.h"
|
||||
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "tcp_helper.h"
|
||||
|
||||
#if !LWIP_STATS || !TCP_STATS || !MEMP_STATS
|
||||
#error "This tests needs TCP- and MEMP-statistics enabled"
|
||||
#endif
|
||||
|
||||
/* Setups/teardown functions */
|
||||
|
||||
static void
|
||||
tcp_setup(void)
|
||||
{
|
||||
tcp_remove_all();
|
||||
}
|
||||
|
||||
static void
|
||||
tcp_teardown(void)
|
||||
{
|
||||
tcp_remove_all();
|
||||
}
|
||||
|
||||
|
||||
/* Test functions */
|
||||
|
||||
/** Call tcp_new() and tcp_abort() and test memp stats */
|
||||
START_TEST(test_tcp_new_abort)
|
||||
{
|
||||
struct tcp_pcb* pcb;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
fail_unless(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
|
||||
|
||||
pcb = tcp_new();
|
||||
fail_unless(pcb != NULL);
|
||||
if (pcb != NULL) {
|
||||
fail_unless(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
|
||||
tcp_abort(pcb);
|
||||
fail_unless(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/** Create an ESTABLISHED pcb and check if receive callback is called */
|
||||
START_TEST(test_tcp_recv_inseq)
|
||||
{
|
||||
struct test_tcp_counters counters;
|
||||
struct tcp_pcb* pcb;
|
||||
struct pbuf* p;
|
||||
char data[] = {1, 2, 3, 4};
|
||||
struct ip_addr remote_ip, local_ip;
|
||||
u16_t data_len;
|
||||
u16_t remote_port = 0x100, local_port = 0x101;
|
||||
struct netif netif;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
/* initialize local vars */
|
||||
memset(&netif, 0, sizeof(netif));
|
||||
IP4_ADDR(&local_ip, 192, 168, 1, 1);
|
||||
IP4_ADDR(&remote_ip, 192, 168, 1, 2);
|
||||
data_len = sizeof(data);
|
||||
/* initialize counter struct */
|
||||
memset(&counters, 0, sizeof(counters));
|
||||
counters.expected_data_len = data_len;
|
||||
counters.expected_data = data;
|
||||
|
||||
/* create and initialize the pcb */
|
||||
pcb = test_tcp_new_counters_pcb(&counters);
|
||||
EXPECT_RET(pcb != NULL);
|
||||
tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
|
||||
|
||||
/* create a segment */
|
||||
p = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0);
|
||||
EXPECT(p != NULL);
|
||||
if (p != NULL) {
|
||||
/* pass the segment to tcp_input */
|
||||
tcp_input(p, &netif);
|
||||
/* check if counters are as expected */
|
||||
EXPECT(counters.close_calls == 0);
|
||||
EXPECT(counters.recv_calls == 1);
|
||||
EXPECT(counters.recved_bytes == data_len);
|
||||
EXPECT(counters.err_calls == 0);
|
||||
}
|
||||
|
||||
/* make sure the pcb is freed */
|
||||
EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
|
||||
tcp_abort(pcb);
|
||||
EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
/** Create the suite including all tests for this module */
|
||||
Suite *
|
||||
tcp_suite(void)
|
||||
{
|
||||
TFun tests[] = {
|
||||
test_tcp_new_abort,
|
||||
test_tcp_recv_inseq,
|
||||
};
|
||||
return create_suite("TCP", tests, sizeof(tests)/sizeof(TFun), tcp_setup, tcp_teardown);
|
||||
}
|
8
net/lwip/test/unit/tcp/test_tcp.h
Normal file
8
net/lwip/test/unit/tcp/test_tcp.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef __TEST_TCP_H__
|
||||
#define __TEST_TCP_H__
|
||||
|
||||
#include "../lwip_check.h"
|
||||
|
||||
Suite *tcp_suite(void);
|
||||
|
||||
#endif
|
433
net/lwip/test/unit/tcp/test_tcp_oos.c
Normal file
433
net/lwip/test/unit/tcp/test_tcp_oos.c
Normal file
@ -0,0 +1,433 @@
|
||||
#include "test_tcp_oos.h"
|
||||
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "tcp_helper.h"
|
||||
|
||||
#if !LWIP_STATS || !TCP_STATS || !MEMP_STATS
|
||||
#error "This tests needs TCP- and MEMP-statistics enabled"
|
||||
#endif
|
||||
#if !TCP_QUEUE_OOSEQ
|
||||
#error "This tests needs TCP_QUEUE_OOSEQ enabled"
|
||||
#endif
|
||||
|
||||
/** CHECK_SEGMENTS_ON_OOSEQ:
|
||||
* 1: check count, seqno and len of segments on pcb->ooseq (strict)
|
||||
* 0: only check that bytes are received in correct order (less strict) */
|
||||
#define CHECK_SEGMENTS_ON_OOSEQ 1
|
||||
|
||||
#if CHECK_SEGMENTS_ON_OOSEQ
|
||||
#define EXPECT_OOSEQ(x) EXPECT(x)
|
||||
#else
|
||||
#define EXPECT_OOSEQ(x)
|
||||
#endif
|
||||
|
||||
/* helper functions */
|
||||
|
||||
/** Get the numbers of segments on the ooseq list */
|
||||
static int tcp_oos_count(struct tcp_pcb* pcb)
|
||||
{
|
||||
int num = 0;
|
||||
struct tcp_seg* seg = pcb->ooseq;
|
||||
while(seg != NULL) {
|
||||
num++;
|
||||
seg = seg->next;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
/** Get the seqno of a segment (by index) on the ooseq list
|
||||
*
|
||||
* @param pcb the pcb to check for ooseq segments
|
||||
* @param seg_index index of the segment on the ooseq list
|
||||
* @return seqno of the segment
|
||||
*/
|
||||
static u32_t
|
||||
tcp_oos_seg_seqno(struct tcp_pcb* pcb, int seg_index)
|
||||
{
|
||||
int num = 0;
|
||||
struct tcp_seg* seg = pcb->ooseq;
|
||||
|
||||
/* then check the actual segment */
|
||||
while(seg != NULL) {
|
||||
if(num == seg_index) {
|
||||
return seg->tcphdr->seqno;
|
||||
}
|
||||
num++;
|
||||
seg = seg->next;
|
||||
}
|
||||
fail();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Get the tcplen of a segment (by index) on the ooseq list
|
||||
*
|
||||
* @param pcb the pcb to check for ooseq segments
|
||||
* @param seg_index index of the segment on the ooseq list
|
||||
* @return tcplen of the segment
|
||||
*/
|
||||
static int
|
||||
tcp_oos_seg_tcplen(struct tcp_pcb* pcb, int seg_index)
|
||||
{
|
||||
int num = 0;
|
||||
struct tcp_seg* seg = pcb->ooseq;
|
||||
|
||||
/* then check the actual segment */
|
||||
while(seg != NULL) {
|
||||
if(num == seg_index) {
|
||||
return TCP_TCPLEN(seg);
|
||||
}
|
||||
num++;
|
||||
seg = seg->next;
|
||||
}
|
||||
fail();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Setup/teardown functions */
|
||||
|
||||
static void
|
||||
tcp_oos_setup(void)
|
||||
{
|
||||
tcp_remove_all();
|
||||
}
|
||||
|
||||
static void
|
||||
tcp_oos_teardown(void)
|
||||
{
|
||||
tcp_remove_all();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Test functions */
|
||||
|
||||
/** create multiple segments and pass them to tcp_input in a wrong
|
||||
* order to see if ooseq-caching works correctly
|
||||
* FIN is received in out-of-sequence segments only */
|
||||
START_TEST(test_tcp_recv_ooseq_FIN_OOSEQ)
|
||||
{
|
||||
struct test_tcp_counters counters;
|
||||
struct tcp_pcb* pcb;
|
||||
struct pbuf *p_8_9, *p_4_8, *p_4_10, *p_2_14, *p_fin, *pinseq;
|
||||
char data[] = {
|
||||
1, 2, 3, 4,
|
||||
5, 6, 7, 8,
|
||||
9, 10, 11, 12,
|
||||
13, 14, 15, 16};
|
||||
struct ip_addr remote_ip, local_ip;
|
||||
u16_t data_len;
|
||||
u16_t remote_port = 0x100, local_port = 0x101;
|
||||
struct netif netif;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
/* initialize local vars */
|
||||
memset(&netif, 0, sizeof(netif));
|
||||
IP4_ADDR(&local_ip, 192, 168, 1, 1);
|
||||
IP4_ADDR(&remote_ip, 192, 168, 1, 2);
|
||||
data_len = sizeof(data);
|
||||
/* initialize counter struct */
|
||||
memset(&counters, 0, sizeof(counters));
|
||||
counters.expected_data_len = data_len;
|
||||
counters.expected_data = data;
|
||||
|
||||
/* create and initialize the pcb */
|
||||
pcb = test_tcp_new_counters_pcb(&counters);
|
||||
EXPECT_RET(pcb != NULL);
|
||||
tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
|
||||
|
||||
/* create segments */
|
||||
/* pinseq is sent as last segment! */
|
||||
pinseq = tcp_create_rx_segment(pcb, &data[0], 4, 0, 0, TCP_ACK);
|
||||
/* p1: 8 bytes before FIN */
|
||||
/* seqno: 8..16 */
|
||||
p_8_9 = tcp_create_rx_segment(pcb, &data[8], 8, 8, 0, TCP_ACK|TCP_FIN);
|
||||
/* p2: 4 bytes before p1, including the first 4 bytes of p1 (partly duplicate) */
|
||||
/* seqno: 4..11 */
|
||||
p_4_8 = tcp_create_rx_segment(pcb, &data[4], 8, 4, 0, TCP_ACK);
|
||||
/* p3: same as p2 but 2 bytes longer */
|
||||
/* seqno: 4..13 */
|
||||
p_4_10 = tcp_create_rx_segment(pcb, &data[4], 10, 4, 0, TCP_ACK);
|
||||
/* p4: 14 bytes before FIN, includes data from p1 and p2, plus partly from pinseq */
|
||||
/* seqno: 2..15 */
|
||||
p_2_14 = tcp_create_rx_segment(pcb, &data[2], 14, 2, 0, TCP_ACK);
|
||||
/* FIN, seqno 16 */
|
||||
p_fin = tcp_create_rx_segment(pcb, NULL, 0,16, 0, TCP_ACK|TCP_FIN);
|
||||
EXPECT(pinseq != NULL);
|
||||
EXPECT(p_8_9 != NULL);
|
||||
EXPECT(p_4_8 != NULL);
|
||||
EXPECT(p_4_10 != NULL);
|
||||
EXPECT(p_2_14 != NULL);
|
||||
EXPECT(p_fin != NULL);
|
||||
if ((pinseq != NULL) && (p_8_9 != NULL) && (p_4_8 != NULL) && (p_4_10 != NULL) && (p_2_14 != NULL) && (p_fin != NULL)) {
|
||||
/* pass the segment to tcp_input */
|
||||
tcp_input(p_8_9, &netif);
|
||||
/* check if counters are as expected */
|
||||
EXPECT(counters.close_calls == 0);
|
||||
EXPECT(counters.recv_calls == 0);
|
||||
EXPECT(counters.recved_bytes == 0);
|
||||
EXPECT(counters.err_calls == 0);
|
||||
/* check ooseq queue */
|
||||
EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 8);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 9); /* includes FIN */
|
||||
|
||||
/* pass the segment to tcp_input */
|
||||
tcp_input(p_4_8, &netif);
|
||||
/* check if counters are as expected */
|
||||
EXPECT(counters.close_calls == 0);
|
||||
EXPECT(counters.recv_calls == 0);
|
||||
EXPECT(counters.recved_bytes == 0);
|
||||
EXPECT(counters.err_calls == 0);
|
||||
/* check ooseq queue */
|
||||
EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 4);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 4);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */
|
||||
|
||||
/* pass the segment to tcp_input */
|
||||
tcp_input(p_4_10, &netif);
|
||||
/* check if counters are as expected */
|
||||
EXPECT(counters.close_calls == 0);
|
||||
EXPECT(counters.recv_calls == 0);
|
||||
EXPECT(counters.recved_bytes == 0);
|
||||
EXPECT(counters.err_calls == 0);
|
||||
/* ooseq queue: unchanged */
|
||||
EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 4);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 4);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */
|
||||
|
||||
/* pass the segment to tcp_input */
|
||||
tcp_input(p_2_14, &netif);
|
||||
/* check if counters are as expected */
|
||||
EXPECT(counters.close_calls == 0);
|
||||
EXPECT(counters.recv_calls == 0);
|
||||
EXPECT(counters.recved_bytes == 0);
|
||||
EXPECT(counters.err_calls == 0);
|
||||
/* check ooseq queue */
|
||||
EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 6);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */
|
||||
|
||||
/* pass the segment to tcp_input */
|
||||
tcp_input(p_fin, &netif);
|
||||
/* check if counters are as expected */
|
||||
EXPECT(counters.close_calls == 0);
|
||||
EXPECT(counters.recv_calls == 0);
|
||||
EXPECT(counters.recved_bytes == 0);
|
||||
EXPECT(counters.err_calls == 0);
|
||||
/* ooseq queue: unchanged */
|
||||
EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 6);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */
|
||||
|
||||
/* pass the segment to tcp_input */
|
||||
tcp_input(pinseq, &netif);
|
||||
/* check if counters are as expected */
|
||||
EXPECT(counters.close_calls == 1);
|
||||
EXPECT(counters.recv_calls == 1);
|
||||
EXPECT(counters.recved_bytes == data_len);
|
||||
EXPECT(counters.err_calls == 0);
|
||||
EXPECT(pcb->ooseq == NULL);
|
||||
}
|
||||
|
||||
/* make sure the pcb is freed */
|
||||
EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
|
||||
tcp_abort(pcb);
|
||||
EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
/** create multiple segments and pass them to tcp_input in a wrong
|
||||
* order to see if ooseq-caching works correctly
|
||||
* FIN is received IN-SEQUENCE at the end */
|
||||
START_TEST(test_tcp_recv_ooseq_FIN_INSEQ)
|
||||
{
|
||||
struct test_tcp_counters counters;
|
||||
struct tcp_pcb* pcb;
|
||||
struct pbuf *p_1_2, *p_4_8, *p_3_11, *p_2_12, *p_15_1, *p_15_1a, *pinseq, *pinseqFIN;
|
||||
char data[] = {
|
||||
1, 2, 3, 4,
|
||||
5, 6, 7, 8,
|
||||
9, 10, 11, 12,
|
||||
13, 14, 15, 16};
|
||||
struct ip_addr remote_ip, local_ip;
|
||||
u16_t data_len;
|
||||
u16_t remote_port = 0x100, local_port = 0x101;
|
||||
struct netif netif;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
/* initialize local vars */
|
||||
memset(&netif, 0, sizeof(netif));
|
||||
IP4_ADDR(&local_ip, 192, 168, 1, 1);
|
||||
IP4_ADDR(&remote_ip, 192, 168, 1, 2);
|
||||
data_len = sizeof(data);
|
||||
/* initialize counter struct */
|
||||
memset(&counters, 0, sizeof(counters));
|
||||
counters.expected_data_len = data_len;
|
||||
counters.expected_data = data;
|
||||
|
||||
/* create and initialize the pcb */
|
||||
pcb = test_tcp_new_counters_pcb(&counters);
|
||||
EXPECT_RET(pcb != NULL);
|
||||
tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
|
||||
|
||||
/* create segments */
|
||||
/* p1: 7 bytes - 2 before FIN */
|
||||
/* seqno: 1..2 */
|
||||
p_1_2 = tcp_create_rx_segment(pcb, &data[1], 2, 1, 0, TCP_ACK);
|
||||
/* p2: 4 bytes before p1, including the first 4 bytes of p1 (partly duplicate) */
|
||||
/* seqno: 4..11 */
|
||||
p_4_8 = tcp_create_rx_segment(pcb, &data[4], 8, 4, 0, TCP_ACK);
|
||||
/* p3: same as p2 but 2 bytes longer and one byte more at the front */
|
||||
/* seqno: 3..13 */
|
||||
p_3_11 = tcp_create_rx_segment(pcb, &data[3], 11, 3, 0, TCP_ACK);
|
||||
/* p4: 13 bytes - 2 before FIN - should be ignored as contained in p1 and p3 */
|
||||
/* seqno: 2..13 */
|
||||
p_2_12 = tcp_create_rx_segment(pcb, &data[2], 12, 2, 0, TCP_ACK);
|
||||
/* pinseq is the first segment that is held back to create ooseq! */
|
||||
/* seqno: 0..3 */
|
||||
pinseq = tcp_create_rx_segment(pcb, &data[0], 4, 0, 0, TCP_ACK);
|
||||
/* p5: last byte before FIN */
|
||||
/* seqno: 15 */
|
||||
p_15_1 = tcp_create_rx_segment(pcb, &data[15], 1, 15, 0, TCP_ACK);
|
||||
/* p6: same as p5, should be ignored */
|
||||
p_15_1a= tcp_create_rx_segment(pcb, &data[15], 1, 15, 0, TCP_ACK);
|
||||
/* pinseqFIN: last 2 bytes plus FIN */
|
||||
/* only segment containing seqno 14 and FIN */
|
||||
pinseqFIN = tcp_create_rx_segment(pcb, &data[14], 2, 14, 0, TCP_ACK|TCP_FIN);
|
||||
EXPECT(pinseq != NULL);
|
||||
EXPECT(p_1_2 != NULL);
|
||||
EXPECT(p_4_8 != NULL);
|
||||
EXPECT(p_3_11 != NULL);
|
||||
EXPECT(p_2_12 != NULL);
|
||||
EXPECT(p_15_1 != NULL);
|
||||
EXPECT(p_15_1a != NULL);
|
||||
EXPECT(pinseqFIN != NULL);
|
||||
if ((pinseq != NULL) && (p_1_2 != NULL) && (p_4_8 != NULL) && (p_3_11 != NULL) && (p_2_12 != NULL)
|
||||
&& (p_15_1 != NULL) && (p_15_1a != NULL) && (pinseqFIN != NULL)) {
|
||||
/* pass the segment to tcp_input */
|
||||
tcp_input(p_1_2, &netif);
|
||||
/* check if counters are as expected */
|
||||
EXPECT(counters.close_calls == 0);
|
||||
EXPECT(counters.recv_calls == 0);
|
||||
EXPECT(counters.recved_bytes == 0);
|
||||
EXPECT(counters.err_calls == 0);
|
||||
/* check ooseq queue */
|
||||
EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2);
|
||||
|
||||
/* pass the segment to tcp_input */
|
||||
tcp_input(p_4_8, &netif);
|
||||
/* check if counters are as expected */
|
||||
EXPECT(counters.close_calls == 0);
|
||||
EXPECT(counters.recv_calls == 0);
|
||||
EXPECT(counters.recved_bytes == 0);
|
||||
EXPECT(counters.err_calls == 0);
|
||||
/* check ooseq queue */
|
||||
EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 4);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 8);
|
||||
|
||||
/* pass the segment to tcp_input */
|
||||
tcp_input(p_3_11, &netif);
|
||||
/* check if counters are as expected */
|
||||
EXPECT(counters.close_calls == 0);
|
||||
EXPECT(counters.recv_calls == 0);
|
||||
EXPECT(counters.recved_bytes == 0);
|
||||
EXPECT(counters.err_calls == 0);
|
||||
/* check ooseq queue */
|
||||
EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2);
|
||||
/* p_3_11 has removed p_4_8 from ooseq */
|
||||
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 3);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 11);
|
||||
|
||||
/* pass the segment to tcp_input */
|
||||
tcp_input(p_2_12, &netif);
|
||||
/* check if counters are as expected */
|
||||
EXPECT(counters.close_calls == 0);
|
||||
EXPECT(counters.recv_calls == 0);
|
||||
EXPECT(counters.recved_bytes == 0);
|
||||
EXPECT(counters.err_calls == 0);
|
||||
/* check ooseq queue */
|
||||
EXPECT_OOSEQ(tcp_oos_count(pcb) == 3);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 2);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 1);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 2) == 3);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 2) == 11);
|
||||
|
||||
/* pass the segment to tcp_input */
|
||||
tcp_input(pinseq, &netif);
|
||||
/* check if counters are as expected */
|
||||
EXPECT(counters.close_calls == 0);
|
||||
EXPECT(counters.recv_calls == 1);
|
||||
EXPECT(counters.recved_bytes == 14);
|
||||
EXPECT(counters.err_calls == 0);
|
||||
EXPECT(pcb->ooseq == NULL);
|
||||
|
||||
/* pass the segment to tcp_input */
|
||||
tcp_input(p_15_1, &netif);
|
||||
/* check if counters are as expected */
|
||||
EXPECT(counters.close_calls == 0);
|
||||
EXPECT(counters.recv_calls == 1);
|
||||
EXPECT(counters.recved_bytes == 14);
|
||||
EXPECT(counters.err_calls == 0);
|
||||
/* check ooseq queue */
|
||||
EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 15);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1);
|
||||
|
||||
/* pass the segment to tcp_input */
|
||||
tcp_input(p_15_1a, &netif);
|
||||
/* check if counters are as expected */
|
||||
EXPECT(counters.close_calls == 0);
|
||||
EXPECT(counters.recv_calls == 1);
|
||||
EXPECT(counters.recved_bytes == 14);
|
||||
EXPECT(counters.err_calls == 0);
|
||||
/* check ooseq queue: unchanged */
|
||||
EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 15);
|
||||
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1);
|
||||
|
||||
/* pass the segment to tcp_input */
|
||||
tcp_input(pinseqFIN, &netif);
|
||||
/* check if counters are as expected */
|
||||
EXPECT(counters.close_calls == 1);
|
||||
EXPECT(counters.recv_calls == 2);
|
||||
EXPECT(counters.recved_bytes == data_len);
|
||||
EXPECT(counters.err_calls == 0);
|
||||
EXPECT(pcb->ooseq == NULL);
|
||||
}
|
||||
|
||||
/* make sure the pcb is freed */
|
||||
EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
|
||||
tcp_abort(pcb);
|
||||
EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/** Create the suite including all tests for this module */
|
||||
Suite *
|
||||
tcp_oos_suite(void)
|
||||
{
|
||||
TFun tests[] = {
|
||||
test_tcp_recv_ooseq_FIN_OOSEQ,
|
||||
test_tcp_recv_ooseq_FIN_INSEQ,
|
||||
};
|
||||
return create_suite("TCP_OOS", tests, sizeof(tests)/sizeof(TFun), tcp_oos_setup, tcp_oos_teardown);
|
||||
}
|
8
net/lwip/test/unit/tcp/test_tcp_oos.h
Normal file
8
net/lwip/test/unit/tcp/test_tcp_oos.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef __TEST_TCP_OOS_H__
|
||||
#define __TEST_TCP_OOS_H__
|
||||
|
||||
#include "../lwip_check.h"
|
||||
|
||||
Suite *tcp_oos_suite(void);
|
||||
|
||||
#endif
|
80
net/lwip/test/unit/udp/test_udp.c
Normal file
80
net/lwip/test/unit/udp/test_udp.c
Normal file
@ -0,0 +1,80 @@
|
||||
#include "test_udp.h"
|
||||
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/stats.h"
|
||||
|
||||
#if !LWIP_STATS || !UDP_STATS || !MEMP_STATS
|
||||
#error "This tests needs UDP- and MEMP-statistics enabled"
|
||||
#endif
|
||||
|
||||
/* Helper functions */
|
||||
static void
|
||||
udp_remove_all(void)
|
||||
{
|
||||
struct udp_pcb *pcb = udp_pcbs;
|
||||
struct udp_pcb *pcb2;
|
||||
|
||||
while(pcb != NULL) {
|
||||
pcb2 = pcb;
|
||||
pcb = pcb->next;
|
||||
udp_remove(pcb2);
|
||||
}
|
||||
fail_unless(lwip_stats.memp[MEMP_UDP_PCB].used == 0);
|
||||
}
|
||||
|
||||
/* Setups/teardown functions */
|
||||
|
||||
static void
|
||||
udp_setup(void)
|
||||
{
|
||||
udp_remove_all();
|
||||
}
|
||||
|
||||
static void
|
||||
udp_teardown(void)
|
||||
{
|
||||
udp_remove_all();
|
||||
}
|
||||
|
||||
|
||||
/* Test functions */
|
||||
|
||||
START_TEST(test_udp_new_remove)
|
||||
{
|
||||
struct udp_pcb* pcb;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
fail_unless(lwip_stats.memp[MEMP_UDP_PCB].used == 0);
|
||||
|
||||
pcb = udp_new();
|
||||
fail_unless(pcb != NULL);
|
||||
if (pcb != NULL) {
|
||||
fail_unless(lwip_stats.memp[MEMP_UDP_PCB].used == 1);
|
||||
udp_remove(pcb);
|
||||
fail_unless(lwip_stats.memp[MEMP_UDP_PCB].used == 0);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_udp_remove)
|
||||
{
|
||||
struct udp_pcb* pcb;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
pcb = NULL;
|
||||
//pcb = udp_new();
|
||||
//fail_unless(pcb != NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
/** Create the suite including all tests for this module */
|
||||
Suite *
|
||||
udp_suite(void)
|
||||
{
|
||||
TFun tests[] = {
|
||||
test_udp_new_remove,
|
||||
test_udp_remove
|
||||
};
|
||||
return create_suite("UDP", tests, sizeof(tests)/sizeof(TFun), udp_setup, udp_teardown);
|
||||
}
|
8
net/lwip/test/unit/udp/test_udp.h
Normal file
8
net/lwip/test/unit/udp/test_udp.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef __TEST_UDP_H__
|
||||
#define __TEST_UDP_H__
|
||||
|
||||
#include "../lwip_check.h"
|
||||
|
||||
Suite* udp_suite(void);
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user