? .ChangeLog.swp
? ChangeLog
Index: CHANGELOG
===================================================================
RCS file: /sources/lwip/lwip/CHANGELOG,v
retrieving revision 1.300
retrieving revision 1.318
diff -u -p -r1.300 -r1.318
--- CHANGELOG	23 Mar 2008 13:49:39 -0000	1.300
+++ CHANGELOG	14 Jul 2008 20:12:36 -0000	1.318
@@ -19,9 +19,77 @@ HISTORY
 
   ++ New features:
 
+  2008-06-30 Simon Goldschmidt
+  * mem.c, opt.h, stats.h: fixed bug #21433: Calling mem_free/pbuf_free from
+    interrupt context isn't safe: LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT allows
+    mem_free to run between mem_malloc iterations. Added illegal counter for
+    mem stats.
+
+  2008-06-27 Simon Goldschmidt
+  * stats.h/.c, some other files: patch #6483: stats module improvement:
+    Added defines to display each module's statistic individually, added stats
+    defines for MEM, MEMP and SYS modules, removed (unused) rexmit counter.
+
+  2008-06-17 Simon Goldschmidt
+  * err.h: patch #6459: Made err_t overridable to use a more efficient type
+    (define LWIP_ERR_T in cc.h)
+
+  2008-06-17 Simon Goldschmidt
+  * slipif.c: patch #6480: Added a configuration option for slipif for symmetry
+    to loopif
+
+  2008-06-17 Simon Goldschmidt (patch by Luca Ceresoli)
+  * netif.c, loopif.c, ip.c, netif.h, loopif.h, opt.h: Checked in slightly
+    modified version of patch # 6370: Moved loopif code to netif.c so that
+    loopback traffic is supported on all netifs (all local IPs).
+    Added option to limit loopback packets for each netifs.
+
 
   ++ Bugfixes:
 
+  2008-08-14 Simon Goldschmidt
+  * api_msg.c: fixed bug #23847: do_close_internal references freed memory (when
+    tcp_close returns != ERR_OK)
+
+  2008-07-08 Frédéric Bernon
+  * stats.h: Fix some build bugs introduced with patch #6483 (missing some parameters
+    in macros, mainly if MEM_STATS=0 and MEMP_STATS=0).
+
+  2008-06-24 Jonathan Larmour
+  * tcp_in.c: Fix for bug #23693 as suggested by Art R. Ensure cseg is unused
+    if tcp_seg_copy fails.
+
+  2008-06-17 Simon Goldschmidt
+  * inet_chksum.c: Checked in some ideas of patch #6460 (loop optimizations)
+    and created defines for swapping bytes and folding u32 to u16.
+
+  2008-05-30 Kieran Mansley
+  * tcp_in.c Remove redundant "if" statement, and use real rcv_wnd
+    rather than rcv_ann_wnd when deciding if packets are in-window.
+    Contributed by <arasmussen@consultant.datasys.swri.edu>
+
+  2008-05-30 Kieran Mansley
+  * mem.h: Fix BUG#23254.  Change macro definition of mem_* to allow
+    passing as function pointers when MEM_LIBC_MALLOC is defined.
+
+  2008-05-09 Jonathan Larmour
+  * err.h, err.c, sockets.c: Fix bug #23119: Reorder timeout error code to
+    stop it being treated as a fatal error.
+
+  2008-04-15 Simon Goldschmidt
+  * dhcp.c: fixed bug #22804: dhcp_stop doesn't clear NETIF_FLAG_DHCP
+    (flag now cleared)
+
+  2008-03-27 Simon Goldschmidt
+  * mem.c, tcpip.c, tcpip.h, opt.h: fixed bug #21433 (Calling mem_free/pbuf_free
+    from interrupt context isn't safe): set LWIP_USE_HEAP_FROM_INTERRUPT to 1
+    in lwipopts.h or use pbuf_free_callback(p)/mem_free_callback(m) to free pbufs
+    or heap memory from interrupt context
+
+  2008-03-26 Simon Goldschmidt
+  * tcp_in.c, tcp.c: fixed bug #22249: division by zero could occur if a remote
+    host sent a zero mss as TCP option.
+
 
 (STABLE-1.3.0)
 
Index: src/api/api_msg.c
===================================================================
RCS file: /sources/lwip/lwip/src/api/api_msg.c,v
retrieving revision 1.102
retrieving revision 1.104
diff -u -p -r1.102 -r1.104
--- src/api/api_msg.c	21 Mar 2008 16:23:14 -0000	1.102
+++ src/api/api_msg.c	15 Jul 2008 11:18:58 -0000	1.104
@@ -598,11 +598,16 @@ do_close_internal(struct netconn *conn)
   LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL));
 
   /* Set back some callback pointers */
+  tcp_arg(conn->pcb.tcp, NULL);
   if (conn->pcb.tcp->state == LISTEN) {
-    tcp_arg(conn->pcb.tcp, NULL);
     tcp_accept(conn->pcb.tcp, NULL);
   } else {
     tcp_recv(conn->pcb.tcp, NULL);
+    tcp_accept(conn->pcb.tcp, NULL);
+    /* some callbacks have to be reset if tcp_close is not successful */
+    tcp_sent(conn->pcb.tcp, NULL);
+    tcp_poll(conn->pcb.tcp, NULL, 4);
+    tcp_err(conn->pcb.tcp, NULL);
   }
   /* Try to close the connection */
   err = tcp_close(conn->pcb.tcp);
@@ -610,11 +615,6 @@ do_close_internal(struct netconn *conn)
     /* Closing succeeded */
     conn->state = NETCONN_NONE;
     /* Set back some callback pointers as conn is going away */
-    tcp_err(conn->pcb.tcp, NULL);
-    tcp_poll(conn->pcb.tcp, NULL, 4);
-    tcp_sent(conn->pcb.tcp, NULL);
-    tcp_recv(conn->pcb.tcp, NULL);
-    tcp_arg(conn->pcb.tcp, NULL);
     conn->pcb.tcp = NULL;
     conn->err = ERR_OK;
     /* Trigger select() in socket layer. This send should something else so the
@@ -623,6 +623,14 @@ do_close_internal(struct netconn *conn)
     API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
     /* wake up the application task */
     sys_sem_signal(conn->op_completed);
+  } else {
+    /* Closing failed, restore some of the callbacks */
+    /* Closing of listen pcb will never fail! */
+    LWIP_ASSERT("Closing a listen pcb may not fail!", (conn->pcb.tcp->state != LISTEN));
+    tcp_sent(conn->pcb.tcp, sent_tcp);
+    tcp_poll(conn->pcb.tcp, poll_tcp, 4);
+    tcp_err(conn->pcb.tcp, err_tcp);
+    tcp_arg(conn->pcb.tcp, conn);
   }
   /* If closing didn't succeed, we get called again either
      from poll_tcp or from sent_tcp */
Index: src/api/err.c
===================================================================
RCS file: /sources/lwip/lwip/src/api/err.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -p -r1.11 -r1.12
--- src/api/err.c	13 Dec 2007 23:06:50 -0000	1.11
+++ src/api/err.c	9 May 2008 12:14:23 -0000	1.12
@@ -44,17 +44,17 @@ static const char *err_strerr[] = {
            "Ok.",                    /* ERR_OK          0  */
            "Out of memory error.",   /* ERR_MEM        -1  */
            "Buffer error.",          /* ERR_BUF        -2  */
-           "Routing problem.",       /* ERR_RTE        -3  */
-           "Connection aborted.",    /* ERR_ABRT       -4  */
-           "Connection reset.",      /* ERR_RST        -5  */
-           "Connection closed.",     /* ERR_CLSD       -6  */
-           "Not connected.",         /* ERR_CONN       -7  */
-           "Illegal value.",         /* ERR_VAL        -8  */
-           "Illegal argument.",      /* ERR_ARG        -9  */
-           "Address in use.",        /* ERR_USE        -10 */
-           "Low-level netif error.", /* ERR_IF         -11 */
-           "Already connected.",     /* ERR_ISCONN     -12 */
-           "Timeout.",               /* ERR_TIMEOUT    -13 */
+           "Timeout.",               /* ERR_TIMEOUT    -3 */
+           "Routing problem.",       /* ERR_RTE        -4  */
+           "Connection aborted.",    /* ERR_ABRT       -5  */
+           "Connection reset.",      /* ERR_RST        -6  */
+           "Connection closed.",     /* ERR_CLSD       -7  */
+           "Not connected.",         /* ERR_CONN       -8  */
+           "Illegal value.",         /* ERR_VAL        -9  */
+           "Illegal argument.",      /* ERR_ARG        -10 */
+           "Address in use.",        /* ERR_USE        -11 */
+           "Low-level netif error.", /* ERR_IF         -12 */
+           "Already connected.",     /* ERR_ISCONN     -13 */
            "Operation in progress."  /* ERR_INPROGRESS -14 */
 };
 
Index: src/api/netdb.c
===================================================================
RCS file: /sources/lwip/lwip/src/api/netdb.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -p -r1.4 -r1.5
--- src/api/netdb.c	26 Jan 2008 16:11:39 -0000	1.4
+++ src/api/netdb.c	16 Jul 2008 20:36:12 -0000	1.5
@@ -326,7 +326,8 @@ lwip_getaddrinfo(const char *nodename, c
   if (nodename != NULL) {
     /* copy nodename to canonname if specified */
     size_t namelen = strlen(nodename);
-    ai->ai_canonname = mem_malloc(namelen + 1);
+    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;
     }
Index: src/api/sockets.c
===================================================================
RCS file: /sources/lwip/lwip/src/api/sockets.c,v
retrieving revision 1.116
retrieving revision 1.117
diff -u -p -r1.116 -r1.117
--- src/api/sockets.c	13 Mar 2008 20:03:57 -0000	1.116
+++ src/api/sockets.c	9 May 2008 12:14:24 -0000	1.117
@@ -128,17 +128,17 @@ static const int err_to_errno_table[] = 
   0,             /* ERR_OK          0      No error, everything OK. */
   ENOMEM,        /* ERR_MEM        -1      Out of memory error.     */
   ENOBUFS,       /* ERR_BUF        -2      Buffer error.            */
-  EHOSTUNREACH,  /* ERR_RTE        -3      Routing problem.         */
-  ECONNABORTED,  /* ERR_ABRT       -4      Connection aborted.      */
-  ECONNRESET,    /* ERR_RST        -5      Connection reset.        */
-  ESHUTDOWN,     /* ERR_CLSD       -6      Connection closed.       */
-  ENOTCONN,      /* ERR_CONN       -7      Not connected.           */
-  EINVAL,        /* ERR_VAL        -8      Illegal value.           */
-  EIO,           /* ERR_ARG        -9      Illegal argument.        */
-  EADDRINUSE,    /* ERR_USE        -10     Address in use.          */
-  -1,            /* ERR_IF         -11     Low-level netif error    */
-  -1,            /* ERR_ISCONN     -12     Already connected.       */
-  ETIMEDOUT,     /* ERR_TIMEOUT    -13     Timeout                  */
+  ETIMEDOUT,     /* ERR_TIMEOUT    -3      Timeout                  */
+  EHOSTUNREACH,  /* ERR_RTE        -4      Routing problem.         */
+  ECONNABORTED,  /* ERR_ABRT       -5      Connection aborted.      */
+  ECONNRESET,    /* ERR_RST        -6      Connection reset.        */
+  ESHUTDOWN,     /* ERR_CLSD       -7      Connection closed.       */
+  ENOTCONN,      /* ERR_CONN       -8      Not connected.           */
+  EINVAL,        /* ERR_VAL        -9      Illegal value.           */
+  EIO,           /* ERR_ARG        -10     Illegal argument.        */
+  EADDRINUSE,    /* ERR_USE        -11     Address in use.          */
+  -1,            /* ERR_IF         -12     Low-level netif error    */
+  -1,            /* ERR_ISCONN     -13     Already connected.       */
   EINPROGRESS    /* ERR_INPROGRESS -14     Operation in progress    */
 };
 
