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:
bernard.xiong 2010-01-13 03:22:23 +00:00
parent ce10330d80
commit a27f7c67bd
73 changed files with 2662 additions and 964 deletions

View File

@ -19,9 +19,180 @@ HISTORY
++ New features: ++ New features:
++ Bugfixes: ++ 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) (STABLE-1.3.1)
++ New features: ++ New features:

View File

@ -72,7 +72,7 @@ current CVS sources and is available from this web page:
http://www.nongnu.org/lwip/ http://www.nongnu.org/lwip/
There is now a constantly growin wiki about lwIP at 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 Also, there are mailing lists you can subscribe at
http://savannah.nongnu.org/mail/?group=lwip http://savannah.nongnu.org/mail/?group=lwip

View File

@ -16,7 +16,7 @@ src/arch/sys_arch_init.c
src/core/dhcp.c src/core/dhcp.c
src/core/dns.c src/core/dns.c
src/core/init.c src/core/init.c
src/core/memp_tiny.c src/core/memp.c
src/core/netif.c src/core/netif.c
src/core/pbuf.c src/core/pbuf.c
src/core/raw.c src/core/raw.c

View File

@ -327,8 +327,9 @@ netconn_recv(struct netconn *conn)
#if LWIP_SO_RCVTIMEO #if LWIP_SO_RCVTIMEO
if (sys_arch_mbox_fetch(conn->recvmbox, (void *)&p, conn->recv_timeout)==SYS_ARCH_TIMEOUT) { if (sys_arch_mbox_fetch(conn->recvmbox, (void *)&p, conn->recv_timeout)==SYS_ARCH_TIMEOUT) {
memp_free(MEMP_NETBUF, buf);
conn->err = ERR_TIMEOUT; conn->err = ERR_TIMEOUT;
p = NULL; return NULL;
} }
#else #else
sys_arch_mbox_fetch(conn->recvmbox, (void *)&p, 0); sys_arch_mbox_fetch(conn->recvmbox, (void *)&p, 0);

View File

@ -168,6 +168,15 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
buf->ptr = p; buf->ptr = p;
buf->addr = addr; buf->addr = addr;
buf->port = port; 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) { if (sys_mbox_trypost(conn->recvmbox, buf) != ERR_OK) {
@ -807,6 +816,8 @@ do_connect(struct api_msg_msg *msg)
break; break;
#endif /* LWIP_TCP */ #endif /* LWIP_TCP */
default: default:
LWIP_ERROR("Invalid netconn type", 0, do{ msg->conn->err = ERR_VAL;
sys_sem_signal(msg->conn->op_completed); }while(0));
break; break;
} }
} }
@ -1149,7 +1160,7 @@ do_close(struct api_msg_msg *msg)
#endif /* LWIP_TCP */ #endif /* LWIP_TCP */
{ {
msg->conn->err = ERR_VAL; msg->conn->err = ERR_VAL;
TCPIP_APIMSG_ACK(msg); sys_sem_signal(msg->conn->op_completed);
} }
} }

View File

@ -62,6 +62,11 @@ netbuf *netbuf_new(void)
buf->p = NULL; buf->p = NULL;
buf->ptr = NULL; buf->ptr = NULL;
buf->addr = NULL; buf->addr = NULL;
buf->port = 0;
#if LWIP_NETBUF_RECVINFO
buf->toaddr = NULL;
buf->toport = 0;
#endif /* LWIP_NETBUF_RECVINFO */
return buf; return buf;
} else { } else {
return NULL; return NULL;

View File

@ -126,7 +126,7 @@ lwip_gethostbyname(const char *name)
u8_t idx; u8_t idx;
for ( idx=0; s_hostent.h_addr_list[idx]; 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] == %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 */ #endif /* DNS_DEBUG */
@ -234,12 +234,6 @@ lwip_freeaddrinfo(struct addrinfo *ai)
struct addrinfo *next; struct addrinfo *next;
while (ai != NULL) { 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; next = ai->ai_next;
mem_free(ai); mem_free(ai);
ai = next; ai = next;
@ -274,6 +268,8 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
struct addrinfo *ai; struct addrinfo *ai;
struct sockaddr_in *sa = NULL; struct sockaddr_in *sa = NULL;
int port_nr = 0; int port_nr = 0;
size_t total_size;
size_t namelen = 0;
if (res == NULL) { if (res == NULL) {
return EAI_FAIL; return EAI_FAIL;
@ -300,19 +296,21 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
} }
} else { } else {
/* service location specified, use loopback address */ /* 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) { if (ai == NULL) {
goto memerr; goto memerr;
} }
memset(ai, 0, sizeof(struct addrinfo)); memset(ai, 0, total_size);
sa = mem_malloc(sizeof(struct sockaddr_in)); sa = (struct sockaddr_in*)((u8_t*)ai + sizeof(struct addrinfo));
if (sa == NULL) {
goto memerr;
}
memset(sa, 0, sizeof(struct sockaddr_in));
/* set up sockaddr */ /* set up sockaddr */
sa->sin_addr.s_addr = addr.addr; sa->sin_addr.s_addr = addr.addr;
sa->sin_family = AF_INET; sa->sin_family = AF_INET;
@ -328,12 +326,7 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
} }
if (nodename != NULL) { if (nodename != NULL) {
/* copy nodename to canonname if specified */ /* copy nodename to canonname if specified */
size_t namelen = strlen(nodename); ai->ai_canonname = ((char*)ai + sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
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;
}
MEMCPY(ai->ai_canonname, nodename, namelen); MEMCPY(ai->ai_canonname, nodename, namelen);
ai->ai_canonname[namelen] = 0; ai->ai_canonname[namelen] = 0;
} }
@ -347,9 +340,6 @@ memerr:
if (ai != NULL) { if (ai != NULL) {
mem_free(ai); mem_free(ai);
} }
if (sa != NULL) {
mem_free(sa);
}
return EAI_MEMORY; return EAI_MEMORY;
} }

View File

@ -58,6 +58,20 @@ do_netifapi_netif_add( struct netifapi_msg_msg *msg)
TCPIP_NETIFAPI_ACK(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 * Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the
* tcpip_thread context. * tcpip_thread context.
@ -103,6 +117,28 @@ netifapi_netif_add(struct netif *netif,
return msg.msg.err; 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 * call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) in a thread-safe
* way by running that function inside the tcpip_thread context. * way by running that function inside the tcpip_thread context.

View File

@ -1068,6 +1068,7 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
sys_sem_signal(socksem); sys_sem_signal(socksem);
return; return;
} }
s = conn->socket;
sys_sem_signal(socksem); sys_sem_signal(socksem);
} }
@ -1500,7 +1501,7 @@ lwip_getsockopt_internal(void *arg)
case IPPROTO_TCP: case IPPROTO_TCP:
switch (optname) { switch (optname) {
case TCP_NODELAY: 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", LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n",
s, (*(int*)optval)?"on":"off") ); s, (*(int*)optval)?"on":"off") );
break; break;
@ -1861,9 +1862,9 @@ lwip_setsockopt_internal(void *arg)
switch (optname) { switch (optname) {
case TCP_NODELAY: case TCP_NODELAY:
if (*(int*)optval) { if (*(int*)optval) {
sock->conn->pcb.tcp->flags |= TF_NODELAY; tcp_nagle_disable(sock->conn->pcb.tcp);
} else { } 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", LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n",
s, (*(int *)optval)?"on":"off") ); s, (*(int *)optval)?"on":"off") );

View File

@ -99,6 +99,10 @@
* MTU is checked to be big enough in dhcp_start */ * MTU is checked to be big enough in dhcp_start */
#define DHCP_MAX_MSG_LEN(netif) (netif->mtu) #define DHCP_MAX_MSG_LEN(netif) (netif->mtu)
#define DHCP_MAX_MSG_LEN_MIN_REQUIRED 576 #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 */ /* DHCP client state machine functions */
static void dhcp_handle_ack(struct netif *netif); 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_discover(struct netif *netif);
static err_t dhcp_select(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); static void dhcp_bind(struct netif *netif);
#if DHCP_DOES_ARP_CHECK #if DHCP_DOES_ARP_CHECK
static void dhcp_check(struct netif *netif);
static err_t dhcp_decline(struct netif *netif); static err_t dhcp_decline(struct netif *netif);
#endif /* DHCP_DOES_ARP_CHECK */ #endif /* DHCP_DOES_ARP_CHECK */
static err_t dhcp_rebind(struct netif *netif); 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); static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state);
/* receive, unfold, parse and free incoming messages */ /* 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 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_ptr(struct dhcp *dhcp, u8_t option_type);
static u8_t dhcp_get_option_byte(u8_t *ptr); static u8_t dhcp_get_option_byte(u8_t *ptr);
#if 0 #if 0
@ -161,7 +166,7 @@ static void
dhcp_handle_nak(struct netif *netif) dhcp_handle_nak(struct netif *netif)
{ {
struct dhcp *dhcp = netif->dhcp; 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)); (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 */ /* Set the interface down since the address must no longer be used, as per RFC2131 */
netif_set_down(netif); netif_set_down(netif);
@ -175,6 +180,7 @@ dhcp_handle_nak(struct netif *netif)
dhcp_discover(netif); dhcp_discover(netif);
} }
#if DHCP_DOES_ARP_CHECK
/** /**
* Checks if the offered IP address is already in use. * Checks if the offered IP address is already in use.
* *
@ -190,20 +196,21 @@ dhcp_check(struct netif *netif)
struct dhcp *dhcp = netif->dhcp; struct dhcp *dhcp = netif->dhcp;
err_t result; err_t result;
u16_t msecs; 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])); (s16_t)netif->name[1]));
dhcp_set_state(dhcp, DHCP_CHECKING); dhcp_set_state(dhcp, DHCP_CHECKING);
/* create an ARP query for the offered IP address, expecting that no host /* create an ARP query for the offered IP address, expecting that no host
responds, as the IP address should not be in use. */ responds, as the IP address should not be in use. */
result = etharp_query(netif, &dhcp->offered_ip_addr, NULL); result = etharp_query(netif, &dhcp->offered_ip_addr, NULL);
if (result != ERR_OK) { 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++; dhcp->tries++;
msecs = 500; msecs = 500;
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; 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)); 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. * Remember the configuration offered by a DHCP server.
@ -216,7 +223,7 @@ dhcp_handle_offer(struct netif *netif)
struct dhcp *dhcp = netif->dhcp; struct dhcp *dhcp = netif->dhcp;
/* obtain the server address */ /* obtain the server address */
u8_t *option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_SERVER_ID); 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)); (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
if (option_ptr != NULL) { if (option_ptr != NULL) {
dhcp->server_ip_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2])); 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; const char *p;
#endif /* LWIP_NETIF_HOSTNAME */ #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); dhcp_set_state(dhcp, DHCP_REQUESTING);
/* create and initialize the DHCP message header */ /* create and initialize the DHCP message header */
@ -286,16 +293,12 @@ dhcp_select(struct netif *netif)
/* shrink the pbuf to the actual content length */ /* shrink the pbuf to the actual content length */
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); 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 */ /* send broadcast to any DHCP server */
udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); 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); dhcp_delete_request(netif);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n")); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n"));
} else { } 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++; dhcp->tries++;
msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000; msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000;
@ -378,7 +381,7 @@ static void
dhcp_timeout(struct netif *netif) dhcp_timeout(struct netif *netif)
{ {
struct dhcp *dhcp = netif->dhcp; 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 */ /* back-off period has passed, or server selection timed out */
if ((dhcp->state == DHCP_BACKING_OFF) || (dhcp->state == DHCP_SELECTING)) { if ((dhcp->state == DHCP_BACKING_OFF) || (dhcp->state == DHCP_SELECTING)) {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout(): restarting discovery\n")); 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_release(netif);
dhcp_discover(netif); dhcp_discover(netif);
} }
#if DHCP_DOES_ARP_CHECK
/* received no ARP reply for the offered address (which is good) */ /* received no ARP reply for the offered address (which is good) */
} else if (dhcp->state == DHCP_CHECKING) { } else if (dhcp->state == DHCP_CHECKING) {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): CHECKING, ARP request timed out\n")); 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 */ /* bind the interface to the offered address */
dhcp_bind(netif); dhcp_bind(netif);
} }
#endif /* DHCP_DOES_ARP_CHECK */
} }
/* did not get response to renew request? */ /* did not get response to renew request? */
else if (dhcp->state == DHCP_RENEWING) { else if (dhcp->state == DHCP_RENEWING) {
@ -421,6 +426,12 @@ dhcp_timeout(struct netif *netif)
dhcp_release(netif); dhcp_release(netif);
dhcp_discover(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")); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): allocated dhcp"));
/* already has DHCP client attached */ /* already has DHCP client attached */
} else { } 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) { if (dhcp->pcb != NULL) {
udp_remove(dhcp->pcb); udp_remove(dhcp->pcb);
} }
if (dhcp->p != NULL) { LWIP_ASSERT("pbuf p_out wasn't freed", dhcp->p_out == NULL);
pbuf_free(dhcp->p); LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL &&
} dhcp->options_in == NULL && dhcp->options_in_len == 0);
} }
/* clear data structure */ /* clear data structure */
@ -652,23 +663,23 @@ dhcp_start(struct netif *netif)
void void
dhcp_inform(struct netif *netif) dhcp_inform(struct netif *netif)
{ {
struct dhcp *dhcp, *old_dhcp = netif->dhcp; struct dhcp *dhcp, *old_dhcp;
err_t result = ERR_OK; err_t result = ERR_OK;
dhcp = mem_malloc(sizeof(struct dhcp)); dhcp = mem_malloc(sizeof(struct dhcp));
if (dhcp == NULL) { 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; return;
} }
netif->dhcp = dhcp;
memset(dhcp, 0, sizeof(struct dhcp)); memset(dhcp, 0, sizeof(struct dhcp));
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): allocated dhcp\n")); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): allocated dhcp\n"));
dhcp->pcb = udp_new(); dhcp->pcb = udp_new();
if (dhcp->pcb == NULL) { if (dhcp->pcb == NULL) {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_inform(): could not obtain pcb")); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform(): could not obtain pcb"));
mem_free((void *)dhcp); goto free_dhcp_and_return;
return;
} }
old_dhcp = netif->dhcp;
netif->dhcp = dhcp;
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): created new udp pcb\n")); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): created new udp pcb\n"));
/* create and initialize the DHCP message header */ /* create and initialize the DHCP message header */
result = dhcp_create_request(netif); result = dhcp_create_request(netif);
@ -688,21 +699,48 @@ dhcp_inform(struct netif *netif)
dhcp->pcb->so_options|=SOF_BROADCAST; dhcp->pcb->so_options|=SOF_BROADCAST;
#endif /* IP_SOF_BROADCAST */ #endif /* IP_SOF_BROADCAST */
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT); 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")); 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_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); dhcp_delete_request(netif);
} else { } 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; dhcp->pcb = NULL;
mem_free((void *)dhcp);
netif->dhcp = old_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 #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) void dhcp_arp_reply(struct netif *netif, struct ip_addr *addr)
{ {
LWIP_ERROR("netif != NULL", (netif != NULL), return;); 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? */ /* is a DHCP client doing an ARP check? */
if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_CHECKING)) { 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)); 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? */ were offered by the DHCP server? */
if (ip_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) { if (ip_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) {
/* we will not accept the offered address */ /* 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); dhcp_decline(netif);
} }
} }
@ -744,7 +783,7 @@ dhcp_decline(struct netif *netif)
struct dhcp *dhcp = netif->dhcp; struct dhcp *dhcp = netif->dhcp;
err_t result = ERR_OK; err_t result = ERR_OK;
u16_t msecs; 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); dhcp_set_state(dhcp, DHCP_BACKING_OFF);
/* create and initialize the DHCP message header */ /* create and initialize the DHCP message header */
result = dhcp_create_request(netif); result = dhcp_create_request(netif);
@ -759,14 +798,13 @@ dhcp_decline(struct netif *netif)
/* resize pbuf to reflect true size of options */ /* resize pbuf to reflect true size of options */
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); 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 */ /* per section 4.4.4, broadcast DECLINE messages */
udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
dhcp_delete_request(netif); dhcp_delete_request(netif);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n")); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n"));
} else { } 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++; dhcp->tries++;
msecs = 10*1000; msecs = 10*1000;
@ -788,7 +826,7 @@ dhcp_discover(struct netif *netif)
struct dhcp *dhcp = netif->dhcp; struct dhcp *dhcp = netif->dhcp;
err_t result = ERR_OK; err_t result = ERR_OK;
u16_t msecs; 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); ip_addr_set(&dhcp->offered_ip_addr, IP_ADDR_ANY);
dhcp_set_state(dhcp, DHCP_SELECTING); dhcp_set_state(dhcp, DHCP_SELECTING);
/* create and initialize the DHCP message header */ /* 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")); 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); 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")); 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); 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")); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n"));
dhcp_delete_request(netif); dhcp_delete_request(netif);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n")); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n"));
} else { } 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++; dhcp->tries++;
#if LWIP_DHCP_AUTOIP_COOP #if LWIP_DHCP_AUTOIP_COOP
@ -849,7 +886,7 @@ dhcp_bind(struct netif *netif)
LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;); LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;);
dhcp = netif->dhcp; dhcp = netif->dhcp;
LWIP_ERROR("dhcp_bind: dhcp != NULL", (dhcp != NULL), return;); 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? */ /* temporary DHCP lease? */
if (dhcp->offered_t1_renew != 0xffffffffUL) { if (dhcp->offered_t1_renew != 0xffffffffUL) {
@ -937,7 +974,7 @@ dhcp_renew(struct netif *netif)
#if LWIP_NETIF_HOSTNAME #if LWIP_NETIF_HOSTNAME
const char *p; const char *p;
#endif /* LWIP_NETIF_HOSTNAME */ #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); dhcp_set_state(dhcp, DHCP_RENEWING);
/* create and initialize the DHCP message header */ /* 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); 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); udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif);
dhcp_delete_request(netif); dhcp_delete_request(netif);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew: RENEWING\n")); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew: RENEWING\n"));
} else { } 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++; dhcp->tries++;
/* back-off on retries, but to a maximum of 20 seconds */ /* 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); pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
/* broadcast to server */ /* 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); udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
dhcp_delete_request(netif); dhcp_delete_request(netif);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind: REBINDING\n")); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind: REBINDING\n"));
} else { } 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++; dhcp->tries++;
msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
@ -1054,6 +1089,52 @@ dhcp_rebind(struct netif *netif)
return result; 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. * Release a DHCP lease.
* *
@ -1065,7 +1146,7 @@ dhcp_release(struct netif *netif)
struct dhcp *dhcp = netif->dhcp; struct dhcp *dhcp = netif->dhcp;
err_t result; err_t result;
u16_t msecs; 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 */ /* idle DHCP client */
dhcp_set_state(dhcp, DHCP_OFF); 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); 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); udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif);
dhcp_delete_request(netif); dhcp_delete_request(netif);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_OFF\n")); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_OFF\n"));
} else { } 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++; dhcp->tries++;
msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; 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. */ /* Remove the flag that says this netif is handled by DHCP. */
netif->flags &= ~NETIF_FLAG_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? */ /* netif is DHCP configured? */
if (dhcp != NULL) { if (dhcp != NULL) {
#if LWIP_DHCP_AUTOIP_COOP #if LWIP_DHCP_AUTOIP_COOP
@ -1135,12 +1215,8 @@ dhcp_stop(struct netif *netif)
udp_remove(dhcp->pcb); udp_remove(dhcp->pcb);
dhcp->pcb = NULL; dhcp->pcb = NULL;
} }
if (dhcp->p != NULL) { LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL &&
pbuf_free(dhcp->p); dhcp->options_in == NULL && dhcp->options_in_len == 0);
dhcp->p = NULL;
}
/* free unfolded reply */
dhcp_free_reply(dhcp);
mem_free((void *)dhcp); mem_free((void *)dhcp);
netif->dhcp = NULL; netif->dhcp = NULL;
} }
@ -1214,39 +1290,44 @@ dhcp_option_long(struct dhcp *dhcp, u32_t value)
* *
*/ */
static err_t static err_t
dhcp_unfold_reply(struct dhcp *dhcp) dhcp_unfold_reply(struct dhcp *dhcp, struct pbuf *p)
{ {
u16_t ret; u16_t ret;
LWIP_ERROR("dhcp != NULL", (dhcp != NULL), return ERR_ARG;); 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 */ /* free any left-overs from previous unfolds */
dhcp_free_reply(dhcp); dhcp_free_reply(dhcp);
/* options present? */ /* options present? */
if (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 = dhcp->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); dhcp->options_in = mem_malloc(dhcp->options_in_len);
if (dhcp->options_in == NULL) { 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; return ERR_MEM;
} }
} }
dhcp->msg_in = mem_malloc(sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN); dhcp->msg_in = mem_malloc(sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
if (dhcp->msg_in == NULL) { if (dhcp->msg_in == NULL) {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_unfold_reply(): could not allocate dhcp->msg_in\n")); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
mem_free((void *)dhcp->options_in); ("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 = NULL;
dhcp->options_in_len = 0;
}
return ERR_MEM; return ERR_MEM;
} }
/** copy the DHCP message without options */ /** 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_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", 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)); sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN));
if (dhcp->options_in != NULL) { if (dhcp->options_in != NULL) {
/** copy the DHCP options */ /** 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_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", LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_unfold_reply(): copied %"U16_F" bytes to dhcp->options_in[]\n",
dhcp->options_in_len)); dhcp->options_in_len));
@ -1258,7 +1339,6 @@ dhcp_unfold_reply(struct dhcp *dhcp)
/** /**
* Free the incoming DHCP message including contiguous copy of * Free the incoming DHCP message including contiguous copy of
* its DHCP options. * its DHCP options.
*
*/ */
static void dhcp_free_reply(struct dhcp *dhcp) static void dhcp_free_reply(struct dhcp *dhcp)
{ {
@ -1267,14 +1347,13 @@ static void dhcp_free_reply(struct dhcp *dhcp)
dhcp->msg_in = NULL; dhcp->msg_in = NULL;
} }
if (dhcp->options_in) { if (dhcp->options_in) {
mem_free((void *)dhcp->options_in); mem_free(dhcp->options_in);
dhcp->options_in = NULL; dhcp->options_in = NULL;
dhcp->options_in_len = 0; dhcp->options_in_len = 0;
} }
LWIP_DEBUGF(DHCP_DEBUG, ("dhcp_free_reply(): free'd\n")); 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 * 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 *options_ptr;
u8_t msg_type; u8_t msg_type;
u8_t i; 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) >> 24 & 0xff), (u16_t)(ntohl(addr->addr) >> 16 & 0xff),
(u16_t)(ntohl(addr->addr) >> 8 & 0xff), (u16_t)(ntohl(addr->addr) & 0xff), port)); (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)); 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(pcb);
LWIP_UNUSED_ARG(addr); LWIP_UNUSED_ARG(addr);
LWIP_UNUSED_ARG(port); 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) { 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; goto free_pbuf_and_return;
} }
/* iterate through hardware address and match against DHCP message */ /* iterate through hardware address and match against DHCP message */
for (i = 0; i < netif->hwaddr_len; i++) { for (i = 0; i < netif->hwaddr_len; i++) {
if (netif->hwaddr[i] != reply_msg->chaddr[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])); (u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i]));
goto free_pbuf_and_return; goto free_pbuf_and_return;
} }
} }
/* match transaction ID against what we expected */ /* match transaction ID against what we expected */
if (ntohl(reply_msg->xid) != dhcp->xid) { 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; goto free_pbuf_and_return;
} }
/* option fields could be unfold? */ /* option fields could be unfold? */
if (dhcp_unfold_reply(dhcp) != ERR_OK) { if (dhcp_unfold_reply(dhcp, p) != ERR_OK) {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("problem unfolding DHCP message - too short on memory?\n")); 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; 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 */ /* obtain pointer to DHCP message type */
options_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_MESSAGE_TYPE); options_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_MESSAGE_TYPE);
if (options_ptr == NULL) { 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; 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); msg_type = dhcp_get_option_byte(options_ptr + 2);
/* message type is DHCP ACK? */ /* message type is DHCP ACK? */
if (msg_type == 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? */ /* in requesting state? */
if (dhcp->state == DHCP_REQUESTING) { if (dhcp->state == DHCP_REQUESTING) {
dhcp_handle_ack(netif); 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) && else if ((msg_type == DHCP_NAK) &&
((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REQUESTING) || ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REQUESTING) ||
(dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING ))) { (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->request_timeout = 0;
dhcp_handle_nak(netif); dhcp_handle_nak(netif);
} }
/* received a DHCP_OFFER in DHCP_SELECTING state? */ /* received a DHCP_OFFER in DHCP_SELECTING state? */
else if ((msg_type == DHCP_OFFER) && (dhcp->state == DHCP_SELECTING)) { 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; dhcp->request_timeout = 0;
/* remember offered lease */ /* remember offered lease */
dhcp_handle_offer(netif); 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: free_pbuf_and_return:
dhcp_free_reply(dhcp); dhcp_free_reply(dhcp);
pbuf_free(p); 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); 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); dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM);
if (dhcp->p_out == NULL) { 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; return ERR_MEM;
} }
LWIP_ASSERT("dhcp_create_request: check that first pbuf can hold struct dhcp_msg", 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) if (dhcp->tries==0)
xid++; xid++;
dhcp->xid = 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)); ("transaction id xid(%"X32_F")\n", xid));
dhcp->msg_out = (struct dhcp_msg *)dhcp->p_out->payload; 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)); */ /* 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? */ /* are the sname and/or file field overloaded with options? */
if (options[offset] == DHCP_OPTION_OVERLOAD) { 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 */ /* skip option type and length */
offset += 2; offset += 2;
overload = options[offset++]; 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) { if (overload != DHCP_OVERLOAD_NONE) {
u16_t field_len; u16_t field_len;
if (overload == DHCP_OVERLOAD_FILE) { 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; options = (u8_t *)&dhcp->msg_in->file;
field_len = DHCP_FILE_LEN; field_len = DHCP_FILE_LEN;
} else if (overload == DHCP_OVERLOAD_SNAME) { } 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; options = (u8_t *)&dhcp->msg_in->sname;
field_len = DHCP_SNAME_LEN; field_len = DHCP_SNAME_LEN;
/* TODO: check if else if () is necessary */ /* TODO: check if else if () is necessary */
} else { } 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; options = (u8_t *)&dhcp->msg_in->sname;
field_len = DHCP_FILE_LEN + DHCP_SNAME_LEN; field_len = DHCP_FILE_LEN + DHCP_SNAME_LEN;
} }

