diff --git a/ChangeLog b/ChangeLog
index 6f59da81e1056d05404a4471237e3a440cbf3456..daf3551d7b78ae89fd222cd0fce6412a4d44f476 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -225,3 +225,5 @@
 	  recv buffering issues, but this is part of a larger buffering issue.
 	* Basic server functionality verified: listen(), accept()
 	* Fix DM90x0 driver problem that caused TX overruns
+	* Add strncmp()
+
diff --git a/Documentation/NuttX.html b/Documentation/NuttX.html
index c8079ed1d45acaca1ebc70371a28c3804cdfda0b..8fa4cc0ad6e9438ac1018a17892e3949b106d4bf 100644
--- a/Documentation/NuttX.html
+++ b/Documentation/NuttX.html
@@ -355,7 +355,8 @@ is available that be used to build a NuttX-compatible arm-elf toolchain.</blockq
 </pre>
 <p><b>DM320 (ARM9)</b>
   This build for the ARM9 target includes a signficant subset of OS
-  features, ethernet driver and full TCP/IP stack (via uIP). (11/8/07)
+  features, ethernet driver and full TCP/IP, UDP and (minimal) ICMP
+  stacks (via uIP). (11/8/07)
 </p>
 <pre>
    text    data     bss     dec     hex filename
@@ -681,6 +682,7 @@ Other memory:
 	  recv buffering issues, but this is part of a larger buffering issue.
 	* Basic server functionality verified: listen(), accept()
 	* Fix DM90x0 driver problem that caused TX overruns
+	* Add strncmp()
 </pre></ul>
 
 <table width ="100%">
diff --git a/TODO b/TODO
index 28b64ece81b8be21e4dac9bdf34bb65e0fae9305..ec53fd2a957105277ef2dfa00fa511536f23f32c 100644
--- a/TODO
+++ b/TODO
@@ -31,21 +31,14 @@ o C++ Support
 o Network
 - Did not implement send() and sendto() timeouts.  Option is setable via setsockopt,
   but is not implemented.
-- netutils/webserver netutils/telnetd (and maybe others) are seriously broken.
+- netutils/telnetd (and maybe others) are seriously broken.
   Need to be re-written to use listen() and accept()
 - Should implement SOCK_RAW
-- listen() and accept() are untested.
 - accept() and recvfrom() need to return connection address
 - Performance Improvements (uIP is not very fast):