Index: src/api/tcpip.c
===================================================================
RCS file: /sources/lwip/lwip/src/api/tcpip.c,v
retrieving revision 1.70
retrieving revision 1.73
diff -u -p -r1.70 -r1.73
--- src/api/tcpip.c	12 Jan 2008 11:52:22 -0000	1.70
+++ src/api/tcpip.c	27 Jun 2008 20:34:51 -0000	1.73
@@ -518,4 +518,42 @@ tcpip_init(void (* initfunc)(void *), vo
   sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
 }
 
+/**
+ * Simple callback function used with tcpip_callback to free a pbuf
+ * (pbuf_free has a wrong signature for tcpip_callback)
+ *
+ * @param p The pbuf (chain) to be dereferenced.
+ */
+static void
+pbuf_free_int(void *p)
+{
+  struct pbuf *q = p;
+  pbuf_free(q);
+}
+
+/**
+ * A simple wrapper function that allows you to free a pbuf from interrupt context.
+ *
+ * @param p The pbuf (chain) to be dereferenced.
+ * @return ERR_OK if callback could be enqueued, an err_t if not
+ */
+err_t
+pbuf_free_callback(struct pbuf *p)
+{
+  return tcpip_callback_with_block(pbuf_free_int, p, 0);
+}
+
+/**
+ * A simple wrapper function that allows you to free heap memory from
+ * interrupt context.
+ *
+ * @param m the heap memory to free
+ * @return ERR_OK if callback could be enqueued, an err_t if not
+ */
+err_t
+mem_free_callback(void *m)
+{
+  return tcpip_callback_with_block(mem_free, m, 0);
+}
+
 #endif /* !NO_SYS */
Index: src/core/dhcp.c
===================================================================
RCS file: /sources/lwip/lwip/src/core/dhcp.c,v
retrieving revision 1.86
retrieving revision 1.87
diff -u -p -r1.86 -r1.87
--- src/core/dhcp.c	4 Mar 2008 14:25:58 -0000	1.86
+++ src/core/dhcp.c	15 Apr 2008 17:24:55 -0000	1.87
@@ -568,6 +568,8 @@ dhcp_start(struct netif *netif)
   LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;);
   dhcp = netif->dhcp;
   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
+  /* Remove the flag that says this netif is handled by DHCP,
+     it is set when we succeeded starting. */
   netif->flags &= ~NETIF_FLAG_DHCP;
 
   /* no DHCP client attached yet? */
@@ -609,6 +611,7 @@ dhcp_start(struct netif *netif)
     dhcp_stop(netif);
     return ERR_MEM;
   }
+  /* Set the flag that says this netif is handled by DHCP. */
   netif->flags |= NETIF_FLAG_DHCP;
   return result;
 }
@@ -1063,6 +1066,8 @@ dhcp_stop(struct netif *netif)
 {
   struct dhcp *dhcp = netif->dhcp;
   LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;);
+  /* 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"));
   /* netif is DHCP configured? */
Index: src/core/mem.c
===================================================================
RCS file: /sources/lwip/lwip/src/core/mem.c,v
retrieving revision 1.59
retrieving revision 1.62
diff -u -p -r1.59 -r1.62
--- src/core/mem.c	4 Mar 2008 16:31:32 -0000	1.59
+++ src/core/mem.c	30 Jun 2008 18:16:51 -0000	1.62
@@ -177,9 +177,36 @@ static u8_t *ram;
 static struct mem *ram_end;
 /** pointer to the lowest free block, this is used for faster search */
 static struct mem *lfree;
+
 /** concurrent access protection */
 static sys_sem_t mem_sem;
 
+#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
+
+static volatile u8_t mem_free_count;
+
+/* Allow mem_free from other (e.g. interrupt) context */
+#define LWIP_MEM_FREE_DECL_PROTECT()  SYS_ARCH_DECL_PROTECT(lev_free)
+#define LWIP_MEM_FREE_PROTECT()       SYS_ARCH_PROTECT(lev_free)
+#define LWIP_MEM_FREE_UNPROTECT()     SYS_ARCH_UNPROTECT(lev_free)
+#define LWIP_MEM_ALLOC_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_alloc)
+#define LWIP_MEM_ALLOC_PROTECT()      SYS_ARCH_PROTECT(lev_alloc)
+#define LWIP_MEM_ALLOC_UNPROTECT()    SYS_ARCH_UNPROTECT(lev_alloc)
+
+#else /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
+
+/* Protect the heap only by using a semaphore */
+#define LWIP_MEM_FREE_DECL_PROTECT()
+#define LWIP_MEM_FREE_PROTECT()    sys_arch_sem_wait(mem_sem, 0)
+#define LWIP_MEM_FREE_UNPROTECT()  sys_sem_signal(mem_sem)
+/* mem_malloc is protected using semaphore AND LWIP_MEM_ALLOC_PROTECT */
+#define LWIP_MEM_ALLOC_DECL_PROTECT()
+#define LWIP_MEM_ALLOC_PROTECT()
+#define LWIP_MEM_ALLOC_UNPROTECT()
+
+#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
+
+
 /**
  * "Plug holes" by combining adjacent empty struct mems.
  * After this function is through, there should not exist
@@ -255,9 +282,7 @@ mem_init(void)
   /* initialize the lowest-free pointer to the start of the heap */
   lfree = (struct mem *)ram;
 
-#if MEM_STATS
-  lwip_stats.mem.avail = MEM_SIZE_ALIGNED;
-#endif /* MEM_STATS */
+  MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED);
 }
 
 /**
@@ -270,6 +295,7 @@ void
 mem_free(void *rmem)
 {
   struct mem *mem;
+  LWIP_MEM_FREE_DECL_PROTECT();
 
   if (rmem == NULL) {
     LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | 2, ("mem_free(p == NULL) was called.\n"));
@@ -277,20 +303,20 @@ mem_free(void *rmem)
   }
   LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0);
 
-  /* protect the heap from concurrent access */
-  sys_arch_sem_wait(mem_sem, 0);
-
   LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
     (u8_t *)rmem < (u8_t *)ram_end);
 
   if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
+    SYS_ARCH_DECL_PROTECT(lev);
     LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_free: illegal memory\n"));
-#if MEM_STATS
-    ++lwip_stats.mem.err;
-#endif /* MEM_STATS */
-    sys_sem_signal(mem_sem);
+    /* protect mem stats from concurrent access */
+    SYS_ARCH_PROTECT(lev);
+    MEM_STATS_INC(illegal);
+    SYS_ARCH_UNPROTECT(lev);
     return;
   }
+  /* protect the heap from concurrent access */
+  LWIP_MEM_FREE_PROTECT();
   /* Get the corresponding struct mem ... */
   mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
   /* ... which has to be in a used state ... */
@@ -303,13 +329,14 @@ mem_free(void *rmem)
     lfree = mem;
   }
 
-#if MEM_STATS
-  lwip_stats.mem.used -= mem->next - ((u8_t *)mem - ram);
-#endif /* MEM_STATS */
+  MEM_STATS_DEC_USED(used, mem->next - ((u8_t *)mem - ram));
 
   /* finally, see if prev or next are free also */
   plug_holes(mem);
-  sys_sem_signal(mem_sem);
+#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
+  mem_free_count = 1;
+#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
+  LWIP_MEM_FREE_UNPROTECT();
 }
 
 /**
@@ -321,6 +348,8 @@ mem_free(void *rmem)
  * @param newsize required size after shrinking (needs to be smaller than or
  *                equal to the previous size)
  * @return for compatibility reasons: is always == rmem, at the moment
+ *         or NULL if newsize is > old size, in which case rmem is NOT touched
+ *         or freed!
  */
 void *
 mem_realloc(void *rmem, mem_size_t newsize)
@@ -328,6 +357,8 @@ mem_realloc(void *rmem, mem_size_t newsi
   mem_size_t size;
   mem_size_t ptr, ptr2;
   struct mem *mem, *mem2;
+  /* use the FREE_PROTECT here: it protects with sem OR SYS_ARCH_PROTECT */
+  LWIP_MEM_FREE_DECL_PROTECT();
 
   /* Expand the size of the allocated memory region so that we can
      adjust for alignment. */
@@ -346,7 +377,12 @@ mem_realloc(void *rmem, mem_size_t newsi
    (u8_t *)rmem < (u8_t *)ram_end);
 
   if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
+    SYS_ARCH_DECL_PROTECT(lev);
     LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_realloc: illegal memory\n"));
+    /* protect mem stats from concurrent access */
+    SYS_ARCH_PROTECT(lev);
+    MEM_STATS_INC(illegal);
+    SYS_ARCH_UNPROTECT(lev);
     return rmem;
   }
   /* Get the corresponding struct mem ... */
@@ -366,11 +402,9 @@ mem_realloc(void *rmem, mem_size_t newsi
   }
 
   /* protect the heap from concurrent access */
-  sys_arch_sem_wait(mem_sem, 0);
+  LWIP_MEM_FREE_PROTECT();
 
-#if MEM_STATS
-  lwip_stats.mem.used -= (size - newsize);
-#endif /* MEM_STATS */
+  MEM_STATS_DEC_USED(used, (size - newsize));
 
   mem2 = (struct mem *)&ram[mem->next];
   if(mem2->used == 0) {
@@ -426,7 +460,10 @@ mem_realloc(void *rmem, mem_size_t newsi
     -> don't do anyhting. 
     -> the remaining space stays unused since it is too small
   } */
-  sys_sem_signal(mem_sem);
+#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
+  mem_free_count = 1;
+#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
+  LWIP_MEM_FREE_UNPROTECT();
   return rmem;
 }
 