View File

@ -961,7 +961,7 @@ dns_gethostbyname(const char *hostname, struct ip_addr *addr, dns_found_callback
#if LWIP_HAVE_LOOPIF #if LWIP_HAVE_LOOPIF
if (strcmp(hostname,"localhost")==0) { if (strcmp(hostname,"localhost")==0) {
addr->addr = INADDR_LOOPBACK; addr->addr = htonl(INADDR_LOOPBACK);
return ERR_OK; return ERR_OK;
} }
#endif /* LWIP_HAVE_LOOPIF */ #endif /* LWIP_HAVE_LOOPIF */

View File

@ -168,6 +168,9 @@
#if (DNS_LOCAL_HOSTLIST && !DNS_LOCAL_HOSTLIST_IS_DYNAMIC && !(defined(DNS_LOCAL_HOSTLIST_INIT))) #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" #error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST"
#endif #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. /* Compile-time checks for deprecated options.
@ -208,6 +211,8 @@ lwip_sanity_check(void)
#if LWIP_TCP #if LWIP_TCP
if (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN) 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")); 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))) 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")); 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) if (TCP_SNDLOWAT > TCP_SND_BUF)

View File

@ -100,7 +100,7 @@
*/ */
#ifndef LWIP_AUTOIP_CREATE_SEED_ADDR #ifndef LWIP_AUTOIP_CREATE_SEED_ADDR
#define LWIP_AUTOIP_CREATE_SEED_ADDR(netif) \ #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))) ((u32_t)((u8_t)(netif->hwaddr[5]))) << 8)))
#endif /* LWIP_AUTOIP_CREATE_SEED_ADDR */ #endif /* LWIP_AUTOIP_CREATE_SEED_ADDR */
@ -108,7 +108,10 @@
static void autoip_handle_arp_conflict(struct netif *netif); static void autoip_handle_arp_conflict(struct netif *netif);
/* creates a pseudo random LL IP-Address for a network interface */ /* 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 */ /* sends an ARP announce */
static err_t autoip_arp_announce(struct netif *netif); 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 */ /* configure interface for use with current LL IP-Address */
static err_t autoip_bind(struct netif *netif); static err_t autoip_bind(struct netif *netif);
/* start sending probes for llipaddr */
static void autoip_start_probing(struct netif *netif);
/** /**
* Initialize this module * Initialize this module
*/ */
void void
autoip_init(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 /* retreat, there was a conflicting ARP in the last
* DEFEND_INTERVAL seconds * 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")); ("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n"));
/* TODO: close all TCP sessions */ /* TODO: close all TCP sessions */
autoip_start(netif); autoip_start(netif);
} else { } 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_handle_arp_conflict(): we are defend, send ARP Announce\n"));
autoip_arp_announce(netif); autoip_arp_announce(netif);
netif->autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND; netif->autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND;
} }
} else { } 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")); ("autoip_handle_arp_conflict(): we do not defend, retreating\n"));
/* TODO: close all TCP sessions */ /* TODO: close all TCP sessions */
autoip_start(netif); 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 * 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 netif network interface on which create the IP-Address
* @param IPAddr ip address to initialize * @param ipaddr ip address to initialize
*/ */
static void 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 /* 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 * compliant to RFC 3927 Section 2.1
@ -184,11 +190,24 @@ autoip_create_addr(struct netif *netif, struct ip_addr *IPAddr)
} }
LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) && LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) &&
(addr <= AUTOIP_RANGE_END)); (addr <= AUTOIP_RANGE_END));
IPAddr->addr = htonl(addr); 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", ("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, &ethbroadcast,
(struct eth_addr *)netif->hwaddr, IP_ADDR_ANY, &ethzero,
&netif->autoip->llipaddr, ARP_REQUEST);
} }
/** /**
@ -215,7 +234,7 @@ autoip_bind(struct netif *netif)
struct autoip *autoip = netif->autoip; struct autoip *autoip = netif->autoip;
struct ip_addr sn_mask, gw_addr; 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", ("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)); (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_create_addr(netif, &(autoip->llipaddr));
autoip->tried_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->state = AUTOIP_STATE_PROBING;
autoip->sent_num = 0; autoip->sent_num = 0;
@ -295,12 +324,24 @@ autoip_start(struct netif *netif)
* accquiring and probing address * accquiring and probing address
* compliant to RFC 3927 Section 2.2.1 * compliant to RFC 3927 Section 2.2.1
*/ */
if(autoip->tried_llipaddr > MAX_CONFLICTS) { if(autoip->tried_llipaddr > MAX_CONFLICTS) {
autoip->ttw = RATE_LIMIT_INTERVAL * AUTOIP_TICKS_PER_SECOND; 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) { if(netif->autoip->ttw > 0) {
netif->autoip->ttw--; netif->autoip->ttw--;
} else { } else {
if(netif->autoip->sent_num == PROBE_NUM) { if(netif->autoip->sent_num >= PROBE_NUM) {
netif->autoip->state = AUTOIP_STATE_ANNOUNCING; netif->autoip->state = AUTOIP_STATE_ANNOUNCING;
netif->autoip->sent_num = 0; netif->autoip->sent_num = 0;
netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND; netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND;
} else { } else {
etharp_request(netif, &(netif->autoip->llipaddr)); autoip_arp_probe(netif);
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | 3, LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
("autoip_tmr() PROBING Sent Probe\n")); ("autoip_tmr() PROBING Sent Probe\n"));
netif->autoip->sent_num++; netif->autoip->sent_num++;
/* calculate time to wait to next probe */ /* calculate time to wait to next probe */
@ -363,21 +404,24 @@ autoip_tmr()
} else { } else {
if(netif->autoip->sent_num == 0) { if(netif->autoip->sent_num == 0) {
/* We are here the first time, so we waited ANNOUNCE_WAIT seconds /* 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); autoip_bind(netif);
} else {
autoip_arp_announce(netif);
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
("autoip_tmr() ANNOUNCING Sent Announce\n"));
} }
netif->autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND;
netif->autoip->sent_num++;
if(netif->autoip->sent_num == ANNOUNCE_NUM) { if(netif->autoip->sent_num >= ANNOUNCE_NUM) {
netif->autoip->state = AUTOIP_STATE_BOUND; netif->autoip->state = AUTOIP_STATE_BOUND;
netif->autoip->sent_num = 0; netif->autoip->sent_num = 0;
netif->autoip->ttw = 0; netif->autoip->ttw = 0;
} else {
autoip_arp_announce(netif);
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | 3,
("autoip_tmr() ANNOUNCING Sent Announce\n"));
netif->autoip->sent_num++;
netif->autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND;
} }
} }
break; break;
@ -397,7 +441,7 @@ autoip_tmr()
void void
autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr) 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)) { if ((netif->autoip != NULL) && (netif->autoip->state != AUTOIP_STATE_OFF)) {
/* when ip.src == llipaddr && hw.src != netif->hwaddr /* 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)) || if ((ip_addr_cmp(&sipaddr, &netif->autoip->llipaddr)) ||
(ip_addr_cmp(&dipaddr, &netif->autoip->llipaddr) && (ip_addr_cmp(&dipaddr, &netif->autoip->llipaddr) &&
!eth_addr_cmp(&netifaddr, &hdr->shwaddr))) { !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_arp_reply(): Probe Conflict detected\n"));
autoip_start(netif); 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) && if (ip_addr_cmp(&sipaddr, &netif->autoip->llipaddr) &&
!eth_addr_cmp(&netifaddr, &hdr->shwaddr)) { !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_arp_reply(): Conflicting ARP-Packet detected\n"));
autoip_handle_arp_conflict(netif); autoip_handle_arp_conflict(netif);
} }

View File

@ -62,40 +62,12 @@
* The interface that provided the packet for the current callback * The interface that provided the packet for the current callback
* invocation. * invocation.
*/ */
static struct netif *current_netif; struct netif *current_netif;
/** /**
* Header of the input packet currently being processed. * Header of the input packet currently being processed.
*/ */
static const struct ip_hdr *current_header; 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;
}
/** /**
* Finds the appropriate network interface for a given IP address. It * 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))) { 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); IP_STATS_INC(ip.rterr);
snmp_inc_ipoutnoroutes(); snmp_inc_ipoutnoroutes();
return NULL; return NULL;
@ -230,7 +202,7 @@ ip_input(struct pbuf *p, struct netif *inp)
/* identify the IP header */ /* identify the IP header */
iphdr = p->payload; iphdr = p->payload;
if (IPH_V(iphdr) != 4) { 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); ip_debug_print(p);
pbuf_free(p); pbuf_free(p);
IP_STATS_INC(ip.err); 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? */ /* 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) || (iphdr_len > p->tot_len)) {
if (iphdr_hlen > p->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", 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)); 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"), " if (iphdr_len > p->tot_len) {
"IP packet dropped.\n", 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)); iphdr_len, p->tot_len));
}
/* free (drop) packet pbufs */ /* free (drop) packet pbufs */
pbuf_free(p); pbuf_free(p);
IP_STATS_INC(ip.lenerr); IP_STATS_INC(ip.lenerr);
@ -267,7 +242,8 @@ ip_input(struct pbuf *p, struct netif *inp)
#if CHECKSUM_CHECK_IP #if CHECKSUM_CHECK_IP
if (inet_chksum(iphdr, iphdr_hlen) != 0) { 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); ip_debug_print(p);
pbuf_free(p); pbuf_free(p);
IP_STATS_INC(ip.chkerr); IP_STATS_INC(ip.chkerr);
@ -336,10 +312,10 @@ ip_input(struct pbuf *p, struct netif *inp)
if (netif == NULL) { if (netif == NULL) {
/* remote port is DHCP server? */ /* remote port is DHCP server? */
if (IPH_PROTO(iphdr) == IP_PROTO_UDP) { 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))); ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen))->dest)));
if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen))->dest) == DHCP_CLIENT_PORT) { 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; netif = inp;
check_ip_src = 0; 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 */ /* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */
#if LWIP_DHCP #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 */ #endif /* LWIP_DHCP */
{ if ((ip_addr_isbroadcast(&(iphdr->src), inp)) || { if ((ip_addr_isbroadcast(&(iphdr->src), inp)) ||
(ip_addr_ismulticast(&(iphdr->src)))) { (ip_addr_ismulticast(&(iphdr->src)))) {
/* packet source is not valid */ /* 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 */ /* free (drop) packet pbufs */
pbuf_free(p); pbuf_free(p);
IP_STATS_INC(ip.drop); IP_STATS_INC(ip.drop);
@ -367,7 +344,7 @@ ip_input(struct pbuf *p, struct netif *inp)
/* packet not for us? */ /* packet not for us? */
if (netif == NULL) { if (netif == NULL) {
/* packet not for us, route or discard */ /* 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 #if IP_FORWARD
/* non-broadcast packet? */ /* non-broadcast packet? */
if (!ip_addr_isbroadcast(&(iphdr->dest), inp)) { if (!ip_addr_isbroadcast(&(iphdr->dest), inp)) {
@ -396,7 +373,7 @@ ip_input(struct pbuf *p, struct netif *inp)
iphdr = p->payload; iphdr = p->payload;
#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */ #else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */
pbuf_free(p); 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)))); ntohs(IPH_OFFSET(iphdr))));
IP_STATS_INC(ip.opterr); IP_STATS_INC(ip.opterr);
IP_STATS_INC(ip.drop); IP_STATS_INC(ip.drop);
@ -414,7 +391,7 @@ ip_input(struct pbuf *p, struct netif *inp)
#else #else
if (iphdr_hlen > IP_HLEN) { if (iphdr_hlen > IP_HLEN) {
#endif /* LWIP_IGMP */ #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); pbuf_free(p);
IP_STATS_INC(ip.opterr); IP_STATS_INC(ip.opterr);
IP_STATS_INC(ip.drop); IP_STATS_INC(ip.drop);
@ -476,7 +453,7 @@ ip_input(struct pbuf *p, struct netif *inp)
#endif /* LWIP_ICMP */ #endif /* LWIP_ICMP */
pbuf_free(p); 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.proterr);
IP_STATS_INC(ip.drop); 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; ip_hlen += optlen_aligned;
/* First write in the IP options */ /* First write in the IP options */
if (pbuf_header(p, optlen_aligned)) { 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); IP_STATS_INC(ip.err);
snmp_inc_ipoutdiscards(); snmp_inc_ipoutdiscards();
return ERR_BUF; 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 */ #endif /* IP_OPTIONS_SEND */
/* generate IP header */ /* generate IP header */
if (pbuf_header(p, IP_HLEN)) { 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); IP_STATS_INC(ip.err);
snmp_inc_ipoutdiscards(); 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); 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); 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)); LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num));
ip_debug_print(p); ip_debug_print(p);
#if (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) #if ENABLE_LOOPBACK
if (ip_addr_cmp(dest, &netif->ip_addr)) { if (ip_addr_cmp(dest, &netif->ip_addr)) {
/* Packet to self, enqueue it for loopback */ /* Packet to self, enqueue it for loopback */
LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()")); LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()"));
return netif_loop_output(netif, p, dest); 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);
} }
/** /**

View File

@ -300,7 +300,7 @@ mem_free(void *rmem)
LWIP_MEM_FREE_DECL_PROTECT(); LWIP_MEM_FREE_DECL_PROTECT();
if (rmem == NULL) { 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; return;
} }
LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0); 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) { if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
SYS_ARCH_DECL_PROTECT(lev); 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 */ /* protect mem stats from concurrent access */
SYS_ARCH_PROTECT(lev); SYS_ARCH_PROTECT(lev);
MEM_STATS_INC(illegal); 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) { if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
SYS_ARCH_DECL_PROTECT(lev); 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 */ /* protect mem stats from concurrent access */
SYS_ARCH_PROTECT(lev); SYS_ARCH_PROTECT(lev);
MEM_STATS_INC(illegal); MEM_STATS_INC(illegal);
@ -599,7 +599,7 @@ mem_malloc(mem_size_t size)
/* if we got interrupted by a mem_free, try again */ /* if we got interrupted by a mem_free, try again */
} while(local_mem_free_count != 0); } while(local_mem_free_count != 0);
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ #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); MEM_STATS_INC(err);
LWIP_MEM_ALLOC_UNPROTECT(); LWIP_MEM_ALLOC_UNPROTECT();
sys_sem_signal(mem_sem); sys_sem_signal(mem_sem);