-- Improve performance by queing TX operations
-  Add simple buffer management.  CONFIG_NET_BUFFERS
-  (1) On write, queue buffer for output get a new buffer for the socket (waiting if
-      nececcesary
-  (2) Copy buffer structure into uip_driver_structure when driver requests write
-      data
-  (3) Extra read buffers will be necessary to buffer TCP data when there is no recv
-      in place to accept the data.  At present, received data is not ACKed, but is
-      eventually lost in this case.
+- Extra read buffers will be necessary to buffer TCP data when there is no recv
+  in place to accept the data.  At present, received data is not ACKed, but is
+  eventually lost in this case.
 - Improve performance by stimulating the driver to accept new TX data before the
   next polling interval.
 
@@ -57,7 +50,11 @@ o Network
       poll on TCP connections connect on the network supported by the driver; UDP
       polling should respond with TX data only if the UDP packet is intended for the
       the network supported by the driver.
-  (2) If there were multiple drivers, polling would occur at double the rate.
+  (2) If there were multiple drivers, polling would occur at double the rate.i
+  Fix by using bound IP address in TCP connection (lipaddr) and verifying that it
+  is in the subnet served by the driver.
+- uIP/Socket callback logic is not thread safe. This means that a socket cannot be
+  used concurrently by two threads.  Minimal fix:  Add mutex to support exclusion.
 
 o USB
 - Implement USB device support
diff --git a/configs/ntosd-dm320/defconfig b/configs/ntosd-dm320/defconfig
index e3f9022bc06b75a7bdbb6cacd9b2ba9a5408fc0f..b3576fd5ac856310459cb6d790e0e723b228cfa3 100644
--- a/configs/ntosd-dm320/defconfig
+++ b/configs/ntosd-dm320/defconfig
@@ -291,6 +291,18 @@ CONFIG_NET_BROADCAST=n
 CONFIG_NET_DHCP_LIGHT=n
 CONFIG_NET_RESOLV_ENTRIES=4
 
+#
+# Settings for examples/uip
+CONFIG_EXAMPLE_UIP_IPADDR=(10<<24|0<<16|0<<8|2)
+CONFIG_EXAMPLE_UIP_DRIPADDR=(10<<24|0<<16|0<<8|1)
+CONFIG_EXAMPLE_UIP_NETMASK=(255<<24|255<<16|255<<8|0)
+CONFIG_EXAMPLE_UIP_SMTP=n
+CONFIG_EXAMPLE_UIP_TELNETD=n
+CONFIG_EXAMPLE_UIP_WEBSERVER=y
+CONFIG_EXAMPLE_UIP_DHCPC=n
+CONFIG_EXAMPLE_UIP_RESOLV=n
+CONFIG_EXAMPLE_UIP_WEBCLIENT=n
+
 #
 # Settings for examples/nettest
 CONFIG_EXAMPLE_NETTEST_SERVER=n
diff --git a/configs/ntosd-dm320/netconfig b/configs/ntosd-dm320/netconfig
index 655ee7d38ad44eabe5ef0d84b3b5af11e036db9d..050196ee5a72812fe5fd2a63dbccfcc661110f05 100644
--- a/configs/ntosd-dm320/netconfig
+++ b/configs/ntosd-dm320/netconfig
@@ -292,6 +292,18 @@ CONFIG_NET_BROADCAST=n
 CONFIG_NET_DHCP_LIGHT=n
 CONFIG_NET_RESOLV_ENTRIES=4
 
+#
+# Settings for examples/uip
+CONFIG_EXAMPLE_UIP_IPADDR=(10<<24|0<<16|0<<8|2)
+CONFIG_EXAMPLE_UIP_DRIPADDR=(10<<24|0<<16|0<<8|1)
+CONFIG_EXAMPLE_UIP_NETMASK=(255<<24|255<<16|255<<8|0)
+CONFIG_EXAMPLE_UIP_SMTP=n
+CONFIG_EXAMPLE_UIP_TELNETD=n
+CONFIG_EXAMPLE_UIP_WEBSERVER=y
+CONFIG_EXAMPLE_UIP_DHCPC=n
+CONFIG_EXAMPLE_UIP_RESOLV=n
+CONFIG_EXAMPLE_UIP_WEBCLIENT=n
+
 #
 # Settings for examples/nettest
 CONFIG_EXAMPLE_NETTEST_SERVER=n
diff --git a/configs/sim/defconfig b/configs/sim/defconfig
index 3f80ded189a45acf073a8d3711bd10d3ba3db545..2d959fbcf3f189ef972c7a07235f8c9c08c8195b 100644
--- a/configs/sim/defconfig
+++ b/configs/sim/defconfig
@@ -258,12 +258,12 @@ CONFIG_NET_RESOLV_ENTRIES=4
 CONFIG_EXAMPLE_UIP_IPADDR=(192<<24|168<<16|0<<8|128)
 CONFIG_EXAMPLE_UIP_DRIPADDR=(192<<24|168<<16|0<<8|1)
 CONFIG_EXAMPLE_UIP_NETMASK=(255<<24|255<<16|255<<8|0)
-#CONFIG_EXAMPLE_UIP_SMTP=
-#CONFIG_EXAMPLE_UIP_TELNETD=
-#CONFIG_EXAMPLE_UIP_WEBSERVER=
-CONFIG_EXAMPLE_UIP_DHCPC=y
-#CONFIG_EXAMPLE_UIP_RESOLV=
-#CONFIG_EXAMPLE_UIP_WEBCLIENT=
+CONFIG_EXAMPLE_UIP_SMTP=n
+CONFIG_EXAMPLE_UIP_TELNETD=n
+CONFIG_EXAMPLE_UIP_WEBSERVER=y
+CONFIG_EXAMPLE_UIP_DHCPC=n
+CONFIG_EXAMPLE_UIP_RESOLV=n
+CONFIG_EXAMPLE_UIP_WEBCLIENT=n
 
 #
 # Settings for examples/nettest
diff --git a/configs/sim/netconfig b/configs/sim/netconfig
index 296389aec0ed08d5350ac7385cca3c97f5d6d642..2cdea0a6133e174bd546f42ab2c78c378f40ed55 100644
--- a/configs/sim/netconfig
+++ b/configs/sim/netconfig
@@ -259,12 +259,12 @@ CONFIG_NET_RESOLV_ENTRIES=4
 CONFIG_EXAMPLE_UIP_IPADDR=(192<<24|168<<16|0<<8|128)
 CONFIG_EXAMPLE_UIP_DRIPADDR=(192<<24|168<<16|0<<8|1)
 CONFIG_EXAMPLE_UIP_NETMASK=(255<<24|255<<16|255<<8|0)
-#CONFIG_EXAMPLE_UIP_SMTP=
-#CONFIG_EXAMPLE_UIP_TELNETD=
-#CONFIG_EXAMPLE_UIP_WEBSERVER=
-CONFIG_EXAMPLE_UIP_DHCPC=y
-#CONFIG_EXAMPLE_UIP_RESOLV=
-#CONFIG_EXAMPLE_UIP_WEBCLIENT=
+CONFIG_EXAMPLE_UIP_SMTP=n
+CONFIG_EXAMPLE_UIP_TELNETD=n
+CONFIG_EXAMPLE_UIP_WEBSERVER=y
+CONFIG_EXAMPLE_UIP_DHCPC=n
+CONFIG_EXAMPLE_UIP_RESOLV=n
+CONFIG_EXAMPLE_UIP_WEBCLIENT=n
 
 #
 # Settings for examples/nettest
diff --git a/drivers/net/dm90x0.c b/drivers/net/dm90x0.c
index 5efca07f4fb03127704c2c540b87b98a1f6422d7..0df832e8f0b0e5d7e4fb398b90bfc726121ed957 100644
--- a/drivers/net/dm90x0.c
+++ b/drivers/net/dm90x0.c
@@ -1357,7 +1357,9 @@ static int dm9x_ifup(struct uip_driver_s *dev)
   uint8 netstatus;
   int i;
 
-  dbg("Bringing the interface up\n" );
+  dbg("Bringing up: %d.%d.%d.%d\n",
+       dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff,
+       (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24 );
 
   /* Initilize DM90x0 chip */
 
diff --git a/examples/uip/main.c b/examples/uip/main.c
index e78634a5a95f2bda9b8616bb2d3e18e104168e61..951cde539d2c32e763c10b0685d5762567c813ae 100644
--- a/examples/uip/main.c
+++ b/examples/uip/main.c
@@ -119,16 +119,16 @@ int user_start(int argc, char *argv[])
 #if !defined(CONFIG_EXAMPLE_UIP_DHCPC)
   struct in_addr addr;
 #endif
-#if defined(CONFIG_EXAMPLE_UIP_DHCPC) || !defined(CONFIG_ARCH_SIM)
+#if defined(CONFIG_EXAMPLE_UIP_DHCPC) || defined(CONFIG_EXAMPLE_UIP_NOMAC)
   uint8 mac[IFHWADDRLEN];
 #endif
 #if defined(CONFIG_EXAMPLE_UIP_DHCPC) || defined(CONFIG_EXAMPLE_UIP_SMTP)
   void *handle;
 #endif
 
-/* Most embedded network interfaces must have a software assigned MAC */
+/* Many embedded network interfaces must have a software assigned MAC */
 
-#if !defined(CONFIG_ARCH_SIM)
+#ifdef CONFIG_EXAMPLE_UIP_NOMAC
   mac[0] = 0x00;
   mac[1] = 0xe0;
   mac[2] = 0xb0;
diff --git a/include/net/uip/httpd.h b/include/net/uip/httpd.h
index ef21cc6ba9b74bfe09a31374dffa52b75d83f1df..44d4d8f4ae0a095fa54cf8a72e2c7604036609c8 100644
--- a/include/net/uip/httpd.h
+++ b/include/net/uip/httpd.h
@@ -1,11 +1,19 @@
-/* httpd.h
+/****************************************************************************
+ * net/uip/httpd.h
  *
- * Copyright (c) 2001-2005, Adam Dunkels.
- * All rights reserved.
+ *   Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ *   Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Based on uIP which also has a BSD style license:
+ *
+ *   Author: Adam Dunkels <adam@sics.se>
+ *   Copyright (c) 2001-2005, Adam Dunkels.
+ *   All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
+ *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
@@ -26,13 +34,22 @@
  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
+ *
+ ****************************************************************************/
 
 #ifndef _NET_UIP_HTTPD_H
 #define _NET_UIP_HTTPD_H
 
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
 #include <sys/types.h>
 
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
 extern void httpd_init(void);
 extern int httpd_listen(void);
 
diff --git a/include/net/uip/uip-lib.h b/include/net/uip/uip-lib.h
index 3f6c9860dfe7660cb2e8e64bd98f678845f8a181..d5799ee56ed58de719d0c9724bbbd1ed8cd5eb80 100644
--- a/include/net/uip/uip-lib.h
+++ b/include/net/uip/uip-lib.h
@@ -42,9 +42,33 @@
 #ifndef __UIPLIB_H__
 #define __UIPLIB_H__
 
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
 #include <nuttx/config.h>
+#include <sched.h>
 #include <netinet/in.h>
 
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/* SOCK_DGRAM is the preferred socket type to use when we just want a
+ * socket for performing drive ioctls.  However, we can't use SOCK_DRAM
+ * if UDP is disabled.
+ */
+
+#ifdef CONFIG_NET_UDP
+# define UIPLIB_SOCK_IOCTL SOCK_DGRAM
+#else
+# define UIPLIB_SOCK_IOCTL SOCK_STREAM
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
 /* Convert a textual representation of an IP address to a numerical representation.
  *
  * This function takes a textual representation of an IP address in
@@ -80,4 +104,8 @@ extern int uip_setdraddr(const char *ifname, const struct in_addr *addr);
 extern int uip_setnetmask(const char *ifname, const struct in_addr *addr);
 #endif
 
+/* Generic server logic */
+
+extern void uip_server(uint16 portno, main_t handler, int stacksize);
+
 #endif /* __UIPLIB_H__ */
diff --git a/netutils/Makefile b/netutils/Makefile
index 6d8132f77d0873f5c1b02fe2ff8bb63b54893282..4e355ab7ff639b70a68d58a394d2c001fffc6118 100644
--- a/netutils/Makefile
+++ b/netutils/Makefile
@@ -39,12 +39,14 @@ MKDEP		= $(TOPDIR)/tools/mkdeps.sh
 
 ifeq ($(CONFIG_NET),y)
 include uiplib/Make.defs
-include dhcpc/Make.defs
-include resolv/Make.defs
 include smtp/Make.defs
 include telnetd/Make.defs
 include webclient/Make.defs
 include webserver/Make.defs
+ifeq ($(CONFIG_NET_UDP),y)
+include dhcpc/Make.defs
+include resolv/Make.defs
+endif
 include Make.str
 endif
 
diff --git a/netutils/uiplib/Make.defs b/netutils/uiplib/Make.defs
index d8b8ac600df6dc804b0e13bdd92b615c9b76aa42..8acb0218d95f9bcb3d06b428046cf1d116d2bba5 100644
--- a/netutils/uiplib/Make.defs
+++ b/netutils/uiplib/Make.defs
@@ -35,4 +35,4 @@
 
 UIPLIB_ASRCS =
 UIPLIB_CSRCS = uiplib.c uip-setmacaddr.c uip-getmacaddr.c uip-sethostaddr.c \
-	uip-gethostaddr.c uip-setdraddr.c uip-setnetmask.c
+	uip-gethostaddr.c uip-setdraddr.c uip-setnetmask.c uip-server.c
diff --git a/netutils/uiplib/uip-gethostaddr.c b/netutils/uiplib/uip-gethostaddr.c
index a8d36efac4211d90173915ce6126d5c5aa05ed12..732721b10153ec8d1662adf4904ca2e31339b1a0 100644
--- a/netutils/uiplib/uip-gethostaddr.c
+++ b/netutils/uiplib/uip-gethostaddr.c
@@ -81,7 +81,7 @@ int uip_gethostaddr(const char *ifname, struct in_addr *addr)
   int ret = ERROR;
   if (ifname && addr)
     {
-      int sockfd = socket(PF_INET, SOCK_DGRAM, 0);
+      int sockfd = socket(PF_INET, UIPLIB_SOCK_IOCTL, 0);
       if (sockfd >= 0)
         {
           struct ifreq req;
diff --git a/netutils/uiplib/uip-getmacaddr.c b/netutils/uiplib/uip-getmacaddr.c
index a8f9361139ec7de11d5cdcfe7ffa61dcae0b8c38..9e7a368ab419d12ec94c133095eae821a58db0ae 100644
--- a/netutils/uiplib/uip-getmacaddr.c
+++ b/netutils/uiplib/uip-getmacaddr.c
@@ -75,7 +75,7 @@ int uip_getmacaddr(const char *ifname, uint8 *macaddr)
     {
       /* Get a socket (only so that we get access to the INET subsystem) */
 
-      int sockfd = socket(PF_INET, SOCK_DGRAM, 0);
+      int sockfd = socket(PF_INET, UIPLIB_SOCK_IOCTL, 0);
       if (sockfd >= 0)
         {
           struct ifreq req;
diff --git a/netutils/uiplib/uip-server.c b/netutils/uiplib/uip-server.c
new file mode 100644
index 0000000000000000000000000000000000000000..aa0ea5b11dd83fc9bf68e5cbaec22598be8aa8f5
--- /dev/null
+++ b/netutils/uiplib/uip-server.c
@@ -0,0 +1,191 @@
+/****************************************************************************
+ * netutils/uiplib/uip-server.c
+ *
+ *   Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ *   Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name Gregory Nutt nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <unistd.h>
+#include <sched.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <net/uip/uip-lib.h>
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+#define errno *get_errno_ptr()
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: uip_server
+ *
+ * Description:
+ *   Implement basic server logic
+ *
+ * Parameters:
+ *   portno    The port to listen on (in network byte order)
+ *   handler   The entrypoint of the task to spawn when a new connection is
+ *             accepted.
+ *   stacksize The stack size needed by the spawned task
+ *
+ * Return:
+ *   Does not return unless an error occurs.
+ *
+ ****************************************************************************/
+
+void uip_server(uint16 portno, main_t handler, int stacksize)
+{
+  struct sockaddr_in myaddr;
+#ifdef CONFIG_NET_HAVE_SOLINGER
+  struct linger ling;
+#endif
+  struct sched_param param;
+  socklen_t addrlen;
+  const char *argv[2];
+  int listensd;
+  int acceptsd;
+#ifdef CONFIG_NET_HAVE_REUSEADDR
+  int optval;
+#endif
+
+  /* Create a new TCP socket to use to listen for connections */
+
+  listensd = socket(PF_INET, SOCK_STREAM, 0);
+  if (listensd < 0)
+    {
+      dbg("socket failure: %d\n", errno);
+      return;
+    }
+
+  /* Set socket to reuse address */
+
+#ifdef CONFIG_NET_HAVE_REUSEADDR
+  optval = 1;
+  if (setsockopt(listensd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(int)) < 0)
+    {
+      dbg("setsockopt SO_REUSEADDR failure: %d\n", errno);
+      goto errout_with_socket;
+    }
+#endif
+
+  /* Bind the socket to a local address */
+
+  myaddr.sin_family      = AF_INET;
+  myaddr.sin_port        = portno;
+  myaddr.sin_addr.s_addr = INADDR_ANY;
+
+  if (bind(listensd, (struct sockaddr*)&myaddr, sizeof(struct sockaddr_in)) < 0)
+    {
+      dbg("bind failure: %d\n", errno);
+      goto errout_with_socket;
+    }
+
+  /* Listen for connections on the bound TCP socket */
+
+  if (listen(listensd, 5) < 0)
+    {
+      dbg("listen failure %d\n", errno);
+      goto errout_with_socket;
+    }
+
+  /* Begin accepting connections */
+
+  dbg("Accepting connections on port %d\n", ntohs(portno));
+  for (;;)
+    {
+      addrlen = sizeof(struct sockaddr_in);
+      acceptsd = accept(listensd, (struct sockaddr*)&myaddr, &addrlen);
+      if (acceptsd < 0)
+        {
+          dbg("accept failure: %d\n", errno);
+          break;;
+        }
+      dbg("Connection accepted -- spawning\n");
+
+      /* Configure to "linger" until all data is sent when the socket is closed */
+
+#ifdef CONFIG_NET_HAVE_SOLINGER
+      ling.l_onoff  = 1;
+      ling.l_linger = 30;     /* timeout is seconds */
+      if (setsockopt(acceptsd, SOL_SOCKET, SO_LINGER, &ling, sizeof(struct linger)) < 0)
+        {
+          close(acceptsd);
+          dbg("setsockopt SO_LINGER failure: %d\n", errno);
+          break;;
+        }
+#endif
+
+      /* Spawn a thread to handle the connection.  The socket descriptor +1 is
+       * provided in as the single argument to the new thread. (The +1 is intended
+       * to handle the valid, zero file descriptor).
+       */
+
+      if (sched_getparam(0, &param) < 0)
+        {
+          close(acceptsd);
+          dbg("sched_getparam failed: %d\n", errno);
+          break;;
+        }
+
+      argv[0] = (char*)(acceptsd + 1);
+      argv[1] = NULL;
+
+      if (task_create("", param.sched_priority, stacksize, handler, argv) < 0)
+        {
+          close(acceptsd);
+          dbg("task_create failed: %d\n", errno);
+          break;;
+        }
+
+      /* We can close our copy of acceptsd now.  This file descriptor was dup'ed
+       * by task_create and we no longer need to retain the reference.
+       */
+
+      close(acceptsd);
+    }
+
+errout_with_socket:
+  close(listensd);
+}
diff --git a/netutils/uiplib/uip-setdraddr.c b/netutils/uiplib/uip-setdraddr.c
index 3b15a9ca9d71fec84bf51d4b7d4dbf479744e9db..e8ab142ec5da2829077685a033d55ad840321926 100644
--- a/netutils/uiplib/uip-setdraddr.c
+++ b/netutils/uiplib/uip-setdraddr.c
@@ -78,7 +78,7 @@ int uip_setdraddr(const char *ifname, const struct in_addr *addr)
   int ret = ERROR;
   if (ifname && addr)
     {
-      int sockfd = socket(PF_INET, SOCK_DGRAM, 0);
+      int sockfd = socket(PF_INET, UIPLIB_SOCK_IOCTL, 0);
       if (sockfd >= 0)
         {
           struct ifreq req;
diff --git a/netutils/uiplib/uip-sethostaddr.c b/netutils/uiplib/uip-sethostaddr.c
index 4a0b979bc105f7eec23a2be972475a8dd9214e7c..6247184ba6b34ca1ebc782c7d3c004f3a14c4bcf 100644
--- a/netutils/uiplib/uip-sethostaddr.c
+++ b/netutils/uiplib/uip-sethostaddr.c
@@ -78,7 +78,7 @@ int uip_sethostaddr(const char *ifname, const struct in_addr *addr)
   int ret = ERROR;
   if (ifname && addr)
     {
-      int sockfd = socket(PF_INET, SOCK_DGRAM, 0);
+      int sockfd = socket(PF_INET, UIPLIB_SOCK_IOCTL, 0);
       if (sockfd >= 0)
         {
           struct ifreq req;
diff --git a/netutils/uiplib/uip-setmacaddr.c b/netutils/uiplib/uip-setmacaddr.c
index b02e204ce112b48621416b7b12c92456e1d6fb19..4b1e675300f95288748c6fd0d6a3ea722564f4e7 100644
--- a/netutils/uiplib/uip-setmacaddr.c
+++ b/netutils/uiplib/uip-setmacaddr.c
@@ -86,7 +86,7 @@ int uip_setmacaddr(const char *ifname, const uint8 *macaddr)
     {
       /* Get a socket (only so that we get access to the INET subsystem) */
 
-      int sockfd = socket(PF_INET, SOCK_DGRAM, 0);
+      int sockfd = socket(PF_INET, UIPLIB_SOCK_IOCTL, 0);
       if (sockfd >= 0)
         {
           struct ifreq req;
diff --git a/netutils/uiplib/uip-setnetmask.c b/netutils/uiplib/uip-setnetmask.c
index 56e579ef3f29c218542c0e6e4da179718a62a446..ff70e5a376e02cec206733e2cfb6eed63664a410 100644
--- a/netutils/uiplib/uip-setnetmask.c
+++ b/netutils/uiplib/uip-setnetmask.c
@@ -78,7 +78,7 @@ int uip_setnetmask(const char *ifname, const struct in_addr *addr)
   int ret = ERROR;
   if (ifname && addr)
     {
-      int sockfd = socket(PF_INET, SOCK_DGRAM, 0);
+      int sockfd = socket(PF_INET, UIPLIB_SOCK_IOCTL, 0);
       if (sockfd >= 0)
         {
           struct ifreq req;
diff --git a/netutils/webserver/httpd-cgi.c b/netutils/webserver/httpd-cgi.c
index 1c7965374e43f9cdf9e604c43b372b482e57eb4b..e93aff1be4c003fb882694549680822ea3361600 100644
--- a/netutils/webserver/httpd-cgi.c
+++ b/netutils/webserver/httpd-cgi.c
@@ -125,7 +125,7 @@ static void file_stats(struct httpd_state *pstate, char *ptr)
   char buffer[16];
   char *pcount = strchr(ptr, ' ') + 1;
   snprintf(buffer, 16, "%5u", httpd_fs_count(pcount));
-  (void)send(pstate->sockout, buffer, strlen(buffer), 0);
+  (void)send(pstate->sockfd, buffer, strlen(buffer), 0);
 }
 #endif
 
diff --git a/netutils/webserver/httpd.c b/netutils/webserver/httpd.c
index 57e60f8723042c30e3e5da90ed60e7dcfb532ca3..2db3436d78932b02eb299613bc2ce58bfc8f4053 100644
--- a/netutils/webserver/httpd.c
+++ b/netutils/webserver/httpd.c
@@ -45,11 +45,17 @@
  * Included Files
  ****************************************************************************/
 
-#include <stdlib.h>
+#include <nuttx/config.h>
+
 #include <sys/socket.h>
+
+#include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
+#include <debug.h>
 
 #include <net/uip/uip.h>
+#include <net/uip/uip-lib.h>
 #include <net/uip/httpd.h>
 
 #include "httpd.h"
@@ -60,9 +66,6 @@
  * Definitions
  ****************************************************************************/
 
-#define STATE_WAITING 0
-#define STATE_OUTPUT  1
-
 #define ISO_nl      0x0a
 #define ISO_space   0x20
 #define ISO_bang    0x21
@@ -71,21 +74,50 @@
 #define ISO_slash   0x2f
 #define ISO_colon   0x3a
 
-#define SEND_STR(psock, str) psock_send(psock, str, strlen(str))
+#define CONFIG_NETUTILS_HTTPD_DUMPBUFFER 1
 
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
 
-static inline int send_file(struct httpd_state *pstate)
+#ifdef CONFIG_NETUTILS_HTTPD_DUMPBUFFER
+static void httpd_dumpbuffer(struct httpd_state *pstate, ssize_t nbytes)
 {
-  return send(pstate->sockout, pstate->file.data, pstate->file.len, 0);
-}
+#ifdef CONFIG_DEBUG
+  char line[128];
+  int ch;
+  int i;
+  int j;
 
-static inline int send_part_of_file(struct httpd_state *pstate)
-{
-  return send(pstate->sockout, pstate->file.data, pstate->len, 0);
+  for (i = 0; i < nbytes; i += 16)
+    {
+      sprintf(line, "%04x: ", i);
+      for ( j = 0; j < 16; j++)
+        {
+          if (i + j < nbytes)
+            {
+              sprintf(&line[strlen(line)], "%02x ", pstate->ht_buffer[i+j] );
+            }
+          else
+            {
+              strcpy(&line[strlen(line)], "   ");
+            }
+        }
+      for ( j = 0; j < 16; j++)
+        {
+          if (i + j < nbytes)
+            {
+              ch = pstate->ht_buffer[i+j];
+              sprintf(&line[strlen(line)], "%c", ch >= 0x20 && ch <= 0x7e ? ch : '.');
+            }
+        }
+      dbg("%s", line);
+    }
+#endif
 }
+#else
+# define httpd_dumpbuffer(pstate,nbytes)
+#endif
 
 static void next_scriptstate(struct httpd_state *pstate)
 {
@@ -95,35 +127,40 @@ static void next_scriptstate(struct httpd_state *pstate)
   pstate->scriptptr = p;
 }
 
-static void handle_script(struct httpd_state *pstate, struct uip_conn *conn)
+static void handle_script(struct httpd_state *pstate)
 {
   char *ptr;
 
   while(pstate->file.len > 0) {
 
-    /* Check if we should start executing a script. */
+    /* Check if we should start executing a script */
+
     if (*pstate->file.data == ISO_percent &&
        *(pstate->file.data + 1) == ISO_bang) {
       pstate->scriptptr = pstate->file.data + 3;
       pstate->scriptlen = pstate->file.len - 3;
-      if (*(pstate->scriptptr - 1) == ISO_colon) {
-	httpd_fs_open(pstate->scriptptr + 1, &pstate->file);
-	send_file(pstate);
-      } else {
-        httpd_cgi(pstate->scriptptr)(pstate, pstate->scriptptr);
-      }
+      if (*(pstate->scriptptr - 1) == ISO_colon)
+        {
+          httpd_fs_open(pstate->scriptptr + 1, &pstate->file);
+          send(pstate->sockfd, pstate->file.data, pstate->file.len, 0);
+        }
+      else
+        {
+          httpd_cgi(pstate->scriptptr)(pstate, pstate->scriptptr);
+        }
       next_scriptstate(pstate);
 
       /* The script is over, so we reset the pointers and continue
-	 sending the rest of the file. */
+	 sending the rest of the file */
       pstate->file.data = pstate->scriptptr;
       pstate->file.len = pstate->scriptlen;
+
     } else {
       /* See if we find the start of script marker in the block of HTML
-	 to be sent. */
+	 to be sent */
 
-      if (pstate->file.len > uip_mss(conn)) {
-	pstate->len = uip_mss(conn);
+      if (pstate->file.len > HTTPD_IOBUFFER_SIZE) {
+	pstate->len = HTTPD_IOBUFFER_SIZE;
       } else {
 	pstate->len = pstate->file.len;
       }
@@ -136,11 +173,11 @@ static void handle_script(struct httpd_state *pstate, struct uip_conn *conn)
       if (ptr != NULL &&
 	 ptr != pstate->file.data) {
 	pstate->len = (int)(ptr - pstate->file.data);
-	if (pstate->len >= uip_mss(conn)) {
-	  pstate->len = uip_mss(conn);
+	if (pstate->len >= HTTPD_IOBUFFER_SIZE) {
+	  pstate->len = HTTPD_IOBUFFER_SIZE;
 	}
       }
-      send_part_of_file(pstate);
+      send(pstate->sockfd, pstate->file.data, pstate->len, 0);
       pstate->file.data += pstate->len;
       pstate->file.len -= pstate->len;
     }
@@ -152,41 +189,41 @@ static int send_headers(struct httpd_state *pstate, const char *statushdr)
   char *ptr;
   int ret;
 
-  ret = send(pstate->sockout, statushdr, strlen(statushdr), 0);
+  ret = send(pstate->sockfd, statushdr, strlen(statushdr), 0);
 
   ptr = strrchr(pstate->filename, ISO_period);
   if (ptr == NULL)
     {
-      ret = send(pstate->sockout, http_content_type_binary, strlen(http_content_type_binary), 0);
+      ret = send(pstate->sockfd, http_content_type_binary, strlen(http_content_type_binary), 0);
     }
   else if (strncmp(http_html, ptr, 5) == 0 || strncmp(http_shtml, ptr, 6) == 0)
     {
-      ret = send(pstate->sockout, http_content_type_html, strlen(http_content_type_html), 0);
+      ret = send(pstate->sockfd, http_content_type_html, strlen(http_content_type_html), 0);
     }
   else if (strncmp(http_css, ptr, 4) == 0)
     {
-      ret = send(pstate->sockout, http_content_type_css, strlen(http_content_type_css), 0);
+      ret = send(pstate->sockfd, http_content_type_css, strlen(http_content_type_css), 0);
     }
   else if (strncmp(http_png, ptr, 4) == 0)
     {
-      ret = send(pstate->sockout, http_content_type_png, strlen(http_content_type_png), 0);
+      ret = send(pstate->sockfd, http_content_type_png, strlen(http_content_type_png), 0);
     }
   else if (strncmp(http_gif, ptr, 4) == 0)
     {
-      ret = send(pstate->sockout, http_content_type_gif, strlen(http_content_type_gif), 0);
+      ret = send(pstate->sockfd, http_content_type_gif, strlen(http_content_type_gif), 0);
     }
   else if (strncmp(http_jpg, ptr, 4) == 0)
     {
-      ret = send(pstate->sockout, http_content_type_jpg, strlen(http_content_type_jpg), 0);
+      ret = send(pstate->sockfd, http_content_type_jpg, strlen(http_content_type_jpg), 0);
     }
   else
     {
-      ret = send(pstate->sockout, http_content_type_plain, strlen(http_content_type_plain), 0);
+      ret = send(pstate->sockfd, http_content_type_plain, strlen(http_content_type_plain), 0);
     }
   return ret;
 }
 
-static void handle_output(struct httpd_state *pstate, struct uip_conn *conn)
+static void httpd_sendfile(struct httpd_state *pstate)
 {
   char *ptr;
 
@@ -195,7 +232,7 @@ static void handle_output(struct httpd_state *pstate, struct uip_conn *conn)
       httpd_fs_open(http_404_html, &pstate->file);
       strcpy(pstate->filename, http_404_html);
       send_headers(pstate, http_header_404);
-      send_file(pstate);
+      send(pstate->sockfd, pstate->file.data, pstate->file.len, 0);
     }
   else
     {
@@ -203,75 +240,102 @@ static void handle_output(struct httpd_state *pstate, struct uip_conn *conn)
       ptr = strchr(pstate->filename, ISO_period);
       if (ptr != NULL && strncmp(ptr, http_shtml, 6) == 0)
         {
-          handle_script(pstate, conn);
+          handle_script(pstate);
         }
       else
         {
-        send_file(pstate);
+          send(pstate->sockfd, pstate->file.data, pstate->file.len, 0);
         }
     }
 }
 
-static int handle_input(struct httpd_state *pstate)
+static inline int httpd_cmd(struct httpd_state *pstate)
 {
   ssize_t recvlen;
+  int i;
+
+  /* Get the next HTTP command.  We will handle only GET */
 
-  if (recv(pstate->sockin, pstate->inputbuf, HTTPD_INBUFFER_SIZE, 0) < 0)
+  recvlen = recv(pstate->sockfd, pstate->ht_buffer, HTTPD_IOBUFFER_SIZE, 0);
+  if (recvlen < 0)
     {
       return ERROR;
     }
+  httpd_dumpbuffer(pstate, recvlen);
 
-  if (strncmp(pstate->inputbuf, http_get, 4) != 0)
-    {
-      return ERROR;
-  }
+  /*  We will handle only GET */
 
-  recvlen = recv(pstate->sockin, pstate->inputbuf, HTTPD_INBUFFER_SIZE, 0);
-  if (recvlen < 0)
+  if (strncmp(pstate->ht_buffer, http_get, 4) != 0)
     {
       return ERROR;
     }
 
-  if (pstate->inputbuf[0] != ISO_slash)
-  {
-    return ERROR;
-  }
+  /* Get the name of the file to provide */
 
-  if (pstate->inputbuf[1] == ISO_space)
+  if (pstate->ht_buffer[4] != ISO_slash)
+    {
+      return ERROR;
+    }
+  else if (pstate->ht_buffer[5] == ISO_space)
     {
       strncpy(pstate->filename, http_index_html, sizeof(pstate->filename));
     }
   else
     {
-      pstate->inputbuf[recvlen - 1] = 0;
-      strncpy(pstate->filename, &pstate->inputbuf[0], sizeof(pstate->filename));
+      for (i = 5; i < sizeof(pstate->filename) + 5 && pstate->ht_buffer[5] != ISO_space; i++)
+        {
+          pstate->filename[i] = pstate->ht_buffer[i+5];
+        }
     }
 
-  pstate->state = STATE_OUTPUT;
+  /* Then send the file */
+
+  httpd_sendfile(pstate);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: httpd_handler
+ *
+ * Description:
+ *   Each time a new connection to port 80 is made, a new thread is created
+ *   that begins at this entry point.  There should be exactly one argument
+ *   and it should be the socket descriptor (+1).
+ *
+ ****************************************************************************/
+
+static int httpd_handler(int argc, char *argv[])
+{
+  struct httpd_state *pstate = (struct httpd_state *)malloc(sizeof(struct httpd_state));
+  int                 sockfd = (int)argv[1] - 1;
+  int                 ret    = ERROR;
+
+  /* Verify that the state structure was successfully allocated */
 
-  while(1)
+  if (pstate)
     {
-      recvlen = recv(pstate->sockin, pstate->inputbuf, HTTPD_INBUFFER_SIZE, 0);
-      if (recvlen < 0)
+      /* Loop processing each HTTP command */
+      do
         {
-          return ERROR;
-        }
+          /* Re-initialize the thread state structure */
 
-      if (strncmp(pstate->inputbuf, http_referer, 8) == 0)
-        {
-          pstate->inputbuf[recvlen - 2] = 0;
+          memset(pstate, 0, sizeof(struct httpd_state));
+          pstate->sockfd = sockfd;
+
+          /* Then handle the next httpd command */
+
+          ret = httpd_cmd(pstate);
         }
-    }
+      while (ret == OK);
 
-  return OK;
-}
+    /* End of command processing -- Clean up and exit */
 
-static void handle_connection(struct httpd_state *pstate, struct uip_conn *conn)
-{
-  handle_input(pstate);
-  if (pstate->state == STATE_OUTPUT) {
-    handle_output(pstate, conn);
+    free(pstate);
   }
+
+  /* Exit the task */
+
+  return 0;
 }
 
 /****************************************************************************
@@ -288,20 +352,24 @@ static void handle_connection(struct httpd_state *pstate, struct uip_conn *conn)
 
 int httpd_listen(void)
 {
-#warning "this is all very broken at the moment"
-  return OK;
+  /* Execute httpd_handler on each connection to port 80 */
+
+  uip_server(HTONS(80), httpd_handler, CONFIG_EXAMPLES_UIP_HTTPDSTACKSIZE);
+
+  /* uip_server only returns on errors */
+
+  return ERROR;
 }
 
 /****************************************************************************
  * Name: httpd_init
  *
  * Description:
- * This function initializes the web server and should be called at system
- * boot-up.
+ *   This function initializes the web server and should be called at system
+ *   boot-up.
  *
  ****************************************************************************/
 
 void httpd_init(void)
 {
-  uip_listen(HTONS(80));
 }
diff --git a/netutils/webserver/httpd.h b/netutils/webserver/httpd.h
index b256c1dd16fa4a6ff9b298daec23f3244ebfb1e4..cf067f8078ab6583d7c90606ab234cb4286b4899 100644
--- a/netutils/webserver/httpd.h
+++ b/netutils/webserver/httpd.h
@@ -1,11 +1,19 @@
-/* httpd.h
+/****************************************************************************
+ * netutils/webserver/httpd.h
  *
- * Copyright (c) 2001-2005, Adam Dunkels.
- * All rights reserved.
+ *   Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ *   Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Based on uIP which also has a BSD style license:
+ *
+ *   Author: Adam Dunkels <adam@sics.se>
+ *   Copyright (c) 2001-2005, Adam Dunkels.
+ *   All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
+ *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
@@ -26,15 +34,33 @@
  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
+ *
+ ****************************************************************************/
 
 #ifndef _NETUTILS_WEBSERVER_HTTPD_H
 #define _NETUTILS_WEBSERVER_HTTPD_H
 
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
 #include <sys/types.h>
 
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
 #define HTTPD_FS_STATISTICS 1
-#define HTTPD_INBUFFER_SIZE 50
+#define HTTPD_IOBUFFER_SIZE 512
+
+#ifndef CONFIG_EXAMPLES_UIP_HTTPDSTACKSIZE
+# define CONFIG_EXAMPLES_UIP_HTTPDSTACKSIZE 4096
+#endif
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
 
 struct httpd_fs_file
 {
@@ -44,13 +70,10 @@ struct httpd_fs_file
 
 struct httpd_state
 {
-  unsigned char timer;
-  int sockin;
-  int sockout;
-  char inputbuf[HTTPD_INBUFFER_SIZE];
+  char ht_buffer[HTTPD_IOBUFFER_SIZE];
   char filename[20];
-  char state;
   struct httpd_fs_file file;
+  int sockfd;                         /* The socket descriptor from accept() */
   int len;
   char *scriptptr;
   int scriptlen;
@@ -58,17 +81,19 @@ struct httpd_state
   unsigned short count;
 };
 
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
 #ifdef HTTPD_FS_STATISTICS
 #if HTTPD_FS_STATISTICS == 1
 extern uint16 httpd_fs_count(char *name);
 #endif /* HTTPD_FS_STATISTICS */
 #endif /* HTTPD_FS_STATISTICS */
 
-/* file must be allocated by caller and will be filled in
- * by the function.
- */
+/* file must be allocated by caller and will be filled in by the function. */
 
-int httpd_fs_open(const char *name, struct httpd_fs_file *file);
+int  httpd_fs_open(const char *name, struct httpd_fs_file *file);
 void httpd_fs_init(void);
 
 #endif /* _NETUTILS_WEBSERVER_HTTPD_H */