@@ -444,6 +481,10 @@ mem_malloc(mem_size_t size)
 {
   mem_size_t ptr, ptr2;
   struct mem *mem, *mem2;
+#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
+  u8_t local_mem_free_count = 0;
+#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
+  LWIP_MEM_ALLOC_DECL_PROTECT();
 
   if (size == 0) {
     return NULL;
@@ -464,88 +505,101 @@ mem_malloc(mem_size_t size)
 
   /* protect the heap from concurrent access */
   sys_arch_sem_wait(mem_sem, 0);
+  LWIP_MEM_ALLOC_PROTECT();
+#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
+  /* run as long as a mem_free disturbed mem_malloc */
+  do {
+    local_mem_free_count = 0;
+#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
+
+    /* Scan through the heap searching for a free block that is big enough,
+     * beginning with the lowest free block.
+     */
+    for (ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE_ALIGNED - size;
+         ptr = ((struct mem *)&ram[ptr])->next) {
+      mem = (struct mem *)&ram[ptr];
+#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
+      mem_free_count = 0;
+      LWIP_MEM_ALLOC_UNPROTECT();
+      /* allow mem_free to run */
+      LWIP_MEM_ALLOC_PROTECT();
+      if (mem_free_count != 0) {
+        local_mem_free_count = mem_free_count;
+      }
+      mem_free_count = 0;
+#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
 
-  /* Scan through the heap searching for a free block that is big enough,
-   * beginning with the lowest free block.
-   */
-  for (ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE_ALIGNED - size;
-       ptr = ((struct mem *)&ram[ptr])->next) {
-    mem = (struct mem *)&ram[ptr];
-
-    if ((!mem->used) &&
-        (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) {
-      /* mem is not used and at least perfect fit is possible:
-       * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */
-
-      if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) {
-        /* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing
-         * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem')
-         * -> split large block, create empty remainder,
-         * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if
-         * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size,
-         * struct mem would fit in but no data between mem2 and mem2->next
-         * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty
-         *       region that couldn't hold data, but when mem->next gets freed,
-         *       the 2 regions would be combined, resulting in more free memory
-         */
-        ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
-        /* create mem2 struct */
-        mem2 = (struct mem *)&ram[ptr2];
-        mem2->used = 0;
-        mem2->next = mem->next;
-        mem2->prev = ptr;
-        /* and insert it between mem and mem->next */
-        mem->next = ptr2;
-        mem->used = 1;
-
-        if (mem2->next != MEM_SIZE_ALIGNED) {
-          ((struct mem *)&ram[mem2->next])->prev = ptr2;
-        }
-#if MEM_STATS
-        lwip_stats.mem.used += (size + SIZEOF_STRUCT_MEM);
-        if (lwip_stats.mem.max < lwip_stats.mem.used) {
-          lwip_stats.mem.max = lwip_stats.mem.used;
+      if ((!mem->used) &&
+          (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) {
+        /* mem is not used and at least perfect fit is possible:
+         * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */
+
+        if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) {
+          /* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing
+           * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem')
+           * -> split large block, create empty remainder,
+           * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if
+           * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size,
+           * struct mem would fit in but no data between mem2 and mem2->next
+           * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty
+           *       region that couldn't hold data, but when mem->next gets freed,
+           *       the 2 regions would be combined, resulting in more free memory
+           */
+          ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
+          /* create mem2 struct */
+          mem2 = (struct mem *)&ram[ptr2];
+          mem2->used = 0;
+          mem2->next = mem->next;
+          mem2->prev = ptr;
+          /* and insert it between mem and mem->next */
+          mem->next = ptr2;
+          mem->used = 1;
+
+          if (mem2->next != MEM_SIZE_ALIGNED) {
+            ((struct mem *)&ram[mem2->next])->prev = ptr2;
+          }
+          MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM));
+        } else {
+          /* (a mem2 struct does no fit into the user data space of mem and mem->next will always
+           * be used at this point: if not we have 2 unused structs in a row, plug_holes should have
+           * take care of this).
+           * -> near fit or excact fit: do not split, no mem2 creation
+           * also can't move mem->next directly behind mem, since mem->next
+           * will always be used at this point!
+           */
+          mem->used = 1;
+          MEM_STATS_INC_USED(used, mem->next - ((u8_t *)mem - ram));
         }
-#endif /* MEM_STATS */
-      } else {
-        /* (a mem2 struct does no fit into the user data space of mem and mem->next will always
-         * be used at this point: if not we have 2 unused structs in a row, plug_holes should have
-         * take care of this).
-         * -> near fit or excact fit: do not split, no mem2 creation
-         * also can't move mem->next directly behind mem, since mem->next
-         * will always be used at this point!
-         */
-        mem->used = 1;
-#if MEM_STATS
-        lwip_stats.mem.used += mem->next - ((u8_t *)mem - ram);
-        if (lwip_stats.mem.max < lwip_stats.mem.used) {
-          lwip_stats.mem.max = lwip_stats.mem.used;
-        }
-#endif /* MEM_STATS */
-      }
 
-      if (mem == lfree) {
-        /* Find next free block after mem and update lowest free pointer */
-        while (lfree->used && lfree != ram_end) {
-          lfree = (struct mem *)&ram[lfree->next];
+        if (mem == lfree) {
+          /* Find next free block after mem and update lowest free pointer */
+          while (lfree->used && lfree != ram_end) {
+            LWIP_MEM_ALLOC_UNPROTECT();
+            /* prevent high interrupt latency... */
+            LWIP_MEM_ALLOC_PROTECT();
+            lfree = (struct mem *)&ram[lfree->next];
+          }
+          LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used)));
         }
-        LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used)));
-      }
-      sys_sem_signal(mem_sem);
-      LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
-       (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
-      LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
-       (unsigned long)((u8_t *)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
-      LWIP_ASSERT("mem_malloc: sanity check alignment",
-        (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0);
+        LWIP_MEM_ALLOC_UNPROTECT();
+        sys_sem_signal(mem_sem);
+        LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
+         (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
+        LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
+         (unsigned long)((u8_t *)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
+        LWIP_ASSERT("mem_malloc: sanity check alignment",
+          (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0);
 
-      return (u8_t *)mem + SIZEOF_STRUCT_MEM;
+        return (u8_t *)mem + SIZEOF_STRUCT_MEM;
+      }
     }
-  }
+#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
+    /* 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));
-#if MEM_STATS
-  ++lwip_stats.mem.err;
-#endif /* MEM_STATS */
+  MEM_STATS_INC(err);
+  LWIP_MEM_ALLOC_UNPROTECT();
   sys_sem_signal(mem_sem);
   return NULL;
 }
Index: src/core/memp.c
===================================================================
RCS file: /sources/lwip/lwip/src/core/memp.c,v
retrieving revision 1.55
retrieving revision 1.56
diff -u -p -r1.55 -r1.56
--- src/core/memp.c	25 Nov 2007 10:43:28 -0000	1.55
+++ src/core/memp.c	27 Jun 2008 18:37:54 -0000	1.56
@@ -252,13 +252,12 @@ memp_init(void)
   struct memp *memp;
   u16_t i, j;
 
-#if MEMP_STATS
   for (i = 0; i < MEMP_MAX; ++i) {
-    lwip_stats.memp[i].used = lwip_stats.memp[i].max =
-      lwip_stats.memp[i].err = 0;
-    lwip_stats.memp[i].avail = memp_num[i];
+    MEMP_STATS_AVAIL(used, i, 0);
+    MEMP_STATS_AVAIL(max, i, 0);
+    MEMP_STATS_AVAIL(err, i, 0);
+    MEMP_STATS_AVAIL(avail, i, memp_num[i]);
   }
-#endif /* MEMP_STATS */
 
   memp = LWIP_MEM_ALIGN(memp_memory);
   /* for every pool: */
@@ -315,20 +314,13 @@ memp_malloc_fn(memp_t type, const char* 
     memp->file = file;
     memp->line = line;
 #endif /* MEMP_OVERFLOW_CHECK */
-#if MEMP_STATS
-    ++lwip_stats.memp[type].used;
-    if (lwip_stats.memp[type].used > lwip_stats.memp[type].max) {
-      lwip_stats.memp[type].max = lwip_stats.memp[type].used;
-    }
-#endif /* MEMP_STATS */
+    MEMP_STATS_INC_USED(used, type);
     LWIP_ASSERT("memp_malloc: memp properly aligned",
                 ((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]));
-#if MEMP_STATS
-    ++lwip_stats.memp[type].err;
-#endif /* MEMP_STATS */
+    MEMP_STATS_INC(err, type);
   }
 
   SYS_ARCH_UNPROTECT(old_level);
@@ -365,9 +357,7 @@ memp_free(memp_t type, void *mem)
 #endif /* MEMP_OVERFLOW_CHECK >= 2 */
 #endif /* MEMP_OVERFLOW_CHECK */
 
-#if MEMP_STATS
-  lwip_stats.memp[type].used--; 
-#endif /* MEMP_STATS */
+  MEMP_STATS_DEC(used, type); 
   
   memp->next = memp_tab[type]; 
   memp_tab[type] = memp;
Index: src/core/netif.c
===================================================================
RCS file: /sources/lwip/lwip/src/core/netif.c,v
retrieving revision 1.65
retrieving revision 1.68
diff -u -p -r1.65 -r1.68
--- src/core/netif.c	9 Oct 2007 20:00:55 -0000	1.65
+++ src/core/netif.c	19 Jun 2008 16:27:18 -0000	1.68
@@ -45,6 +45,12 @@
 #include "lwip/snmp.h"
 #include "lwip/igmp.h"
 #include "netif/etharp.h"
+#if ENABLE_LOOPBACK
+#include "lwip/sys.h"
+#if LWIP_NETIF_LOOPBACK_MULTITHREADING
+#include "lwip/tcpip.h"
+#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
+#endif /* ENABLE_LOOPBACK */
 
 #if LWIP_NETIF_STATUS_CALLBACK
 #define NETIF_STATUS_CALLBACK(n) { if (n->status_callback) (n->status_callback)(n); }
@@ -106,6 +112,10 @@ netif_add(struct netif *netif, struct ip
 #if LWIP_IGMP
   netif->igmp_mac_filter = NULL;
 #endif /* LWIP_IGMP */
+#if ENABLE_LOOPBACK
+  netif->loop_first = NULL;
+  netif->loop_last = NULL;
+#endif /* ENABLE_LOOPBACK */
 
   /* remember netif specific state information data */
   netif->state = state;
@@ -114,6 +124,9 @@ netif_add(struct netif *netif, struct ip
 #if LWIP_NETIF_HWADDRHINT
   netif->addr_hint = NULL;
 #endif /* LWIP_NETIF_HWADDRHINT*/
+#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS
+  netif->loop_cnt_current = 0;
+#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */
 
   netif_set_addr(netif, ipaddr, netmask, gw);
 
@@ -493,7 +506,158 @@ u8_t netif_is_link_up(struct netif *neti
  */
 void netif_set_link_callback(struct netif *netif, void (* link_callback)(struct netif *netif ))
 {
-    if ( netif )
-        netif->link_callback = link_callback;
+  if (netif) {
+    netif->link_callback = link_callback;
+  }
 }
 #endif /* LWIP_NETIF_LINK_CALLBACK */
+
+#if ENABLE_LOOPBACK
+/**
+ * Send an IP packet to be received on the same netif (loopif-like).
+ * The pbuf is simply copied and handed back to netif->input.
+ * In multithreaded mode, this is done directly since netif->input must put
+ * the packet on a queue.
+ * In callback mode, the packet is put on an internal queue and is fed to
+ * netif->input by netif_poll().
+ *
+ * @param netif the lwip network interface structure
+ * @param p the (IP) packet to 'send'
+ * @param ipaddr the ip address to send the packet to (not used)
+ * @return ERR_OK if the packet has been sent
+ *         ERR_MEM if the pbuf used to copy the packet couldn't be allocated
+ */
+err_t
+netif_loop_output(struct netif *netif, struct pbuf *p,
+       struct ip_addr *ipaddr)
+{
+  struct pbuf *r;
+  err_t err;
+  struct pbuf *last;
+#if LWIP_LOOPBACK_MAX_PBUFS
+  u8_t clen = 0;
+#endif /* LWIP_LOOPBACK_MAX_PBUFS */
+  SYS_ARCH_DECL_PROTECT(lev);
+  LWIP_UNUSED_ARG(ipaddr);
+
+  /* Allocate a new pbuf */
+  r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM);
+  if (r == NULL) {
+    return ERR_MEM;
+  }
+#if LWIP_LOOPBACK_MAX_PBUFS
+  clen = pbuf_clen(r);
+  /* check for overflow or too many pbuf on queue */
+  if(((netif->loop_cnt_current + clen) < netif->loop_cnt_current) ||
+    ((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) {
+      pbuf_free(r);
+      r = NULL;
+      return ERR_MEM;
+  }
+  netif->loop_cnt_current += clen;
+#endif /* LWIP_LOOPBACK_MAX_PBUFS */
+
+  /* Copy the whole pbuf queue p into the single pbuf r */
+  if ((err = pbuf_copy(r, p)) != ERR_OK) {
+    pbuf_free(r);
+    r = NULL;
+    return err;
+  }
+
+  /* Put the packet on a linked list which gets emptied through calling
+     netif_poll(). */
+
+  /* let last point to the last pbuf in chain r */
+  for (last = r; last->next != NULL; last = last->next);
+
+  SYS_ARCH_PROTECT(lev);
+  if(netif->loop_first != NULL) {
+    LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL);
+    netif->loop_last->next = r;
+    netif->loop_last = last;
+  } else {
+    netif->loop_first = r;
+    netif->loop_last = last;
+  }
+  SYS_ARCH_UNPROTECT(lev);
+
+#if LWIP_NETIF_LOOPBACK_MULTITHREADING
+  /* For multithreading environment, schedule a call to netif_poll */
+  tcpip_callback(netif_poll, netif);
+#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
+
+  return ERR_OK;
+}
+
+/**
+ * Call netif_poll() in the main loop of your application. This is to prevent
+ * reentering non-reentrant functions like tcp_input(). Packets passed to
+ * netif_loop_output() are put on a list that is passed to netif->input() by
+ * netif_poll().
+ */
+void
+netif_poll(struct netif *netif)
+{
+  struct pbuf *in;
+  SYS_ARCH_DECL_PROTECT(lev);
+
+  do {
+    /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
+    SYS_ARCH_PROTECT(lev);
+    in = netif->loop_first;
+    if(in != NULL) {
+      struct pbuf *in_end = in;
+#if LWIP_LOOPBACK_MAX_PBUFS
+      u8_t clen = pbuf_clen(in);
+      /* adjust the number of pbufs on queue */
+      LWIP_ASSERT("netif->loop_cnt_current underflow",
+        ((netif->loop_cnt_current - clen) < netif->loop_cnt_current));
+      netif->loop_cnt_current -= clen;
+#endif /* LWIP_LOOPBACK_MAX_PBUFS */
+      while(in_end->len != in_end->tot_len) {
+        LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
+        in_end = in_end->next;
+      }
+      /* 'in_end' now points to the last pbuf from 'in' */
+      if(in_end == netif->loop_last) {
+        /* this was the last pbuf in the list */
+        netif->loop_first = netif->loop_last = NULL;
+      } else {
+        /* pop the pbuf off the list */
+        netif->loop_first = in_end->next;
+        LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL);
+      }
+      /* De-queue the pbuf from its successors on the 'loop_' list. */
+      in_end->next = NULL;
+    }
+    SYS_ARCH_UNPROTECT(lev);
+
+    if(in != NULL) {
+      /* loopback packets are always IP packets! */
+      if(ip_input(in, netif) != ERR_OK) {
+        pbuf_free(in);
+      }
+      /* Don't reference the packet any more! */
+      in = NULL;
+    }
+  /* go on while there is a packet on the list */
+  } while(netif->loop_first != NULL);
+}
+
+#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
+/**
+ * Calls netif_poll() for every netif on the netif_list.
+ */
+void
+netif_poll_all(void)
+{
+  struct netif *netif = netif_list;
+  /* loop through netifs */
+  while (netif != NULL) {
+    netif_poll(netif);
+    /* proceed to next network interface */
+    netif = netif->next;
+  }
+}
+#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
+#endif /* ENABLE_LOOPBACK */
Index: src/core/pbuf.c
===================================================================
RCS file: /sources/lwip/lwip/src/core/pbuf.c,v
retrieving revision 1.127
retrieving revision 1.128
diff -u -p -r1.127 -r1.128
--- src/core/pbuf.c	4 Mar 2008 16:37:46 -0000	1.127
+++ src/core/pbuf.c	1 Apr 2008 19:05:40 -0000	1.128
@@ -667,8 +667,8 @@ pbuf_dechain(struct pbuf *p)
  *
  * @note Only one packet is copied, no packet queue!
  *
- * @param p_to pbuf source of the copy
- * @param p_from pbuf destination of the copy
+ * @param p_to pbuf destination of the copy
+ * @param p_from pbuf source of the copy
  *
  * @return ERR_OK if pbuf was copied
  *         ERR_ARG if one of the pbufs is NULL or p_to is not big
Index: src/core/stats.c
===================================================================
RCS file: /sources/lwip/lwip/src/core/stats.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -p -r1.27 -r1.28
--- src/core/stats.c	4 Mar 2008 16:31:32 -0000	1.27
+++ src/core/stats.c	27 Jun 2008 18:37:54 -0000	1.28
@@ -54,7 +54,6 @@ stats_display_proto(struct stats_proto *
 {
   LWIP_PLATFORM_DIAG(("\n%s\n\t", name));
   LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", proto->xmit)); 
-  LWIP_PLATFORM_DIAG(("rexmit: %"STAT_COUNTER_F"\n\t", proto->rexmit)); 
   LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", proto->recv)); 
   LWIP_PLATFORM_DIAG(("fw: %"STAT_COUNTER_F"\n\t", proto->fw)); 
   LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", proto->drop)); 
@@ -68,6 +67,7 @@ stats_display_proto(struct stats_proto *
   LWIP_PLATFORM_DIAG(("cachehit: %"STAT_COUNTER_F"\n", proto->cachehit)); 
 }
 
+#if IGMP_STATS
 void
 stats_display_igmp(struct stats_igmp *igmp)
 {
@@ -82,7 +82,9 @@ stats_display_igmp(struct stats_igmp *ig
   LWIP_PLATFORM_DIAG(("report_rxed: %"STAT_COUNTER_F"\n\t", igmp->report_rxed)); 
   LWIP_PLATFORM_DIAG(("group_query_rxed: %"STAT_COUNTER_F"\n", igmp->group_query_rxed));
 }
+#endif /* IGMP_STATS */
 
+#if MEM_STATS || MEMP_STATS
 void
 stats_display_mem(struct stats_mem *mem, char *name)
 {
@@ -93,48 +95,53 @@ stats_display_mem(struct stats_mem *mem,
   LWIP_PLATFORM_DIAG(("err: %"U32_F"\n", (u32_t)mem->err));
 }
 
+#if MEMP_STATS
 void
-stats_display(void)
+stats_display_memp(struct stats_mem *mem, int index)
 {
-#if MEMP_STATS
-  s16_t i;
   char * memp_names[] = {
 #define LWIP_MEMPOOL(name,num,size,desc) desc,
 #include "lwip/memp_std.h"
   };
-#endif
-#if LINK_STATS
-  stats_display_proto(&lwip_stats.link, "LINK");
-#endif
-#if ETHARP_STATS
-  stats_display_proto(&lwip_stats.etharp, "ETHARP");
-#endif
-#if IPFRAG_STATS
-  stats_display_proto(&lwip_stats.ip_frag, "IP_FRAG");
-#endif
-#if IP_STATS
-  stats_display_proto(&lwip_stats.ip, "IP");
-#endif
-#if ICMP_STATS
-  stats_display_proto(&lwip_stats.icmp, "ICMP");
-#endif
-#if IGMP_STATS
-  stats_display_igmp(&lwip_stats.igmp);
-#endif
-#if UDP_STATS
-  stats_display_proto(&lwip_stats.udp, "UDP");
-#endif
-#if TCP_STATS
-  stats_display_proto(&lwip_stats.tcp, "TCP");
-#endif
-#if MEM_STATS
-  stats_display_mem(&lwip_stats.mem, "HEAP");
-#endif
-#if MEMP_STATS
+  if(index < MEMP_MAX) {
+    stats_display_mem(mem, memp_names[index]);
+  }
+}
+#endif /* MEMP_STATS */
+#endif /* MEM_STATS || MEMP_STATS */
+
+#if SYS_STATS
+void
+stats_display_sys(struct stats_sys *sys)
+{
+  LWIP_PLATFORM_DIAG(("\nSYS\n\t"));
+  LWIP_PLATFORM_DIAG(("sem.used: %"U32_F"\n\t", (u32_t)sys->sem.used)); 
+  LWIP_PLATFORM_DIAG(("sem.max:  %"U32_F"\n\t", (u32_t)sys->sem.max)); 
+  LWIP_PLATFORM_DIAG(("sem.err:  %"U32_F"\n\t", (u32_t)sys->sem.err)); 
+  LWIP_PLATFORM_DIAG(("mbox.used: %"U32_F"\n\t", (u32_t)sys->mbox.used)); 
+  LWIP_PLATFORM_DIAG(("mbox.max:  %"U32_F"\n\t", (u32_t)sys->mbox.max)); 
+  LWIP_PLATFORM_DIAG(("mbox.err:  %"U32_F"\n\t", (u32_t)sys->mbox.err)); 
+}
+#endif /* SYS_STATS */
+
+void
+stats_display(void)
+{
+  s16_t i;
+
+  LINK_STATS_DISPLAY();
+  ETHARP_STATS_DISPLAY();
+  IPFRAG_STATS_DISPLAY();
+  IP_STATS_DISPLAY();
+  IGMP_STATS_DISPLAY();
+  ICMP_STATS_DISPLAY();
+  UDP_STATS_DISPLAY();
+  TCP_STATS_DISPLAY();
+  MEM_STATS_DISPLAY();
   for (i = 0; i < MEMP_MAX; i++) {
-    stats_display_mem(&lwip_stats.memp[i], memp_names[i]);
+    MEMP_STATS_DISPLAY(i);
   }
-#endif
+  SYS_STATS_DISPLAY();
 }
 #endif /* LWIP_STATS_DISPLAY */
 
Index: src/core/sys.c
===================================================================
RCS file: /sources/lwip/lwip/src/core/sys.c,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -p -r1.32 -r1.33
--- src/core/sys.c	25 Nov 2007 13:57:05 -0000	1.32
+++ src/core/sys.c	16 Jul 2008 20:36:12 -0000	1.33
@@ -65,7 +65,7 @@ struct sswt_cb
 void
 sys_mbox_fetch(sys_mbox_t mbox, void **msg)
 {
-  u32_t time;
+  u32_t time_needed;
   struct sys_timeouts *timeouts;
   struct sys_timeo *tmptimeout;
   sys_timeout_handler h;
@@ -76,18 +76,18 @@ sys_mbox_fetch(sys_mbox_t mbox, void **m
 
   if (!timeouts || !timeouts->next) {
     UNLOCK_TCPIP_CORE();
-    time = sys_arch_mbox_fetch(mbox, msg, 0);
+    time_needed = sys_arch_mbox_fetch(mbox, msg, 0);
     LOCK_TCPIP_CORE();
   } else {
     if (timeouts->next->time > 0) {
       UNLOCK_TCPIP_CORE();
-      time = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time);
+      time_needed = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time);
       LOCK_TCPIP_CORE();
     } else {
-      time = SYS_ARCH_TIMEOUT;
+      time_needed = SYS_ARCH_TIMEOUT;
     }
 
-    if (time == SYS_ARCH_TIMEOUT) {
+    if (time_needed == SYS_ARCH_TIMEOUT) {
       /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
          could be fetched. We should now call the timeout handler and
          deallocate the memory allocated for the timeout. */
@@ -107,8 +107,8 @@ sys_mbox_fetch(sys_mbox_t mbox, void **m
       /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
          occured. The time variable is set to the number of
          milliseconds we waited for the message. */
-      if (time < timeouts->next->time) {
-        timeouts->next->time -= time;
+      if (time_needed < timeouts->next->time) {
+        timeouts->next->time -= time_needed;
       } else {
         timeouts->next->time = 0;
       }
@@ -125,7 +125,7 @@ sys_mbox_fetch(sys_mbox_t mbox, void **m
 void
 sys_sem_wait(sys_sem_t sem)
 {
-  u32_t time;
+  u32_t time_needed;
   struct sys_timeouts *timeouts;
   struct sys_timeo *tmptimeout;
   sys_timeout_handler h;
@@ -139,12 +139,12 @@ sys_sem_wait(sys_sem_t sem)
     sys_arch_sem_wait(sem, 0);
   } else {
     if (timeouts->next->time > 0) {
-      time = sys_arch_sem_wait(sem, timeouts->next->time);
+      time_needed = sys_arch_sem_wait(sem, timeouts->next->time);
     } else {
-      time = SYS_ARCH_TIMEOUT;
+      time_needed = SYS_ARCH_TIMEOUT;
     }
 
-    if (time == SYS_ARCH_TIMEOUT) {
+    if (time_needed == SYS_ARCH_TIMEOUT) {
       /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
         could be fetched. We should now call the timeout handler and
         deallocate the memory allocated for the timeout. */
@@ -164,8 +164,8 @@ sys_sem_wait(sys_sem_t sem)
       /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
          occured. The time variable is set to the number of
          milliseconds we waited for the message. */
-      if (time < timeouts->next->time) {
-        timeouts->next->time -= time;
+      if (time_needed < timeouts->next->time) {
+        timeouts->next->time -= time_needed;
       } else {
         timeouts->next->time = 0;
       }
Index: src/core/tcp.c
===================================================================
RCS file: /sources/lwip/lwip/src/core/tcp.c,v
retrieving revision 1.85
retrieving revision 1.86
diff -u -p -r1.85 -r1.86
--- src/core/tcp.c	22 Jan 2008 21:15:15 -0000	1.85
+++ src/core/tcp.c	26 Mar 2008 11:57:13 -0000	1.86
@@ -509,7 +509,8 @@ tcp_connect(struct tcp_pcb *pcb, struct 
   pcb->rcv_wnd = TCP_WND;
   pcb->rcv_ann_wnd = TCP_WND;
   pcb->snd_wnd = TCP_WND;
-  /* The send MSS is updated when an MSS option is received. */
+  /* As initial send MSS, we use TCP_MSS but limit it to 536.
+     The send MSS is updated when an MSS option is received. */
   pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
 #if TCP_CALCULATE_EFF_SEND_MSS
   pcb->mss = tcp_eff_send_mss(pcb->mss, ipaddr);
@@ -991,7 +992,8 @@ tcp_alloc(u8_t prio)
     pcb->rcv_ann_wnd = TCP_WND;
     pcb->tos = 0;
     pcb->ttl = TCP_TTL;
-    /* The send MSS is updated when an MSS option is received. */
+    /* As initial send MSS, we use TCP_MSS but limit it to 536.
+       The send MSS is updated when an MSS option is received. */
     pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
     pcb->rto = 3000 / TCP_SLOW_INTERVAL;
     pcb->sa = 0;
Index: src/core/tcp_in.c
===================================================================
RCS file: /sources/lwip/lwip/src/core/tcp_in.c,v
retrieving revision 1.97
retrieving revision 1.100
diff -u -p -r1.97 -r1.100
--- src/core/tcp_in.c	22 Jan 2008 21:15:15 -0000	1.97
+++ src/core/tcp_in.c	24 Jun 2008 15:46:39 -0000	1.100
@@ -511,7 +511,7 @@ tcp_process(struct tcp_pcb *pcb)
       }
     } else {
       if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, 
-                          pcb->rcv_nxt+pcb->rcv_ann_wnd)) {
+                          pcb->rcv_nxt+pcb->rcv_wnd)) {
         acceptable = 1;
       }
     }
@@ -1038,7 +1038,7 @@ tcp_receive(struct tcp_pcb *pcb)
        and below rcv_nxt + rcv_wnd) in order to be further
        processed. */
     if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, 
-                        pcb->rcv_nxt + pcb->rcv_ann_wnd - 1)){
+                        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
@@ -1195,14 +1195,14 @@ tcp_receive(struct tcp_pcb *pcb)
                   } 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_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);
+                    }
                   }
                 }
                 break;
@@ -1282,10 +1282,7 @@ tcp_receive(struct tcp_pcb *pcb)
 
       }
     } else {
-      if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, 
-                          pcb->rcv_nxt + pcb->rcv_ann_wnd-1)){
-        tcp_ack_now(pcb);
-      }
+      tcp_ack_now(pcb);
     }
   } else {
     /* Segments with length 0 is taken care of here. Segments that
@@ -1331,7 +1328,8 @@ tcp_parseopt(struct tcp_pcb *pcb)
         opts[c + 1] == 0x04) {
         /* An MSS option with the right option length. */
         mss = (opts[c + 2] << 8) | opts[c + 3];
-        pcb->mss = mss > TCP_MSS? TCP_MSS: mss;
+        /* Limit the mss to the configured TCP_MSS and prevent division by zero */
+        pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss;
 
         /* And we are done processing options. */
         break;
Index: src/core/ipv4/autoip.c
===================================================================
RCS file: /sources/lwip/lwip/src/core/ipv4/autoip.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -p -r1.16 -r1.17
--- src/core/ipv4/autoip.c	26 Jan 2008 16:11:40 -0000	1.16
+++ src/core/ipv4/autoip.c	17 Jun 2008 20:16:23 -0000	1.17
@@ -395,8 +395,8 @@ autoip_arp_reply(struct netif *netif, st
     /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
      * structure packing (not using structure copy which breaks strict-aliasing rules).
      */
-    MEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr));
-    MEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr));
+    SMEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr));
+    SMEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr));
       
     if ((netif->autoip->state == AUTOIP_STATE_PROBING) ||
         ((netif->autoip->state == AUTOIP_STATE_ANNOUNCING) &&
Index: src/core/ipv4/inet_chksum.c
===================================================================
RCS file: /sources/lwip/lwip/src/core/ipv4/inet_chksum.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -p -r1.4 -r1.5
--- src/core/ipv4/inet_chksum.c	10 Mar 2008 16:12:31 -0000	1.4
+++ src/core/ipv4/inet_chksum.c	17 Jun 2008 20:06:25 -0000	1.5
@@ -41,8 +41,6 @@
 #include "lwip/inet_chksum.h"
 #include "lwip/inet.h"
 
-#include <string.h>
-
 /* These are some reference implementations of the checksum algorithm, with the
  * aim of being simple, correct and fully portable. Checksumming is the
  * first thing you would want to optimize for your platform. If you create
@@ -65,6 +63,11 @@
 # define LWIP_CHKSUM_ALGORITHM 0
 #endif
 
+/** Like the name says... */
+#define SWAP_BYTES_IN_WORD(w) ((w & 0xff) << 8) | ((w & 0xff00) >> 8)
+/** Split an u32_t in two u16_ts and add them up */
+#define FOLD_U32T(u)          ((u >> 16) + (u & 0x0000ffffUL))
+
 #if (LWIP_CHKSUM_ALGORITHM == 1) /* Version #1 */
 /**
  * lwip checksum
@@ -86,8 +89,7 @@ lwip_standard_chksum(void *dataptr, u16_
   acc = 0;
   /* dataptr may be at odd or even addresses */
   octetptr = (u8_t*)dataptr;
-  while (len > 1)
-  {
+  while (len > 1) {
     /* declare first octet as most significant
        thus assume network order, ignoring host order */
     src = (*octetptr) << 8;
@@ -98,8 +100,7 @@ lwip_standard_chksum(void *dataptr, u16_
     acc += src;
     len -= 2;
   }
-  if (len > 0)
-  {
+  if (len > 0) {
     /* accumulate remaining octet */
     src = (*octetptr) << 8;
     acc += src;
@@ -154,19 +155,22 @@ lwip_standard_chksum(void *dataptr, int 
   }
 
   /* Consume left-over byte, if any */
-  if (len > 0)
+  if (len > 0) {
     ((u8_t *)&t)[0] = *(u8_t *)ps;;
+  }
 
   /* Add end bytes */
   sum += t;
 
-  /*  Fold 32-bit sum to 16 bits */
-  while ((sum >> 16) != 0)
-    sum = (sum & 0xffff) + (sum >> 16);
+  /* Fold 32-bit sum to 16 bits
+     calling this twice is propably faster than if statements... */
+  sum = FOLD_U32T(sum);
+  sum = FOLD_U32T(sum);
 
   /* Swap if alignment was odd */
-  if (odd)
-    sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8);
+  if (odd) {
+    sum = SWAP_BYTES_IN_WORD(sum);
+  }
 
   return sum;
 }
@@ -211,18 +215,20 @@ lwip_standard_chksum(void *dataptr, int 
 
   while (len > 7)  {
     tmp = sum + *pl++;          /* ping */
-    if (tmp < sum)
+    if (tmp < sum) {
       tmp++;                    /* add back carry */
+    }
 
     sum = tmp + *pl++;          /* pong */
-    if (sum < tmp)
+    if (sum < tmp) {
       sum++;                    /* add back carry */
+    }
 
     len -= 8;
   }
 
   /* make room in upper bits */
-  sum = (sum >> 16) + (sum & 0xffff);
+  sum = FOLD_U32T(sum);
 
   ps = (u16_t *)pl;
 
@@ -233,16 +239,20 @@ lwip_standard_chksum(void *dataptr, int 
   }
 
   /* dangling tail byte remaining? */
-  if (len > 0)                  /* include odd byte */
+  if (len > 0) {                /* include odd byte */
     ((u8_t *)&t)[0] = *(u8_t *)ps;
+  }
 
   sum += t;                     /* add end bytes */
 
-  while ((sum >> 16) != 0)      /* combine halves */
-    sum = (sum >> 16) + (sum & 0xffff);
+  /* Fold 32-bit sum to 16 bits
+     calling this twice is propably faster than if statements... */
+  sum = FOLD_U32T(sum);
+  sum = FOLD_U32T(sum);
 
-  if (odd)
-    sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8);
+  if (odd) {
+    sum = SWAP_BYTES_IN_WORD(sum);
+  }
 
   return sum;
 }
@@ -277,18 +287,18 @@ inet_chksum_pseudo(struct pbuf *p,
       (void *)q, (void *)q->next));
     acc += LWIP_CHKSUM(q->payload, q->len);
     /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
-    while ((acc >> 16) != 0) {
-      acc = (acc & 0xffffUL) + (acc >> 16);
-    }
+    /* just executing this next line is probably faster that the if statement needed
+       to check whether we really need to execute it, and does no harm */
+    acc = FOLD_U32T(acc);
     if (q->len % 2 != 0) {
       swapped = 1 - swapped;
-      acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
+      acc = SWAP_BYTES_IN_WORD(acc);
     }
     /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
   }
 
   if (swapped) {
-    acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
+    acc = SWAP_BYTES_IN_WORD(acc);
   }
   acc += (src->addr & 0xffffUL);
   acc += ((src->addr >> 16) & 0xffffUL);
@@ -297,9 +307,10 @@ inet_chksum_pseudo(struct pbuf *p,
   acc += (u32_t)htons((u16_t)proto);
   acc += (u32_t)htons(proto_len);
 
-  while ((acc >> 16) != 0) {
-    acc = (acc & 0xffffUL) + (acc >> 16);
-  }
+  /* Fold 32-bit sum to 16 bits
+     calling this twice is propably faster than if statements... */
+  acc = FOLD_U32T(acc);
+  acc = FOLD_U32T(acc);
   LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
   return (u16_t)~(acc & 0xffffUL);
 }
@@ -340,18 +351,17 @@ inet_chksum_pseudo_partial(struct pbuf *
     chksum_len -= chklen;
     LWIP_ASSERT("delete me", chksum_len < 0x7fff);
     /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
-    while ((acc >> 16) != 0) {
-      acc = (acc & 0xffffUL) + (acc >> 16);
-    }
+    /* fold the upper bit down */
+    acc = FOLD_U32T(acc);
     if (q->len % 2 != 0) {
       swapped = 1 - swapped;
-      acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
+      acc = SWAP_BYTES_IN_WORD(acc);
     }
     /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
   }
 
   if (swapped) {
-    acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
+    acc = SWAP_BYTES_IN_WORD(acc);
   }
   acc += (src->addr & 0xffffUL);
   acc += ((src->addr >> 16) & 0xffffUL);
@@ -360,9 +370,10 @@ inet_chksum_pseudo_partial(struct pbuf *
   acc += (u32_t)htons((u16_t)proto);
   acc += (u32_t)htons(proto_len);
 
-  while ((acc >> 16) != 0) {
-    acc = (acc & 0xffffUL) + (acc >> 16);
-  }
+  /* Fold 32-bit sum to 16 bits
+     calling this twice is propably faster than if statements... */
+  acc = FOLD_U32T(acc);
+  acc = FOLD_U32T(acc);
   LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
   return (u16_t)~(acc & 0xffffUL);
 }
@@ -380,13 +391,7 @@ inet_chksum_pseudo_partial(struct pbuf *
 u16_t
 inet_chksum(void *dataptr, u16_t len)
 {
-  u32_t acc;
-
-  acc = LWIP_CHKSUM(dataptr, len);
-  while ((acc >> 16) != 0) {
-    acc = (acc & 0xffff) + (acc >> 16);
-  }
-  return (u16_t)~(acc & 0xffff);
+  return ~LWIP_CHKSUM(dataptr, len);
 }
 
 /**
@@ -407,17 +412,15 @@ inet_chksum_pbuf(struct pbuf *p)
   swapped = 0;
   for(q = p; q != NULL; q = q->next) {
     acc += LWIP_CHKSUM(q->payload, q->len);
-    while ((acc >> 16) != 0) {
-      acc = (acc & 0xffffUL) + (acc >> 16);
-    }
+    acc = FOLD_U32T(acc);
     if (q->len % 2 != 0) {
       swapped = 1 - swapped;
-      acc = (acc & 0x00ffUL << 8) | (acc & 0xff00UL >> 8);
+      acc = SWAP_BYTES_IN_WORD(acc);
     }
   }
 
   if (swapped) {
-    acc = ((acc & 0x00ffUL) << 8) | ((acc & 0xff00UL) >> 8);
+    acc = SWAP_BYTES_IN_WORD(acc);
   }
   return (u16_t)~(acc & 0xffffUL);
 }
Index: src/core/ipv4/ip.c
===================================================================
RCS file: /sources/lwip/lwip/src/core/ipv4/ip.c,v
retrieving revision 1.66
retrieving revision 1.68
diff -u -p -r1.66 -r1.68
--- src/core/ipv4/ip.c	14 Jan 2008 20:53:23 -0000	1.66
+++ src/core/ipv4/ip.c	17 Jun 2008 19:39:22 -0000	1.68
@@ -531,9 +531,19 @@ ip_output_if(struct pbuf *p, struct ip_a
   LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num));
   ip_debug_print(p);
 
-  LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
+#if (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF)
+  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);
+    return netif->output(netif, p, dest);
+  }
 }
 
 /**
Index: src/include/lwip/debug.h
===================================================================
RCS file: /sources/lwip/lwip/src/include/lwip/debug.h,v
retrieving revision 1.37
retrieving revision 1.39
diff -u -p -r1.37 -r1.39
--- src/include/lwip/debug.h	22 Sep 2007 11:16:07 -0000	1.37
+++ src/include/lwip/debug.h	16 Jul 2008 20:36:22 -0000	1.39
@@ -61,26 +61,28 @@
 #define LWIP_DBG_HALT          0x08U
 
 #ifndef LWIP_NOASSERT
-#define LWIP_ASSERT(x,y) do { if(!(y)) LWIP_PLATFORM_ASSERT(x); } while(0)
+#define LWIP_ASSERT(message, assertion) do { if(!(assertion)) \
+  LWIP_PLATFORM_ASSERT(message); } while(0)
 #else  /* LWIP_NOASSERT */
-#define LWIP_ASSERT(x,y) 
+#define LWIP_ASSERT(message, assertion) 
 #endif /* LWIP_NOASSERT */
 
-/** print "m" message only if "e" is true, and execute "h" expression */
+/** if "expression" isn't true, then print "message" and execute "handler" expression */
 #ifndef LWIP_ERROR
-#define LWIP_ERROR(m,e,h) do { if (!(e)) { LWIP_PLATFORM_ASSERT(m); h;}} while(0)
+#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \
+  LWIP_PLATFORM_ASSERT(message); handler;}} while(0)
 #endif /* LWIP_ERROR */
 
 #ifdef LWIP_DEBUG
 /** print debug message only if debug message type is enabled...
  *  AND is of correct type AND is at least LWIP_DBG_LEVEL
  */