View File

@ -290,6 +290,10 @@ memp_init(void)
memp_overflow_check_all(); memp_overflow_check_all();
#endif /* MEMP_OVERFLOW_CHECK */ #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. * Get an element from a specific pool.
@ -309,6 +313,7 @@ memp_malloc(memp_t type)
memp_malloc_fn(memp_t type, const char* file, const int line) memp_malloc_fn(memp_t type, const char* file, const int line)
#endif #endif
{ {
#if !MEMP_MEM_MALLOC
struct memp *memp; struct memp *memp;
SYS_ARCH_DECL_PROTECT(old_level); 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); ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0);
memp = (struct memp*)((u8_t*)memp + MEMP_SIZE); memp = (struct memp*)((u8_t*)memp + MEMP_SIZE);
} else { } 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); MEMP_STATS_INC(err, type);
} }
SYS_ARCH_UNPROTECT(old_level); SYS_ARCH_UNPROTECT(old_level);
return memp; 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 void
memp_free(memp_t type, void *mem) memp_free(memp_t type, void *mem)
{ {
#if !MEMP_MEM_MALLOC
struct memp *memp; struct memp *memp;
SYS_ARCH_DECL_PROTECT(old_level); SYS_ARCH_DECL_PROTECT(old_level);
@ -381,6 +415,19 @@ memp_free(memp_t type, void *mem)
#endif /* MEMP_SANITY_CHECK */ #endif /* MEMP_SANITY_CHECK */
SYS_ARCH_UNPROTECT(old_level); 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 */
} }
#endif /* MEMP_MEM_MALLOC */

View File

@ -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);
}

View File

@ -52,6 +52,13 @@
#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
#endif /* ENABLE_LOOPBACK */ #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 #if LWIP_NETIF_STATUS_CALLBACK
#define NETIF_STATUS_CALLBACK(n) { if (n->status_callback) (n->status_callback)(n); } #define NETIF_STATUS_CALLBACK(n) { if (n->status_callback) (n->status_callback)(n); }
#else #else
@ -271,14 +278,14 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
if ((ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0) if ((ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0)
{ {
/* extern struct tcp_pcb *tcp_active_pcbs; defined by tcp.h */ /* 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; pcb = tcp_active_pcbs;
while (pcb != NULL) { while (pcb != NULL) {
/* PCB bound to current local interface address? */ /* PCB bound to current local interface address? */
if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) { if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) {
/* this connection must be aborted */ /* this connection must be aborted */
struct tcp_pcb *next = pcb->next; 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); tcp_abort(pcb);
pcb = next; pcb = next;
} else { } else {
@ -303,7 +310,7 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
snmp_insert_ipaddridx_tree(netif); snmp_insert_ipaddridx_tree(netif);
snmp_insert_iprteidx_tree(0,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], netif->name[0], netif->name[1],
ip4_addr1(&netif->ip_addr), ip4_addr1(&netif->ip_addr),
ip4_addr2(&netif->ip_addr), ip4_addr2(&netif->ip_addr),
@ -323,7 +330,7 @@ void
netif_set_gw(struct netif *netif, struct ip_addr *gw) netif_set_gw(struct netif *netif, struct ip_addr *gw)
{ {
ip_addr_set(&(netif->gw), 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], netif->name[0], netif->name[1],
ip4_addr1(&netif->gw), ip4_addr1(&netif->gw),
ip4_addr2(&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 */ /* set new netmask to netif */
ip_addr_set(&(netif->netmask), netmask); ip_addr_set(&(netif->netmask), netmask);
snmp_insert_iprteidx_tree(0, netif); 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], netif->name[0], netif->name[1],
ip4_addr1(&netif->netmask), ip4_addr1(&netif->netmask),
ip4_addr2(&netif->netmask), ip4_addr2(&netif->netmask),
@ -407,6 +414,12 @@ void netif_set_up(struct netif *netif)
} }
#endif /* LWIP_ARP */ #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; 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 #if LWIP_ARP
/* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */
if (netif->flags & NETIF_FLAG_ETHARP) { if (netif->flags & NETIF_FLAG_ETHARP) {
@ -472,7 +498,7 @@ void netif_set_link_up(struct netif *netif )
igmp_report_groups( netif); igmp_report_groups( netif);
} }
#endif /* LWIP_IGMP */ #endif /* LWIP_IGMP */
}
NETIF_LINK_CALLBACK(netif); NETIF_LINK_CALLBACK(netif);
} }

View File

