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