-#define LWIP_DEBUGF(debug,x) do { \
+#define LWIP_DEBUGF(debug, message) do { \
                                if ( \
                                    ((debug) & LWIP_DBG_ON) && \
                                    ((debug) & LWIP_DBG_TYPES_ON) && \
                                    ((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) { \
-                                 LWIP_PLATFORM_DIAG(x); \
+                                 LWIP_PLATFORM_DIAG(message); \
                                  if ((debug) & LWIP_DBG_HALT) { \
                                    while(1); \
                                  } \
@@ -88,7 +90,7 @@
                              } while(0)
 
 #else  /* LWIP_DEBUG */
-#define LWIP_DEBUGF(debug,x) 
+#define LWIP_DEBUGF(debug, message) 
 #endif /* LWIP_DEBUG */
 
 #endif /* __LWIP_DEBUG_H__ */
Index: src/include/lwip/err.h
===================================================================
RCS file: /sources/lwip/lwip/src/include/lwip/err.h,v
retrieving revision 1.13
retrieving revision 1.15
diff -u -p -r1.13 -r1.15
--- src/include/lwip/err.h	13 Dec 2007 23:06:50 -0000	1.13
+++ src/include/lwip/err.h	17 Jun 2008 20:27:32 -0000	1.15
@@ -33,37 +33,43 @@
 #define __LWIP_ERR_H__
 
 #include "lwip/opt.h"
+#include "lwip/arch.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-typedef s8_t err_t;
+/** Define LWIP_ERR_T in cc.h if you want to use
+ *  a different type for your platform (must be signed). */
+#ifdef LWIP_ERR_T
+typedef LWIP_ERR_T err_t;
+#else /* LWIP_ERR_T */
+ typedef s8_t err_t;
+#endif /* LWIP_ERR_T*/
 
 /* Definitions for error constants. */
 
 #define ERR_OK          0    /* No error, everything OK. */
 #define ERR_MEM        -1    /* Out of memory error.     */
 #define ERR_BUF        -2    /* Buffer error.            */
-#define ERR_RTE        -3    /* Routing problem.         */
+#define ERR_TIMEOUT    -3    /* Timeout.                 */
+#define ERR_RTE        -4    /* Routing problem.         */
 
 #define ERR_IS_FATAL(e) ((e) < ERR_RTE)
 
-#define ERR_ABRT       -4    /* Connection aborted.      */
-#define ERR_RST        -5    /* Connection reset.        */
-#define ERR_CLSD       -6    /* Connection closed.       */
-#define ERR_CONN       -7    /* Not connected.           */
+#define ERR_ABRT       -5    /* Connection aborted.      */
+#define ERR_RST        -6    /* Connection reset.        */
+#define ERR_CLSD       -7    /* Connection closed.       */
+#define ERR_CONN       -8    /* Not connected.           */
 
-#define ERR_VAL        -8    /* Illegal value.           */
+#define ERR_VAL        -9    /* Illegal value.           */
 
-#define ERR_ARG        -9    /* Illegal argument.        */
+#define ERR_ARG        -10   /* Illegal argument.        */
 
-#define ERR_USE        -10   /* Address in use.          */
+#define ERR_USE        -11   /* Address in use.          */
 
-#define ERR_IF         -11   /* Low-level netif error    */
-#define ERR_ISCONN     -12   /* Already connected.       */
-
-#define ERR_TIMEOUT    -13   /* Timeout.                 */
+#define ERR_IF         -12   /* Low-level netif error    */
+#define ERR_ISCONN     -13   /* Already connected.       */
 
 #define ERR_INPROGRESS -14   /* Operation in progress    */
 
Index: src/include/lwip/mem.h
===================================================================
RCS file: /sources/lwip/lwip/src/include/lwip/mem.h,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -p -r1.21 -r1.22
--- src/include/lwip/mem.h	4 Mar 2008 16:31:32 -0000	1.21
+++ src/include/lwip/mem.h	30 May 2008 11:37:15 -0000	1.22
@@ -50,16 +50,16 @@ typedef size_t mem_size_t;
  * allow these defines to be overridden.
  */
 #ifndef mem_free
-#define mem_free(x) free(x)
+#define mem_free free
 #endif
 #ifndef mem_malloc
-#define mem_malloc(x) malloc(x)
+#define mem_malloc malloc
 #endif
 #ifndef mem_calloc
-#define mem_calloc(x, y) calloc(x, y)
+#define mem_calloc calloc
 #endif
 #ifndef mem_realloc
-#define mem_realloc(x, size) (x)
+#define mem_realloc realloc
 #endif
 #else /* MEM_LIBC_MALLOC */
 
Index: src/include/lwip/netif.h
===================================================================
RCS file: /sources/lwip/lwip/src/include/lwip/netif.h,v
retrieving revision 1.43
retrieving revision 1.46
diff -u -p -r1.43 -r1.46
--- src/include/lwip/netif.h	9 Oct 2007 19:59:59 -0000	1.43
+++ src/include/lwip/netif.h	19 Jun 2008 16:27:23 -0000	1.46
@@ -34,6 +34,8 @@
 
 #include "lwip/opt.h"
 
+#define ENABLE_LOOPBACK (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF)
+
 #include "lwip/err.h"
 
 #include "lwip/ip_addr.h"
@@ -165,6 +167,14 @@ struct netif {
 #if LWIP_NETIF_HWADDRHINT
   u8_t *addr_hint;
 #endif /* LWIP_NETIF_HWADDRHINT */
+#if ENABLE_LOOPBACK
+  /* List of packets to be queued for ourselves. */
+  struct pbuf *loop_first;
+  struct pbuf *loop_last;
+#if LWIP_LOOPBACK_MAX_PBUFS
+  u16_t loop_cnt_current;
+#endif /* LWIP_LOOPBACK_MAX_PBUFS */
+#endif /* ENABLE_LOOPBACK */
 };
 
 #if LWIP_SNMP
@@ -242,4 +252,12 @@ void netif_set_link_callback(struct neti
 }
 #endif
 
+#if ENABLE_LOOPBACK
+err_t netif_loop_output(struct netif *netif, struct pbuf *p, struct ip_addr *dest_ip);
+void netif_poll(struct netif *netif);
+#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
+void netif_poll_all(void);
+#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
+#endif /* ENABLE_LOOPBACK */
+
 #endif /* __LWIP_NETIF_H__ */
Index: src/include/lwip/opt.h
===================================================================
RCS file: /sources/lwip/lwip/src/include/lwip/opt.h,v
retrieving revision 1.116
retrieving revision 1.122
diff -u -p -r1.116 -r1.122
--- src/include/lwip/opt.h	31 Jan 2008 18:19:29 -0000	1.116
+++ src/include/lwip/opt.h	30 Jun 2008 18:16:52 -0000	1.122
@@ -155,6 +155,27 @@
 #define MEMP_USE_CUSTOM_POOLS           0
 #endif
 
+/**
+ * Set this to 1 if you want to free PBUF_RAM pbufs (or call mem_free()) from
+ * interrupt context (or another context that doesn't allow waiting for a
+ * semaphore).
+ * If set to 1, mem_malloc will be protected by a semaphore and SYS_ARCH_PROTECT,
+ * while mem_free will only use SYS_ARCH_PROTECT. mem_malloc SYS_ARCH_UNPROTECTs
+ * with each loop so that mem_free can run.
+ *
+ * ATTENTION: As you can see from the above description, this leads to dis-/
+ * enabling interrupts often, which can be slow! Also, on low memory, mem_malloc
+ * can need longer.
+ *
+ * If you don't want that, at least for NO_SYS=0, you can still use the following
+ * functions to enqueue a deallocation call which then runs in the tcpip_thread
+ * context:
+ * - pbuf_free_callback(p);
+ * - mem_free_callback(m);
+ */
+#ifndef LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
+#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 0
+#endif
 
 /*
    ------------------------------------------------
@@ -815,6 +836,39 @@
 #define LWIP_NETIF_HWADDRHINT           0
 #endif
 
+/**
+ * LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP
+ * address equal to the netif IP address, looping them back up the stack.
+ */
+#ifndef LWIP_NETIF_LOOPBACK
+#define LWIP_NETIF_LOOPBACK             0
+#endif
+
+/**
+ * LWIP_LOOPBACK_MAX_PBUFS: Maximum number of pbufs on queue for loopback
+ * sending for each netif (0 = disabled)
+ */
+#ifndef LWIP_LOOPBACK_MAX_PBUFS
+#define LWIP_LOOPBACK_MAX_PBUFS         0
+#endif
+
+/**
+ * LWIP_NETIF_LOOPBACK_MULTITHREADING: Indicates whether threading is enabled in
+ * the system, as netifs must change how they behave depending on this setting
+ * for the LWIP_NETIF_LOOPBACK option to work.
+ * Setting this is needed to avoid reentering non-reentrant functions like
+ * tcp_input().
+ *    LWIP_NETIF_LOOPBACK_MULTITHREADING==1: Indicates that the user is using a
+ *       multithreaded environment like tcpip.c. In this case, netif->input()
+ *       is called directly.
+ *    LWIP_NETIF_LOOPBACK_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup.
+ *       The packets are put on a list and netif_poll() must be called in
+ *       the main application loop.
+ */
+#ifndef LWIP_NETIF_LOOPBACK_MULTITHREADING
+#define LWIP_NETIF_LOOPBACK_MULTITHREADING    (!NO_SYS)
+#endif
+
 /*
    ------------------------------------
    ---------- LOOPIF options ----------
@@ -827,20 +881,16 @@
 #define LWIP_HAVE_LOOPIF                0
 #endif
 
+/*
+   ------------------------------------
+   ---------- SLIPIF options ----------
+   ------------------------------------
+*/
 /**
- * LWIP_LOOPIF_MULTITHREADING: Indicates whether threading is enabled in
- * the system, as LOOPIF must change how it behaves depending on this setting.
- * Setting this is needed to avoid reentering non-reentrant functions like
- * tcp_input().
- *    LWIP_LOOPIF_MULTITHREADING==1: Indicates that the user is using a
- *       multithreaded environment like tcpip.c. In this case, netif->input()
- *       is called directly.
- *    LWIP_LOOPIF_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup.
- *       The packets are put on a list and loopif_poll() must be called in
- *       the main application loop.
+ * LWIP_HAVE_SLIPIF==1: Support slip interface and slipif.c
  */
-#ifndef LWIP_LOOPIF_MULTITHREADING
-#define LWIP_LOOPIF_MULTITHREADING      1
+#ifndef LWIP_HAVE_SLIPIF
+#define LWIP_HAVE_SLIPIF                0
 #endif
 
 /*
Index: src/include/lwip/sio.h
===================================================================
RCS file: /sources/lwip/lwip/src/include/lwip/sio.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -p -r1.7 -r1.8
--- src/include/lwip/sio.h	6 Sep 2007 16:43:44 -0000	1.7
+++ src/include/lwip/sio.h	27 Mar 2008 18:06:02 -0000	1.8
@@ -32,16 +32,24 @@
  * It needs to be implemented by those platforms which need SLIP or PPP
  */
 
+#ifndef __SIO_H__
+#define __SIO_H__
+
 #include "lwip/arch.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+/* If you want to define sio_fd_t elsewhere or differently,
+   define this in your cc.h file. */
 #ifndef __sio_fd_t_defined
 typedef void * sio_fd_t;
 #endif
 
+/* The following functions can be defined to something else in your cc.h file
+   or be implemented in your custom sio.c file. */
+
 #ifndef sio_open
 sio_fd_t sio_open(u8_t);
 #endif
@@ -69,3 +77,5 @@ void sio_read_abort(sio_fd_t);
 #ifdef __cplusplus
 }
 #endif
+
+#endif /* __SIO_H__ */
Index: src/include/lwip/sockets.h
===================================================================
RCS file: /sources/lwip/lwip/src/include/lwip/sockets.h,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -p -r1.38 -r1.39
--- src/include/lwip/sockets.h	2 Dec 2007 15:24:02 -0000	1.38
+++ src/include/lwip/sockets.h	26 Apr 2008 10:46:23 -0000	1.39
@@ -177,7 +177,22 @@ typedef struct ip_mreq {
 } ip_mreq;
 #endif /* LWIP_IGMP */
 
-/* Unimplemented for now... */
+/*
+ * The Type of Service provides an indication of the abstract
+ * parameters of the quality of service desired.  These parameters are
+ * to be used to guide the selection of the actual service parameters
+ * when transmitting a datagram through a particular network.  Several
+ * networks offer service precedence, which somehow treats high
+ * precedence traffic as more important than other traffic (generally
+ * by accepting only traffic above a certain precedence at time of high
+ * load).  The major choice is a three way tradeoff between low-delay,
+ * high-reliability, and high-throughput.
+ * The use of the Delay, Throughput, and Reliability indications may
+ * increase the cost (in some sense) of the service.  In many networks
+ * better performance for one of these parameters is coupled with worse
+ * performance on another.  Except for very unusual cases at most two
+ * of these three indications should be set.
+ */
 #define IPTOS_TOS_MASK          0x1E
 #define IPTOS_TOS(tos)          ((tos) & IPTOS_TOS_MASK)
 #define IPTOS_LOWDELAY          0x10
@@ -187,7 +202,13 @@ typedef struct ip_mreq {
 #define IPTOS_MINCOST           IPTOS_LOWCOST
 
 /*
- * Definitions for IP precedence (also in ip_tos) (Unimplemented)
+ * The Network Control precedence designation is intended to be used
+ * within a network only.  The actual use and control of that
+ * designation is up to each network. The Internetwork Control
+ * designation is intended for use by gateway control originators only.
+ * If the actual use of these precedence designations is of concern to
+ * a particular network, it is the responsibility of that network to
+ * control the access to, and use of, those precedence designations.
  */
 #define IPTOS_PREC_MASK                 0xe0
 #define IPTOS_PREC(tos)                ((tos) & IPTOS_PREC_MASK)
Index: src/include/lwip/stats.h
===================================================================
RCS file: /sources/lwip/lwip/src/include/lwip/stats.h,v
retrieving revision 1.19
retrieving revision 1.23
diff -u -p -r1.19 -r1.23
--- src/include/lwip/stats.h	28 Nov 2007 21:25:07 -0000	1.19
+++ src/include/lwip/stats.h	8 Jul 2008 09:15:57 -0000	1.23
@@ -57,7 +57,6 @@ extern "C" {
 
 struct stats_proto {
   STAT_COUNTER xmit;             /* Transmitted packets. */
-  STAT_COUNTER rexmit;           /* Retransmitted packets. */
   STAT_COUNTER recv;             /* Received packets. */
   STAT_COUNTER fw;               /* Forwarded packets. */
   STAT_COUNTER drop;             /* Dropped packets. */
@@ -87,7 +86,8 @@ struct stats_mem {
   mem_size_t avail;
   mem_size_t used;
   mem_size_t max;
-  mem_size_t err;
+  STAT_COUNTER err;
+  STAT_COUNTER illegal;
 };
 
 struct stats_syselem {
@@ -142,64 +142,138 @@ extern struct stats_ lwip_stats;
 #define stats_init() /* Compatibility define, not init needed. */
 
 #define STATS_INC(x) ++lwip_stats.x
+#define STATS_DEC(x) --lwip_stats.x
 #else
 #define stats_init()
 #define STATS_INC(x)
+#define STATS_DEC(x)
 #endif /* LWIP_STATS */
 
 #if TCP_STATS
 #define TCP_STATS_INC(x) STATS_INC(x)
+#define TCP_STATS_DISPLAY() stats_display_proto(&lwip_stats.tcp, "TCP")
 #else
 #define TCP_STATS_INC(x)
+#define TCP_STATS_DISPLAY()
 #endif
 
 #if UDP_STATS
 #define UDP_STATS_INC(x) STATS_INC(x)
+#define UDP_STATS_DISPLAY() stats_display_proto(&lwip_stats.udp, "UDP")
 #else
 #define UDP_STATS_INC(x)
+#define UDP_STATS_DISPLAY()
 #endif
 
 #if ICMP_STATS
 #define ICMP_STATS_INC(x) STATS_INC(x)
+#define ICMP_STATS_DISPLAY() stats_display_proto(&lwip_stats.icmp, "ICMP")
 #else
 #define ICMP_STATS_INC(x)
+#define ICMP_STATS_DISPLAY()
 #endif
 
 #if IGMP_STATS
 #define IGMP_STATS_INC(x) STATS_INC(x)
+#define IGMP_STATS_DISPLAY() stats_display_igmp(&lwip_stats.igmp)
 #else
 #define IGMP_STATS_INC(x)
+#define IGMP_STATS_DISPLAY()
 #endif
 
 #if IP_STATS
 #define IP_STATS_INC(x) STATS_INC(x)
+#define IP_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip, "IP")
 #else
 #define IP_STATS_INC(x)
+#define IP_STATS_DISPLAY()
 #endif
 
 #if IPFRAG_STATS
 #define IPFRAG_STATS_INC(x) STATS_INC(x)
+#define IPFRAG_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip_frag, "IP_FRAG")
 #else
 #define IPFRAG_STATS_INC(x)
+#define IPFRAG_STATS_DISPLAY()
 #endif
 
 #if ETHARP_STATS
 #define ETHARP_STATS_INC(x) STATS_INC(x)
+#define ETHARP_STATS_DISPLAY() stats_display_proto(&lwip_stats.etharp, "ETHARP")
 #else
 #define ETHARP_STATS_INC(x)
+#define ETHARP_STATS_DISPLAY()
 #endif
 
 #if LINK_STATS
 #define LINK_STATS_INC(x) STATS_INC(x)
+#define LINK_STATS_DISPLAY() stats_display_proto(&lwip_stats.link, "LINK")
 #else
 #define LINK_STATS_INC(x)
+#define LINK_STATS_DISPLAY()
+#endif
+
+#if MEM_STATS
+#define MEM_STATS_AVAIL(x, y) lwip_stats.mem.x = y
+#define MEM_STATS_INC(x) STATS_INC(mem.x)
+#define MEM_STATS_INC_USED(x, y) do { lwip_stats.mem.used += y; \
+                                    if (lwip_stats.mem.max < lwip_stats.mem.used) { \
+                                        lwip_stats.mem.max = lwip_stats.mem.used; \
+                                    } \
+                                 } while(0)
+#define MEM_STATS_DEC_USED(x, y) lwip_stats.mem.x -= y
+#define MEM_STATS_DISPLAY() stats_display_mem(&lwip_stats.mem, "HEAP")
+#else
+#define MEM_STATS_AVAIL(x, y)
+#define MEM_STATS_INC(x)
+#define MEM_STATS_INC_USED(x, y)
+#define MEM_STATS_DEC_USED(x, y)
+#define MEM_STATS_DISPLAY()
+#endif
+
+#if MEMP_STATS
+#define MEMP_STATS_AVAIL(x, i, y) lwip_stats.memp[i].x = y
+#define MEMP_STATS_INC(x, i) STATS_INC(memp[i].x)
+#define MEMP_STATS_DEC(x, i) STATS_DEC(memp[i].x)
+#define MEMP_STATS_INC_USED(x, i) do { ++lwip_stats.memp[i].used; \
+                                    if (lwip_stats.memp[i].max < lwip_stats.memp[i].used) { \
+                                        lwip_stats.memp[i].max = lwip_stats.memp[i].used; \
+                                    } \
+                                 } while(0)
+#define MEMP_STATS_DISPLAY(i) stats_display_memp(&lwip_stats.memp[i], i)
+#else
+#define MEMP_STATS_AVAIL(x, i, y)
+#define MEMP_STATS_INC(x, i)
+#define MEMP_STATS_DEC(x, i)
+#define MEMP_STATS_INC_USED(x, i)
+#define MEMP_STATS_DISPLAY(i)
+#endif
+
+#if SYS_STATS
+#define SYS_STATS_INC(x) STATS_INC(sys.x)
+#define SYS_STATS_DEC(x) STATS_DEC(sys.x)
+#define SYS_STATS_DISPLAY() stats_display_sys(&lwip_stats.sys)
+#else
+#define SYS_STATS_INC(x)
+#define SYS_STATS_DEC(x)
+#define SYS_STATS_DISPLAY()
 #endif
 
 /* Display of statistics */
 #if LWIP_STATS_DISPLAY
 void stats_display(void);
+void stats_display_proto(struct stats_proto *proto, char *name);
+void stats_display_igmp(struct stats_igmp *igmp);
+void stats_display_mem(struct stats_mem *mem, char *name);
+void stats_display_memp(struct stats_mem *mem, int index);
+void stats_display_sys(struct stats_sys *sys);
 #else
 #define stats_display()
+#define stats_display_proto(proto, name)
+#define stats_display_igmp(igmp)
+#define stats_display_mem(mem, name)
+#define stats_display_memp(mem, index)
+#define stats_display_sys(sys)
 #endif /* LWIP_STATS_DISPLAY */
 
 #ifdef __cplusplus
Index: src/include/lwip/tcpip.h
===================================================================
RCS file: /sources/lwip/lwip/src/include/lwip/tcpip.h,v
retrieving revision 1.24
retrieving revision 1.27
diff -u -p -r1.24 -r1.27
--- src/include/lwip/tcpip.h	12 Jan 2008 11:52:22 -0000	1.24
+++ src/include/lwip/tcpip.h	27 Jun 2008 20:34:55 -0000	1.27
@@ -83,7 +83,11 @@ err_t tcpip_netifapi_lock(struct netifap
 #endif /* LWIP_NETIF_API */
 
 err_t tcpip_callback_with_block(void (*f)(void *ctx), void *ctx, u8_t block);
-#define tcpip_callback(f,ctx) tcpip_callback_with_block(f,ctx,1)
+#define tcpip_callback(f, ctx)              tcpip_callback_with_block(f, ctx, 1)
+
+/* free pbufs or heap memory from another context without blocking */
+err_t pbuf_free_callback(struct pbuf *p);
+err_t mem_free_callback(void *m);
 
 err_t tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg);
 #define tcpip_untimeout(h, arg) tcpip_timeout(0xffffffff, h, arg)
Index: src/include/netif/loopif.h
===================================================================
RCS file: /sources/lwip/lwip/src/include/netif/loopif.h,v
retrieving revision 1.7
retrieving revision 1.9
diff -u -p -r1.7 -r1.9
--- src/include/netif/loopif.h	10 May 2007 10:59:20 -0000	1.7
+++ src/include/netif/loopif.h	17 Jun 2008 20:12:22 -0000	1.9
@@ -32,6 +32,7 @@
 #ifndef __NETIF_LOOPIF_H__
 #define __NETIF_LOOPIF_H__
 
+#include "lwip/opt.h"
 #include "lwip/netif.h"
 #include "lwip/err.h"
 
@@ -39,9 +40,9 @@
 extern "C" {
 #endif
 
-#if !LWIP_LOOPIF_MULTITHREADING
-void loopif_poll(struct netif *netif);
-#endif
+#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
+#define loopif_poll netif_poll
+#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
 
 err_t loopif_init(struct netif *netif);
 
Index: src/netif/etharp.c
===================================================================
RCS file: /sources/lwip/lwip/src/netif/etharp.c,v
retrieving revision 1.145
retrieving revision 1.148
diff -u -p -r1.145 -r1.148
--- src/netif/etharp.c	4 Mar 2008 13:41:24 -0000	1.145
+++ src/netif/etharp.c	19 Jun 2008 16:40:59 -0000	1.148
@@ -353,7 +353,7 @@ find_entry(struct ip_addr *ipaddr, u8_t 
    * 1) empty entry
    * 2) oldest stable entry
    * 3) oldest pending entry without queued packets
-   * 4) oldest pending entry without queued packets
+   * 4) oldest pending entry with queued packets
    * 
    * { ETHARP_TRY_HARD is set at this point }
    */ 