@ -81,41 +81,71 @@
aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */ aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */
#define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) #define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE)
#if TCP_QUEUE_OOSEQ #if !TCP_QUEUE_OOSEQ || NO_SYS
#define ALLOC_POOL_PBUF(p) do { (p) = alloc_pool_pbuf(); } while (0) #define PBUF_POOL_IS_EMPTY()
#else #else /* !TCP_QUEUE_OOSEQ || NO_SYS */
#define ALLOC_POOL_PBUF(p) do { (p) = memp_malloc(MEMP_PBUF_POOL); } while (0) /** Define this to 0 to prevent freeing ooseq pbufs when the PBUF_POOL is empty */
#endif #ifndef PBUF_POOL_FREE_OOSEQ
#define PBUF_POOL_FREE_OOSEQ 1
#endif /* PBUF_POOL_FREE_OOSEQ */
#if PBUF_POOL_FREE_OOSEQ
#if TCP_QUEUE_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 * 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 run out of pool pbufs. It's better to give priority to new packets
* if we're running out. * 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 * static void
alloc_pool_pbuf(void) pbuf_free_ooseq(void* arg)
{ {
struct tcp_pcb *pcb; struct tcp_pcb* pcb;
struct pbuf *p; SYS_ARCH_DECL_PROTECT(old_level);
LWIP_UNUSED_ARG(arg);
retry: SYS_ARCH_PROTECT(old_level);
p = memp_malloc(MEMP_PBUF_POOL); pbuf_free_ooseq_queued = 0;
if (NULL == p) { SYS_ARCH_UNPROTECT(old_level);
for (pcb=tcp_active_pcbs; NULL != pcb; pcb = pcb->next) {
for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) {
if (NULL != pcb->ooseq) { 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); tcp_segs_free(pcb->ooseq);
pcb->ooseq = NULL; pcb->ooseq = NULL;
goto retry; 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). * 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; struct pbuf *p, *q, *r;
u16_t offset; u16_t offset;
s32_t rem_len; /* remaining length */ 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 */ /* determine header offset */
offset = 0; offset = 0;
@ -181,9 +211,10 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
switch (type) { switch (type) {
case PBUF_POOL: case PBUF_POOL:
/* allocate head of pbuf chain into p */ /* allocate head of pbuf chain into p */
ALLOC_POOL_PBUF(p); p = memp_malloc(MEMP_PBUF_POOL);
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE | 3, ("pbuf_alloc: allocated pbuf %p\n", (void *)p)); LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc: allocated pbuf %p\n", (void *)p));
if (p == NULL) { if (p == NULL) {
PBUF_POOL_IS_EMPTY();
return NULL; return NULL;
} }
p->type = type; p->type = type;
@ -213,8 +244,9 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
rem_len = length - p->len; rem_len = length - p->len;
/* any remaining pbufs to be allocated? */ /* any remaining pbufs to be allocated? */
while (rem_len > 0) { while (rem_len > 0) {
ALLOC_POOL_PBUF(q); q = memp_malloc(MEMP_PBUF_POOL);
if (q == NULL) { if (q == NULL) {
PBUF_POOL_IS_EMPTY();
/* free chain so far allocated */ /* free chain so far allocated */
pbuf_free(p); pbuf_free(p);
/* bail out unsuccesfully */ /* 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 */ /* only allocate memory for the pbuf structure */
p = memp_malloc(MEMP_PBUF); p = memp_malloc(MEMP_PBUF);
if (p == NULL) { 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")); (type == PBUF_ROM) ? "ROM" : "REF"));
return NULL; return NULL;
} }
@ -286,7 +319,7 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
p->ref = 1; p->ref = 1;
/* set flags */ /* set flags */
p->flags = 0; 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; 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; p->payload = (u8_t *)p->payload - header_size_increment;
/* boundary check fails? */ /* boundary check fails? */
if ((u8_t *)p->payload < (u8_t *)p + SIZEOF_STRUCT_PBUF) { 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", LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
(void *)p->payload, ("pbuf_header: failed as %p < %p (not enough space for new header size)\n",
(void *)(p + 1)));\ (void *)p->payload, (void *)(p + 1)));
/* restore old payload pointer */ /* restore old payload pointer */
p->payload = payload; p->payload = payload;
/* bail out unsuccesfully */ /* bail out unsuccesfully */
@ -455,7 +488,7 @@ pbuf_header(struct pbuf *p, s16_t header_size_increment)
p->len += header_size_increment; p->len += header_size_increment;
p->tot_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)); (void *)payload, (void *)p->payload, header_size_increment));
return 0; return 0;
@ -504,10 +537,11 @@ pbuf_free(struct pbuf *p)
if (p == NULL) { if (p == NULL) {
LWIP_ASSERT("p != NULL", p != NULL); LWIP_ASSERT("p != NULL", p != NULL);
/* if assertions are disabled, proceed with debug output */ /* 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; 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; PERF_START;
@ -534,7 +568,7 @@ pbuf_free(struct pbuf *p)
if (ref == 0) { if (ref == 0) {
/* remember next pbuf in chain for next iteration */ /* remember next pbuf in chain for next iteration */
q = p->next; 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; type = p->type;
/* is this a pbuf from the pool? */ /* is this a pbuf from the pool? */
if (type == PBUF_POOL) { if (type == PBUF_POOL) {
@ -552,7 +586,7 @@ pbuf_free(struct pbuf *p)
/* p->ref > 0, this pbuf is still referenced to */ /* p->ref > 0, this pbuf is still referenced to */
/* (and so the remaining pbufs in chain as well) */ /* (and so the remaining pbufs in chain as well) */
} else { } 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 */ /* stop walking through the chain */
p = NULL; p = NULL;
} }
@ -657,7 +691,7 @@ pbuf_chain(struct pbuf *h, struct pbuf *t)
pbuf_cat(h, t); pbuf_cat(h, t);
/* t is now referenced by h */ /* t is now referenced by h */
pbuf_ref(t); 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 */ /* total length of pbuf p is its own length only */
p->tot_len = p->len; p->tot_len = p->len;
/* q is no longer referenced by p, free it */ /* 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); tail_gone = pbuf_free(q);
if (tail_gone > 0) { 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)); ("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q));
} }
/* return remaining tail or NULL if deallocated */ /* 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; 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)); (void*)p_to, (void*)p_from));
/* is the target big enough to hold the source? */ /* 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;); (p_to->next == NULL), return ERR_VAL;);
} }
} while (p_from); } 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; return ERR_OK;
} }

View File

@ -210,7 +210,7 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
struct ip_addr *src_ip; struct ip_addr *src_ip;
struct pbuf *q; /* q will be sent down the stack */ 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? */ /* not enough space to add an IP header to first pbuf in given p chain? */
if (pbuf_header(p, IP_HLEN)) { 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); q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM);
/* new header pbuf could not be allocated? */ /* new header pbuf could not be allocated? */
if (q == NULL) { 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; return ERR_MEM;
} }
/* chain header q in front of given pbuf p */ /* 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) { 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() */ /* free any temporary header pbuf allocated by pbuf_header() */
if (q != p) { if (q != p) {
pbuf_free(q); pbuf_free(q);
@ -246,7 +246,7 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
#if IP_SOF_BROADCAST #if IP_SOF_BROADCAST
/* broadcast filter? */ /* broadcast filter? */
if ( ((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(ipaddr, netif) ) { 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() */ /* free any temporary header pbuf allocated by pbuf_header() */
if (q != p) { if (q != p) {
pbuf_free(q); pbuf_free(q);
@ -335,7 +335,7 @@ struct raw_pcb *
raw_new(u8_t proto) { raw_new(u8_t proto) {
struct raw_pcb *pcb; 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); pcb = memp_malloc(MEMP_RAW_PCB);
/* could allocate RAW PCB? */ /* could allocate RAW PCB? */

View File

@ -2077,25 +2077,25 @@ void snmp_get_snmpenableauthentraps(u8_t *value)
void void
noleafs_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) noleafs_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
{ {
if (ident_len){} LWIP_UNUSED_ARG(ident_len);
if (ident){} LWIP_UNUSED_ARG(ident);
od->instance = MIB_OBJECT_NONE; od->instance = MIB_OBJECT_NONE;
} }
void void
noleafs_get_value(struct obj_def *od, u16_t len, void *value) noleafs_get_value(struct obj_def *od, u16_t len, void *value)
{ {
if (od){} LWIP_UNUSED_ARG(od);
if (len){} LWIP_UNUSED_ARG(len);
if (value){} LWIP_UNUSED_ARG(value);
} }
u8_t u8_t
noleafs_set_test(struct obj_def *od, u16_t len, void *value) noleafs_set_test(struct obj_def *od, u16_t len, void *value)
{ {
if (od){} LWIP_UNUSED_ARG(od);
if (len){} LWIP_UNUSED_ARG(len);
if (value){} LWIP_UNUSED_ARG(value);
/* can't set */ /* can't set */
return 0; return 0;
} }
@ -2103,9 +2103,9 @@ noleafs_set_test(struct obj_def *od, u16_t len, void *value)
void void
noleafs_set_value(struct obj_def *od, u16_t len, void *value) noleafs_set_value(struct obj_def *od, u16_t len, void *value)
{ {
if (od){} LWIP_UNUSED_ARG(od);
if (len){} LWIP_UNUSED_ARG(len);
if (value){} 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; u8_t id, set_ok;
if (value) {} LWIP_UNUSED_ARG(value);
set_ok = 0; set_ok = 0;
id = od->id_inst_ptr[0]; id = od->id_inst_ptr[0];
switch (id) switch (id)
@ -2332,7 +2332,7 @@ interfaces_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
static void static void
interfaces_get_value(struct obj_def *od, u16_t len, void *value) 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) if (od->id_inst_ptr[0] == 1)
{ {
s32_t *sint_ptr = value; 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 ip_addr ip;
struct netif *netif; 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_ifindextonetif(od->id_inst_ptr[1], &netif);
snmp_oidtoip(&od->id_inst_ptr[2], &ip); 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; u8_t id;
if (len) {} LWIP_UNUSED_ARG(len);
id = od->id_inst_ptr[0]; id = od->id_inst_ptr[0];
switch (id) switch (id)
{ {
@ -2985,7 +2986,7 @@ ip_set_test(struct obj_def *od, u16_t len, void *value)
u8_t id, set_ok; u8_t id, set_ok;
s32_t *sint_ptr = value; s32_t *sint_ptr = value;
if (len) {} LWIP_UNUSED_ARG(len);
set_ok = 0; set_ok = 0;
id = od->id_inst_ptr[0]; id = od->id_inst_ptr[0];
switch (id) switch (id)
@ -3065,7 +3066,7 @@ ip_addrentry_get_value(struct obj_def *od, u16_t len, void *value)
struct ip_addr ip; struct ip_addr ip;
struct netif *netif = netif_list; struct netif *netif = netif_list;
if (len) {} LWIP_UNUSED_ARG(len);
snmp_oidtoip(&od->id_inst_ptr[1], &ip); snmp_oidtoip(&od->id_inst_ptr[1], &ip);
ip.addr = htonl(ip.addr); ip.addr = htonl(ip.addr);
ifidx = 0; ifidx = 0;
@ -3408,7 +3409,8 @@ ip_ntomentry_get_value(struct obj_def *od, u16_t len, void *value)
struct ip_addr ip; struct ip_addr ip;
struct netif *netif; 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_ifindextonetif(od->id_inst_ptr[1], &netif);
snmp_oidtoip(&od->id_inst_ptr[2], &ip); 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; u32_t *uint_ptr = value;
u8_t id; u8_t id;
if (len){} LWIP_UNUSED_ARG(len);
id = od->id_inst_ptr[0]; id = od->id_inst_ptr[0];
switch (id) switch (id)
{ {
@ -3636,7 +3638,7 @@ tcp_get_value(struct obj_def *od, u16_t len, void *value)
s32_t *sint_ptr = value; s32_t *sint_ptr = value;
u8_t id; u8_t id;
if (len){} LWIP_UNUSED_ARG(len);
id = od->id_inst_ptr[0]; id = od->id_inst_ptr[0];
switch (id) switch (id)
{ {
@ -3804,7 +3806,7 @@ udp_get_value(struct obj_def *od, u16_t len, void *value)
u32_t *uint_ptr = value; u32_t *uint_ptr = value;
u8_t id; u8_t id;
if (len){} LWIP_UNUSED_ARG(len);
id = od->id_inst_ptr[0]; id = od->id_inst_ptr[0];
switch (id) switch (id)
{ {
@ -3870,7 +3872,7 @@ udpentry_get_value(struct obj_def *od, u16_t len, void *value)
struct ip_addr ip; struct ip_addr ip;
u16_t port; u16_t port;
if (len){} LWIP_UNUSED_ARG(len);
snmp_oidtoip(&od->id_inst_ptr[1], &ip); snmp_oidtoip(&od->id_inst_ptr[1], &ip);
ip.addr = htonl(ip.addr); ip.addr = htonl(ip.addr);
port = od->id_inst_ptr[5]; 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; u32_t *uint_ptr = value;
u8_t id; u8_t id;
if (len){} LWIP_UNUSED_ARG(len);
id = od->id_inst_ptr[0]; id = od->id_inst_ptr[0];
switch (id) switch (id)
{ {
@ -4080,7 +4082,7 @@ snmp_set_test(struct obj_def *od, u16_t len, void *value)
{ {
u8_t id, set_ok; u8_t id, set_ok;
if (len) {} LWIP_UNUSED_ARG(len);
set_ok = 0; set_ok = 0;
id = od->id_inst_ptr[0]; id = od->id_inst_ptr[0];
if (id == 30) if (id == 30)
@ -4113,7 +4115,7 @@ snmp_set_value(struct obj_def *od, u16_t len, void *value)
{ {
u8_t id; u8_t id;
if (len) {} LWIP_UNUSED_ARG(len);
id = od->id_inst_ptr[0]; id = od->id_inst_ptr[0];
if (id == 30) if (id == 30)
{ {

View File

@ -118,7 +118,7 @@ snmp_netiftoifindex(struct netif *netif, s32_t *ifidx)
u16_t i; u16_t i;
i = 0; i = 0;
while (nif != netif) while ((nif != NULL) && (nif != netif))
{ {
nif = nif->next; nif = nif->next;
i++; i++;

View File

@ -97,7 +97,7 @@ sys_mbox_fetch(sys_mbox_t mbox, void **msg)
arg = tmptimeout->arg; arg = tmptimeout->arg;
memp_free(MEMP_SYS_TIMEOUT, tmptimeout); memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
if (h != NULL) { 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); h(arg);
} }
@ -154,7 +154,7 @@ sys_sem_wait(sys_sem_t sem)
arg = tmptimeout->arg; arg = tmptimeout->arg;
memp_free(MEMP_SYS_TIMEOUT, tmptimeout); memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
if (h != NULL) { 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); h(arg);
} }
@ -203,7 +203,7 @@ sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
timeouts = sys_arch_timeouts(); timeouts = sys_arch_timeouts();
LWIP_DEBUGF(SYS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" h=%p arg=%p\n", 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) { if (timeouts == NULL) {
LWIP_ASSERT("sys_timeout: timeouts != NULL", 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)) { if ((t->h == h) && (t->arg == arg)) {
/* We have a match */ /* We have a match */
/* Unlink from previous in list */ /* Unlink from previous in list */
if (prev_t == NULL) if (prev_t == NULL) {
timeouts->next = t->next; timeouts->next = t->next;
else } else {
prev_t->next = t->next; prev_t->next = t->next;
}
/* If not the last one, add time of this one back to 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; t->next->time += t->time;
}
memp_free(MEMP_SYS_TIMEOUT, t); memp_free(MEMP_SYS_TIMEOUT, t);
return; return;
} }

View File

@ -50,9 +50,24 @@
#include "lwip/snmp.h" #include "lwip/snmp.h"
#include "lwip/tcp.h" #include "lwip/tcp.h"
#include "lwip/debug.h" #include "lwip/debug.h"
#include "lwip/stats.h"
#include <string.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). */ /* Incremented every coarse grained timer shot (typically every 500 ms). */
u32_t tcp_ticks; u32_t tcp_ticks;
const u8_t tcp_backoff[13] = 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; 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 */ /* we can advertise more window */
pcb->rcv_ann_wnd = pcb->rcv_wnd; pcb->rcv_ann_wnd = pcb->rcv_wnd;
return new_right_edge - pcb->rcv_ann_right_edge; return new_right_edge - pcb->rcv_ann_right_edge;
@ -564,6 +579,7 @@ tcp_slowtmr(void)
struct tcp_pcb *pcb, *pcb2, *prev; struct tcp_pcb *pcb, *pcb2, *prev;
u16_t eff_wnd; u16_t eff_wnd;
u8_t pcb_remove; /* flag if a PCB should be removed */ 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_t err;
err = ERR_OK; err = ERR_OK;
@ -583,6 +599,7 @@ tcp_slowtmr(void)
LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT); LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT);
pcb_remove = 0; pcb_remove = 0;
pcb_reset = 0;
if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) { if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) {
++pcb_remove; ++pcb_remove;
@ -666,7 +683,8 @@ tcp_slowtmr(void)
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip), ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip))); ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
tcp_abort(pcb); ++pcb_remove;
++pcb_reset;
} }
#if LWIP_TCP_KEEPALIVE #if LWIP_TCP_KEEPALIVE
else if((u32_t)(tcp_ticks - pcb->tmr) > 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); 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; pcb2 = pcb->next;
memp_free(MEMP_TCP_PCB, pcb); 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 * Default receive callback that is called if the user didn't register
* a recv callback for the pcb. * 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) tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{ {
arg = arg; LWIP_UNUSED_ARG(arg);
if (p != NULL) { if (p != NULL) {
tcp_recved(pcb, p->tot_len);
pbuf_free(p); pbuf_free(p);
} else if (err == ERR_OK) { } else if (err == ERR_OK) {
return tcp_close(pcb); return tcp_close(pcb);
@ -993,9 +1016,18 @@ tcp_alloc(u8_t prio)
pcb = memp_malloc(MEMP_TCP_PCB); pcb = memp_malloc(MEMP_TCP_PCB);
if (pcb == NULL) { if (pcb == NULL) {
/* Try killing active connections with lower priority than the new one. */ /* 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); tcp_kill_prio(prio);
/* Try to allocate a tcp_pcb again. */ /* Try to allocate a tcp_pcb again. */
pcb = memp_malloc(MEMP_TCP_PCB); 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) { 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. * Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first.
* *
* @param pcblist PCB list to purge. * @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 void
tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb) 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 */ #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 #if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
/** /**
* Print a tcp header for debugging purposes. * Print a tcp header for debugging purposes.
@ -1333,42 +1371,7 @@ tcp_debug_print(struct tcp_hdr *tcphdr)
void void
tcp_debug_print_state(enum tcp_state s) tcp_debug_print_state(enum tcp_state s)
{ {
LWIP_DEBUGF(TCP_DEBUG, ("State: ")); LWIP_DEBUGF(TCP_DEBUG, ("State: %s\n", tcp_state_str[s]));
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;
}
} }
/** /**

View File

@ -74,7 +74,7 @@ struct tcp_pcb *tcp_input_pcb;
/* Forward declarations. */ /* Forward declarations. */
static err_t tcp_process(struct tcp_pcb *pcb); 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 void tcp_parseopt(struct tcp_pcb *pcb);
static err_t tcp_listen_input(struct tcp_pcb_listen *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; return;
} }
} }
tcp_input_pcb = pcb; tcp_input_pcb = pcb;
err = tcp_process(pcb); err = tcp_process(pcb);
tcp_input_pcb = NULL;
/* A return value of ERR_ABRT means that tcp_abort() was called /* 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. */ and that the pcb has been freed. If so, we don't do anything. */
if (err != ERR_ABRT) { if (err != ERR_ABRT) {
@ -338,12 +336,17 @@ tcp_input(struct pbuf *p, struct netif *inp)
TCP_EVENT_RECV(pcb, NULL, ERR_OK, err); TCP_EVENT_RECV(pcb, NULL, ERR_OK, err);
} }
/* If there were no errors, we try to send something out. */ tcp_input_pcb = NULL;
if (err == ERR_OK) { /* Try to send something out. */
tcp_output(pcb); 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 */ /* give up our reference to inseg.p */
@ -352,12 +355,6 @@ tcp_input(struct pbuf *p, struct netif *inp)
pbuf_free(inseg.p); pbuf_free(inseg.p);
inseg.p = NULL; inseg.p = NULL;
} }
#if TCP_INPUT_DEBUG
#if TCP_DEBUG
tcp_debug_print_state(pcb->state);
#endif /* TCP_DEBUG */
#endif /* TCP_INPUT_DEBUG */
} else { } else {
/* If no matching PCB was found, send a TCP RST (reset) to the /* 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 static err_t
tcp_timewait_input(struct tcp_pcb *pcb) tcp_timewait_input(struct tcp_pcb *pcb)
{ {
if (TCP_SEQ_GT(seqno + tcplen, pcb->rcv_nxt)) { /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */
pcb->rcv_nxt = seqno + tcplen; /* 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) { /* - fourth, check the SYN bit, */
tcp_ack_now(pcb); 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;
}
if ((tcplen > 0)) {
/* Acknowledge data, FIN or out-of-window SYN */
pcb->flags |= TF_ACK_NOW;
return tcp_output(pcb); 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. */ * we'd better pass it on to the application as well. */
tcp_receive(pcb); 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); pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
if (recv_flags & TF_GOT_FIN) { if (recv_flags & TF_GOT_FIN) {
@ -660,7 +685,7 @@ tcp_process(struct tcp_pcb *pcb)
if (recv_flags & TF_GOT_FIN) { if (recv_flags & TF_GOT_FIN) {
if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) { if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
LWIP_DEBUGF(TCP_DEBUG, 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_ack_now(pcb);
tcp_pcb_purge(pcb); tcp_pcb_purge(pcb);
TCP_RMV(&tcp_active_pcbs, pcb); TCP_RMV(&tcp_active_pcbs, pcb);
@ -677,7 +702,7 @@ tcp_process(struct tcp_pcb *pcb)
case FIN_WAIT_2: case FIN_WAIT_2:
tcp_receive(pcb); tcp_receive(pcb);
if (recv_flags & TF_GOT_FIN) { 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_ack_now(pcb);
tcp_pcb_purge(pcb); tcp_pcb_purge(pcb);
TCP_RMV(&tcp_active_pcbs, pcb); TCP_RMV(&tcp_active_pcbs, pcb);
@ -688,7 +713,7 @@ tcp_process(struct tcp_pcb *pcb)
case CLOSING: case CLOSING:
tcp_receive(pcb); tcp_receive(pcb);
if (flags & TCP_ACK && ackno == pcb->snd_nxt) { 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_pcb_purge(pcb);
TCP_RMV(&tcp_active_pcbs, pcb); TCP_RMV(&tcp_active_pcbs, pcb);
pcb->state = TIME_WAIT; pcb->state = TIME_WAIT;
@ -698,7 +723,7 @@ tcp_process(struct tcp_pcb *pcb)
case LAST_ACK: case LAST_ACK:
tcp_receive(pcb); tcp_receive(pcb);
if (flags & TCP_ACK && ackno == pcb->snd_nxt) { 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 */ /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */
recv_flags |= TF_CLOSED; recv_flags |= TF_CLOSED;
} }
@ -709,6 +734,47 @@ tcp_process(struct tcp_pcb *pcb)
return ERR_OK; 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 * 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 * 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. * estimation, the RTT is estimated here as well.
* *
* Called from tcp_process(). * 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) tcp_receive(struct tcp_pcb *pcb)
{ {
struct tcp_seg *next; struct tcp_seg *next;
@ -735,7 +799,7 @@ tcp_receive(struct tcp_pcb *pcb)
s16_t m; s16_t m;
u32_t right_wnd_edge; u32_t right_wnd_edge;
u16_t new_tot_len; u16_t new_tot_len;
u8_t accepted_inseq = 0; int found_dupack = 0;
if (flags & TCP_ACK) { if (flags & TCP_ACK) {
right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2; right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2;
@ -762,47 +826,58 @@ tcp_receive(struct tcp_pcb *pcb)
#endif /* TCP_WND_DEBUG */ #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; pcb->acked = 0;
/* Clause 2 */
if (tcplen == 0) {
/* Clause 3 */
if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge){ 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; ++pcb->dupacks;
if (pcb->dupacks >= 3 && pcb->unacked != NULL) { if (pcb->dupacks > 3) {
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 /* Inflate the congestion window, but not if it means that
the value overflows. */ the value overflows. */
if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
pcb->cwnd += pcb->mss; 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)){ } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){
/* We come here when the ACK acknowledges new data. */ /* We come here when the ACK acknowledges new data. */
@ -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_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))); 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); pcb->snd_queuelen -= pbuf_clen(next->p);
tcp_seg_free(next); tcp_seg_free(next);
@ -908,6 +988,10 @@ tcp_receive(struct tcp_pcb *pcb)
pcb->unsent = pcb->unsent->next; pcb->unsent = pcb->unsent->next;
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); 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))); 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); pcb->snd_queuelen -= pbuf_clen(next->p);
tcp_seg_free(next); tcp_seg_free(next);
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen)); 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, if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
pcb->rcv_nxt + pcb->rcv_wnd - 1)){ pcb->rcv_nxt + pcb->rcv_wnd - 1)){
if (pcb->rcv_nxt == seqno) { if (pcb->rcv_nxt == seqno) {
accepted_inseq = 1;
/* The incoming segment is the next in sequence. We check if /* The incoming segment is the next in sequence. We check if
we have to trim the end of the segment and update rcv_nxt we have to trim the end of the segment and update rcv_nxt
and pass the data to the application. */ 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")); ("tcp_receive: received in-order FIN, binning ooseq queue\n"));
/* Received in-order FIN means anything that was received /* Received in-order FIN means anything that was received
* out of order must now have been received in-order, so * 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) { while (pcb->ooseq != NULL) {
struct tcp_seg *old_ooseq = pcb->ooseq; struct tcp_seg *old_ooseq = pcb->ooseq;
pcb->ooseq = pcb->ooseq->next; 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) { else {
/* We have to trim the second edge of the incoming segment. */ struct tcp_seg* next = pcb->ooseq;
LWIP_ASSERT("tcp_receive: trimmed segment would have zero length\n", struct tcp_seg *old_seg;
TCP_SEQ_GT(pcb->ooseq->tcphdr->seqno, seqno)); /* 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 */ /* FIN in inseg already handled by dropping whole ooseq queue */
inseg.len = (u16_t)(pcb->ooseq->tcphdr->seqno - seqno); inseg.len = (u16_t)(pcb->ooseq->tcphdr->seqno - seqno);
if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
@ -1104,15 +1215,8 @@ tcp_receive(struct tcp_pcb *pcb)
tcplen = TCP_TCPLEN(&inseg); tcplen = TCP_TCPLEN(&inseg);
LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n", LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n",
(seqno + tcplen) == pcb->ooseq->tcphdr->seqno); (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 */ #endif /* TCP_QUEUE_OOSEQ */
@ -1180,7 +1284,6 @@ tcp_receive(struct tcp_pcb *pcb)
} }
} }
pcb->ooseq = cseg->next; pcb->ooseq = cseg->next;
tcp_seg_free(cseg); tcp_seg_free(cseg);
} }
@ -1192,7 +1295,7 @@ tcp_receive(struct tcp_pcb *pcb)
} else { } else {
/* We get here if the incoming segment is out-of-sequence. */ /* We get here if the incoming segment is out-of-sequence. */
tcp_ack_now(pcb); tcp_send_empty_ack(pcb);
#if TCP_QUEUE_OOSEQ #if TCP_QUEUE_OOSEQ
/* We queue the segment on the ->ooseq queue. */ /* We queue the segment on the ->ooseq queue. */
if (pcb->ooseq == NULL) { if (pcb->ooseq == NULL) {
@ -1219,25 +1322,16 @@ tcp_receive(struct tcp_pcb *pcb)
discard. */ discard. */
if (inseg.len > next->len) { if (inseg.len > next->len) {
/* The incoming segment is larger than the old /* 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. */ one. */
cseg = tcp_seg_copy(&inseg); cseg = tcp_seg_copy(&inseg);
if (cseg != NULL) { if (cseg != NULL) {
cseg->next = next->next;
if (prev != NULL) { if (prev != NULL) {
prev->next = cseg; prev->next = cseg;
} else { } else {
pcb->ooseq = cseg; pcb->ooseq = cseg;
} }
tcp_seg_free(next); tcp_oos_insert_segment(cseg, 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);
}
}
} }
break; break;
} else { } else {
@ -1253,51 +1347,44 @@ tcp_receive(struct tcp_pcb *pcb)
than the sequence number of the first segment on the than the sequence number of the first segment on the
queue. We put the incoming segment first on the queue. We put the incoming segment first on the
queue. */ 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); cseg = tcp_seg_copy(&inseg);
if (cseg != NULL) { if (cseg != NULL) {
cseg->next = next;
pcb->ooseq = cseg; pcb->ooseq = cseg;
tcp_oos_insert_segment(cseg, next);
} }
break; break;
} }
} else } else {
/*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) && /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) &&
TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/ TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/
if(TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)){ if (TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)) {
/* The sequence number of the incoming segment is in /* The sequence number of the incoming segment is in
between the sequence numbers of the previous and between the sequence numbers of the previous and
the next segment on ->ooseq. We trim and insert the the next segment on ->ooseq. We trim trim the previous
incoming segment and trim the previous segment, if segment, delete next segments that included in received segment
needed. */ and trim received, 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); cseg = tcp_seg_copy(&inseg);
if (cseg != NULL) { if (cseg != NULL) {
cseg->next = next;
prev->next = cseg;
if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) { if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) {
/* We need to trim the prev segment. */ /* We need to trim the prev segment. */
prev->len = (u16_t)(seqno - prev->tcphdr->seqno); prev->len = (u16_t)(seqno - prev->tcphdr->seqno);
pbuf_realloc(prev->p, prev->len); 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 /* If the "next" segment is the last segment on the
ooseq queue, we add the incoming segment to the end ooseq queue, we add the incoming segment to the end
of the list. */ of the list. */
if (next->next == NULL && if (next->next == NULL &&
TCP_SEQ_GT(seqno, next->tcphdr->seqno)) { 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); next->next = tcp_seg_copy(&inseg);
if (next->next != NULL) { if (next->next != NULL) {
if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) { if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) {
@ -1316,7 +1403,8 @@ tcp_receive(struct tcp_pcb *pcb)
} }
} else { } else {
tcp_ack_now(pcb); /* The incoming segment is not withing the window. */
tcp_send_empty_ack(pcb);
} }
} else { } else {
/* Segments with length 0 is taken care of here. Segments that /* 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); tcp_ack_now(pcb);
} }
} }
return accepted_inseq;
} }
/** /**

View File

@ -132,7 +132,7 @@ tcp_write(struct tcp_pcb *pcb, const void *data, u16_t len, u8_t apiflags)
} }
return ERR_OK; return ERR_OK;
} else { } 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; return ERR_CONN;
} }
} }
@ -174,7 +174,8 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
/* fail on too much data */ /* fail on too much data */
if (len > pcb->snd_buf) { 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; pcb->flags |= TF_NAGLEMEMERR;
return ERR_MEM; return ERR_MEM;
} }
@ -194,7 +195,8 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
queuelen = pcb->snd_queuelen; queuelen = pcb->snd_queuelen;
/* check for configured max queuelen and possible overflow */ /* check for configured max queuelen and possible overflow */
if ((queuelen >= TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_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); TCP_STATS_INC(tcp.memerr);
pcb->flags |= TF_NAGLEMEMERR; pcb->flags |= TF_NAGLEMEMERR;
return ERR_MEM; 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. */ /* Allocate memory for tcp_seg, and fill in fields. */
seg = memp_malloc(MEMP_TCP_SEG); seg = memp_malloc(MEMP_TCP_SEG);
if (seg == NULL) { 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")); ("tcp_enqueue: could not allocate memory for tcp_seg\n"));
goto memerr; 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. */ * ROM or other static memory, and need not be copied. */
if (apiflags & TCP_WRITE_FLAG_COPY) { if (apiflags & TCP_WRITE_FLAG_COPY) {
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen + optlen, PBUF_RAM)) == NULL) { 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)); ("tcp_enqueue : could not allocate memory for pbuf copy size %"U16_F"\n", seglen));
goto memerr; goto memerr;
} }
@ -259,7 +261,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
else { else {
/* First, allocate a pbuf for the headers. */ /* First, allocate a pbuf for the headers. */
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) { 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")); ("tcp_enqueue: could not allocate memory for header pbuf\n"));
goto memerr; 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. */ /* If allocation fails, we have to deallocate the header pbuf as well. */
pbuf_free(seg->p); pbuf_free(seg->p);
seg->p = NULL; 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")); ("tcp_enqueue: could not allocate memory for zero-copy pbuf\n"));
goto memerr; 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 /* Now that there are more segments queued, we check again if the
length of the queue exceeds the configured maximum or overflows. */ length of the queue exceeds the configured maximum or overflows. */
if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { 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; goto memerr;
} }
@ -301,7 +304,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
/* build TCP header */ /* build TCP header */
if (pbuf_header(seg->p, TCP_HLEN)) { 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); TCP_STATS_INC(tcp.err);
goto memerr; goto memerr;
} }
@ -343,11 +346,13 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
if (useg != NULL && if (useg != NULL &&
TCP_TCPLEN(useg) != 0 && TCP_TCPLEN(useg) != 0 &&
!(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) && !(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 */ /* fit within max seg size */
(useg->len + queue->len <= pcb->mss) && (useg->len + queue->len <= pcb->mss) &&
/* only concatenate segments with the same options */ /* 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 */ /* Remove TCP header from first segment of our to-be-queued list */
if(pbuf_header(queue->p, -(TCP_HLEN + optlen))) { if(pbuf_header(queue->p, -(TCP_HLEN + optlen))) {
/* Can we cope with this failing? Just assert for now */ /* 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--; queuelen--;
pbuf_free(old_q); pbuf_free(old_q);
} }
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)); LWIP_ASSERT("zero-length pbuf", (queue->p != NULL) && (queue->p->len > 0));
pbuf_cat(useg->p, queue->p); pbuf_cat(useg->p, queue->p);
useg->len += queue->len; useg->len += queue->len;
useg->next = queue->next; 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)); 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) { if (seg == queue) {
@ -443,56 +454,21 @@ tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts)
} }
#endif #endif
/** Send an ACK without data.
/**
* Find out what we can send and send it
* *
* @param pcb Protocol control block for the TCP connection to send data * @param pcb Protocol control block for the TCP connection to send the ACK
* @return ERR_OK if data has been sent or nothing to send
* another err_t on error
*/ */
err_t err_t
tcp_output(struct tcp_pcb *pcb) tcp_send_empty_ack(struct tcp_pcb *pcb)
{ {
struct pbuf *p; struct pbuf *p;
struct tcp_hdr *tcphdr; 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; 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
input processing code to call us when input processing is done
with. */
if (tcp_input_pcb == pcb) {
return ERR_OK;
}
wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
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.
*
* If data is to be sent, we will just piggyback the ACK (see below).
*/
if (pcb->flags & TF_ACK_NOW &&
(seg == NULL ||
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
#if LWIP_TCP_TIMESTAMPS #if LWIP_TCP_TIMESTAMPS
if (pcb->flags & TF_TIMESTAMP) if (pcb->flags & TF_TIMESTAMP) {
optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS); optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
}
#endif #endif
p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen, PBUF_RAM); p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen, PBUF_RAM);
if (p == NULL) { if (p == NULL) {
@ -510,8 +486,9 @@ tcp_output(struct tcp_pcb *pcb)
#if LWIP_TCP_TIMESTAMPS #if LWIP_TCP_TIMESTAMPS
pcb->ts_lastacksent = pcb->rcv_nxt; pcb->ts_lastacksent = pcb->rcv_nxt;
if (pcb->flags & TF_TIMESTAMP) if (pcb->flags & TF_TIMESTAMP) {
tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1)); tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1));
}
#endif #endif
#if CHECKSUM_GEN_TCP #if CHECKSUM_GEN_TCP
@ -528,6 +505,52 @@ tcp_output(struct tcp_pcb *pcb)
pbuf_free(p); pbuf_free(p);
return ERR_OK; return ERR_OK;
}
/**
* Find out what we can send and send it
*
* @param pcb Protocol control block for the TCP connection to send data
* @return ERR_OK if data has been sent or nothing to send
* another err_t on error
*/
err_t
tcp_output(struct tcp_pcb *pcb)
{
struct tcp_seg *seg, *useg;
u32_t wnd, snd_nxt;
#if TCP_CWND_DEBUG
s16_t i = 0;
#endif /* TCP_CWND_DEBUG */
/* First, check if we are invoked by the TCP input processing
code. If so, we do not output anything. Instead, we rely on the
input processing code to call us when input processing is done
with. */
if (tcp_input_pcb == pcb) {
return ERR_OK;
}
wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
seg = pcb->unsent;
/* 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.
*
* If data is to be sent, we will just piggyback the ACK (see below).
*/
if (pcb->flags & TF_ACK_NOW &&
(seg == NULL ||
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
return tcp_send_empty_ack(pcb);
}
/* 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 #if TCP_OUTPUT_DEBUG
@ -853,9 +876,50 @@ tcp_rexmit(struct tcp_pcb *pcb)
/* Do the actual retransmission. */ /* Do the actual retransmission. */
snmp_inc_tcpretranssegs(); 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 * Send keepalive packets to keep a connection active although
* no data is sent over it. * no data is sent over it.
@ -924,6 +988,8 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
struct pbuf *p; struct pbuf *p;
struct tcp_hdr *tcphdr; struct tcp_hdr *tcphdr;
struct tcp_seg *seg; struct tcp_seg *seg;
u16_t len;
u8_t is_fin;
LWIP_DEBUGF(TCP_DEBUG, LWIP_DEBUGF(TCP_DEBUG,
("tcp_zero_window_probe: sending ZERO WINDOW probe to %" ("tcp_zero_window_probe: sending ZERO WINDOW probe to %"
@ -944,8 +1010,10 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
if(seg == NULL) if(seg == NULL)
return; 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) { if(p == NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n")); LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n"));
return; return;
@ -955,8 +1023,13 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
tcphdr = tcp_output_set_header(pcb, p, 0, seg->tcphdr->seqno); tcphdr = tcp_output_set_header(pcb, p, 0, seg->tcphdr->seqno);
/* Copy in one byte from the head of the unacked queue */ 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; *((char *)p->payload + sizeof(struct tcp_hdr)) = *(char *)seg->dataptr;
}
#if CHECKSUM_GEN_TCP #if CHECKSUM_GEN_TCP
tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip,

View File

@ -241,7 +241,7 @@ udp_input(struct pbuf *p, struct netif *inp)
if (inet_chksum_pseudo_partial(p, (struct ip_addr *)&(iphdr->src), if (inet_chksum_pseudo_partial(p, (struct ip_addr *)&(iphdr->src),
(struct ip_addr *)&(iphdr->dest), (struct ip_addr *)&(iphdr->dest),
IP_PROTO_UDPLITE, p->tot_len, chklen) != 0) { IP_PROTO_UDPLITE, p->tot_len, chklen) != 0) {
LWIP_DEBUGF(UDP_DEBUG | 2, LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
("udp_input: UDP Lite datagram discarded due to failing checksum\n")); ("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
UDP_STATS_INC(udp.chkerr); UDP_STATS_INC(udp.chkerr);
UDP_STATS_INC(udp.drop); UDP_STATS_INC(udp.drop);
@ -258,7 +258,7 @@ udp_input(struct pbuf *p, struct netif *inp)
if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src), if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
(struct ip_addr *)&(iphdr->dest), (struct ip_addr *)&(iphdr->dest),
IP_PROTO_UDP, p->tot_len) != 0) { 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_input: UDP datagram discarded due to failing checksum\n"));
UDP_STATS_INC(udp.chkerr); UDP_STATS_INC(udp.chkerr);
UDP_STATS_INC(udp.drop); UDP_STATS_INC(udp.drop);
@ -282,7 +282,7 @@ udp_input(struct pbuf *p, struct netif *inp)
/* callback */ /* callback */
if (pcb->recv != NULL) { if (pcb->recv != NULL) {
/* now the recv function is responsible for freeing p */ /* 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 { } else {
/* no recv function registered? then we have to free the pbuf! */ /* no recv function registered? then we have to free the pbuf! */
pbuf_free(p); pbuf_free(p);
@ -362,7 +362,7 @@ udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
{ {
struct netif *netif; 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 */ /* find the outgoing network interface for this packet */
#if LWIP_IGMP #if LWIP_IGMP
@ -373,7 +373,7 @@ udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
/* no outgoing network interface could be found? */ /* no outgoing network interface could be found? */
if (netif == NULL) { 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); UDP_STATS_INC(udp.rterr);
return ERR_RTE; return ERR_RTE;
} }
@ -411,17 +411,18 @@ udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
#if IP_SOF_BROADCAST #if IP_SOF_BROADCAST
/* broadcast filter? */ /* broadcast filter? */
if ( ((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(dst_ip, netif) ) { 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; return ERR_VAL;
} }
#endif /* IP_SOF_BROADCAST */ #endif /* IP_SOF_BROADCAST */
/* if the PCB is not yet bound to a port, bind it here */ /* if the PCB is not yet bound to a port, bind it here */
if (pcb->local_port == 0) { 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); err = udp_bind(pcb, &pcb->local_ip, pcb->local_port);
if (err != ERR_OK) { 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; 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); q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM);
/* new header pbuf could not be allocated? */ /* new header pbuf could not be allocated? */
if (q == NULL) { 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; return ERR_MEM;
} }
/* chain header q in front of given pbuf p */ /* 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; struct udp_pcb *ipcb;
u8_t rebind; 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); 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; rebind = 0;
/* Check for double bind and rebind of the same pcb */ /* Check for double bind and rebind of the same pcb */

View File

@ -52,6 +52,10 @@
#include "lwip/udp.h" #include "lwip/udp.h"
#include "netif/etharp.h" #include "netif/etharp.h"
#ifdef __cplusplus
extern "C" {
#endif
/* AutoIP Timing */ /* AutoIP Timing */
#define AUTOIP_TMR_INTERVAL 100 #define AUTOIP_TMR_INTERVAL 100
#define AUTOIP_TICKS_PER_SECOND (1000 / AUTOIP_TMR_INTERVAL) #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 */ /** Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds */
void autoip_tmr(void); 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 */
#endif /* __LWIP_AUTOIP_H__ */ #endif /* __LWIP_AUTOIP_H__ */

View File

@ -33,9 +33,6 @@
#define __LWIP_ICMP_H__ #define __LWIP_ICMP_H__
#include "lwip/opt.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/pbuf.h"
#include "lwip/ip_addr.h" #include "lwip/ip_addr.h"
#include "lwip/netif.h" #include "lwip/netif.h"
@ -70,11 +67,6 @@ enum icmp_te_type {
ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */ 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 #ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h" # include "arch/bpstruct.h"
#endif #endif
@ -103,10 +95,17 @@ PACK_STRUCT_END
#define ICMPH_TYPE_SET(hdr, t) ((hdr)->type = (t)) #define ICMPH_TYPE_SET(hdr, t) ((hdr)->type = (t))
#define ICMPH_CODE_SET(hdr, c) ((hdr)->code = (c)) #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 #ifdef __cplusplus
} }
#endif #endif
#endif /* LWIP_ICMP */
#endif /* __LWIP_ICMP_H__ */ #endif /* __LWIP_ICMP_H__ */

View File

@ -153,6 +153,11 @@ PACK_STRUCT_END
#define IPH_PROTO_SET(hdr, proto) (hdr)->_ttl_proto = (htons((proto) | (IPH_TTL(hdr) << 8))) #define IPH_PROTO_SET(hdr, proto) (hdr)->_ttl_proto = (htons((proto) | (IPH_TTL(hdr) << 8)))
#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum) #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. */ #define ip_init() /* Compatibility define, not init needed. */
struct netif *ip_route(struct ip_addr *dest); struct netif *ip_route(struct ip_addr *dest);
err_t ip_input(struct pbuf *p, struct netif *inp); 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, u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options,
u16_t optlen); u16_t optlen);
#endif /* IP_OPTIONS_SEND */ #endif /* IP_OPTIONS_SEND */
struct netif *ip_current_netif(void); /** Get the interface that received the current packet.
const struct ip_hdr *ip_current_header(void); * 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 #if IP_DEBUG
void ip_debug_print(struct pbuf *p); void ip_debug_print(struct pbuf *p);
#else #else

View File

@ -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_addr3(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff)
#define ip4_addr4(ipaddr) ((u16_t)(ntohl((ipaddr)->addr)) & 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 #ifdef __cplusplus
} }
#endif #endif

View File

@ -83,7 +83,7 @@ struct api_msg_msg {
size_t len; size_t len;
u8_t apiflags; u8_t apiflags;
} w; } w;
/** used ofr do_recv */ /** used for do_recv */
struct { struct {
u16_t len; u16_t len;
} r; } r;

View File

@ -35,12 +35,13 @@
#include "lwip/arch.h" #include "lwip/arch.h"
/** lower two bits indicate debug level /** lower two bits indicate debug level
* - 0 off * - 0 all
* - 1 warning * - 1 warning
* - 2 serious * - 2 serious
* - 3 severe * - 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_WARNING 0x01 /* bad checksums, dropped packets, ... */
#define LWIP_DBG_LEVEL_SERIOUS 0x02 /* memory allocation failures, ... */ #define LWIP_DBG_LEVEL_SERIOUS 0x02 /* memory allocation failures, ... */
#define LWIP_DBG_LEVEL_SEVERE 0x03 #define LWIP_DBG_LEVEL_SEVERE 0x03

View File

@ -24,22 +24,20 @@ extern "C" {
struct dhcp struct dhcp
{ {
/** current DHCP state machine state */
u8_t state;
/** retries of current request */
u8_t tries;
/** transaction identifier of last sent request */ /** transaction identifier of last sent request */
u32_t xid; u32_t xid;
/** our connection to the DHCP server */ /** our connection to the DHCP server */
struct udp_pcb *pcb; struct udp_pcb *pcb;
/** (first) pbuf of incoming msg */
struct pbuf *p;
/** incoming msg */ /** incoming msg */
struct dhcp_msg *msg_in; struct dhcp_msg *msg_in;
/** incoming msg options */ /** incoming msg options */
struct dhcp_msg *options_in; void *options_in;
/** ingoing msg options length */ /** ingoing msg options length */
u16_t options_in_len; 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 pbuf *p_out; /* pbuf of outcoming msg */
struct dhcp_msg *msg_out; /* outgoing 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); void dhcp_stop(struct netif *netif);
/** inform server of our manual IP address */ /** inform server of our manual IP address */
void dhcp_inform(struct netif *netif); 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 enabled, check whether the offered IP address is not in use, using ARP */
#if DHCP_DOES_ARP_CHECK #if DHCP_DOES_ARP_CHECK

View File

@ -43,7 +43,7 @@ extern "C" {
/** x.X.x: Minor version of the stack */ /** x.X.x: Minor version of the stack */
#define LWIP_VERSION_MINOR 3U #define LWIP_VERSION_MINOR 3U
/** x.x.X: Revision of the stack */ /** 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 release candidates, this is set to 1..254
* For official releases, this is set to 255 (LWIP_RC_RELEASE) * For official releases, this is set to 255 (LWIP_RC_RELEASE)
* For development versions (CVS), this is set to 0 (LWIP_RC_DEVELOPMENT) */ * For development versions (CVS), this is set to 0 (LWIP_RC_DEVELOPMENT) */

View File

@ -84,8 +84,6 @@ extern const u16_t memp_sizes[MEMP_MAX];
#include "mem.h" #include "mem.h"
#define memp_init() #define memp_init()
#define memp_malloc(type) mem_malloc(memp_sizes[type])
#define memp_free(type, mem) mem_free(mem)
#else /* MEMP_MEM_MALLOC */ #else /* MEMP_MEM_MALLOC */
@ -98,6 +96,7 @@ struct memp_malloc_helper
#endif /* MEM_USE_POOLS */ #endif /* MEM_USE_POOLS */
void memp_init(void); void memp_init(void);
#endif /* MEMP_MEM_MALLOC */
#if MEMP_OVERFLOW_CHECK #if MEMP_OVERFLOW_CHECK
void *memp_malloc_fn(memp_t type, const char* file, const int line); void *memp_malloc_fn(memp_t type, const char* file, const int line);
@ -107,8 +106,6 @@ void *memp_malloc(memp_t type);
#endif #endif
void memp_free(memp_t type, void *mem); void memp_free(memp_t type, void *mem);
#endif /* MEMP_MEM_MALLOC */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -34,6 +34,7 @@
#include "lwip/opt.h" #include "lwip/opt.h"
#include "lwip/pbuf.h" #include "lwip/pbuf.h"
#include "lwip/ip_addr.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -43,6 +44,10 @@ struct netbuf {
struct pbuf *p, *ptr; struct pbuf *p, *ptr;
struct ip_addr *addr; struct ip_addr *addr;
u16_t port; u16_t port;
#if LWIP_NETBUF_RECVINFO
struct ip_addr *toaddr;
u16_t toport;
#endif /* LWIP_NETBUF_RECVINFO */
}; };
/* Network buffer functions: */ /* Network buffer functions: */
@ -69,6 +74,10 @@ void netbuf_first (struct netbuf *buf);
#define netbuf_len(buf) ((buf)->p->tot_len) #define netbuf_len(buf) ((buf)->p->tot_len)
#define netbuf_fromaddr(buf) ((buf)->addr) #define netbuf_fromaddr(buf) ((buf)->addr)
#define netbuf_fromport(buf) ((buf)->port) #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 #ifdef __cplusplus
} }

View File

@ -103,7 +103,7 @@ int lwip_getaddrinfo(const char *nodename,
#define gethostbyname(name) lwip_gethostbyname(name) #define gethostbyname(name) lwip_gethostbyname(name)
#define gethostbyname_r(name, ret, buf, buflen, result, h_errnop) \ #define gethostbyname_r(name, ret, buf, buflen, result, h_errnop) \
lwip_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) \ #define getaddrinfo(nodname, servname, hints, res) \
lwip_getaddrinfo(nodname, servname, hints, res) lwip_getaddrinfo(nodname, servname, hints, res)
#endif /* LWIP_COMPAT_SOCKETS */ #endif /* LWIP_COMPAT_SOCKETS */

View File

@ -131,12 +131,12 @@ struct netif {
/* the hostname for this netif, NULL is a valid value */ /* the hostname for this netif, NULL is a valid value */
char* hostname; char* hostname;
#endif /* LWIP_NETIF_HOSTNAME */ #endif /* LWIP_NETIF_HOSTNAME */
/** maximum transfer unit (in bytes) */
u16_t mtu;
/** number of bytes used in hwaddr */ /** number of bytes used in hwaddr */
u8_t hwaddr_len; u8_t hwaddr_len;
/** link level hardware address of this interface */ /** link level hardware address of this interface */
u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; u8_t hwaddr[NETIF_MAX_HWADDR_LEN];
/** maximum transfer unit (in bytes) */
u16_t mtu;
/** flags (see NETIF_FLAG_ above) */ /** flags (see NETIF_FLAG_ above) */
u8_t flags; u8_t flags;
/** descriptive abbreviation */ /** descriptive abbreviation */

View File

@ -78,6 +78,11 @@ err_t netifapi_netif_add ( struct netif *netif,
err_t (* init)(struct netif *netif), err_t (* init)(struct netif *netif),
err_t (* input)(struct pbuf *p, 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, err_t netifapi_netif_common ( struct netif *netif,
void (* voidfunc)(struct netif *netif), void (* voidfunc)(struct netif *netif),
err_t (* errtfunc)(struct netif *netif) ); err_t (* errtfunc)(struct netif *netif) );

View File

@ -366,6 +366,16 @@
#define ETHARP_TRUST_IP_MAC 1 #define ETHARP_TRUST_IP_MAC 1
#endif #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 ---------- ---------- IP options ----------
@ -718,6 +728,13 @@
#define UDP_TTL (IP_DEFAULT_TTL) #define UDP_TTL (IP_DEFAULT_TTL)
#endif #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 ---------- ---------- TCP options ----------
@ -742,7 +759,7 @@
* (2 * TCP_MSS) for things to work well * (2 * TCP_MSS) for things to work well
*/ */
#ifndef TCP_WND #ifndef TCP_WND
#define TCP_WND 2048 #define TCP_WND (4 * TCP_MSS)
#endif #endif
/** /**
@ -768,14 +785,14 @@
#endif #endif
/** /**
* TCP_MSS: TCP Maximum segment size. (default is 128, a *very* * TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default,
* conservative default.) * you might want to increase this.)
* For the receive side, this MSS is advertised to the remote side * For the receive side, this MSS is advertised to the remote side
* when opening a connection. For the transmit size, this MSS sets * when opening a connection. For the transmit size, this MSS sets
* an upper limit on the MSS advertised by the remote host. * an upper limit on the MSS advertised by the remote host.
*/ */
#ifndef TCP_MSS #ifndef TCP_MSS
#define TCP_MSS 128 #define TCP_MSS 536
#endif #endif
/** /**
@ -803,7 +820,7 @@
* as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. * as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work.
*/ */
#ifndef TCP_SND_QUEUELEN #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 #endif
/** /**
@ -812,7 +829,7 @@
* TCP snd_buf for select to return writable. * TCP snd_buf for select to return writable.
*/ */
#ifndef TCP_SNDLOWAT #ifndef TCP_SNDLOWAT
#define TCP_SNDLOWAT (TCP_SND_BUF/2) #define TCP_SNDLOWAT ((TCP_SND_BUF)/2)
#endif #endif
/** /**
@ -1322,21 +1339,21 @@
* MEM_STATS==1: Enable mem.c stats. * MEM_STATS==1: Enable mem.c stats.
*/ */
#ifndef MEM_STATS #ifndef MEM_STATS
#define MEM_STATS 1 #define MEM_STATS ((MEM_LIBC_MALLOC == 0) && (MEM_USE_POOLS == 0))
#endif #endif
/** /**
* MEMP_STATS==1: Enable memp.c pool stats. * MEMP_STATS==1: Enable memp.c pool stats.
*/ */
#ifndef MEMP_STATS #ifndef MEMP_STATS
#define MEMP_STATS 1 #define MEMP_STATS (MEMP_MEM_MALLOC == 0)
#endif #endif
/** /**
* SYS_STATS==1: Enable system stats (sem and mbox counts, etc). * SYS_STATS==1: Enable system stats (sem and mbox counts, etc).
*/ */
#ifndef SYS_STATS #ifndef SYS_STATS
#define SYS_STATS 1 #define SYS_STATS (NO_SYS == 0)
#endif #endif
#else #else
@ -1510,9 +1527,12 @@
#endif #endif
#define PPP_MINMRU 128 /* No MRUs below this */ #define PPP_MINMRU 128 /* No MRUs below this */
#ifndef MAXNAMELEN
#define MAXNAMELEN 256 /* max length of hostname or name for auth */ #define MAXNAMELEN 256 /* max length of hostname or name for auth */
#endif
#ifndef MAXSECRETLEN
#define MAXSECRETLEN 256 /* max length of password or secret */ #define MAXSECRETLEN 256 /* max length of password or secret */
#endif
#endif /* PPP_SUPPORT */ #endif /* PPP_SUPPORT */
@ -1574,7 +1594,7 @@
* messages are written. * messages are written.
*/ */
#ifndef LWIP_DBG_MIN_LEVEL #ifndef LWIP_DBG_MIN_LEVEL
#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_OFF #define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL
#endif #endif
/** /**

View File

@ -51,27 +51,87 @@ typedef void * sio_fd_t;
or be implemented in your custom sio.c file. */ or be implemented in your custom sio.c file. */
#ifndef sio_open #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 #endif
#ifndef sio_send #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 #endif
#ifndef sio_recv #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 #endif
#ifndef sio_read #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 #endif
#ifndef sio_write #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 #endif
#ifndef sio_read_abort #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 #endif
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -78,6 +78,9 @@ void tcp_err (struct tcp_pcb *pcb,
#define tcp_mss(pcb) ((pcb)->mss) #define tcp_mss(pcb) ((pcb)->mss)
#define tcp_sndbuf(pcb) ((pcb)->snd_buf) #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 #if TCP_LISTEN_BACKLOG
#define tcp_accepted(pcb) (((struct tcp_pcb_listen *)(pcb))->accepts_pending--) #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: */ /* Only used by IP to pass a TCP segment to TCP: */
void tcp_input (struct pbuf *p, struct netif *inp); void tcp_input (struct pbuf *p, struct netif *inp);
/* Used within the TCP code only: */ /* Used within the TCP code only: */
err_t tcp_send_empty_ack(struct tcp_pcb *pcb);
err_t tcp_output (struct tcp_pcb *pcb); err_t tcp_output (struct tcp_pcb *pcb);
void tcp_rexmit (struct tcp_pcb *pcb); void tcp_rexmit (struct tcp_pcb *pcb);
void tcp_rexmit_rto (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); 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 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 * - 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) * 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) || \ #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 != NULL) && (((tpcb)->unsent->next != NULL) || \
((tpcb)->unsent->len >= (tpcb)->mss))) \ ((tpcb)->unsent->len >= (tpcb)->mss))) \
) ? 1 : 0) ) ? 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_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_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_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 = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (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 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 || \ #define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0))
TCPH_FLAGS((seg)->tcphdr) & TCP_SYN)? 1: 0))
enum tcp_state { enum tcp_state {
CLOSED = 0, CLOSED = 0,
@ -489,9 +494,7 @@ err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
if((pcb)->recv != NULL) { \ if((pcb)->recv != NULL) { \
(ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); \ (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); \
} else { \ } else { \
(ret) = ERR_OK; \ (ret) = tcp_recv_null(NULL, (pcb), (p), (err)); \
if (p != NULL) \
pbuf_free(p); \
} \ } \
} while (0) } 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); u16_t tcp_eff_send_mss(u16_t sendmss, struct ip_addr *addr);
#endif /* TCP_CALCULATE_EFF_SEND_MSS */ #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 struct tcp_pcb *tcp_input_pcb;
extern u32_t tcp_ticks; extern u32_t tcp_ticks;
const char* tcp_debug_state_str(enum tcp_state s);
#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG #if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
void tcp_debug_print(struct tcp_hdr *tcphdr); void tcp_debug_print(struct tcp_hdr *tcphdr);
void tcp_debug_print_flags(u8_t flags); 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) { \ if(*pcbs == npcb) { \
*pcbs = (*pcbs)->next; \ *pcbs = (*pcbs)->next; \
} else for(tcp_tmp_pcb = *pcbs; tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->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; \ tcp_tmp_pcb->next = npcb->next; \
break; \ break; \
} \ } \
@ -679,7 +687,7 @@ extern struct tcp_pcb *tcp_tmp_pcb; /* Only used for temporary storage. */
for(tcp_tmp_pcb = *pcbs; \ for(tcp_tmp_pcb = *pcbs; \
tcp_tmp_pcb != NULL; \ tcp_tmp_pcb != NULL; \
tcp_tmp_pcb = tcp_tmp_pcb->next) { \ 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; \ tcp_tmp_pcb->next = npcb->next; \
break; \ break; \
} \ } \

View File

@ -94,6 +94,9 @@ struct udp_pcb {
* The callback is responsible for freeing the pbuf * The callback is responsible for freeing the pbuf
* if it's not used any more. * 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 arg user supplied argument (udp_pcb.recv_arg)
* @param pcb the udp_pcb which received data * @param pcb the udp_pcb which received data
* @param p the packet buffer that was received * @param p the packet buffer that was received

View File

@ -85,13 +85,34 @@ PACK_STRUCT_END
# include "arch/epstruct.h" # include "arch/epstruct.h"
#endif #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 #ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h" # include "arch/bpstruct.h"
#endif #endif
PACK_STRUCT_BEGIN PACK_STRUCT_BEGIN
/** the ARP message */ /** the ARP message */
struct etharp_hdr { struct etharp_hdr {
PACK_STRUCT_FIELD(struct eth_hdr ethhdr);
PACK_STRUCT_FIELD(u16_t hwtype); PACK_STRUCT_FIELD(u16_t hwtype);
PACK_STRUCT_FIELD(u16_t proto); PACK_STRUCT_FIELD(u16_t proto);
PACK_STRUCT_FIELD(u16_t _hwlen_protolen); PACK_STRUCT_FIELD(u16_t _hwlen_protolen);
@ -106,24 +127,15 @@ PACK_STRUCT_END
# include "arch/epstruct.h" # include "arch/epstruct.h"
#endif #endif
#ifdef PACK_STRUCT_USE_INCLUDES #define SIZEOF_ETHARP_HDR 28
# include "arch/bpstruct.h" #define SIZEOF_ETHARP_PACKET (SIZEOF_ETH_HDR + SIZEOF_ETHARP_HDR)
#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
/** 5 seconds period */ /** 5 seconds period */
#define ARP_TMR_INTERVAL 5000 #define ARP_TMR_INTERVAL 5000
#define ETHTYPE_ARP 0x0806 #define ETHTYPE_ARP 0x0806
#define ETHTYPE_IP 0x0800 #define ETHTYPE_IP 0x0800
#define ETHTYPE_VLAN 0x8100
#define ETHTYPE_PPPOEDISC 0x8863 /* PPP Over Ethernet Discovery Stage */ #define ETHTYPE_PPPOEDISC 0x8863 /* PPP Over Ethernet Discovery Stage */
#define ETHTYPE_PPPOE 0x8864 /* PPP Over Ethernet Session Stage */ #define ETHTYPE_PPPOE 0x8864 /* PPP Over Ethernet Session Stage */

View File

@ -41,6 +41,7 @@ extern "C" {
#endif #endif
err_t slipif_init(struct netif * netif); err_t slipif_init(struct netif * netif);
void slipif_poll(struct netif *netif);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -91,6 +91,12 @@
#define mem_free rt_free #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 /* 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 sends a lot of data out of ROM (or other static memory), this
should be set high. */ should be set high. */

View File

@ -23,3 +23,7 @@ slipif.c
protocol. It requires a sio (serial I/O) module to work. protocol. It requires a sio (serial I/O) module to work.
ppp/ Point-to-Point Protocol stack 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.

View File

@ -468,7 +468,7 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e
{ {
s8_t i; s8_t i;
u8_t k; 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_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", 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), 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 void
etharp_ip_input(struct netif *netif, struct pbuf *p) 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;); LWIP_ERROR("netif != NULL", (netif != NULL), return;);
/* Only insert an entry if the source IP address of the /* Only insert an entry if the source IP address of the
incoming IP packet comes from a host on the local network. */ 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? */ /* 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 */ /* do nothing */
return; return;
} }
@ -594,7 +602,7 @@ etharp_ip_input(struct netif *netif, struct pbuf *p)
/* update ARP table */ /* update ARP table */
/* @todo We could use ETHARP_TRY_HARD if we think we are going to talk /* @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. */ * 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) etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
{ {
struct etharp_hdr *hdr; struct etharp_hdr *hdr;
struct eth_hdr *ethhdr;
/* these are aligned properly, whereas the ARP header fields might not be */ /* these are aligned properly, whereas the ARP header fields might not be */
struct ip_addr sipaddr, dipaddr; struct ip_addr sipaddr, dipaddr;
u8_t i; 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 /* 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! */ since a struct etharp_hdr is pointed to p->payload, so it musn't be chained! */
if (p->len < sizeof(struct etharp_hdr)) { if (p->len < SIZEOF_ETHARP_PACKET) {
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))); 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.lenerr);
ETHARP_STATS_INC(etharp.drop); ETHARP_STATS_INC(etharp.drop);
pbuf_free(p); pbuf_free(p);
return; 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": */ /* RFC 826 "Packet Reception": */
if ((hdr->hwtype != htons(HWTYPE_ETHERNET)) || if ((hdr->hwtype != htons(HWTYPE_ETHERNET)) ||
(hdr->_hwlen_protolen != htons((ETHARP_HWADDR_LEN << 8) | sizeof(struct ip_addr))) || (hdr->_hwlen_protolen != htons((ETHARP_HWADDR_LEN << 8) | sizeof(struct ip_addr))) ||
(hdr->proto != htons(ETHTYPE_IP)) || (hdr->proto != htons(ETHTYPE_IP)) ||
(hdr->ethhdr.type != htons(ETHTYPE_ARP))) { (ethhdr->type != htons(ETHTYPE_ARP))) {
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | 1, 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", ("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.proterr);
ETHARP_STATS_INC(etharp.drop); ETHARP_STATS_INC(etharp.drop);
pbuf_free(p); pbuf_free(p);
@ -719,12 +736,12 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
i--; i--;
hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i]; hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i];
#if LWIP_AUTOIP #if LWIP_AUTOIP
hdr->ethhdr.dest.addr[i] = ethdst_hwaddr[i]; ethhdr->dest.addr[i] = ethdst_hwaddr[i];
#else /* LWIP_AUTOIP */ #else /* LWIP_AUTOIP */
hdr->ethhdr.dest.addr[i] = hdr->shwaddr.addr[i]; ethhdr->dest.addr[i] = hdr->shwaddr.addr[i];
#endif /* LWIP_AUTOIP */ #endif /* LWIP_AUTOIP */
hdr->shwaddr.addr[i] = ethaddr->addr[i]; 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 /* 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 */ /* make room for Ethernet header - should not fail */
if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) { if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
/* bail out */ /* 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); LINK_STATS_INC(link.lenerr);
return ERR_BUF; return ERR_BUF;
} }
@ -1034,23 +1052,26 @@ etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
struct pbuf *p; struct pbuf *p;
err_t result = ERR_OK; err_t result = ERR_OK;
u8_t k; /* ARP entry index */ u8_t k; /* ARP entry index */
struct eth_hdr *ethhdr;
struct etharp_hdr *hdr; struct etharp_hdr *hdr;
#if LWIP_AUTOIP #if LWIP_AUTOIP
const u8_t * ethdst_hwaddr; const u8_t * ethdst_hwaddr;
#endif /* LWIP_AUTOIP */ #endif /* LWIP_AUTOIP */
/* allocate a pbuf for the outgoing ARP request packet */ /* 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? */ /* could allocate a pbuf for an ARP request? */
if (p == NULL) { 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); ETHARP_STATS_INC(etharp.memerr);
return ERR_MEM; return ERR_MEM;
} }
LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr", 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")); LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n"));
hdr->opcode = htons(opcode); 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]; hdr->dhwaddr.addr[k] = hwdst_addr->addr[k];
/* Write the Ethernet MAC-Addresses */ /* Write the Ethernet MAC-Addresses */
#if LWIP_AUTOIP #if LWIP_AUTOIP
hdr->ethhdr.dest.addr[k] = ethdst_hwaddr[k]; ethhdr->dest.addr[k] = ethdst_hwaddr[k];
#else /* LWIP_AUTOIP */ #else /* LWIP_AUTOIP */
hdr->ethhdr.dest.addr[k] = ethdst_addr->addr[k]; ethhdr->dest.addr[k] = ethdst_addr->addr[k];
#endif /* LWIP_AUTOIP */ #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->sipaddr = *(struct ip_addr2 *)ipsrc_addr;
hdr->dipaddr = *(struct ip_addr2 *)ipdst_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 */ /* set hwlen and protolen together */
hdr->_hwlen_protolen = htons((ETHARP_HWADDR_LEN << 8) | sizeof(struct ip_addr)); 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 */ /* send ARP query */
result = netif->linkoutput(netif, p); result = netif->linkoutput(netif, p);
ETHARP_STATS_INC(etharp.xmit); ETHARP_STATS_INC(etharp.xmit);
@ -1126,6 +1147,7 @@ err_t
ethernet_input(struct pbuf *p, struct netif *netif) ethernet_input(struct pbuf *p, struct netif *netif)
{ {
struct eth_hdr* ethhdr; struct eth_hdr* ethhdr;
u16_t type;
/* points to packet payload, which starts with an Ethernet header */ /* points to packet payload, which starts with an Ethernet header */
ethhdr = p->payload; 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)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5],
(unsigned)htons(ethhdr->type))); (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? */ /* IP packet? */
case ETHTYPE_IP: case ETHTYPE_IP:
#if ETHARP_TRUST_IP_MAC #if ETHARP_TRUST_IP_MAC
@ -1145,7 +1182,7 @@ ethernet_input(struct pbuf *p, struct netif *netif)
etharp_ip_input(netif, p); etharp_ip_input(netif, p);
#endif /* ETHARP_TRUST_IP_MAC */ #endif /* ETHARP_TRUST_IP_MAC */
/* skip Ethernet header */ /* 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); LWIP_ASSERT("Can't move over header in packet", 0);
pbuf_free(p); pbuf_free(p);
p = NULL; p = NULL;

View File

@ -301,26 +301,18 @@ FINSH_FUNCTION_EXPORT(set_dns, set DNS server address);
void list_if() 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]); 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: %s\n", ip_ntoa(&(netif_default->ip_addr.addr)));
rt_kprintf("ip address: %d.%d.%d.%d\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3); 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)));
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);
#if LWIP_DNS #if LWIP_DNS
{
struct ip_addr ip_addr;
ip_addr = dns_getserver(0); ip_addr = dns_getserver(0);
addr = (struct _ip_addr*)&ip_addr; rt_kprintf("dns server: %d.%d.%d.%d\n", ip_ntoa(&ip_addr));
rt_kprintf("dns server: %d.%d.%d.%d\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3); }
#endif #endif
} }
FINSH_FUNCTION_EXPORT(list_if, list network interface information); FINSH_FUNCTION_EXPORT(list_if, list network interface information);

View File

@ -82,6 +82,8 @@
#include "cbcp.h" #include "cbcp.h"
#endif /* CBCP_SUPPORT */ #endif /* CBCP_SUPPORT */
#include <string.h>
/*************************/ /*************************/
/*** LOCAL DEFINITIONS ***/ /*** LOCAL DEFINITIONS ***/
/*************************/ /*************************/

View File

@ -82,6 +82,7 @@
#include "chap.h" #include "chap.h"
#include "chpms.h" #include "chpms.h"
#include <string.h>
/*************************/ /*************************/
/*** LOCAL DEFINITIONS ***/ /*** LOCAL DEFINITIONS ***/

View File

@ -1,4 +1,7 @@
/*** WARNING - THIS CODE HAS NOT BEEN FINISHED! ***/ /*** 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. * chpms.c - Network MicroSoft Challenge Handshake Authentication Protocol program file.
* *

View File

@ -64,6 +64,8 @@
#include "fsm.h" #include "fsm.h"
#include <string.h>
/*************************/ /*************************/
/*** LOCAL DEFINITIONS ***/ /*** LOCAL DEFINITIONS ***/
@ -551,7 +553,7 @@ fsm_timeout(void *arg)
break; break;
default: 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])); PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
} }
} }

View File

@ -183,20 +183,7 @@ static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
/*** LOCAL FUNCTION DEFINITIONS ***/ /*** LOCAL FUNCTION DEFINITIONS ***/
/**********************************/ /**********************************/
/* #define inet_ntoa(addr) ip_ntoa(((struct ip_addr*)&(addr)))
* 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
/* /*
* ipcp_init - Initialize IPCP. * ipcp_init - Initialize IPCP.

View File

@ -42,6 +42,8 @@
#include "md5.h" #include "md5.h"
#include <string.h>
/* /*
*********************************************************************** ***********************************************************************
** Message-digest routines: ** ** Message-digest routines: **

View File

@ -61,6 +61,8 @@
#include "auth.h" #include "auth.h"
#include "pap.h" #include "pap.h"
#include <string.h>
/***********************************/ /***********************************/
/*** LOCAL FUNCTION DECLARATIONS ***/ /*** LOCAL FUNCTION DECLARATIONS ***/
/***********************************/ /***********************************/
@ -490,6 +492,7 @@ upap_rauthack(upap_state *u, u_char *inp, int id, int len)
msg = (char *) inp; msg = (char *) inp;
PRINTMSG(msg, msglen); PRINTMSG(msg, msglen);
UNTIMEOUT(upap_timeout, u); /* Cancel timeout */
u->us_clientstate = UPAPCS_OPEN; u->us_clientstate = UPAPCS_OPEN;
auth_withpeer_success(u->us_unit, PPP_PAP); auth_withpeer_success(u->us_unit, PPP_PAP);