@@ -1130,7 +1130,14 @@ ethernet_input(struct pbuf *p, struct ne
 
   /* points to packet payload, which starts with an Ethernet header */
   ethhdr = p->payload;
-  
+  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE,
+    ("ethernet_input: dest:%02x:%02x:%02x:%02x:%02x:%02x, src:%02x:%02x:%02x:%02x:%02x:%02x, type:%2hx\n",
+     (unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2],
+     (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5],
+     (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2],
+     (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5],
+     (unsigned)htons(ethhdr->type)));
+
   switch (htons(ethhdr->type)) {
     /* IP packet? */
     case ETHTYPE_IP:
@@ -1165,6 +1172,8 @@ ethernet_input(struct pbuf *p, struct ne
 #endif /* PPPOE_SUPPORT */
 
     default:
+      ETHARP_STATS_INC(etharp.proterr);
+      ETHARP_STATS_INC(etharp.drop);
       pbuf_free(p);
       p = NULL;
       break;
Index: src/netif/loopif.c
===================================================================
RCS file: /sources/lwip/lwip/src/netif/loopif.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -p -r1.26 -r1.27
--- src/netif/loopif.c	31 Aug 2007 10:14:09 -0000	1.26
+++ src/netif/loopif.c	12 Jun 2008 20:10:10 -0000	1.27
@@ -40,149 +40,8 @@
 #if LWIP_HAVE_LOOPIF
 
 #include "netif/loopif.h"
-#include "lwip/pbuf.h"
 #include "lwip/snmp.h"
 
-#include <string.h>
-
-#if !LWIP_LOOPIF_MULTITHREADING
-
-#include "lwip/sys.h"
-#include "lwip/mem.h"
-
-/* helper struct for the linked list of pbufs */
-struct loopif_private {
-  struct pbuf *first;
-  struct pbuf *last;
-};
-
-/**
- * Call loopif_poll() in the main loop of your application. This is to prevent
- * reentering non-reentrant functions like tcp_input(). Packets passed to
- * loopif_output() are put on a list that is passed to netif->input() by
- * loopif_poll().
- *
- * @param netif the lwip network interface structure for this loopif
- */
-void
-loopif_poll(struct netif *netif)
-{
-  SYS_ARCH_DECL_PROTECT(lev);
-  struct pbuf *in, *in_end;
-  struct loopif_private *priv = (struct loopif_private*)netif->state;
-
-  LWIP_ERROR("priv != NULL", (priv != NULL), return;);
-
-  do {
-    /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
-    SYS_ARCH_PROTECT(lev);
-    in = priv->first;
-    if(in) {
-      in_end = in;
-      while(in_end->len != in_end->tot_len) {
-        LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
-        in_end = in_end->next;
-      }
-      /* 'in_end' now points to the last pbuf from 'in' */
-      if(in_end == priv->last) {
-        /* this was the last pbuf in the list */
-        priv->first = priv->last = NULL;
-      } else {
-        /* pop the pbuf off the list */
-        priv->first = in_end->next;
-        LWIP_ASSERT("should not be null since first != last!", priv->first != NULL);
-      }
-    }
-    SYS_ARCH_UNPROTECT(lev);
-  
-    if(in != NULL) {
-      if(in_end->next != NULL) {
-        /* De-queue the pbuf from its successors on the 'priv' list. */
-        in_end->next = NULL;
-      }
-      if(netif->input(in, netif) != ERR_OK) {
-        pbuf_free(in);
-      }
-      /* Don't reference the packet any more! */
-      in = NULL;
-      in_end = NULL;
-    }
-  /* go on while there is a packet on the list */
-  } while(priv->first != NULL);
-}
-#endif /* LWIP_LOOPIF_MULTITHREADING */
-
-/**
- * Send an IP packet over the loopback interface.
- * The pbuf is simply copied and handed back to netif->input.
- * In multithreaded mode, this is done directly since netif->input must put
- * the packet on a queue.
- * In callback mode, the packet is put on an internal queue and is fed to
- * netif->input by loopif_poll().
- *
- * @param netif the lwip network interface structure for this loopif
- * @param p the (IP) packet to 'send'
- * @param ipaddr the ip address to send the packet to (not used for loopif)
- * @return ERR_OK if the packet has been sent
- *         ERR_MEM if the pbuf used to copy the packet couldn't be allocated
- */
-static err_t
-loopif_output(struct netif *netif, struct pbuf *p,
-       struct ip_addr *ipaddr)
-{
-#if !LWIP_LOOPIF_MULTITHREADING
-  SYS_ARCH_DECL_PROTECT(lev);
-  struct loopif_private *priv;
-  struct pbuf *last;
-#endif /* LWIP_LOOPIF_MULTITHREADING */
-  struct pbuf *r;
-  err_t err;
-
-  LWIP_UNUSED_ARG(ipaddr);
-
-  /* Allocate a new pbuf */
-  r = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
-  if (r == NULL) {
-    return ERR_MEM;
-  }
-
-  /* Copy the whole pbuf queue p into the single pbuf r */
-  if ((err = pbuf_copy(r, p)) != ERR_OK) {
-    pbuf_free(r);
-    r = NULL;
-    return err;
-  }
-
-#if LWIP_LOOPIF_MULTITHREADING
-  /* Multithreading environment, netif->input() is supposed to put the packet
-     into a mailbox, so we can safely call it here without risking to re-enter
-     functions that are not reentrant (TCP!!!) */
-  if(netif->input(r, netif) != ERR_OK) {
-    pbuf_free(r);
-    r = NULL;
-  }
-#else /* LWIP_LOOPIF_MULTITHREADING */
-  /* Raw API without threads: put the packet on a linked list which gets emptied
-     through calling loopif_poll(). */
-  priv = (struct loopif_private*)netif->state;
-
-  /* let last point to the last pbuf in chain r */
-  for (last = r; last->next != NULL; last = last->next);
-  SYS_ARCH_PROTECT(lev);
-  if(priv->first != NULL) {
-    LWIP_ASSERT("if first != NULL, last must also be != NULL", priv->last != NULL);
-    priv->last->next = r;
-    priv->last = last;
-  } else {
-    priv->first = r;
-    priv->last = last;
-  }
-  SYS_ARCH_UNPROTECT(lev);
-#endif /* LWIP_LOOPIF_MULTITHREADING */
-
-  return ERR_OK;    
-}
-
 /**
  * Initialize a lwip network interface structure for a loopback interface
  *
@@ -193,16 +52,6 @@ loopif_output(struct netif *netif, struc
 err_t
 loopif_init(struct netif *netif)
 {
-#if !LWIP_LOOPIF_MULTITHREADING
-  struct loopif_private *priv;
-
-  priv = (struct loopif_private*)mem_malloc(sizeof(struct loopif_private));
-  if(priv == NULL) 
-    return ERR_MEM;
-  priv->first = priv->last = NULL;
-  netif->state = priv;
-#endif /* LWIP_LOOPIF_MULTITHREADING */
-
   /* initialize the snmp variables and counters inside the struct netif
    * ifSpeed: no assumption can be made!
    */
@@ -210,7 +59,7 @@ loopif_init(struct netif *netif)
 
   netif->name[0] = 'l';
   netif->name[1] = 'o';
-  netif->output = loopif_output;
+  netif->output = netif_loop_output;
   return ERR_OK;
 }
 
Index: src/netif/slipif.c
===================================================================
RCS file: /sources/lwip/lwip/src/netif/slipif.c,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -p -r1.29 -r1.30
--- src/netif/slipif.c	30 Nov 2007 17:22:21 -0000	1.29
+++ src/netif/slipif.c	17 Jun 2008 20:14:05 -0000	1.30
@@ -44,6 +44,9 @@
 
 #include "netif/slipif.h"
 #include "lwip/opt.h"
+
+#if LWIP_HAVE_SLIPIF
+
 #include "lwip/def.h"
 #include "lwip/pbuf.h"
 #include "lwip/sys.h"
@@ -273,3 +276,4 @@ slipif_init(struct netif *netif)
   sys_thread_new(SLIPIF_THREAD_NAME, slipif_loop, netif, SLIPIF_THREAD_STACKSIZE, SLIPIF_THREAD_PRIO);
   return ERR_OK;
 }
+#endif /* LWIP_HAVE_SLIPIF */