View File

@ -166,7 +166,7 @@ typedef struct PPPControl_s {
ext_accm outACCM; /* Async-Ctl-Char-Map for output. */ ext_accm outACCM; /* Async-Ctl-Char-Map for output. */
#if PPPOS_SUPPORT && VJ_SUPPORT #if PPPOS_SUPPORT && VJ_SUPPORT
int vjEnabled; /* Flag indicating VJ compression enabled. */ 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 */ #endif /* PPPOS_SUPPORT && VJ_SUPPORT */
struct netif netif; struct netif netif;
@ -235,7 +235,7 @@ struct protent *ppp_protocols[] = {
* Buffers for outgoing packets. This must be accessed only from the appropriate * 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. * 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 void
pppLinkTerminated(int pd) pppLinkTerminated(int pd)
{ {
PPPControl *pc = &pppControl[pd];
PPPDEBUG((LOG_DEBUG, "pppLinkTerminated: unit %d\n", pd)); PPPDEBUG((LOG_DEBUG, "pppLinkTerminated: unit %d\n", pd));
#if PPPOE_SUPPORT #if PPPOE_SUPPORT
if(pc->ethif) { if(pppControl[pd].ethif) {
pppoe_disconnect(pc->pppoe_sc); pppoe_disconnect(pppControl[pd].pppoe_sc);
} else } else
#endif /* PPPOE_SUPPORT */ #endif /* PPPOE_SUPPORT */
{ {
@ -325,13 +323,11 @@ pppLinkTerminated(int pd)
void void
pppLinkDown(int pd) pppLinkDown(int pd)
{ {
PPPControl *pc = &pppControl[pd];
PPPDEBUG((LOG_DEBUG, "pppLinkDown: unit %d\n", pd)); PPPDEBUG((LOG_DEBUG, "pppLinkDown: unit %d\n", pd));
#if PPPOE_SUPPORT #if PPPOE_SUPPORT
if(pc->ethif) { if(pppControl[pd].ethif) {
pppoe_disconnect(pc->pppoe_sc); pppoe_disconnect(pppControl[pd].pppoe_sc);
} else } else
#endif /* PPPOE_SUPPORT */ #endif /* PPPOE_SUPPORT */
{ {
@ -383,7 +379,7 @@ pppHupCB(void *arg)
struct ppp_settings ppp_settings; struct ppp_settings ppp_settings;
err_t void
pppInit(void) pppInit(void)
{ {
struct protent *protp; struct protent *protp;
@ -395,15 +391,10 @@ pppInit(void)
magicInit(); magicInit();
for (i = 0; i < NUM_PPP; i++) {
pppControl[i].openFlag = 0;
subnetMask = htonl(0xffffff00); subnetMask = htonl(0xffffff00);
outpacket_buf[i] = (u_char *)mem_malloc(PPP_MRU+PPP_HDRLEN); for (i = 0; i < NUM_PPP; i++) {
if(!outpacket_buf[i]) { pppControl[i].openFlag = 0;
return ERR_MEM;
}
/* /*
* Initialize to the standard option set. * 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 #if PPPOE_SUPPORT
pppoe_init(); pppoe_init();
#endif /* PPPOE_SUPPORT */ #endif /* PPPOE_SUPPORT */
return ERR_OK;
} }
void void
@ -601,7 +584,7 @@ int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const cha
pppControl[pd].openFlag = !0; pppControl[pd].openFlag = !0;
} }
/* Launch a deamon thread. */ /* PPP session descriptor found, start PPPoE */
if (pd >= 0) { if (pd >= 0) {
pppControl[pd].openFlag = 1; pppControl[pd].openFlag = 1;
@ -824,9 +807,9 @@ static err_t
pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr) pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr)
{ {
int pd = (int)netif->state; int pd = (int)netif->state;
u_short protocol = PPP_IP;
PPPControl *pc = &pppControl[pd]; PPPControl *pc = &pppControl[pd];
#if PPPOS_SUPPORT #if PPPOS_SUPPORT
u_short protocol = PPP_IP;
u_int fcsOut = PPP_INITFCS; u_int fcsOut = PPP_INITFCS;
struct pbuf *headMB = NULL, *tailMB = NULL, *p; struct pbuf *headMB = NULL, *tailMB = NULL, *p;
u_char c; 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. */ * and the peer will just drop it if it's not accepting it. */
if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !pb) { if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !pb) {
PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad parms prot=%d pb=%p\n", 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.opterr);
LINK_STATS_INC(link.drop); LINK_STATS_INC(link.drop);
return ERR_ARG; return ERR_ARG;
@ -1294,7 +1277,7 @@ GetMask(u32_t addr)
* sifvjcomp - config tcp header compression * sifvjcomp - config tcp header compression
*/ */
int int
sifvjcomp( int pd, int vjcomp, int cidcomp, int maxcid) sifvjcomp(int pd, int vjcomp, int cidcomp, int maxcid)
{ {
#if PPPOS_SUPPORT && VJ_SUPPORT #if PPPOS_SUPPORT && VJ_SUPPORT
PPPControl *pc = &pppControl[pd]; PPPControl *pc = &pppControl[pd];
@ -1304,6 +1287,11 @@ sifvjcomp( int pd, int vjcomp, int cidcomp, int maxcid)
pc->vjComp.maxSlotIndex = maxcid; pc->vjComp.maxSlotIndex = maxcid;
PPPDEBUG((LOG_INFO, "sifvjcomp: VJ compress enable=%d slot=%d max slot=%d\n", PPPDEBUG((LOG_INFO, "sifvjcomp: VJ compress enable=%d slot=%d max slot=%d\n",
vjcomp, cidcomp, maxcid)); 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 */ #endif /* PPPOS_SUPPORT && VJ_SUPPORT */
return 0; return 0;
@ -1381,6 +1369,8 @@ sifdown(int pd)
PPPDEBUG((LOG_WARNING, "sifdown[%d]: bad parms\n", pd)); PPPDEBUG((LOG_WARNING, "sifdown[%d]: bad parms\n", pd));
} else { } else {
pc->if_up = 0; pc->if_up = 0;
/* make sure the netif status callback is called */
netif_set_down(&pc->netif);
netif_remove(&pc->netif); netif_remove(&pc->netif);
PPPDEBUG((LOG_DEBUG, "sifdown: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); PPPDEBUG((LOG_DEBUG, "sifdown: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
if(pc->linkStatusCB) { if(pc->linkStatusCB) {
@ -1537,8 +1527,8 @@ pppMain(void *arg)
if(c > 0) { if(c > 0) {
pppInProc(pd, p->payload, c); pppInProc(pd, p->payload, c);
} else { } else {
PPPDEBUG((LOG_DEBUG, "pppMain: unit %d sio_read len=%d returned %d\n", pd, p->len, c)); /* nothing received, give other tasks a chance to run */
sys_msleep(1); /* give other tasks a chance to run */ sys_msleep(1);
} }
} }
} }
@ -1658,7 +1648,7 @@ pppInput(void *arg)
switch(protocol) { switch(protocol) {
case PPP_VJC_COMP: /* VJ compressed TCP */ 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)); 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 * 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. */ /* Something's wrong so drop it. */
PPPDEBUG((LOG_WARNING, "pppInput[%d]: Dropping VJ compressed\n", pd)); 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. */ /* 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)); 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; break;
case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */ 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)); 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 * 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. */ /* Something's wrong so drop it. */
PPPDEBUG((LOG_WARNING, "pppInput[%d]: Dropping VJ uncompressed\n", pd)); 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. */ /* No handler for this protocol so drop the packet. */
PPPDEBUG((LOG_INFO, PPPDEBUG((LOG_INFO,
"pppInput[%d]: drop VJ UnComp in %d:.*H\n", "pppInput[%d]: drop VJ UnComp in %d:.*H\n",
pd, nb->len, LWIP_MIN(nb->len * 2, 40), nb->payload)); pd, nb->len, LWIP_MIN(nb->len * 2, 40), nb->payload));
#endif /* VJ_SUPPORT */ #endif /* PPPOS_SUPPORT && VJ_SUPPORT */
break; break;
case PPP_IP: /* Internet Protocol */ case PPP_IP: /* Internet Protocol */

View File

@ -333,7 +333,7 @@ struct ppp_addrs {
*****************************/ *****************************/
/* Buffers for outgoing packets. */ /* 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; 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. */ /* Initialize the PPP subsystem. */
err_t pppInit(void); void pppInit(void);
/* Warning: Using PPPAUTHTYPE_ANY might have security consequences. /* Warning: Using PPPAUTHTYPE_ANY might have security consequences.
* RFC 1994 says: * RFC 1994 says:

View File

@ -398,7 +398,7 @@ pppoe_dispatch_disc_pkt(struct netif *netif, struct pbuf *pb)
#endif #endif
struct pppoehdr *ph; struct pppoehdr *ph;
struct pppoetag pt; struct pppoetag pt;
int off = 0, err, errortag; int off, err, errortag;
struct eth_hdr *ethhdr; struct eth_hdr *ethhdr;
pb = pppSingleBuf(pb); pb = pppSingleBuf(pb);
@ -410,7 +410,7 @@ pppoe_dispatch_disc_pkt(struct netif *netif, struct pbuf *pb)
goto done; goto done;
} }
ethhdr = (struct eth_hdr *)pb->payload; ethhdr = (struct eth_hdr *)pb->payload;
off += sizeof(*ethhdr); off = sizeof(*ethhdr);
ac_cookie = NULL; ac_cookie = NULL;
ac_cookie_len = 0; ac_cookie_len = 0;
@ -419,7 +419,7 @@ pppoe_dispatch_disc_pkt(struct netif *netif, struct pbuf *pb)
hunique_len = 0; hunique_len = 0;
#endif #endif
session = 0; session = 0;
if (pb->len - off <= PPPOE_HEADERLEN) { if (pb->len - off < PPPOE_HEADERLEN) {
printf("pppoe: packet too short: %d\n", pb->len); printf("pppoe: packet too short: %d\n", pb->len);
goto done; goto done;
} }

View File

@ -41,6 +41,7 @@
#include "ppp.h" #include "ppp.h"
#include "pppdebug.h" #include "pppdebug.h"
#include <string.h>
#if MD5_SUPPORT /* this module depends on MD5 */ #if MD5_SUPPORT /* this module depends on MD5 */
#define RANDPOOLSZ 16 /* Bytes stored in the pool of randomness. */ #define RANDPOOLSZ 16 /* Bytes stored in the pool of randomness. */

View File

@ -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 * packet. This assumes that nb and comp are not null and that the first
* buffer of the chain contains a valid IP header. * buffer of the chain contains a valid IP header.
* Return the VJ type code indicating whether or not the packet was * Return the VJ type code indicating whether or not the packet was

View File

@ -39,7 +39,7 @@
/* /*
* This is an arch independent SLIP netif. The specific serial hooks must be * 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" #include "netif/slipif.h"
@ -54,12 +54,28 @@
#include "lwip/snmp.h" #include "lwip/snmp.h"
#include "lwip/sio.h" #include "lwip/sio.h"
#define SLIP_BLOCK 1
#define SLIP_DONTBLOCK 0
#define SLIP_END 0300 /* 0xC0 */ #define SLIP_END 0300 /* 0xC0 */
#define SLIP_ESC 0333 /* 0xDB */ #define SLIP_ESC 0333 /* 0xDB */
#define SLIP_ESC_END 0334 /* 0xDC */ #define SLIP_ESC_END 0334 /* 0xDC */
#define SLIP_ESC_ESC 0335 /* 0xDD */ #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 * Send a pbuf doing the necessary SLIP encapsulation
@ -74,6 +90,7 @@
err_t err_t
slipif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr) slipif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
{ {
struct slipif_priv *priv;
struct pbuf *q; struct pbuf *q;
u16_t i; u16_t i;
u8_t c; u8_t c;
@ -84,73 +101,101 @@ slipif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
LWIP_UNUSED_ARG(ipaddr); LWIP_UNUSED_ARG(ipaddr);
priv = netif->state;
/* Send pbuf out on the serial I/O device. */ /* 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 (q = p; q != NULL; q = q->next) {
for (i = 0; i < q->len; i++) { for (i = 0; i < q->len; i++) {
c = ((u8_t *)q->payload)[i]; c = ((u8_t *)q->payload)[i];
switch (c) { switch (c) {
case SLIP_END: case SLIP_END:
sio_send(SLIP_ESC, netif->state); sio_send(SLIP_ESC, priv->sd);
sio_send(SLIP_ESC_END, netif->state); sio_send(SLIP_ESC_END, priv->sd);
break; break;
case SLIP_ESC: case SLIP_ESC:
sio_send(SLIP_ESC, netif->state); sio_send(SLIP_ESC, priv->sd);
sio_send(SLIP_ESC_ESC, netif->state); sio_send(SLIP_ESC_ESC, priv->sd);
break; break;
default: default:
sio_send(c, netif->state); sio_send(c, priv->sd);
break; break;
} }
} }
} }
sio_send(SLIP_END, netif->state); sio_send(SLIP_END, priv->sd);
return ERR_OK; 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 * 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 * @param netif the lwip network interface structure for this slipif
* @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 * @return The IP packet when SLIP_END is received
*/ */
static struct pbuf * static struct pbuf *
slipif_input(struct netif *netif) slipif_input(struct netif *netif, u8_t block)
{ {
struct slipif_priv *priv;
u8_t c; u8_t c;
/* q is the whole pbuf chain for a packet, p is the current pbuf in the chain */ struct pbuf *t;
struct pbuf *p, *q;
u16_t recved;
u16_t i;
LWIP_ASSERT("netif != NULL", (netif != NULL)); LWIP_ASSERT("netif != NULL", (netif != NULL));
LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); LWIP_ASSERT("netif->state != NULL", (netif->state != NULL));
q = p = NULL; priv = netif->state;
recved = i = 0;
c = 0;
while (1) { while (slip_sio_read(priv->sd, &c, 1, block) > 0) {
c = sio_recv(netif->state); switch (priv->state) {
case SLIP_RECV_NORMAL:
switch (c) { switch (c) {
case SLIP_END: case SLIP_END:
if (recved > 0) { if (priv->recved > 0) {
/* Received whole packet. */ /* Received whole packet. */
/* Trim the pbuf to the size of the received packet. */ /* Trim the pbuf to the size of the received packet. */
pbuf_realloc(q, recved); pbuf_realloc(priv->q, priv->recved);
LINK_STATS_INC(link.recv); LINK_STATS_INC(link.recv);
LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n")); LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n"));
return q; 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; break;
case SLIP_RECV_ESCAPE:
case SLIP_ESC:
c = sio_recv(netif->state);
switch (c) { switch (c) {
case SLIP_ESC_END: case SLIP_ESC_END:
c = SLIP_END; c = SLIP_END;
@ -159,52 +204,52 @@ slipif_input(struct netif *netif)
c = SLIP_ESC; c = SLIP_ESC;
break; break;
} }
priv->state = SLIP_RECV_NORMAL;
/* FALLTHROUGH */ /* FALLTHROUGH */
}
default:
/* byte received, packet not yet completely received */ /* byte received, packet not yet completely received */
if (p == NULL) { if (priv->p == NULL) {
/* allocate a new pbuf */ /* allocate a new pbuf */
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n")); LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n"));
p = pbuf_alloc(PBUF_LINK, PBUF_POOL_BUFSIZE, PBUF_POOL); priv->p = pbuf_alloc(PBUF_LINK, (PBUF_POOL_BUFSIZE - PBUF_LINK_HLEN), PBUF_POOL);
if (p == NULL) { if (priv->p == NULL) {
LINK_STATS_INC(link.drop); LINK_STATS_INC(link.drop);
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n")); LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n"));
/* don't process any further since we got no pbuf to receive to */ /* don't process any further since we got no pbuf to receive to */
break; break;
} }
if (q != NULL) { if (priv->q != NULL) {
/* 'chain' the pbuf to the existing chain */ /* 'chain' the pbuf to the existing chain */
pbuf_cat(q, p); pbuf_cat(priv->q, priv->p);
} else { } else {
/* p is the first pbuf in the chain */ /* p is the first pbuf in the chain */
q = p; priv->q = priv->p;
} }
} }
/* this automatically drops bytes if > MAX_SIZE */ /* this automatically drops bytes if > SLIP_MAX_SIZE */
if ((p != NULL) && (recved <= MAX_SIZE)) { if ((priv->p != NULL) && (priv->recved <= SLIP_MAX_SIZE)) {
((u8_t *)p->payload)[i] = c; ((u8_t *)priv->p->payload)[priv->i] = c;
recved++; priv->recved++;
i++; priv->i++;
if (i >= p->len) { if (priv->i >= priv->p->len) {
/* on to the next pbuf */ /* on to the next pbuf */
i = 0; priv->i = 0;
if (p->next != NULL && p->next->len > 0) { if (priv->p->next != NULL && priv->p->next->len > 0) {
/* p is a chain, on to the next in the chain */ /* p is a chain, on to the next in the chain */
p = p->next; priv->p = priv->p->next;
} else { } else {
/* p is a single pbuf, set it to NULL so next time a new /* p is a single pbuf, set it to NULL so next time a new
* pbuf is allocated */ * pbuf is allocated */
p = NULL; priv->p = NULL;
} }
} }
} }
break;
}
} }
return NULL; return NULL;
} }
@ -217,13 +262,13 @@ slipif_input(struct netif *netif)
* @param nf the lwip network interface structure for this slipif * @param nf the lwip network interface structure for this slipif
*/ */
static void static void
slipif_loop(void *nf) slipif_loop_thread(void *nf)
{ {
struct pbuf *p; struct pbuf *p;
struct netif *netif = (struct netif *)nf; struct netif *netif = (struct netif *)nf;
while (1) { while (1) {
p = slipif_input(netif); p = slipif_input(netif, SLIP_BLOCK);
if (p != NULL) { if (p != NULL) {
if (netif->input(p, netif) != ERR_OK) { if (netif->input(p, netif) != ERR_OK) {
pbuf_free(p); pbuf_free(p);
@ -242,6 +287,7 @@ slipif_loop(void *nf)
* *
* @param netif the lwip network interface structure for this slipif * @param netif the lwip network interface structure for this slipif
* @return ERR_OK if serial line could be opened, * @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 * ERR_IF is serial line couldn't be opened
* *
* @note netif->num must contain the number of the serial port to open * @note netif->num must contain the number of the serial port to open
@ -250,22 +296,39 @@ slipif_loop(void *nf)
err_t err_t
slipif_init(struct netif *netif) slipif_init(struct netif *netif)
{ {
struct slipif_priv *priv;
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%"U16_F"\n", (u16_t)netif->num)); 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[0] = 's';
netif->name[1] = 'l'; netif->name[1] = 'l';
netif->output = slipif_output; netif->output = slipif_output;
netif->mtu = MAX_SIZE; netif->mtu = SLIP_MAX_SIZE;
netif->flags = NETIF_FLAG_POINTTOPOINT; netif->flags |= NETIF_FLAG_POINTTOPOINT;
/* Try to open the serial port (netif->num contains the port number). */ /* Try to open the serial port (netif->num contains the port number). */
netif->state = sio_open(netif->num); priv->sd = sio_open(netif->num);
if (!netif->state) { if (!priv->sd) {
/* Opening the serial port failed. */ /* Opening the serial port failed. */
mem_free(priv);
return ERR_IF; 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 /* initialize the snmp variables and counters inside the struct netif
* ifSpeed: no assumption can be made without knowing more about the * ifSpeed: no assumption can be made without knowing more about the
* serial line! * serial line!
@ -273,7 +336,32 @@ slipif_init(struct netif *netif)
NETIF_INIT_SNMP(netif, snmp_ifType_slip, 0); NETIF_INIT_SNMP(netif, snmp_ifType_slip, 0);
/* Create a thread to poll the serial line. */ /* 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; 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 */ #endif /* LWIP_HAVE_SLIPIF */

View 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__ */

View 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;
}

View 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;
}

View 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

View 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);
}

View File

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

View 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);
}

View 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

View 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);
}

View File

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