NetServices Stack source

Dependents:   HelloWorld ServoInterfaceBoardExample1 4180_Lab4

Files at this revision

API Documentation at this revision

Comitter:
donatien
Date:
Tue Jul 27 15:59:42 2010 +0000
Parent:
4:fd826cad83c0
Child:
6:b7dd7cde8ad2
Commit message:

Changed in this revision

api/DNSRequest.h Show annotated file Show diff for this revision Revisions of this file
api/TCPSocket.h Show annotated file Show diff for this revision Revisions of this file
api/UDPSocket.h Show annotated file Show diff for this revision Revisions of this file
dbg/dbg.cpp Show annotated file Show diff for this revision Revisions of this file
dbg/dbg.h Show annotated file Show diff for this revision Revisions of this file
drv/eth/eth_drv.cpp Show annotated file Show diff for this revision Revisions of this file
drv/gprsmodule/GPRSModule.cpp Show annotated file Show diff for this revision Revisions of this file
drv/gprsmodule/GPRSModule.h Show annotated file Show diff for this revision Revisions of this file
drv/telit/telit.cpp Show diff for this revision Revisions of this file
drv/telit/telit.h Show diff for this revision Revisions of this file
drv/umtsstick/UMTSStick.cpp Show annotated file Show diff for this revision Revisions of this file
drv/usb/UsbEndpoint.cpp Show annotated file Show diff for this revision Revisions of this file
drv/usb/UsbHostMgr.cpp Show annotated file Show diff for this revision Revisions of this file
drv/usb/UsbHostMgr.h Show annotated file Show diff for this revision Revisions of this file
drv/usb/usb_mem.c Show annotated file Show diff for this revision Revisions of this file
if/eth/EthernetNetIf.cpp Show annotated file Show diff for this revision Revisions of this file
if/eth/EthernetNetIf.h Show annotated file Show diff for this revision Revisions of this file
if/gprsmodule/GPRSModuleNetIf.cpp Show annotated file Show diff for this revision Revisions of this file
if/gprsmodule/GPRSModuleNetIf.h Show annotated file Show diff for this revision Revisions of this file
if/lwip/lwipNetTcpSocket.cpp Show annotated file Show diff for this revision Revisions of this file
if/lwip/lwipNetUdpSocket.cpp Show annotated file Show diff for this revision Revisions of this file
if/lwip/lwipNetUdpSocket.h Show annotated file Show diff for this revision Revisions of this file
if/net/ipaddr.h Show annotated file Show diff for this revision Revisions of this file
if/net/netif.h Show annotated file Show diff for this revision Revisions of this file
if/ppp/PPPNetIf.cpp Show annotated file Show diff for this revision Revisions of this file
if/umtsstick/UMTSStickNetIf.h Show annotated file Show diff for this revision Revisions of this file
lwip/arch/cc.h Show annotated file Show diff for this revision Revisions of this file
lwip/core/def.c Show annotated file Show diff for this revision Revisions of this file
lwip/core/dhcp.c Show annotated file Show diff for this revision Revisions of this file
lwip/core/dns.c Show annotated file Show diff for this revision Revisions of this file
lwip/core/init.c Show annotated file Show diff for this revision Revisions of this file
lwip/core/ipv4/autoip.c Show annotated file Show diff for this revision Revisions of this file
lwip/core/ipv4/icmp.c Show annotated file Show diff for this revision Revisions of this file
lwip/core/ipv4/igmp.c Show annotated file Show diff for this revision Revisions of this file
lwip/core/ipv4/ip.c Show annotated file Show diff for this revision Revisions of this file
lwip/core/ipv4/ip_addr.c Show annotated file Show diff for this revision Revisions of this file
lwip/core/ipv4/ip_frag.c Show annotated file Show diff for this revision Revisions of this file
lwip/core/mem.c Show annotated file Show diff for this revision Revisions of this file
lwip/core/memp.c Show annotated file Show diff for this revision Revisions of this file
lwip/core/pbuf.c Show annotated file Show diff for this revision Revisions of this file
lwip/core/raw.c Show annotated file Show diff for this revision Revisions of this file
lwip/core/snmp/mib2.c Show annotated file Show diff for this revision Revisions of this file
lwip/core/snmp/mib_structs.c Show annotated file Show diff for this revision Revisions of this file
lwip/core/snmp/msg_out.c Show annotated file Show diff for this revision Revisions of this file
lwip/core/stats.c Show annotated file Show diff for this revision Revisions of this file
lwip/core/tcp.c Show annotated file Show diff for this revision Revisions of this file
lwip/core/tcp_in.c Show annotated file Show diff for this revision Revisions of this file
lwip/core/tcp_out.c Show annotated file Show diff for this revision Revisions of this file
lwip/core/timers.c Show annotated file Show diff for this revision Revisions of this file
lwip/core/udp.c Show annotated file Show diff for this revision Revisions of this file
lwip/include/ipv4/lwip/autoip.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/ipv4/lwip/icmp.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/ipv4/lwip/inet.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/ipv4/lwip/ip.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/ipv4/lwip/ip_addr.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/ipv4/lwip/ip_frag.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/lwip/api.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/lwip/api_msg.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/lwip/def.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/lwip/dhcp.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/lwip/dns.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/lwip/err.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/lwip/init.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/lwip/mem.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/lwip/memp_std.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/lwip/netbuf.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/lwip/netif.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/lwip/opt.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/lwip/pbuf.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/lwip/snmp_asn1.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/lwip/snmp_structs.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/lwip/sockets.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/lwip/stats.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/lwip/sys.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/lwip/tcp_impl.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/lwip/tcpip.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/lwip/timers.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/lwip/udp.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/netif/etharp.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/netif/ppp_oe.h Show annotated file Show diff for this revision Revisions of this file
lwip/lwipopts.h Show annotated file Show diff for this revision Revisions of this file
lwip/lwipopts_light.h Show diff for this revision Revisions of this file
lwip/netif/etharp.c Show annotated file Show diff for this revision Revisions of this file
lwip/netif/ppp/fsm.c Show annotated file Show diff for this revision Revisions of this file
lwip/netif/ppp/ppp.c Show annotated file Show diff for this revision Revisions of this file
lwip/netif/ppp/vj.c Show annotated file Show diff for this revision Revisions of this file
netCfg.h Show annotated file Show diff for this revision Revisions of this file
services/email/smtp/SMTPClient.cpp Show annotated file Show diff for this revision Revisions of this file
services/http/client/HTTPClient.cpp Show annotated file Show diff for this revision Revisions of this file
services/http/client/HTTPClient.h Show annotated file Show diff for this revision Revisions of this file
services/http/server/HTTPServer.h Show annotated file Show diff for this revision Revisions of this file
services/mysql/MySQLClient.cpp Show annotated file Show diff for this revision Revisions of this file
services/mysql/MySQLClient.h Show annotated file Show diff for this revision Revisions of this file
services/mysql/sha1.h Show annotated file Show diff for this revision Revisions of this file
services/ntp/NTPClient.cpp Show annotated file Show diff for this revision Revisions of this file
services/ntp/NTPClient.h Show annotated file Show diff for this revision Revisions of this file
--- a/api/DNSRequest.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/api/DNSRequest.h	Tue Jul 27 15:59:42 2010 +0000
@@ -27,38 +27,66 @@
 #include "if/net/net.h"
 //Essentially it is a safe interface to NetDnsRequest
 
+///DNS Request Errors
 enum DNSRequestErr
 {
   __DNS_MIN = -0xFFFF,
-  DNS_SETUP, //NetDnsRequest not properly configured
-  DNS_IF, //If has problems, does not exist or is not initialized
-  DNS_MEM, //Not enough mem
-  DNS_INUSE, //If/Port is in use
-  DNS_PROCESSING, //Req has not completed
+  DNS_SETUP, ///DNSRequest not properly configured
+  DNS_IF, ///Interface has problems, does not exist or is not initialized
+  DNS_MEM, ///Not enough mem
+  DNS_INUSE, ///Interface / Port is in use
+  DNS_PROCESSING, ///Request has not completed
 //...
   DNS_OK = 0
 };
 
+///DNS Request Result Events
 enum DNSReply
 {
   DNS_PRTCL,
-  DNS_NOTFOUND, //Hostname is unknown
-  DNS_ERROR, //Problem with DNS Service
+  DNS_NOTFOUND, ///Hostname is unknown
+  DNS_ERROR, ///Problem with DNS Service
   //...
   DNS_FOUND,
 };
 
+///This is a simple DNS Request class
+/**
+  This class exposes an API to deal with DNS Requests
+*/
 class DNSRequest
 {
 public:
+  ///Creates a new request
   DNSRequest();
   ~DNSRequest();
   
+  ///Resolves an hostname
+  /*
+  @param hostname : hostname to resolve
+  */
   DNSRequestErr resolve(const char* hostname);
+  
+  ///Resolves an hostname
+  /*
+  @param host : hostname to resolve, the result will be stored in the IpAddr field of this object
+  */
   DNSRequestErr resolve(Host* pHost);
   
+  ///Setups callback
+  /**
+  The callback function will be called on result.
+  @param pMethod : callback function
+  */  
+  void setOnReply( void (*pMethod)(DNSReply) );
+  
   class CDummy;
-  void setOnReply( void (*pMethod)(DNSReply) );
+  ///Setups callback
+  /**
+  The callback function will be called on result.
+  @param pItem : instance of class on which to execute the callback method
+  @param pMethod : callback method
+  */
   template<class T> 
   void setOnReply( T* pItem, void (T::*pMethod)(DNSReply) )
   {
@@ -66,8 +94,13 @@
     m_pCbMeth = (void (CDummy::*)(DNSReply)) pMethod;
   }
   
+  ///Gets IP address once it has been resolved
+  /*
+  @param pIp : pointer to an IpAddr instance in which to store the resolved IP address
+  */
   DNSRequestErr getResult(IpAddr* pIp);
   
+  ///Close DNS Request before completion
   DNSRequestErr close();
   
 protected:
--- a/api/TCPSocket.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/api/TCPSocket.h	Tue Jul 27 15:59:42 2010 +0000
@@ -27,58 +27,92 @@
 #include "if/net/net.h"
 //Essentially it is a safe interface to NetTcpSocket
 
+///TCP Socket Errors
 enum TCPSocketErr
 {
   __TCPSOCKET_MIN = -0xFFFF,
-  TCPSOCKET_SETUP, //NetTcpSocket not properly configured
+  TCPSOCKET_SETUP, ///TCPSocket not properly configured
   TCPSOCKET_TIMEOUT,
-  TCPSOCKET_IF, //If has problems, does not exist or is not initialized
-  TCPSOCKET_MEM, //Not enough mem
-  TCPSOCKET_INUSE, //If/Port is in use
-  TCPSOCKET_EMPTY, //Connections queue is empty
-  TCPSOCKET_RST, // Connection was reset by remote host
+  TCPSOCKET_IF, ///Interface has problems, does not exist or is not initialized
+  TCPSOCKET_MEM, ///Not enough mem
+  TCPSOCKET_INUSE, ///Interface / Port is in use
+  TCPSOCKET_EMPTY, ///Connections queue is empty
+  TCPSOCKET_RST, ///Connection was reset by remote host
 //...
   TCPSOCKET_OK = 0
 };
 
+///TCP Socket Events
 enum TCPSocketEvent
 {
-  TCPSOCKET_CONNECTED, //Connected to host, must call accept() if we were listening
-  TCPSOCKET_ACCEPT,  //Connected to client
-  TCPSOCKET_READABLE, //Data in buf
-  TCPSOCKET_WRITEABLE, //Can write data to buf
-  TCPSOCKET_CONTIMEOUT,
-  TCPSOCKET_CONRST,
-  TCPSOCKET_CONABRT,
-  TCPSOCKET_ERROR,
-  TCPSOCKET_DISCONNECTED
+  TCPSOCKET_CONNECTED, ///Connected to host
+  TCPSOCKET_ACCEPT,  ///Client is connected, must call accept() to get a new Socket
+  TCPSOCKET_READABLE, ///Data in buf
+  TCPSOCKET_WRITEABLE, ///Can write data to buf
+  TCPSOCKET_CONTIMEOUT, ///Connection timed out
+  TCPSOCKET_CONRST, ///Connection was reset by remote host
+  TCPSOCKET_CONABRT, ///Connection was aborted
+  TCPSOCKET_ERROR, ///Unknown error
+  TCPSOCKET_DISCONNECTED ///Disconnected
 };
 
-
+///This is a simple TCP Socket class
+/**
+  This class exposes an API to deal with TCP Sockets
+*/
 class TCPSocket
 {
 public:
+  ///Creates a new socket
   TCPSocket();
 protected:
   TCPSocket(NetTcpSocket* pNetTcpSocket);
 public:
+  ///Closes if needed and destroys the socket
   ~TCPSocket(); //close()
   
+  ///Binds the socket to (local) host
   TCPSocketErr bind(const Host& me);
+  
+  ///Starts listening
   TCPSocketErr listen();
+  
+  ///Connects socket to host
   TCPSocketErr connect(const Host& host);
+  
+  ///Accepts connection from client and gets connected socket
   TCPSocketErr accept(Host* pClient, TCPSocket** ppNewTcpSocket);
   
+  ///Sends data
+  /*
+  @return a negative error code or the number of bytes transmitted
+  */
   int /*if < 0 : TCPSocketErr*/ send(const char* buf, int len);
+  
+  ///Receives data
+  /*
+  @return a negative error code or the number of bytes received
+  */
   int /*if < 0 : TCPSocketErr*/ recv(char* buf, int len);
 
   /* TODO NTH : printf / scanf helpers that call send/recv */
 
+  ///Closes socket
   TCPSocketErr close();
 
+  //Callbacks
+  ///Setups callback
+  /**
+  @param pMethod : callback function
+  */
+  void setOnEvent( void (*pMethod)(TCPSocketEvent) );
+  
   class CDummy;
-  //Callbacks
-  void setOnEvent( void (*pMethod)(TCPSocketEvent) );
+  ///Setups callback
+  /**
+  @param pItem : instance of class on which to execute the callback method
+  @param pMethod : callback method
+  */
   template<class T> 
   void setOnEvent( T* pItem, void (T::*pMethod)(TCPSocketEvent) )
   {
@@ -86,7 +120,8 @@
     m_pCbMeth = (void (CDummy::*)(TCPSocketEvent)) pMethod;
   }
   
-  void resetOnEvent(); //Disable callback
+  ///Disables callback
+  void resetOnEvent(); 
   
 protected:
   void onNetTcpSocketEvent(NetTcpSocketEvent e);
--- a/api/UDPSocket.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/api/UDPSocket.h	Tue Jul 27 15:59:42 2010 +0000
@@ -27,41 +27,70 @@
 #include "if/net/net.h"
 //Essentially it is a safe interface to NetUdpSocket
 
+///UDP Socket Errors
 enum UDPSocketErr
 {
   __UDPSOCKET_MIN = -0xFFFF,
-  UDPSOCKET_SETUP, //NetUdpSocket not properly configured
-  UDPSOCKET_IF, //If has problems, does not exist or is not initialized
-  UDPSOCKET_MEM, //Not enough mem
-  UDPSOCKET_INUSE, //If/Port is in use
+  UDPSOCKET_SETUP, ///UDPSocket not properly configured
+  UDPSOCKET_IF, ///Interface has problems, does not exist or is not initialized
+  UDPSOCKET_MEM, ///Not enough mem
+  UDPSOCKET_INUSE, ///Interface / Port is in use
 //...
   UDPSOCKET_OK = 0
 };
 
+///UDP Socket Event(s)
 enum UDPSocketEvent //Only one lonely event here... but who knows, maybe some day there'll be another one!
 {
-  UDPSOCKET_READABLE, //Data in buf
+  UDPSOCKET_READABLE, ///Data in buf
 };
 
-
+///This is a simple UDP Socket class
+/**
+  This class exposes an API to deal with UDP Sockets
+*/
 class UDPSocket
 {
 public:
+  ///Creates a new socket
   UDPSocket();
   ~UDPSocket(); //close()
   
+  ///Binds the socket to (local) host (or TODO: a multicast address)
   UDPSocketErr bind(const Host& me);
   
+  ///Sends data
+  /*
+  @param pHost : host to send data to
+  @return a negative error code or the number of bytes transmitted
+  */
   int /*if < 0 : UDPSocketErr*/ sendto(const char* buf, int len, Host* pHost);
+  
+  ///Receives data
+  /*
+  @param pHost : host from which this piece of data comes from
+  @return a negative error code or the number of bytes received
+  */
   int /*if < 0 : UDPSocketErr*/ recvfrom(char* buf, int len, Host* pHost);
 
   /* TODO NTH : printf / scanf helpers that call send/recv */
 
+  ///Closes socket
   UDPSocketErr close();
 
+  //Callbacks
+  ///Setups callback
+  /**
+  @param pMethod : callback function
+  */  
+  void setOnEvent( void (*pMethod)(UDPSocketEvent) );
+  
   class CDummy;
-  //Callbacks
-  void setOnEvent( void (*pMethod)(UDPSocketEvent) );
+  ///Setups callback
+  /**
+  @param pItem : instance of class on which to execute the callback method
+  @param pMethod : callback method
+  */
   template<class T> 
   void setOnEvent( T* pItem, void (T::*pMethod)(UDPSocketEvent) )
   {
@@ -69,7 +98,8 @@
     m_pCbMeth = (void (CDummy::*)(UDPSocketEvent)) pMethod;
   }
   
-  void resetOnEvent(); //Disable callback
+  ///Disables callback
+  void resetOnEvent();
 
 protected:
   void onNetUdpSocketEvent(NetUdpSocketEvent e);
--- a/dbg/dbg.cpp	Fri Jul 09 14:46:47 2010 +0000
+++ b/dbg/dbg.cpp	Tue Jul 27 15:59:42 2010 +0000
@@ -27,31 +27,18 @@
 #include "mbed.h"
 #include <cstdarg>
 
-//LocalFileSystem dbgfs("dbgsfs"); 
-
-//static FILE* m_fp = NULL;
-
 void DebugStream::debug(const char* format, ...)
-{
-//  if(!m_fp)
-//    m_fp = fopen("/dbgsfs/dbg.txt", "a");
-  
+{ 
   va_list argp;
   
   va_start(argp, format);
   vprintf(format, argp);
-  //vfprintf(m_fp, format, argp);
   va_end(argp);
-  
- // printf("\r\n"); //Flush
-  //local("local");               // Create the local filesystem under the name "local"
-  
-//  fclose(m_fp);
 }
 
 void DebugStream::release()
 {
-  //fclose(m_fp);
+
 }
 
 void DebugStream::breakPoint(const char* file, int line)
--- a/dbg/dbg.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/dbg/dbg.h	Tue Jul 27 15:59:42 2010 +0000
@@ -28,6 +28,7 @@
 #define __DEBUG
 #endif
 
+///To define to enable debugging in one file
 #ifdef __DEBUG
 
 #ifndef __DEBUGSTREAM
@@ -47,8 +48,15 @@
 #undef DBG
 #undef DBG_END
 #undef BREAK
+
+///Debug output (if enabled), same syntax as printf, with heading info
 #define DBG(...) do{ DebugStream::debug("[%s:%s@%d] ", __FILE__, __FUNCTION__, __LINE__); DebugStream::debug(__VA_ARGS__); } while(0);
+
+///Debug output (if enabled), same syntax as printf, no heading info
+#define DBGL(...) do{ DebugStream::debug(__VA_ARGS__); } while(0);
 #define DBG_END DebugStream::release
+
+///Break point usin serial debug interface (if debug enbaled)
 #define BREAK() DebugStream::breakPoint(__FILE__, __LINE__)
 #endif
 
--- a/drv/eth/eth_drv.cpp	Fri Jul 09 14:46:47 2010 +0000
+++ b/drv/eth/eth_drv.cpp	Tue Jul 27 15:59:42 2010 +0000
@@ -170,7 +170,7 @@
   
   /* device capabilities */
   /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
-  netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
+  netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_IGMP;
 
   netif->state = NULL;
   eth_netif = netif;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drv/gprsmodule/GPRSModule.cpp	Tue Jul 27 15:59:42 2010 +0000
@@ -0,0 +1,100 @@
+
+/*
+Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
+ 
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+ 
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+ 
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "gprsmodule.h"
+
+#include "mbed.h"
+
+//#define __DEBUG
+#include "dbg/dbg.h"
+
+#include "netCfg.h"
+#if NET_GPRS_MODULE
+
+GPRSModule::GPRSModule(PinName pwrSetPin, PinName pwrMonPin) : m_pwrSetPin(pwrSetPin), m_pwrMonPin(pwrMonPin)
+{
+  //m_pwrSetPin.write(0);
+
+  //m_pwrMonPin.mode(PullDown);
+}
+
+GPRSModule::~GPRSModule() {
+
+}
+
+bool GPRSModule::isOn() //True if on
+{ 
+  return m_pwrMonPin.read();
+}
+
+bool GPRSModule::on() //True if OK
+{ 
+  Timer tmr;
+  if(!m_pwrMonPin.read()){
+    //On
+    DBG("Switching On...\n");
+    m_pwrSetPin.write(1);
+    wait(1.);
+    m_pwrSetPin.write(0);
+       
+    tmr.start();
+    while(!m_pwrMonPin.read())
+    {
+      wait(.001);
+      if(tmr.read() > 2)
+      { 
+         DBG("ERROR - MUST RESET MODULE\n");
+         break;
+      }
+    }
+    tmr.stop();
+  }
+  wait(.1);
+  return m_pwrMonPin.read();
+}
+
+bool GPRSModule::off() { //True if OK
+  Timer tmr;
+  if(m_pwrMonPin.read()){
+    //Off
+    DBG("Switching Off...\n");
+    m_pwrSetPin.write(1);
+    wait(3.);
+    m_pwrSetPin.write(0);
+      DBG("Waiting....\n"); 
+    tmr.start();
+    while(m_pwrMonPin.read())
+    {
+      wait(.001);
+      if(tmr.read() > 15)
+      { 
+         DBG("ERROR - MUST RESET MODULE\n");
+         break;
+      }
+    }
+    tmr.stop();
+  }
+  return !m_pwrMonPin.read();
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drv/gprsmodule/GPRSModule.h	Tue Jul 27 15:59:42 2010 +0000
@@ -0,0 +1,47 @@
+
+/*
+Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
+ 
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+ 
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+ 
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#ifndef GPRSMODULE_H
+#define GPRSMODULE_H
+
+#include "mbed.h"
+
+class GPRSModule
+{
+public:
+  GPRSModule(PinName pwrSetPin, PinName pwrMonPin);
+  ~GPRSModule();
+  
+  bool isOn(); //True if on
+  bool on(); //True if OK
+  bool off(); //True if OK
+  
+protected:
+ 
+private:
+  DigitalOut m_pwrSetPin;
+  DigitalIn m_pwrMonPin;
+
+};
+
+#endif
--- a/drv/telit/telit.cpp	Fri Jul 09 14:46:47 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-
-/*
-Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
- 
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
- 
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
- 
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-*/
-
-#include "telit.h"
-
-#include "mbed.h"
-
-//#define __DEBUG
-#include "dbg/dbg.h"
-
-#include "netCfg.h"
-#if NET_TELIT
-
-Telit::Telit(PinName pwrSetPin, PinName pwrMonPin) : m_pwrSetPin(pwrSetPin), m_pwrMonPin(pwrMonPin)
-{
-  //m_pwrSetPin.write(0);
-
-  //m_pwrMonPin.mode(PullDown);
-}
-
-Telit::~Telit() {
-
-}
-
-bool Telit::isOn() //True if on
-{ 
-  return m_pwrMonPin.read();
-}
-
-bool Telit::on() //True if OK
-{ 
-  Timer tmr;
-  if(!m_pwrMonPin.read()){
-    //On
-    DBG("Switching On...\n");
-    m_pwrSetPin.write(1);
-    wait(1.);
-    m_pwrSetPin.write(0);
-       
-    tmr.start();
-    while(!m_pwrMonPin.read())
-    {
-      wait(.001);
-      if(tmr.read() > 2)
-      { 
-         DBG("ERROR - MUST RESET MODULE\n");
-         break;
-      }
-    }
-    tmr.stop();
-  }
-  wait(.1);
-  return m_pwrMonPin.read();
-}
-
-bool Telit::off() { //True if OK
-  Timer tmr;
-  if(m_pwrMonPin.read()){
-    //Off
-    DBG("Switching Off...\n");
-    m_pwrSetPin.write(1);
-    wait(3.);
-    m_pwrSetPin.write(0);
-      DBG("Waiting....\n"); 
-    tmr.start();
-    while(m_pwrMonPin.read())
-    {
-      wait(.001);
-      if(tmr.read() > 15)
-      { 
-         DBG("ERROR - MUST RESET MODULE\n");
-         break;
-      }
-    }
-    tmr.stop();
-  }
-  return !m_pwrMonPin.read();
-}
-
-#endif
--- a/drv/telit/telit.h	Fri Jul 09 14:46:47 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-
-/*
-Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
- 
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
- 
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
- 
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-*/
-
-#ifndef TELIT_H
-#define TELIT_H
-
-#include "mbed.h"
-
-class Telit
-{
-public:
-  Telit(PinName pwrSetPin, PinName pwrMonPin);
-  ~Telit();
-  
-  bool isOn(); //True if on
-  bool on(); //True if OK
-  bool off(); //True if OK
-  
-protected:
- 
-private:
-  DigitalOut m_pwrSetPin;
-  DigitalIn m_pwrMonPin;
-
-};
-
-#endif
--- a/drv/umtsstick/UMTSStick.cpp	Fri Jul 09 14:46:47 2010 +0000
+++ b/drv/umtsstick/UMTSStick.cpp	Tue Jul 27 15:59:42 2010 +0000
@@ -116,6 +116,11 @@
       ready = true;
   }
   
+  wait(2); //Wait for device to be initialized
+  
+  if(!m_host.devicesCount())
+    return UMTSERR_DISCONNECTED;
+  
   m_pDev = m_host.getDevice(0);
   
   while(!m_pDev->enumerated())
@@ -124,9 +129,7 @@
     if(!m_host.devicesCount())
       return UMTSERR_DISCONNECTED;
   }
-  
-  wait(3);
-  
+   
   return UMTSERR_OK;
 }
 
--- a/drv/usb/UsbEndpoint.cpp	Fri Jul 09 14:46:47 2010 +0000
+++ b/drv/usb/UsbEndpoint.cpp	Tue Jul 27 15:59:42 2010 +0000
@@ -55,6 +55,9 @@
   m_pTdTail = (volatile HCTD*)usb_get_td();
   
   //printf("\r\n--m_pEd = %p--\r\n", m_pEd);
+  DBG("m_pEd = %p\n", m_pEd);
+  DBG("m_pTdHead = %p\n", m_pTdHead);
+  DBG("m_pTdTail = %p\n", m_pTdTail);
   
   //Init Ed & Td
   //printf("\r\n--Ep Init--\r\n");
@@ -330,10 +333,10 @@
 
 void UsbEndpoint::onCompletion()
 {
-  DBG("Transfer completed\n");
+  //DBG("Transfer completed\n");
   if( m_pTdHead->Control >> 28  )
   {
-    DBG("\r\nTD Failed with condition code %01x\r\n", m_pTdHead->Control >> 28 );
+    DBG("TD Failed with condition code %01x\n", m_pTdHead->Control >> 28 );
     m_status = (int)USBERR_TDFAIL;
   }
   else if( m_pEd->HeadTd & 0x1 )
@@ -346,7 +349,7 @@
   {
     //Done
     int len;
-    DBG("m_pTdHead->CurrBufPtr = %08x, m_pBufStartPtr=%08x\n", m_pTdHead->CurrBufPtr, (uint32_t) m_pBufStartPtr);
+    //DBG("m_pTdHead->CurrBufPtr = %08x, m_pBufStartPtr=%08x\n", m_pTdHead->CurrBufPtr, (uint32_t) m_pBufStartPtr);
     if(m_pTdHead->CurrBufPtr)
       len = m_pTdHead->CurrBufPtr - (uint32_t) m_pBufStartPtr;
     else
@@ -359,7 +362,7 @@
   }
   else
   {
-    DBG("\r\nUnknown error...\r\n");
+    DBG("Unknown error...\n");
     m_status = (int)USBERR_ERROR;
   }
   m_result = true;
@@ -373,7 +376,7 @@
       return;
   do
   {
-    DBG("sOnCompletion (pTd = %08x)\n", pTd);
+    //DBG("sOnCompletion (pTd = %08x)\n", pTd);
     UsbEndpoint* pEp = m_pHeadEp;  
     do
     {
--- a/drv/usb/UsbHostMgr.cpp	Fri Jul 09 14:46:47 2010 +0000
+++ b/drv/usb/UsbHostMgr.cpp	Tue Jul 27 15:59:42 2010 +0000
@@ -61,7 +61,7 @@
 
 UsbHostMgr::UsbHostMgr() : m_lpDevices()
 {
-  if(!pMgr)
+  /*if(!pMgr)*/ //Assume singleton
     pMgr = this;
   usb_mem_init();
   memset(m_lpDevices, NULL, sizeof(UsbDevice*) * USB_HOSTMGR_MAX_DEVS);
@@ -165,6 +165,15 @@
 
 void UsbHostMgr::poll() //Enumerate connected devices, etc
 {
+  /* Check for any connected devices */
+  if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CCS)  //Root device connected
+  {
+    //Device connected
+    wait(1);
+    DBG("Device connected (%08x)\n", LPC_USB->HcRhPortStatus1);
+    onUsbDeviceConnected(0, 1); //Hub 0 (root hub), Port 1 (count starts at 1)
+  }
+  
   for(int i = 0; i < devicesCount(); i++)
   {
     if( (m_lpDevices[i]->m_connected)
--- a/drv/usb/UsbHostMgr.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/drv/usb/UsbHostMgr.h	Tue Jul 27 15:59:42 2010 +0000
@@ -29,7 +29,7 @@
 #include "UsbInc.h"
 #include "UsbDevice.h"
 
-#define USB_HOSTMGR_MAX_DEVS 1 //1 device max for now... will be more when hubs are supported
+#define USB_HOSTMGR_MAX_DEVS 2 //2 devices max for now... will be more when hubs are supported
 
 class UsbDevice;
 
--- a/drv/usb/usb_mem.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/drv/usb/usb_mem.c	Tue Jul 27 15:59:42 2010 +0000
@@ -38,15 +38,15 @@
 #define TOTAL_SIZE (HCCA_SIZE + (EDS_COUNT*ED_SIZE) + (TDS_COUNT*TD_SIZE))
 
 
-static volatile byte usb_buf[TOTAL_SIZE] __attribute((section("AHBSRAM1"),aligned)) __attribute__((at(0x20080000)));  //256 bytes aligned!
+static volatile __align(256) byte usb_buf[TOTAL_SIZE] __attribute((section("AHBSRAM1"),aligned));  //256 bytes aligned!
 
 static volatile byte* usb_hcca;  //256 bytes aligned!
 
 static volatile byte* usb_edBuf;  //4 bytes aligned!
 static volatile byte* usb_tdBuf;  //4 bytes aligned!
 
-static byte usb_edBufAlloc[EDS_COUNT];
-static byte usb_tdBufAlloc[TDS_COUNT];
+static byte usb_edBufAlloc[EDS_COUNT] __attribute((section("AHBSRAM1"),aligned));
+static byte usb_tdBufAlloc[TDS_COUNT] __attribute((section("AHBSRAM1"),aligned));
 
 void usb_mem_init()
 {
--- a/if/eth/EthernetNetIf.cpp	Fri Jul 09 14:46:47 2010 +0000
+++ b/if/eth/EthernetNetIf.cpp	Tue Jul 27 15:59:42 2010 +0000
@@ -22,9 +22,12 @@
 */
 
 #include "EthernetNetIf.h"
+
 #include "netif/etharp.h"
 #include "lwip/dhcp.h"
 #include "lwip/dns.h"
+#include "lwip/igmp.h"
+
 #include "drv/eth/eth_drv.h"
 #include "mbed.h"
 
@@ -34,7 +37,7 @@
 #include "netCfg.h"
 #if NET_ETH
 
-EthernetNetIf::EthernetNetIf() : LwipNetIf(), m_ethArpTimer(), m_dhcpCoarseTimer(), m_dhcpFineTimer(), m_pNetIf(NULL),
+EthernetNetIf::EthernetNetIf() : LwipNetIf(), m_ethArpTimer(), m_dhcpCoarseTimer(), m_dhcpFineTimer(), m_igmpTimer(), m_pNetIf(NULL),
 m_netmask(255,255,255,255), m_gateway(), m_hostname(NULL)
 {
   m_hostname = NULL;
@@ -42,7 +45,7 @@
   m_useDhcp = true;
 }
 
-EthernetNetIf::EthernetNetIf(IpAddr ip, IpAddr netmask, IpAddr gateway, IpAddr dns) : LwipNetIf(), m_ethArpTimer(), m_dhcpCoarseTimer(), m_dhcpFineTimer(), m_pNetIf(NULL), m_hostname(NULL) //W/o DHCP
+EthernetNetIf::EthernetNetIf(IpAddr ip, IpAddr netmask, IpAddr gateway, IpAddr dns) : LwipNetIf(), m_ethArpTimer(), m_dhcpCoarseTimer(), m_dhcpFineTimer(), m_igmpTimer(), m_pNetIf(NULL), m_hostname(NULL) //W/o DHCP
 {
   m_hostname = NULL;
   m_netmask = netmask;
@@ -57,6 +60,7 @@
 {
   if(m_pNetIf)
   {
+    igmp_stop(m_pNetIf); //Stop IGMP processing
     netif_set_down(m_pNetIf);
     netif_remove(m_pNetIf);
     delete m_pNetIf;
@@ -129,6 +133,10 @@
     }
   }
   
+  #if LWIP_IGMP
+  igmp_start(m_pNetIf); //Start IGMP processing
+  #endif
+  
   m_ip = IpAddr(&(m_pNetIf->ip_addr));
    
   DBG("Connected, IP : %d.%d.%d.%d\n", m_ip[0], m_ip[1], m_ip[2], m_ip[3]);
@@ -143,6 +151,13 @@
     m_ethArpTimer.reset();
     etharp_tmr();
   }
+  #if LWIP_IGMP
+  if(m_igmpTimer.read_ms()>=IGMP_TMR_INTERVAL)
+  {
+    m_igmpTimer.reset();
+    igmp_tmr();
+  }
+  #endif
   LwipNetIf::poll();
   eth_poll();
 }
--- a/if/eth/EthernetNetIf.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/if/eth/EthernetNetIf.h	Tue Jul 27 15:59:42 2010 +0000
@@ -34,17 +34,33 @@
 enum EthernetErr
 {
   __ETH_MIN = -0xFFFF,
-  ETH_TIMEOUT, //Timeout during setup
+  ETH_TIMEOUT, ///Timeout during setup
   ETH_OK = 0
 };
 
+///Ethernet network interface
+/**
+This class provides Ethernet connectivity to the stack
+*/
 class EthernetNetIf : public LwipNetIf
 {
 public:
+  ///Instantiates the Interface and register it against the stack, DHCP will be used
   EthernetNetIf(); //W/ DHCP
+
+  ///Instantiates the Interface and register it against the stack, DHCP will not be used
+  /**
+  IpAddr is a container class that can be constructed with either 4 bytes or no parameters for a null IP address.
+  */
   EthernetNetIf(IpAddr ip, IpAddr netmask, IpAddr gateway, IpAddr dns); //W/o DHCP
   virtual ~EthernetNetIf();
   
+  ///Brings the interface up
+  /**
+  Uses DHCP if necessary
+  @param timeout_ms : You can set the timeout parameter in milliseconds, if not it defaults to 15s
+  @return : ETH_OK on success or ETH_TIMEOUT on timeout
+  */
   EthernetErr setup(int timeout_ms = 15000);
 
   virtual void poll();
@@ -53,6 +69,7 @@
   Timer m_ethArpTimer;
   Timer m_dhcpCoarseTimer;
   Timer m_dhcpFineTimer;
+  Timer m_igmpTimer;
     
   bool m_useDhcp;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/if/gprsmodule/GPRSModuleNetIf.cpp	Tue Jul 27 15:59:42 2010 +0000
@@ -0,0 +1,119 @@
+
+/*
+Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
+ 
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+ 
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+ 
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "netCfg.h"
+#if NET_GPRS_MODULE
+
+#include "GPRSModuleNetIf.h"
+
+#define __DEBUG
+#include "dbg/dbg.h"
+
+GPRSModuleNetIf::GPRSModuleNetIf(PinName tx, PinName rx, PinName pwrSetPin, PinName pwrMonPin, int baud /*= 115200*/) : PPPNetIf(NULL), m_module(pwrSetPin, pwrMonPin), m_serial(tx, rx)
+{
+  PPPNetIf::m_pIf = new GPRSModem();
+  m_serial.baud(baud);
+}
+
+GPRSModuleNetIf::~GPRSModuleNetIf()
+{
+  delete PPPNetIf::m_pIf;
+}
+  
+PPPErr GPRSModuleNetIf::connect(const char* apn /*= NULL*/, const char* userId /*= NULL*/, const char* password /*= NULL*/) //Connect using GPRS
+{
+  if(m_module.isOn())
+  {
+    DBG("Resetting module...\n");
+    m_module.off(); //Reset module if needed
+  }
+  
+  wait(4);
+
+  DBG("Powering on module.\n")
+  if(!m_module.on()) //Could not power on module
+  {
+    DBG("Could not power on module.\n");
+    return PPP_MODEM;
+  }
+  
+  wait(10); //Wait for module to init.
+
+  ATErr atErr;
+  for(int i=0; i<3; i++)
+  {
+    atErr = m_pIf->open(&m_serial); //3 tries
+    if(!atErr)
+      break;
+    DBG("Could not open AT If, trying again.\n");
+    wait(4);
+  }
+    
+  if(atErr)
+  {
+    m_module.off();
+    return PPP_MODEM;
+  }
+    
+  DBG("AT If opened.\n");
+
+  PPPErr pppErr;
+  for(int i=0; i<3; i++)
+  {  
+    DBG("Trying to connect.\n");
+    pppErr = PPPNetIf::GPRSConnect(apn, userId, password);
+    if(!pppErr)
+      break;
+    DBG("Could not connect.\n");
+    wait(4);
+  }
+  if(pppErr)
+  {
+    m_module.off();
+    return pppErr;
+  }
+    
+  DBG("Connected.\n");
+  
+  return PPP_OK;
+}
+
+PPPErr GPRSModuleNetIf::disconnect()
+{
+  DBG("Disconnecting...\n");
+  PPPErr pppErr = PPPNetIf::disconnect();
+  if(pppErr)
+    return pppErr;
+    
+  m_pIf->close();
+  
+  DBG("Powering off module.\n")
+  m_module.off(); //Power off module
+  
+  DBG("Off.\n")
+  
+  return PPP_OK;
+}
+  
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/if/gprsmodule/GPRSModuleNetIf.h	Tue Jul 27 15:59:42 2010 +0000
@@ -0,0 +1,51 @@
+
+/*
+Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
+ 
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+ 
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+ 
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#ifndef GPRSMODULENETIF_H
+#define GPRSMODULENETIF_H
+
+#include "mbed.h"
+
+#include "if/net/net.h"
+#include "if/ppp/PPPNetIf.h"
+
+#include "drv/gprs/GPRSModem.h"
+#include "drv/gprsmodule/GPRSModule.h"
+
+class GPRSModuleNetIf : protected PPPNetIf
+{
+public:
+  GPRSModuleNetIf(PinName tx, PinName rx, PinName pwrSetPin, PinName pwrMonPin, int baud = 115200); 
+  virtual ~GPRSModuleNetIf();
+  
+  PPPErr connect(const char* apn = NULL, const char* userId = NULL, const char* password = NULL); //Connect using GPRS
+  PPPErr disconnect();
+  
+private:
+  GPRSModule m_module;
+  Serial m_serial;
+
+};
+
+#endif
+
--- a/if/lwip/lwipNetTcpSocket.cpp	Fri Jul 09 14:46:47 2010 +0000
+++ b/if/lwip/lwipNetTcpSocket.cpp	Tue Jul 27 15:59:42 2010 +0000
@@ -33,9 +33,12 @@
 LwipNetTcpSocket::LwipNetTcpSocket(tcp_pcb* pPcb /*= NULL*/) : NetTcpSocket(), m_pPcb(pPcb), m_lpInNetTcpSocket(), //Passes a pcb if already created (by an accept req for instance), in that case transfers ownership
 m_pReadPbuf(NULL)
 {
-  DBG("\r\nNew NetTcpSocket %p\r\n", (void*)this);
+  DBG("New NetTcpSocket %p\n", (void*)this);
   if(!m_pPcb)
+  {
     m_pPcb = tcp_new();
+    DBG("Creating new PCB %p\n", m_pPcb);
+  }
   if(m_pPcb)
   {
     //Setup callbacks
@@ -46,7 +49,7 @@
     tcp_err( (tcp_pcb*) m_pPcb, LwipNetTcpSocket::sErrCb );
     //Connected callback is defined in connect()
     //Accept callback is defined in listen()
-    DBG("\r\nNetTcpSocket created.\r\n");
+    DBG("NetTcpSocket created.\n");
   }
 }
 
@@ -104,7 +107,7 @@
   ip_addr_t ip = host.getIp().getStruct();
   err_t err = tcp_connect( (tcp_pcb*) m_pPcb, &ip, host.getPort(), LwipNetTcpSocket::sConnectedCb );
   
-  if(!err)
+  if(err)
     return NETTCPSOCKET_MEM;
     
   return NETTCPSOCKET_OK;
@@ -156,7 +159,7 @@
   
 /*  if(*ppNewNetTcpSocket == NULL)
   {
-    DBG("\r\nNot enough mem, socket dropped in LwipNetTcpSocket::accept.\r\n");
+    DBG("Not enough mem, socket dropped in LwipNetTcpSocket::accept.\n");
     tcp_abort(pInPcb);
   }*/
   
@@ -253,7 +256,7 @@
 
 NetTcpSocketErr LwipNetTcpSocket::close()
 {
-  //DBG("\r\nLwipNetTcpSocket::close() : Closing...\r\n");
+  //DBG("LwipNetTcpSocket::close() : Closing...\n");
 
   if(m_closed)
     return NETTCPSOCKET_OK; //Already being closed
@@ -267,13 +270,13 @@
  
   if( !!tcp_close( (tcp_pcb*) m_pPcb) )
   {
-    DBG("\r\nLwipNetTcpSocket::close() could not close properly, abort.\r\n");
+    DBG("LwipNetTcpSocket::close() could not close properly, abort.\n");
     tcp_abort( (tcp_pcb*) m_pPcb);
     m_pPcb = NULL;
     return NETTCPSOCKET_MEM;
   }
   
-  DBG("\r\nLwipNetTcpSocket::close() : connection closed successfully.\r\n");
+  DBG("LwipNetTcpSocket::close() : connection closed successfully.\n");
   
   m_pPcb = NULL;
   return NETTCPSOCKET_OK;
@@ -291,7 +294,7 @@
 {
   if(err)
   {
-    DBG("\r\nError %d in LwipNetTcpSocket::acceptCb.\r\n", err);
+    DBG("Error %d in LwipNetTcpSocket::acceptCb.\n", err);
     return err;
   }
   //FIXME: MEM Errs
@@ -300,7 +303,7 @@
   
   if(pNewNetTcpSocket == NULL)
   {
-    DBG("\r\nNot enough mem, socket dropped in LwipNetTcpSocket::acceptCb.\r\n");
+    DBG("Not enough mem, socket dropped in LwipNetTcpSocket::acceptCb.\n");
     tcp_abort(newpcb);
     return ERR_ABRT;
   }
@@ -322,7 +325,7 @@
 
 void LwipNetTcpSocket::errCb(err_t err)
 {
-  DBG("\r\nNetTcpSocket %p - Error %d in LwipNetTcpSocket::errCb.\r\n", (void*)this, err);
+  DBG("NetTcpSocket %p - Error %d in LwipNetTcpSocket::errCb.\n", (void*)this, err);
   //WARN: At this point, m_pPcb has been freed by lwIP
   m_pPcb = NULL;
   //These errors are fatal, discard all events queued before so that the errors are handled first
@@ -337,7 +340,7 @@
   
 err_t LwipNetTcpSocket::sentCb(tcp_pcb* tpcb, u16_t len)
 {
-//  DBG("\r\n%d bytes ACKed by host.\r\n", len);
+//  DBG("%d bytes ACKed by host.\n", len);
   queueEvent(NETTCPSOCKET_WRITEABLE);
   return ERR_OK;
 }
@@ -345,7 +348,7 @@
 err_t LwipNetTcpSocket::recvCb(tcp_pcb* tpcb, pbuf *p, err_t err)
 {
   //Store pbuf ptr
- // DBG("\r\nReceive CB with err = %d & len = %d.\r\n", err, p->tot_len);
+ // DBG("Receive CB with err = %d & len = %d.\n", err, p->tot_len);
 //  tcp_recved( (tcp_pcb*) m_pPcb, p->tot_len); //Acknowledge the reception
   
   if(err)
@@ -355,7 +358,7 @@
   }
   else if(!p)
   {
-    DBG("\r\nNetTcpSocket %p - Connection closed by remote host (LwipNetTcpSocket::recvCb).\r\n", (void*)this);
+    DBG("NetTcpSocket %p - Connection closed by remote host (LwipNetTcpSocket::recvCb).\n", (void*)this);
     //Buf is NULL, that means that the connection has been closed by remote host
     
     //FIX: 27/05/2010: We do not want to deallocate the socket while some data might still be readable
@@ -398,7 +401,7 @@
   
   if( m_pReadPbuf )
   {
-    DBG("\r\nDeallocating unread data.\r\n");
+    DBG("Deallocating unread data.\n");
     pbuf_free((pbuf*)m_pReadPbuf); //Free all unread data
     m_pReadPbuf = NULL;
     recv(NULL,0); //Update recv ptr position
@@ -423,7 +426,7 @@
 {
   if( !arg )
   {
-    DBG("\r\nNetTcpSocket - Error %d in LwipNetTcpSocket::sErrCb.\r\n", err);
+    DBG("NetTcpSocket - Error %d in LwipNetTcpSocket::sErrCb.\n", err);
     return; //The socket has been destroyed, discard error
   }
   LwipNetTcpSocket* pMe = (LwipNetTcpSocket*) arg;
--- a/if/lwip/lwipNetUdpSocket.cpp	Fri Jul 09 14:46:47 2010 +0000
+++ b/if/lwip/lwipNetUdpSocket.cpp	Tue Jul 27 15:59:42 2010 +0000
@@ -23,6 +23,7 @@
 
 #include "lwipNetUdpSocket.h"
 #include "lwip/udp.h"
+#include "lwip/igmp.h"
 
 //#define __DEBUG
 #include "dbg/dbg.h"
@@ -30,9 +31,9 @@
 #include "netCfg.h"
 #if NET_LWIP_STACK
 
-LwipNetUdpSocket::LwipNetUdpSocket(udp_pcb* pPcb /*= NULL*/) : NetUdpSocket(), m_pPcb(pPcb), m_lInPkt() //Passes a pcb if already created (by an accept req for instance), in that case transfers ownership
+LwipNetUdpSocket::LwipNetUdpSocket(udp_pcb* pPcb /*= NULL*/) : NetUdpSocket(), m_pPcb(pPcb), m_lInPkt(), m_multicastGroup() //Passes a pcb if already created (by an accept req for instance), in that case transfers ownership
 {
-  DBG("\r\nNew LwipNetUdpSocket %p (pPCb=%p)\r\n", (void*)this, (void*) pPcb);
+  DBG("New LwipNetUdpSocket %p (pPCb=%p)\n", (void*)this, (void*) pPcb);
   if(!m_pPcb)
     m_pPcb = udp_new();
   if(m_pPcb)
@@ -49,10 +50,23 @@
   
 NetUdpSocketErr LwipNetUdpSocket::bind(const Host& me)
 {
+  err_t err;
+  
   if(!m_pPcb)
     return NETUDPSOCKET_MEM; //NetUdpSocket was not properly initialised, should destroy it & retry
+   
+  #if LWIP_IGMP //Multicast support enabled
+  if(me.getIp().isMulticast())
+  {
+    DBG("This is a multicast addr, joining multicast group\n");
+    m_multicastGroup = me.getIp();
+    err = igmp_joingroup(IP_ADDR_ANY, &(m_multicastGroup.getStruct()));
+    if(err)
+      return NETUDPSOCKET_IF; //Could not find or create group
+  }
+  #endif
 
-  err_t err = udp_bind( (udp_pcb*) m_pPcb, IP_ADDR_ANY, me.getPort()); //IP_ADDR_ANY : Bind the connection to all local addresses
+  err = udp_bind( (udp_pcb*) m_pPcb, IP_ADDR_ANY, me.getPort()); //IP_ADDR_ANY : Bind the connection to all local addresses
   if(err)
     return NETUDPSOCKET_INUSE;
 
@@ -85,7 +99,7 @@
   pbuf_free( p );
   if(err)
     return NETUDPSOCKET_SETUP; //Connection problem
-  DBG("\r\n%d bytes sent in UDP Socket.\r\n", len);
+  DBG("%d bytes sent in UDP Socket.\n", len);
   return len;
 }
 
@@ -157,7 +171,7 @@
 
 NetUdpSocketErr LwipNetUdpSocket::close()
 {
-  DBG("\r\nLwipNetUdpSocket::close() : Closing...\r\n");
+  DBG("LwipNetUdpSocket::close() : Closing...\n");
 
   if(m_closed)
     return NETUDPSOCKET_OK; //Already being closed
@@ -166,12 +180,13 @@
   if( !m_pPcb ) //Pcb doesn't exist (anymore)
     return NETUDPSOCKET_MEM;
     
-  DBG("\r\nLwipNetUdpSocket::close() : Cleanup...\r\n");
+  DBG("LwipNetUdpSocket::close() : Cleanup...\n");
     
   //Cleanup incoming data
   cleanUp();
- 
-  DBG("\r\nLwipNetUdpSocket::close() : removing m_pPcb...\r\n");
+  
+
+  DBG("LwipNetUdpSocket::close() : removing m_pPcb...\n");
   udp_remove( (udp_pcb*) m_pPcb);
     
   m_pPcb = NULL;
@@ -188,7 +203,7 @@
 
 void LwipNetUdpSocket::recvCb(udp_pcb* pcb, struct pbuf* p, ip_addr_t* addr, u16_t port)
 {
-  DBG("\r\n Packet of length %d arrived in UDP Socket.\r\n", p->tot_len);
+  DBG(" Packet of length %d arrived in UDP Socket.\n", p->tot_len);
   list<InPacket>::iterator it;
   for ( it = m_lInPkt.begin(); it != m_lInPkt.end(); it++ )
   {
@@ -219,6 +234,15 @@
     udp_recv( (udp_pcb*) m_pPcb, NULL, (void*) NULL );
   }
   
+  //Leaving multicast group(Ok because LwIP has a refscount for multicast group)
+  #if LWIP_IGMP //Multicast support enabled
+  if(m_multicastGroup.isMulticast())
+  {
+    igmp_leavegroup(IP_ADDR_ANY, &(m_multicastGroup.getStruct()));
+    m_multicastGroup = IpAddr();
+  }
+  #endif
+  
   list<InPacket>::iterator it;
   for ( it = m_lInPkt.begin(); it != m_lInPkt.end(); it++ )
   {
--- a/if/lwip/lwipNetUdpSocket.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/if/lwip/lwipNetUdpSocket.h	Tue Jul 27 15:59:42 2010 +0000
@@ -70,6 +70,7 @@
   };
   
   list<InPacket> m_lInPkt;
+  IpAddr m_multicastGroup;
   
   //Static callback : Transforms into a C++ callback
   static void sRecvCb(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port);
--- a/if/net/ipaddr.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/if/net/ipaddr.h	Tue Jul 27 15:59:42 2010 +0000
@@ -29,7 +29,12 @@
 #include "netCfg.h"
 #if NET_LWIP_STACK
 #include "lwip/ip_addr.h"
+
+#ifdef __LWIP_DEBUG
+#undef __LWIP_DEBUG
 #endif
+#endif
+
 class IpAddr;
 
 class IpAddr //Basically a C++ frontend to ip_addr_t
@@ -59,6 +64,7 @@
     m_ip[3] = 0;
   }
   
+
   #if NET_LWIP_STACK
   ip_addr_t getStruct() const
   {
@@ -96,6 +102,16 @@
     return (*((uint32_t*)m_ip) == 0);
   }
   
+  bool isBroadcast() const
+  {
+    return (*((uint32_t*)m_ip) == 0xFFFFFFFF);
+  }
+  
+  bool isMulticast() const
+  {
+    return ((m_ip[0] & 0xF0) == 0xE0);
+  }
+  
 private:
   uint8_t m_ip[4];
 };
--- a/if/net/netif.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/if/net/netif.h	Tue Jul 27 15:59:42 2010 +0000
@@ -48,6 +48,8 @@
   virtual void poll() = 0;
   virtual NetDnsRequest* dnsRequest(const char* hostname) = 0; //Create a new NetDnsRequest object
   virtual NetDnsRequest* dnsRequest(Host* pHost) = 0; //Create a new NetDnsRequest object
+  
+  //!Returns the IP of the interface once it's connected
   IpAddr getIp() const;
   
 protected:
--- a/if/ppp/PPPNetIf.cpp	Fri Jul 09 14:46:47 2010 +0000
+++ b/if/ppp/PPPNetIf.cpp	Tue Jul 27 15:59:42 2010 +0000
@@ -33,14 +33,13 @@
 #include "netCfg.h"
 #if NET_PPP
 
-#define PPP_TIMEOUT 30000//60000
+#define PPP_TIMEOUT 60000
 
 #define BUF_SIZE 128
 
 PPPNetIf::PPPNetIf(GPRSModem* pIf) : LwipNetIf(), m_pIf(pIf),/* m_open(false),*/ m_connected(false), m_status(PPP_DISCONNECTED), m_fd(0) //, m_id(0)
 {
   //FIXME: Check static refcount
-  pppInit();
   m_buf = new uint8_t[BUF_SIZE];
 }
 
@@ -72,6 +71,7 @@
 PPPErr PPPNetIf::GPRSConnect(const char* apn, const char* userId, const char* password) //Connect using GPRS
 {
   LwipNetIf::init();
+  pppInit();
   //TODO: Tell ATIf that we get ownership of the serial port
     
   GPRSErr gprsErr;
@@ -79,14 +79,14 @@
   if(gprsErr)
     return PPP_NETWORK;
     
-  DBG("\r\nPPPNetIf: If Connected.\r\n");
+  DBG("PPPNetIf: If Connected.\n");
 
   if( userId == NULL )
     pppSetAuth(PPPAUTHTYPE_NONE, NULL, NULL);
   else
     pppSetAuth(PPPAUTHTYPE_PAP, userId, password); //TODO: Allow CHAP as well
     
-  DBG("\r\nPPPNetIf: Set Auth.\r\n");
+  DBG("PPPNetIf: Set Auth.\n");
   
   //wait(1.);
   
@@ -95,14 +95,14 @@
   m_status = PPP_CONNECTING;
   DBG("m_pIf = %p\n", m_pIf);
   int res = pppOverSerialOpen((void*)m_pIf, sPppCallback, (void*)this);
-  DBG("\r\nPPP connected\r\n");
+  DBG("PPP connected\n");
   if(res<0)
   {
     disconnect();
     return PPP_PROTOCOL;
   }
   
-  DBG("\r\nPPPNetIf: PPP Started with res = %d.\r\n", res);
+  DBG("PPPNetIf: PPP Started with res = %d.\n", res);
   
   m_fd = res;
   m_connected = true;
@@ -113,13 +113,13 @@
     poll();
     if(t.read_ms()>PPP_TIMEOUT)
     {
-      DBG("\r\nPPPNetIf: Timeout.\r\n");  
+      DBG("PPPNetIf: Timeout.\n");  
       disconnect();
       return PPP_PROTOCOL;
     }
   }
   
-  DBG("\r\nPPPNetIf: Callback returned.\r\n");
+  DBG("PPPNetIf: Callback returned.\n");
   
   if( m_status == PPP_DISCONNECTED )
   {
@@ -203,11 +203,15 @@
   {
     //No error
     case PPPERR_NONE:
+      {
+        struct ppp_addrs* addrs = (struct ppp_addrs*) arg;
+        m_ip = IpAddr(&(addrs->our_ipaddr)); //Set IP
+      }
       m_status = PPP_CONNECTED;
       break;
     default:
       //Disconnected
-      DBG("\r\nPPPNetIf: Callback errCode = %d.\r\n", errCode);
+      DBG("PPPNetIf: Callback errCode = %d.\n", errCode);
       m_status = PPP_DISCONNECTED;
     break;
   }
--- a/if/umtsstick/UMTSStickNetIf.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/if/umtsstick/UMTSStickNetIf.h	Tue Jul 27 15:59:42 2010 +0000
@@ -31,14 +31,39 @@
 
 #include "drv/umtsstick/UMTSStick.h"
 
-class UMTSStickNetIf : protected PPPNetIf
+///UMTS Stick network interface
+/**
+This class provides connectivity to the stack using a 3G (or LTE etc...) stick
+Plug it to your USB host using two Pull-down resistors on the D+/D- lines
+*/
+class UMTSStickNetIf : public LwipNetIf, protected PPPNetIf
 {
 public:
+  ///Instantiates the Interface and register it against the stack
   UMTSStickNetIf(); 
   virtual ~UMTSStickNetIf();
   
+  ///Tries to connect to the stick
+  /**
+  This method tries to obtain a virtual serial port interface from the stick
+  It waits for a stick to be connected, switches it from CDFS to virtual serial port mode if needed,
+  and obtains a virtual serial port from it
+  @return : A negative error code on error or 0 on success
+  */
   UMTSStickErr setup(); //UMTSStickErr is from /drv/umtsstick/UMTSStick.h
+  
+  ///Establishes a PPP connection
+  /**
+  This method opens an AT interface on the serial interface, initializes and configures the stick,
+  then opens a PPP connection and authenticates with the parameters
+  \param apn : APN of the interface, if NULL uses the SIM default value
+  \param userId : user with which to authenticate during the PPP connection, if NULL does not authenticate
+  \param password : associated password
+  @return : A negative error code on error or 0 on success
+  */
   PPPErr connect(const char* apn = NULL, const char* userId = NULL, const char* password = NULL); //Connect using GPRS
+  
+  ///Disconnects the PPP connection
   PPPErr disconnect();
   
 private:
--- a/lwip/arch/cc.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/arch/cc.h	Tue Jul 27 15:59:42 2010 +0000
@@ -29,9 +29,8 @@
 #define FALSE 0
 #endif
 
-#ifndef DBG
-//#error
-#endif
+#include <stdlib.h>
+#define LWIP_RAND rand
 
 #define LWIP_PLATFORM_DIAG(x) DBG x
 #define LWIP_PLATFORM_ASSERT(x) DBG(x)
@@ -57,5 +56,7 @@
 #define PACK_STRUCT_BEGIN __packed
 #define PACK_STRUCT_END
 
+#define LWIP_CHKSUM_ALGORITHM 3
+
 
 #endif /* __LWIP_ARCH_CC_H__ */
--- a/lwip/core/def.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/core/def.c	Tue Jul 27 15:59:42 2010 +0000
@@ -75,7 +75,7 @@
 u16_t
 lwip_ntohs(u16_t n)
 {
-  return htons(n);
+  return lwip_htons(n);
 }
 
 /**
@@ -102,7 +102,7 @@
 u32_t
 lwip_ntohl(u32_t n)
 {
-  return htonl(n);
+  return lwip_htonl(n);
 }
 
 #endif /* (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) */
--- a/lwip/core/dhcp.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/core/dhcp.c	Tue Jul 27 15:59:42 2010 +0000
@@ -761,6 +761,9 @@
     break;
   default:
     dhcp->tries = 0;
+#if LWIP_DHCP_AUTOIP_COOP
+    dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
+#endif /* LWIP_DHCP_AUTOIP_COOP */
     dhcp_discover(netif);
     break;
   }
@@ -942,11 +945,11 @@
     /* subnet mask not given, choose a safe subnet mask given the network class */
     u8_t first_octet = ip4_addr1(&dhcp->offered_ip_addr);
     if (first_octet <= 127) {
-      ip4_addr_set_u32(&sn_mask, htonl(0xff000000));
+      ip4_addr_set_u32(&sn_mask, PP_HTONL(0xff000000));
     } else if (first_octet >= 192) {
-      ip4_addr_set_u32(&sn_mask, htonl(0xffffff00));
+      ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffffff00));
     } else {
-      ip4_addr_set_u32(&sn_mask, htonl(0xffff0000));
+      ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffff0000));
     }
   }
 
@@ -956,7 +959,7 @@
     /* copy network address */
     ip_addr_get_network(&gw_addr, &dhcp->offered_ip_addr, &sn_mask);
     /* use first host address on network as gateway */
-    ip4_addr_set_u32(&gw_addr, ip4_addr_get_u32(&gw_addr) | htonl(0x00000001));
+    ip4_addr_set_u32(&gw_addr, ip4_addr_get_u32(&gw_addr) | PP_HTONL(0x00000001));
   }
 
 #if LWIP_DHCP_AUTOIP_COOP
@@ -1206,8 +1209,9 @@
 void
 dhcp_stop(struct netif *netif)
 {
-  struct dhcp *dhcp = netif->dhcp;
+  struct dhcp *dhcp;
   LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;);
+  dhcp = netif->dhcp;
   /* Remove the flag that says this netif is handled by DHCP. */
   netif->flags &= ~NETIF_FLAG_DHCP;
 
@@ -1430,9 +1434,10 @@
         value = ntohl(value);
       } else {
         LWIP_ASSERT("invalid decode_len", decode_len == 1);
+        value = ((u8_t*)&value)[0];
       }
-        dhcp_got_option(dhcp, decode_idx);
-        dhcp_set_option_value(dhcp, decode_idx, value);
+      dhcp_got_option(dhcp, decode_idx);
+      dhcp_set_option_value(dhcp, decode_idx, value);
     }
     if (offset >= q->len) {
       offset -= q->len;
@@ -1663,7 +1668,7 @@
   for (i = 0; i < DHCP_FILE_LEN; i++) {
     dhcp->msg_out->file[i] = 0;
   }
-  dhcp->msg_out->cookie = htonl(DHCP_MAGIC_COOKIE);
+  dhcp->msg_out->cookie = PP_HTONL(DHCP_MAGIC_COOKIE);
   dhcp->options_out_len = 0;
   /* fill options field with an incrementing array (for debugging purposes) */
   for (i = 0; i < DHCP_OPTIONS_LEN; i++) {
--- a/lwip/core/dns.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/core/dns.c	Tue Jul 27 15:59:42 2010 +0000
@@ -1,970 +1,969 @@
-/**
- * @file
- * DNS - host name to IP address resolver.
- *
- */
-
-/**
-
- * This file implements a DNS host name to IP address resolver.
-
- * Port to lwIP from uIP
- * by Jim Pettinato April 2007
-
- * uIP version Copyright (c) 2002-2003, 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
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- *    products derived from this software without specific prior
- *    written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
- *
- *
- * DNS.C
- *
- * The lwIP DNS resolver functions are used to lookup a host name and
- * map it to a numerical IP address. It maintains a list of resolved
- * hostnames that can be queried with the dns_lookup() function.
- * New hostnames can be resolved using the dns_query() function.
- *
- * The lwIP version of the resolver also adds a non-blocking version of
- * gethostbyname() that will work with a raw API application. This function
- * checks for an IP address string first and converts it if it is valid.
- * gethostbyname() then does a dns_lookup() to see if the name is 
- * already in the table. If so, the IP is returned. If not, a query is 
- * issued and the function returns with a ERR_INPROGRESS status. The app
- * using the dns client must then go into a waiting state.
- *
- * Once a hostname has been resolved (or found to be non-existent),
- * the resolver code calls a specified callback function (which 
- * must be implemented by the module that uses the resolver).
- */
-
-/*-----------------------------------------------------------------------------
- * RFC 1035 - Domain names - implementation and specification
- * RFC 2181 - Clarifications to the DNS Specification
- *----------------------------------------------------------------------------*/
-
-/** @todo: define good default values (rfc compliance) */
-/** @todo: improve answer parsing, more checkings... */
-/** @todo: check RFC1035 - 7.3. Processing responses */
-
-/*-----------------------------------------------------------------------------
- * Includes
- *----------------------------------------------------------------------------*/
-
-#include "lwip/opt.h"
-
-#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/udp.h"
-#include "lwip/mem.h"
-#include "lwip/memp.h"
-#include "lwip/dns.h"
-#include "lwip/debug.h"
-
-#include <string.h>
-
-/** DNS server IP address */
-#ifndef DNS_SERVER_ADDRESS
-#define DNS_SERVER_ADDRESS(ipaddr)        (ip4_addr_set_u32(ipaddr, ipaddr_addr("208.67.222.222"))) /* resolver1.opendns.com */
-#endif
-
-/** DNS server port address */
-#ifndef DNS_SERVER_PORT
-#define DNS_SERVER_PORT           53
-#endif
-
-/** DNS maximum number of retries when asking for a name, before "timeout". */
-#ifndef DNS_MAX_RETRIES
-#define DNS_MAX_RETRIES           4
-#endif
-
-/** DNS resource record max. TTL (one week as default) */
-#ifndef DNS_MAX_TTL
-#define DNS_MAX_TTL               604800
-#endif
-
-/* DNS protocol flags */
-#define DNS_FLAG1_RESPONSE        0x80
-#define DNS_FLAG1_OPCODE_STATUS   0x10
-#define DNS_FLAG1_OPCODE_INVERSE  0x08
-#define DNS_FLAG1_OPCODE_STANDARD 0x00
-#define DNS_FLAG1_AUTHORATIVE     0x04
-#define DNS_FLAG1_TRUNC           0x02
-#define DNS_FLAG1_RD              0x01
-#define DNS_FLAG2_RA              0x80
-#define DNS_FLAG2_ERR_MASK        0x0f
-#define DNS_FLAG2_ERR_NONE        0x00
-#define DNS_FLAG2_ERR_NAME        0x03
-
-/* DNS protocol states */
-#define DNS_STATE_UNUSED          0
-#define DNS_STATE_NEW             1
-#define DNS_STATE_ASKING          2
-#define DNS_STATE_DONE            3
-
-#ifdef PACK_STRUCT_USE_INCLUDES
-#  include "arch/bpstruct.h"
-#endif
-PACK_STRUCT_BEGIN
-/** DNS message header */
-struct dns_hdr {
-  PACK_STRUCT_FIELD(u16_t id);
-  PACK_STRUCT_FIELD(u8_t flags1);
-  PACK_STRUCT_FIELD(u8_t flags2);
-  PACK_STRUCT_FIELD(u16_t numquestions);
-  PACK_STRUCT_FIELD(u16_t numanswers);
-  PACK_STRUCT_FIELD(u16_t numauthrr);
-  PACK_STRUCT_FIELD(u16_t numextrarr);
-} PACK_STRUCT_STRUCT;
-PACK_STRUCT_END
-#ifdef PACK_STRUCT_USE_INCLUDES
-#  include "arch/epstruct.h"
-#endif
-#define SIZEOF_DNS_HDR 12
-
-/** DNS query message structure.
-    No packing needed: only used locally on the stack. */
-struct dns_query {
-  /* DNS query record starts with either a domain name or a pointer
-     to a name already present somewhere in the packet. */
-  u16_t type;
-  u16_t cls;
-};
-#define SIZEOF_DNS_QUERY 4
-
-/** DNS answer message structure.
-    No packing needed: only used locally on the stack. */
-struct dns_answer {
-  /* DNS answer record starts with either a domain name or a pointer
-     to a name already present somewhere in the packet. */
-  u16_t type;
-  u16_t cls;
-  u32_t ttl;
-  u16_t len;
-};
-#define SIZEOF_DNS_ANSWER 10
-
-/** DNS table entry */
-struct dns_table_entry {
-  u8_t  state;
-  u8_t  numdns;
-  u8_t  tmr;
-  u8_t  retries;
-  u8_t  seqno;
-  u8_t  err;
-  u32_t ttl;
-  char name[DNS_MAX_NAME_LENGTH];
-  ip_addr_t ipaddr;
-  /* pointer to callback on DNS query done */
-  dns_found_callback found;
-  void *arg;
-};
-
-#if DNS_LOCAL_HOSTLIST
-
-#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
-/** Local host-list. For hostnames in this list, no
- *  external name resolution is performed */
-static struct local_hostlist_entry *local_hostlist_dynamic;
-#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
-
-/** Defining this allows the local_hostlist_static to be placed in a different
- * linker section (e.g. FLASH) */
-#ifndef DNS_LOCAL_HOSTLIST_STORAGE_PRE
-#define DNS_LOCAL_HOSTLIST_STORAGE_PRE static
-#endif /* DNS_LOCAL_HOSTLIST_STORAGE_PRE */
-/** Defining this allows the local_hostlist_static to be placed in a different
- * linker section (e.g. FLASH) */
-#ifndef DNS_LOCAL_HOSTLIST_STORAGE_POST
-#define DNS_LOCAL_HOSTLIST_STORAGE_POST
-#endif /* DNS_LOCAL_HOSTLIST_STORAGE_POST */
-DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static[]
-  DNS_LOCAL_HOSTLIST_STORAGE_POST = DNS_LOCAL_HOSTLIST_INIT;
-
-#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
-
-static void dns_init_local();
-#endif /* DNS_LOCAL_HOSTLIST */
-
-
-/* forward declarations */
-static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port);
-static void dns_check_entries(void);
-
-/*-----------------------------------------------------------------------------
- * Globales
- *----------------------------------------------------------------------------*/
-
-/* DNS variables */
-static struct udp_pcb        *dns_pcb;
-static u8_t                   dns_seqno;
-static struct dns_table_entry dns_table[DNS_TABLE_SIZE];
-static ip_addr_t              dns_servers[DNS_MAX_SERVERS];
-/** Contiguous buffer for processing responses */
-static u8_t                   dns_payload_buffer[LWIP_MEM_ALIGN_BUFFER(DNS_MSG_SIZE)];
-static u8_t*                  dns_payload;
-
-/**
- * Initialize the resolver: set up the UDP pcb and configure the default server
- * (DNS_SERVER_ADDRESS).
- */
-void
-dns_init()
-{
-  ip_addr_t dnsserver;
-
-  dns_payload = (u8_t *)LWIP_MEM_ALIGN(dns_payload_buffer);
-  
-  /* initialize default DNS server address */
-  DNS_SERVER_ADDRESS(&dnsserver);
-
-  LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n"));
-
-  /* if dns client not yet initialized... */
-  if (dns_pcb == NULL) {
-    dns_pcb = udp_new();
-
-    if (dns_pcb != NULL) {
-      /* initialize DNS table not needed (initialized to zero since it is a
-       * global variable) */
-      LWIP_ASSERT("For implicit initialization to work, DNS_STATE_UNUSED needs to be 0",
-        DNS_STATE_UNUSED == 0);
-
-      /* initialize DNS client */
-      udp_bind(dns_pcb, IP_ADDR_ANY, 0);
-      udp_recv(dns_pcb, dns_recv, NULL);
-
-      /* initialize default DNS primary server */
-      dns_setserver(0, &dnsserver);
-    }
-  }
-#if DNS_LOCAL_HOSTLIST
-  dns_init_local();
-#endif
-}
-
-/**
- * Initialize one of the DNS servers.
- *
- * @param numdns the index of the DNS server to set must be < DNS_MAX_SERVERS
- * @param dnsserver IP address of the DNS server to set
- */
-void
-dns_setserver(u8_t numdns, ip_addr_t *dnsserver)
-{
-  if ((numdns < DNS_MAX_SERVERS) && (dns_pcb != NULL) &&
-      (dnsserver != NULL) && !ip_addr_isany(dnsserver)) {
-    dns_servers[numdns] = (*dnsserver);
-  }
-}
-
-/**
- * Obtain one of the currently configured DNS server.
- *
- * @param numdns the index of the DNS server
- * @return IP address of the indexed DNS server or "ip_addr_any" if the DNS
- *         server has not been configured.
- */
-ip_addr_t
-dns_getserver(u8_t numdns)
-{
-  if (numdns < DNS_MAX_SERVERS) {
-    return dns_servers[numdns];
-  } else {
-    return *IP_ADDR_ANY;
-  }
-}
-
-/**
- * The DNS resolver client timer - handle retries and timeouts and should
- * be called every DNS_TMR_INTERVAL milliseconds (every second by default).
- */
-void
-dns_tmr(void)
-{
-  if (dns_pcb != NULL) {
-    LWIP_DEBUGF(DNS_DEBUG, ("dns_tmr: dns_check_entries\n"));
-    dns_check_entries();
-  }
-}
-
-#if DNS_LOCAL_HOSTLIST
-static void
-dns_init_local()
-{
-#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT)
-  int i;
-  struct local_hostlist_entry *entry;
-  /* Dynamic: copy entries from DNS_LOCAL_HOSTLIST_INIT to list */
-  struct local_hostlist_entry local_hostlist_init[] = DNS_LOCAL_HOSTLIST_INIT;
-  size_t namelen;
-  for (i = 0; i < sizeof(local_hostlist_init) / sizeof(struct local_hostlist_entry); i++) {
-    struct local_hostlist_entry *init_entry = &local_hostlist_init[i];
-    LWIP_ASSERT("invalid host name (NULL)", init_entry->name != NULL);
-    namelen = strlen(init_entry->name);
-    LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN);
-    entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST);
-    LWIP_ASSERT("mem-error in dns_init_local", entry != NULL);
-    if (entry != NULL) {
-      entry->name = (char*)entry + sizeof(struct local_hostlist_entry);
-      MEMCPY((char*)entry->name, init_entry->name, namelen);
-      ((char*)entry->name)[namelen] = 0;
-      entry->addr = init_entry->addr;
-      entry->next = local_hostlist_dynamic;
-      local_hostlist_dynamic = entry;
-    }
-  }
-#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) */
-}
-
-/**
- * Scans the local host-list for a hostname.
- *
- * @param hostname Hostname to look for in the local host-list
- * @return The first IP address for the hostname in the local host-list or
- *         IPADDR_NONE if not found.
- */
-static u32_t
-dns_lookup_local(const char *hostname)
-{
-#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
-  struct local_hostlist_entry *entry = local_hostlist_dynamic;
-  while(entry != NULL) {
-    if(strcmp(entry->name, hostname) == 0) {
-      return ip4_addr_get_u32(&entry->addr);
-    }
-    entry = entry->next;
-  }
-#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
-  int i;
-  for (i = 0; i < sizeof(local_hostlist_static) / sizeof(struct local_hostlist_entry); i++) {
-    if(strcmp(local_hostlist_static[i].name, hostname) == 0) {
-      return ip4_addr_get_u32(&local_hostlist_static[i].addr);
-    }
-  }
-#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
-  return IPADDR_NONE;
-}
-
-#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
-/** Remove all entries from the local host-list for a specific hostname
- * and/or IP addess
- *
- * @param hostname hostname for which entries shall be removed from the local
- *                 host-list
- * @param addr address for which entries shall be removed from the local host-list
- * @return the number of removed entries
- */
-int
-dns_local_removehost(const char *hostname, const ip_addr_t *addr)
-{
-  int removed = 0;
-  struct local_hostlist_entry *entry = local_hostlist_dynamic;
-  struct local_hostlist_entry *last_entry = NULL;
-  while (entry != NULL) {
-    if (((hostname == NULL) || !strcmp(entry->name, hostname)) &&
-        ((addr == NULL) || ip_addr_cmp(&entry->addr, addr))) {
-      struct local_hostlist_entry *free_entry;
-      if (last_entry != NULL) {
-        last_entry->next = entry->next;
-      } else {
-        local_hostlist_dynamic = entry->next;
-      }
-      free_entry = entry;
-      entry = entry->next;
-      memp_free(MEMP_LOCALHOSTLIST, free_entry);
-      removed++;
-    } else {
-      last_entry = entry;
-      entry = entry->next;
-    }
-  }
-  return removed;
-}
-
-/**
- * Add a hostname/IP address pair to the local host-list.
- * Duplicates are not checked.
- *
- * @param hostname hostname of the new entry
- * @param addr IP address of the new entry
- * @return ERR_OK if succeeded or ERR_MEM on memory error
- */
-err_t
-dns_local_addhost(const char *hostname, const ip_addr_t *addr)
-{
-  struct local_hostlist_entry *entry;
-  size_t namelen;
-  LWIP_ASSERT("invalid host name (NULL)", hostname != NULL);
-  namelen = strlen(hostname);
-  LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN);
-  entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST);
-  if (entry == NULL) {
-    return ERR_MEM;
-  }
-  entry->name = (char*)entry + sizeof(struct local_hostlist_entry);
-  MEMCPY((char*)entry->name, hostname, namelen);
-  ((char*)entry->name)[namelen] = 0;
-  ip_addr_copy(entry->addr, *addr);
-  entry->next = local_hostlist_dynamic;
-  local_hostlist_dynamic = entry;
-  return ERR_OK;
-}
-#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC*/
-#endif /* DNS_LOCAL_HOSTLIST */
-
-/**
- * Look up a hostname in the array of known hostnames.
- *
- * @note This function only looks in the internal array of known
- * hostnames, it does not send out a query for the hostname if none
- * was found. The function dns_enqueue() can be used to send a query
- * for a hostname.
- *
- * @param name the hostname to look up
- * @return the hostname's IP address, as u32_t (instead of ip_addr_t to
- *         better check for failure: != IPADDR_NONE) or IPADDR_NONE if the hostname
- *         was not found in the cached dns_table.
- */
-static u32_t
-dns_lookup(const char *name)
-{
-  u8_t i;
-#if DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN)
-  u32_t addr;
-#endif /* DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) */
-#if DNS_LOCAL_HOSTLIST
-  if ((addr = dns_lookup_local(name)) != IPADDR_NONE) {
-    return addr;
-  }
-#endif /* DNS_LOCAL_HOSTLIST */
-#ifdef DNS_LOOKUP_LOCAL_EXTERN
-  if((addr = DNS_LOOKUP_LOCAL_EXTERN(name)) != IPADDR_NONE) {
-    return addr;
-  }
-#endif /* DNS_LOOKUP_LOCAL_EXTERN */
-
-  /* Walk through name list, return entry if found. If not, return NULL. */
-  for (i = 0; i < DNS_TABLE_SIZE; ++i) {
-    if ((dns_table[i].state == DNS_STATE_DONE) &&
-        (strcmp(name, dns_table[i].name) == 0)) {
-      LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name));
-      ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr));
-      LWIP_DEBUGF(DNS_DEBUG, ("\n"));
-      return ip4_addr_get_u32(&dns_table[i].ipaddr);
-    }
-  }
-
-  return IPADDR_NONE;
-}
-
-#if DNS_DOES_NAME_CHECK
-/**
- * Compare the "dotted" name "query" with the encoded name "response"
- * to make sure an answer from the DNS server matches the current dns_table
- * entry (otherwise, answers might arrive late for hostname not on the list
- * any more).
- *
- * @param query hostname (not encoded) from the dns_table
- * @param response encoded hostname in the DNS response
- * @return 0: names equal; 1: names differ
- */
-static u8_t
-dns_compare_name(unsigned char *query, unsigned char *response)
-{
-  unsigned char n;
-
-  do {
-    n = *response++;
-    /** @see RFC 1035 - 4.1.4. Message compression */
-    if ((n & 0xc0) == 0xc0) {
-      /* Compressed name */
-      break;
-    } else {
-      /* Not compressed name */
-      while (n > 0) {
-        if ((*query) != (*response)) {
-          return 1;
-        }
-        ++response;
-        ++query;
-        --n;
-      };
-      ++query;
-    }
-  } while (*response != 0);
-
-  return 0;
-}
-#endif /* DNS_DOES_NAME_CHECK */
-
-/**
- * Walk through a compact encoded DNS name and return the end of the name.
- *
- * @param query encoded DNS name in the DNS server response
- * @return end of the name
- */
-static unsigned char *
-dns_parse_name(unsigned char *query)
-{
-  unsigned char n;
-
-  do {
-    n = *query++;
-    /** @see RFC 1035 - 4.1.4. Message compression */
-    if ((n & 0xc0) == 0xc0) {
-      /* Compressed name */
-      break;
-    } else {
-      /* Not compressed name */
-      while (n > 0) {
-        ++query;
-        --n;
-      };
-    }
-  } while (*query != 0);
-
-  return query + 1;
-}
-
-/**
- * Send a DNS query packet.
- *
- * @param numdns index of the DNS server in the dns_servers table
- * @param name hostname to query
- * @param id index of the hostname in dns_table, used as transaction ID in the
- *        DNS query packet
- * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise
- */
-static err_t
-dns_send(u8_t numdns, const char* name, u8_t id)
-{
-  err_t err;
-  struct dns_hdr *hdr;
-  struct dns_query qry;
-  struct pbuf *p;
-  char *query, *nptr;
-  const char *pHostname;
-  u8_t n;
-
-  LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n",
-              (u16_t)(numdns), name));
-  LWIP_ASSERT("dns server out of array", numdns < DNS_MAX_SERVERS);
-  LWIP_ASSERT("dns server has no IP address set", !ip_addr_isany(&dns_servers[numdns]));
-
-  /* if here, we have either a new query or a retry on a previous query to process */
-  p = pbuf_alloc(PBUF_TRANSPORT, SIZEOF_DNS_HDR + DNS_MAX_NAME_LENGTH +
-                 SIZEOF_DNS_QUERY, PBUF_RAM);
-  if (p != NULL) {
-    LWIP_ASSERT("pbuf must be in one piece", p->next == NULL);
-    /* fill dns header */
-    hdr = (struct dns_hdr*)p->payload;
-    memset(hdr, 0, SIZEOF_DNS_HDR);
-    hdr->id = htons(id);
-    hdr->flags1 = DNS_FLAG1_RD;
-    hdr->numquestions = PP_HTONS(1);
-    query = (char*)hdr + SIZEOF_DNS_HDR;
-    pHostname = name;
-    --pHostname;
-
-    /* convert hostname into suitable query format. */
-    do {
-      ++pHostname;
-      nptr = query;
-      ++query;
-      for(n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
-        *query = *pHostname;
-        ++query;
-        ++n;
-      }
-      *nptr = n;
-    } while(*pHostname != 0);
-    *query++='\0';
-
-    /* fill dns query */
-    qry.type = PP_HTONS(DNS_RRTYPE_A);
-    qry.cls = PP_HTONS(DNS_RRCLASS_IN);
-    SMEMCPY(query, &qry, SIZEOF_DNS_QUERY);
-
-    /* resize pbuf to the exact dns query */
-    pbuf_realloc(p, (u16_t)((query + SIZEOF_DNS_QUERY) - ((char*)(p->payload))));
-
-    /* connect to the server for faster receiving */
-    udp_connect(dns_pcb, &dns_servers[numdns], DNS_SERVER_PORT);
-    /* send dns packet */
-    err = udp_sendto(dns_pcb, p, &dns_servers[numdns], DNS_SERVER_PORT);
-
-    /* free pbuf */
-    pbuf_free(p);
-  } else {
-    err = ERR_MEM;
-  }
-
-  return err;
-}
-
-/**
- * dns_check_entry() - see if pEntry has not yet been queried and, if so, sends out a query.
- * Check an entry in the dns_table:
- * - send out query for new entries
- * - retry old pending entries on timeout (also with different servers)
- * - remove completed entries from the table if their TTL has expired
- *
- * @param i index of the dns_table entry to check
- */
-static void
-dns_check_entry(u8_t i)
-{
-  err_t err;
-  struct dns_table_entry *pEntry = &dns_table[i];
-
-  LWIP_ASSERT("array index out of bounds", i < DNS_TABLE_SIZE);
-
-  switch(pEntry->state) {
-
-    case DNS_STATE_NEW: {
-      /* initialize new entry */
-      pEntry->state   = DNS_STATE_ASKING;
-      pEntry->numdns  = 0;
-      pEntry->tmr     = 1;
-      pEntry->retries = 0;
-      
-      /* send DNS packet for this entry */
-      err = dns_send(pEntry->numdns, pEntry->name, i);
-      if (err != ERR_OK) {
-        LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING,
-                    ("dns_send returned error: %d\n", err));
-      }
-      break;
-    }
-
-    case DNS_STATE_ASKING: {
-      if (--pEntry->tmr == 0) {
-        if (++pEntry->retries == DNS_MAX_RETRIES) {
-          if ((pEntry->numdns+1<DNS_MAX_SERVERS) && !ip_addr_isany(&dns_servers[pEntry->numdns+1])) {
-            /* change of server */
-            pEntry->numdns++;
-            pEntry->tmr     = 1;
-            pEntry->retries = 0;
-            break;
-          } else {
-            LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": timeout\n", pEntry->name));
-            /* call specified callback function if provided */
-            if (pEntry->found)
-              (*pEntry->found)(pEntry->name, NULL, pEntry->arg);
-            /* flush this entry */
-            pEntry->state   = DNS_STATE_UNUSED;
-            pEntry->found   = NULL;
-            break;
-          }
-        }
-
-        /* wait longer for the next retry */
-        pEntry->tmr = pEntry->retries;
-
-        /* send DNS packet for this entry */
-        err = dns_send(pEntry->numdns, pEntry->name, i);
-        if (err != ERR_OK) {
-          LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING,
-                      ("dns_send returned error: %d\n", err));
-        }
-      }
-      break;
-    }
-
-    case DNS_STATE_DONE: {
-      /* if the time to live is nul */
-      if (--pEntry->ttl == 0) {
-        LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": flush\n", pEntry->name));
-        /* flush this entry */
-        pEntry->state = DNS_STATE_UNUSED;
-        pEntry->found = NULL;
-      }
-      break;
-    }
-    case DNS_STATE_UNUSED:
-      /* nothing to do */
-      break;
-    default:
-      LWIP_ASSERT("unknown dns_table entry state:", 0);
-      break;
-  }
-}
-
-/**
- * Call dns_check_entry for each entry in dns_table - check all entries.
- */
-static void
-dns_check_entries(void)
-{
-  u8_t i;
-
-  for (i = 0; i < DNS_TABLE_SIZE; ++i) {
-    dns_check_entry(i);
-  }
-}
-
-/**
- * Receive input function for DNS response packets arriving for the dns UDP pcb.
- *
- * @params see udp.h
- */
-static void
-dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
-{
-  u16_t i;
-  char *pHostname;
-  struct dns_hdr *hdr;
-  struct dns_answer ans;
-  struct dns_table_entry *pEntry;
-  u16_t nquestions, nanswers;
-
-  LWIP_UNUSED_ARG(arg);
-  LWIP_UNUSED_ARG(pcb);
-  LWIP_UNUSED_ARG(addr);
-  LWIP_UNUSED_ARG(port);
-
-  /* is the dns message too big ? */
-  if (p->tot_len > DNS_MSG_SIZE) {
-    LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too big\n"));
-    /* free pbuf and return */
-    goto memerr;
-  }
-
-  /* is the dns message big enough ? */
-  if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + SIZEOF_DNS_ANSWER)) {
-    LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n"));
-    /* free pbuf and return */
-    goto memerr;
-  }
-
-  /* copy dns payload inside static buffer for processing */ 
-  if (pbuf_copy_partial(p, dns_payload, p->tot_len, 0) == p->tot_len) {
-    /* The ID in the DNS header should be our entry into the name table. */
-    hdr = (struct dns_hdr*)dns_payload;
-    i = htons(hdr->id);
-    if (i < DNS_TABLE_SIZE) {
-      pEntry = &dns_table[i];
-      if(pEntry->state == DNS_STATE_ASKING) {
-        /* This entry is now completed. */
-        pEntry->state = DNS_STATE_DONE;
-        pEntry->err   = hdr->flags2 & DNS_FLAG2_ERR_MASK;
-
-        /* We only care about the question(s) and the answers. The authrr
-           and the extrarr are simply discarded. */
-        nquestions = htons(hdr->numquestions);
-        nanswers   = htons(hdr->numanswers);
-
-        /* Check for error. If so, call callback to inform. */
-        if (((hdr->flags1 & DNS_FLAG1_RESPONSE) == 0) || (pEntry->err != 0) || (nquestions != 1)) {
-          LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in flags\n", pEntry->name));
-          /* call callback to indicate error, clean up memory and return */
-          goto responseerr;
-        }
-
-#if DNS_DOES_NAME_CHECK
-        /* Check if the name in the "question" part match with the name in the entry. */
-        if (dns_compare_name((unsigned char *)(pEntry->name), (unsigned char *)dns_payload + SIZEOF_DNS_HDR) != 0) {
-          LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", pEntry->name));
-          /* call callback to indicate error, clean up memory and return */
-          goto responseerr;
-        }
-#endif /* DNS_DOES_NAME_CHECK */
-
-        /* Skip the name in the "question" part */
-        pHostname = (char *) dns_parse_name((unsigned char *)dns_payload + SIZEOF_DNS_HDR) + SIZEOF_DNS_QUERY;
-
-        while (nanswers > 0) {
-          /* skip answer resource record's host name */
-          pHostname = (char *) dns_parse_name((unsigned char *)pHostname);
-
-          /* Check for IP address type and Internet class. Others are discarded. */
-          SMEMCPY(&ans, pHostname, SIZEOF_DNS_ANSWER);
-          if((ans.type == PP_HTONS(DNS_RRTYPE_A)) && (ans.cls == PP_HTONS(DNS_RRCLASS_IN)) &&
-             (ans.len == PP_HTONS(sizeof(ip_addr_t))) ) {
-            /* read the answer resource record's TTL, and maximize it if needed */
-            pEntry->ttl = ntohl(ans.ttl);
-            if (pEntry->ttl > DNS_MAX_TTL) {
-              pEntry->ttl = DNS_MAX_TTL;
-            }
-            /* read the IP address after answer resource record's header */
-            SMEMCPY(&(pEntry->ipaddr), (pHostname+SIZEOF_DNS_ANSWER), sizeof(ip_addr_t));
-            LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", pEntry->name));
-            ip_addr_debug_print(DNS_DEBUG, (&(pEntry->ipaddr)));
-            LWIP_DEBUGF(DNS_DEBUG, ("\n"));
-            /* call specified callback function if provided */
-            if (pEntry->found) {
-              (*pEntry->found)(pEntry->name, &pEntry->ipaddr, pEntry->arg);
-            }
-            /* deallocate memory and return */
-            goto memerr;
-          } else {
-            pHostname = pHostname + SIZEOF_DNS_ANSWER + htons(ans.len);
-          }
-          --nanswers;
-        }
-        LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in response\n", pEntry->name));
-        /* call callback to indicate error, clean up memory and return */
-        goto responseerr;
-      }
-    }
-  }
-
-  /* deallocate memory and return */
-  goto memerr;
-
-responseerr:
-  /* ERROR: call specified callback function with NULL as name to indicate an error */
-  if (pEntry->found) {
-    (*pEntry->found)(pEntry->name, NULL, pEntry->arg);
-  }
-  /* flush this entry */
-  pEntry->state = DNS_STATE_UNUSED;
-  pEntry->found = NULL;
-
-memerr:
-  /* free pbuf */
-  pbuf_free(p);
-  return;
-}
-
-/**
- * Queues a new hostname to resolve and sends out a DNS query for that hostname
- *
- * @param name the hostname that is to be queried
- * @param found a callback founction to be called on success, failure or timeout
- * @param callback_arg argument to pass to the callback function
- * @return @return a err_t return code.
- */
-static err_t
-dns_enqueue(const char *name, dns_found_callback found, void *callback_arg)
-{
-  u8_t i;
-  u8_t lseq, lseqi;
-  struct dns_table_entry *pEntry = NULL;
-  size_t namelen;
-
-  /* search an unused entry, or the oldest one */
-  lseq = lseqi = 0;
-  for (i = 0; i < DNS_TABLE_SIZE; ++i) {
-    pEntry = &dns_table[i];
-    /* is it an unused entry ? */
-    if (pEntry->state == DNS_STATE_UNUSED)
-      break;
-
-    /* check if this is the oldest completed entry */
-    if (pEntry->state == DNS_STATE_DONE) {
-      if ((dns_seqno - pEntry->seqno) > lseq) {
-        lseq = dns_seqno - pEntry->seqno;
-        lseqi = i;
-      }
-    }
-  }
-
-  /* if we don't have found an unused entry, use the oldest completed one */
-  if (i == DNS_TABLE_SIZE) {
-    if ((lseqi >= DNS_TABLE_SIZE) || (dns_table[lseqi].state != DNS_STATE_DONE)) {
-      /* no entry can't be used now, table is full */
-      LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS entries table is full\n", name));
-      return ERR_MEM;
-    } else {
-      /* use the oldest completed one */
-      i = lseqi;
-      pEntry = &dns_table[i];
-    }
-  }
-
-  /* use this entry */
-  LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS entry %"U16_F"\n", name, (u16_t)(i)));
-
-  /* fill the entry */
-  pEntry->state = DNS_STATE_NEW;
-  pEntry->seqno = dns_seqno++;
-  pEntry->found = found;
-  pEntry->arg   = callback_arg;
-  namelen = LWIP_MIN(strlen(name), DNS_MAX_NAME_LENGTH-1);
-  MEMCPY(pEntry->name, name, namelen);
-  pEntry->name[namelen] = 0;
-
-  /* force to send query without waiting timer */
-  dns_check_entry(i);
-
-  /* dns query is enqueued */
-  return ERR_INPROGRESS;
-}
-
-/**
- * Resolve a hostname (string) into an IP address.
- * NON-BLOCKING callback version for use with raw API!!!
- *
- * Returns immediately with one of err_t return codes:
- * - ERR_OK if hostname is a valid IP address string or the host
- *   name is already in the local names table.
- * - ERR_INPROGRESS enqueue a request to be sent to the DNS server
- *   for resolution if no errors are present.
- *
- * @param hostname the hostname that is to be queried
- * @param addr pointer to a ip_addr_t where to store the address if it is already
- *             cached in the dns_table (only valid if ERR_OK is returned!)
- * @param found a callback function to be called on success, failure or timeout (only if
- *              ERR_INPROGRESS is returned!)
- * @param callback_arg argument to pass to the callback function
- * @return a err_t return code.
- */
-err_t
-dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found,
-                  void *callback_arg)
-{
-  u32_t ipaddr;
-  /* not initialized or no valid server yet, or invalid addr pointer
-   * or invalid hostname or invalid hostname length */
-  if ((dns_pcb == NULL) || (addr == NULL) ||
-      (!hostname) || (!hostname[0]) ||
-      (strlen(hostname) >= DNS_MAX_NAME_LENGTH)) {
-    return ERR_VAL;
-  }
-
-#if LWIP_HAVE_LOOPIF
-  if (strcmp(hostname, "localhost")==0) {
-    ip_addr_set_loopback(addr);
-    return ERR_OK;
-  }
-#endif /* LWIP_HAVE_LOOPIF */
-
-  /* host name already in octet notation? set ip addr and return ERR_OK */
-  ipaddr = ipaddr_addr(hostname);
-  if (ipaddr == IPADDR_NONE) {
-    /* already have this address cached? */
-    ipaddr = dns_lookup(hostname);
-  }
-  if (ipaddr != IPADDR_NONE) {
-    ip4_addr_set_u32(addr, ipaddr);
-    return ERR_OK;
-  }
-
-  /* queue query with specified callback */
-  return dns_enqueue(hostname, found, callback_arg);
-}
-
-#endif /* LWIP_DNS */
+/**
+ * @file
+ * DNS - host name to IP address resolver.
+ *
+ */
+
+/**
+
+ * This file implements a DNS host name to IP address resolver.
+
+ * Port to lwIP from uIP
+ * by Jim Pettinato April 2007
+
+ * uIP version Copyright (c) 2002-2003, 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
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ *
+ * DNS.C
+ *
+ * The lwIP DNS resolver functions are used to lookup a host name and
+ * map it to a numerical IP address. It maintains a list of resolved
+ * hostnames that can be queried with the dns_lookup() function.
+ * New hostnames can be resolved using the dns_query() function.
+ *
+ * The lwIP version of the resolver also adds a non-blocking version of
+ * gethostbyname() that will work with a raw API application. This function
+ * checks for an IP address string first and converts it if it is valid.
+ * gethostbyname() then does a dns_lookup() to see if the name is 
+ * already in the table. If so, the IP is returned. If not, a query is 
+ * issued and the function returns with a ERR_INPROGRESS status. The app
+ * using the dns client must then go into a waiting state.
+ *
+ * Once a hostname has been resolved (or found to be non-existent),
+ * the resolver code calls a specified callback function (which 
+ * must be implemented by the module that uses the resolver).
+ */
+
+/*-----------------------------------------------------------------------------
+ * RFC 1035 - Domain names - implementation and specification
+ * RFC 2181 - Clarifications to the DNS Specification
+ *----------------------------------------------------------------------------*/
+
+/** @todo: define good default values (rfc compliance) */
+/** @todo: improve answer parsing, more checkings... */
+/** @todo: check RFC1035 - 7.3. Processing responses */
+
+/*-----------------------------------------------------------------------------
+ * Includes
+ *----------------------------------------------------------------------------*/
+
+#include "lwip/opt.h"
+
+#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
+
+#include "lwip/udp.h"
+#include "lwip/mem.h"
+#include "lwip/memp.h"
+#include "lwip/dns.h"
+
+#include <string.h>
+
+/** DNS server IP address */
+#ifndef DNS_SERVER_ADDRESS
+#define DNS_SERVER_ADDRESS(ipaddr)        (ip4_addr_set_u32(ipaddr, ipaddr_addr("208.67.222.222"))) /* resolver1.opendns.com */
+#endif
+
+/** DNS server port address */
+#ifndef DNS_SERVER_PORT
+#define DNS_SERVER_PORT           53
+#endif
+
+/** DNS maximum number of retries when asking for a name, before "timeout". */
+#ifndef DNS_MAX_RETRIES
+#define DNS_MAX_RETRIES           4
+#endif
+
+/** DNS resource record max. TTL (one week as default) */
+#ifndef DNS_MAX_TTL
+#define DNS_MAX_TTL               604800
+#endif
+
+/* DNS protocol flags */
+#define DNS_FLAG1_RESPONSE        0x80
+#define DNS_FLAG1_OPCODE_STATUS   0x10
+#define DNS_FLAG1_OPCODE_INVERSE  0x08
+#define DNS_FLAG1_OPCODE_STANDARD 0x00
+#define DNS_FLAG1_AUTHORATIVE     0x04
+#define DNS_FLAG1_TRUNC           0x02
+#define DNS_FLAG1_RD              0x01
+#define DNS_FLAG2_RA              0x80
+#define DNS_FLAG2_ERR_MASK        0x0f
+#define DNS_FLAG2_ERR_NONE        0x00
+#define DNS_FLAG2_ERR_NAME        0x03
+
+/* DNS protocol states */
+#define DNS_STATE_UNUSED          0
+#define DNS_STATE_NEW             1
+#define DNS_STATE_ASKING          2
+#define DNS_STATE_DONE            3
+
+#ifdef PACK_STRUCT_USE_INCLUDES
+#  include "arch/bpstruct.h"
+#endif
+PACK_STRUCT_BEGIN
+/** DNS message header */
+struct dns_hdr {
+  PACK_STRUCT_FIELD(u16_t id);
+  PACK_STRUCT_FIELD(u8_t flags1);
+  PACK_STRUCT_FIELD(u8_t flags2);
+  PACK_STRUCT_FIELD(u16_t numquestions);
+  PACK_STRUCT_FIELD(u16_t numanswers);
+  PACK_STRUCT_FIELD(u16_t numauthrr);
+  PACK_STRUCT_FIELD(u16_t numextrarr);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+#ifdef PACK_STRUCT_USE_INCLUDES
+#  include "arch/epstruct.h"
+#endif
+#define SIZEOF_DNS_HDR 12
+
+/** DNS query message structure.
+    No packing needed: only used locally on the stack. */
+struct dns_query {
+  /* DNS query record starts with either a domain name or a pointer
+     to a name already present somewhere in the packet. */
+  u16_t type;
+  u16_t cls;
+};
+#define SIZEOF_DNS_QUERY 4
+
+/** DNS answer message structure.
+    No packing needed: only used locally on the stack. */
+struct dns_answer {
+  /* DNS answer record starts with either a domain name or a pointer
+     to a name already present somewhere in the packet. */
+  u16_t type;
+  u16_t cls;
+  u32_t ttl;
+  u16_t len;
+};
+#define SIZEOF_DNS_ANSWER 10
+
+/** DNS table entry */
+struct dns_table_entry {
+  u8_t  state;
+  u8_t  numdns;
+  u8_t  tmr;
+  u8_t  retries;
+  u8_t  seqno;
+  u8_t  err;
+  u32_t ttl;
+  char name[DNS_MAX_NAME_LENGTH];
+  ip_addr_t ipaddr;
+  /* pointer to callback on DNS query done */
+  dns_found_callback found;
+  void *arg;
+};
+
+#if DNS_LOCAL_HOSTLIST
+
+#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
+/** Local host-list. For hostnames in this list, no
+ *  external name resolution is performed */
+static struct local_hostlist_entry *local_hostlist_dynamic;
+#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
+
+/** Defining this allows the local_hostlist_static to be placed in a different
+ * linker section (e.g. FLASH) */
+#ifndef DNS_LOCAL_HOSTLIST_STORAGE_PRE
+#define DNS_LOCAL_HOSTLIST_STORAGE_PRE static
+#endif /* DNS_LOCAL_HOSTLIST_STORAGE_PRE */
+/** Defining this allows the local_hostlist_static to be placed in a different
+ * linker section (e.g. FLASH) */
+#ifndef DNS_LOCAL_HOSTLIST_STORAGE_POST
+#define DNS_LOCAL_HOSTLIST_STORAGE_POST
+#endif /* DNS_LOCAL_HOSTLIST_STORAGE_POST */
+DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static[]
+  DNS_LOCAL_HOSTLIST_STORAGE_POST = DNS_LOCAL_HOSTLIST_INIT;
+
+#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
+
+static void dns_init_local();
+#endif /* DNS_LOCAL_HOSTLIST */
+
+
+/* forward declarations */
+static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port);
+static void dns_check_entries(void);
+
+/*-----------------------------------------------------------------------------
+ * Globales
+ *----------------------------------------------------------------------------*/
+
+/* DNS variables */
+static struct udp_pcb        *dns_pcb;
+static u8_t                   dns_seqno;
+static struct dns_table_entry dns_table[DNS_TABLE_SIZE];
+static ip_addr_t              dns_servers[DNS_MAX_SERVERS];
+/** Contiguous buffer for processing responses */
+static u8_t                   dns_payload_buffer[LWIP_MEM_ALIGN_BUFFER(DNS_MSG_SIZE)];
+static u8_t*                  dns_payload;
+
+/**
+ * Initialize the resolver: set up the UDP pcb and configure the default server
+ * (DNS_SERVER_ADDRESS).
+ */
+void
+dns_init()
+{
+  ip_addr_t dnsserver;
+
+  dns_payload = (u8_t *)LWIP_MEM_ALIGN(dns_payload_buffer);
+  
+  /* initialize default DNS server address */
+  DNS_SERVER_ADDRESS(&dnsserver);
+
+  LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n"));
+
+  /* if dns client not yet initialized... */
+  if (dns_pcb == NULL) {
+    dns_pcb = udp_new();
+
+    if (dns_pcb != NULL) {
+      /* initialize DNS table not needed (initialized to zero since it is a
+       * global variable) */
+      LWIP_ASSERT("For implicit initialization to work, DNS_STATE_UNUSED needs to be 0",
+        DNS_STATE_UNUSED == 0);
+
+      /* initialize DNS client */
+      udp_bind(dns_pcb, IP_ADDR_ANY, 0);
+      udp_recv(dns_pcb, dns_recv, NULL);
+
+      /* initialize default DNS primary server */
+      dns_setserver(0, &dnsserver);
+    }
+  }
+#if DNS_LOCAL_HOSTLIST
+  dns_init_local();
+#endif
+}
+
+/**
+ * Initialize one of the DNS servers.
+ *
+ * @param numdns the index of the DNS server to set must be < DNS_MAX_SERVERS
+ * @param dnsserver IP address of the DNS server to set
+ */
+void
+dns_setserver(u8_t numdns, ip_addr_t *dnsserver)
+{
+  if ((numdns < DNS_MAX_SERVERS) && (dns_pcb != NULL) &&
+      (dnsserver != NULL) && !ip_addr_isany(dnsserver)) {
+    dns_servers[numdns] = (*dnsserver);
+  }
+}
+
+/**
+ * Obtain one of the currently configured DNS server.
+ *
+ * @param numdns the index of the DNS server
+ * @return IP address of the indexed DNS server or "ip_addr_any" if the DNS
+ *         server has not been configured.
+ */
+ip_addr_t
+dns_getserver(u8_t numdns)
+{
+  if (numdns < DNS_MAX_SERVERS) {
+    return dns_servers[numdns];
+  } else {
+    return *IP_ADDR_ANY;
+  }
+}
+
+/**
+ * The DNS resolver client timer - handle retries and timeouts and should
+ * be called every DNS_TMR_INTERVAL milliseconds (every second by default).
+ */
+void
+dns_tmr(void)
+{
+  if (dns_pcb != NULL) {
+    LWIP_DEBUGF(DNS_DEBUG, ("dns_tmr: dns_check_entries\n"));
+    dns_check_entries();
+  }
+}
+
+#if DNS_LOCAL_HOSTLIST
+static void
+dns_init_local()
+{
+#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT)
+  int i;
+  struct local_hostlist_entry *entry;
+  /* Dynamic: copy entries from DNS_LOCAL_HOSTLIST_INIT to list */
+  struct local_hostlist_entry local_hostlist_init[] = DNS_LOCAL_HOSTLIST_INIT;
+  size_t namelen;
+  for (i = 0; i < sizeof(local_hostlist_init) / sizeof(struct local_hostlist_entry); i++) {
+    struct local_hostlist_entry *init_entry = &local_hostlist_init[i];
+    LWIP_ASSERT("invalid host name (NULL)", init_entry->name != NULL);
+    namelen = strlen(init_entry->name);
+    LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN);
+    entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST);
+    LWIP_ASSERT("mem-error in dns_init_local", entry != NULL);
+    if (entry != NULL) {
+      entry->name = (char*)entry + sizeof(struct local_hostlist_entry);
+      MEMCPY((char*)entry->name, init_entry->name, namelen);
+      ((char*)entry->name)[namelen] = 0;
+      entry->addr = init_entry->addr;
+      entry->next = local_hostlist_dynamic;
+      local_hostlist_dynamic = entry;
+    }
+  }
+#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) */
+}
+
+/**
+ * Scans the local host-list for a hostname.
+ *
+ * @param hostname Hostname to look for in the local host-list
+ * @return The first IP address for the hostname in the local host-list or
+ *         IPADDR_NONE if not found.
+ */
+static u32_t
+dns_lookup_local(const char *hostname)
+{
+#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
+  struct local_hostlist_entry *entry = local_hostlist_dynamic;
+  while(entry != NULL) {
+    if(strcmp(entry->name, hostname) == 0) {
+      return ip4_addr_get_u32(&entry->addr);
+    }
+    entry = entry->next;
+  }
+#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
+  int i;
+  for (i = 0; i < sizeof(local_hostlist_static) / sizeof(struct local_hostlist_entry); i++) {
+    if(strcmp(local_hostlist_static[i].name, hostname) == 0) {
+      return ip4_addr_get_u32(&local_hostlist_static[i].addr);
+    }
+  }
+#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
+  return IPADDR_NONE;
+}
+
+#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
+/** Remove all entries from the local host-list for a specific hostname
+ * and/or IP addess
+ *
+ * @param hostname hostname for which entries shall be removed from the local
+ *                 host-list
+ * @param addr address for which entries shall be removed from the local host-list
+ * @return the number of removed entries
+ */
+int
+dns_local_removehost(const char *hostname, const ip_addr_t *addr)
+{
+  int removed = 0;
+  struct local_hostlist_entry *entry = local_hostlist_dynamic;
+  struct local_hostlist_entry *last_entry = NULL;
+  while (entry != NULL) {
+    if (((hostname == NULL) || !strcmp(entry->name, hostname)) &&
+        ((addr == NULL) || ip_addr_cmp(&entry->addr, addr))) {
+      struct local_hostlist_entry *free_entry;
+      if (last_entry != NULL) {
+        last_entry->next = entry->next;
+      } else {
+        local_hostlist_dynamic = entry->next;
+      }
+      free_entry = entry;
+      entry = entry->next;
+      memp_free(MEMP_LOCALHOSTLIST, free_entry);
+      removed++;
+    } else {
+      last_entry = entry;
+      entry = entry->next;
+    }
+  }
+  return removed;
+}
+
+/**
+ * Add a hostname/IP address pair to the local host-list.
+ * Duplicates are not checked.
+ *
+ * @param hostname hostname of the new entry
+ * @param addr IP address of the new entry
+ * @return ERR_OK if succeeded or ERR_MEM on memory error
+ */
+err_t
+dns_local_addhost(const char *hostname, const ip_addr_t *addr)
+{
+  struct local_hostlist_entry *entry;
+  size_t namelen;
+  LWIP_ASSERT("invalid host name (NULL)", hostname != NULL);
+  namelen = strlen(hostname);
+  LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN);
+  entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST);
+  if (entry == NULL) {
+    return ERR_MEM;
+  }
+  entry->name = (char*)entry + sizeof(struct local_hostlist_entry);
+  MEMCPY((char*)entry->name, hostname, namelen);
+  ((char*)entry->name)[namelen] = 0;
+  ip_addr_copy(entry->addr, *addr);
+  entry->next = local_hostlist_dynamic;
+  local_hostlist_dynamic = entry;
+  return ERR_OK;
+}
+#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC*/
+#endif /* DNS_LOCAL_HOSTLIST */
+
+/**
+ * Look up a hostname in the array of known hostnames.
+ *
+ * @note This function only looks in the internal array of known
+ * hostnames, it does not send out a query for the hostname if none
+ * was found. The function dns_enqueue() can be used to send a query
+ * for a hostname.
+ *
+ * @param name the hostname to look up
+ * @return the hostname's IP address, as u32_t (instead of ip_addr_t to
+ *         better check for failure: != IPADDR_NONE) or IPADDR_NONE if the hostname
+ *         was not found in the cached dns_table.
+ */
+static u32_t
+dns_lookup(const char *name)
+{
+  u8_t i;
+#if DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN)
+  u32_t addr;
+#endif /* DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) */
+#if DNS_LOCAL_HOSTLIST
+  if ((addr = dns_lookup_local(name)) != IPADDR_NONE) {
+    return addr;
+  }
+#endif /* DNS_LOCAL_HOSTLIST */
+#ifdef DNS_LOOKUP_LOCAL_EXTERN
+  if((addr = DNS_LOOKUP_LOCAL_EXTERN(name)) != IPADDR_NONE) {
+    return addr;
+  }
+#endif /* DNS_LOOKUP_LOCAL_EXTERN */
+
+  /* Walk through name list, return entry if found. If not, return NULL. */
+  for (i = 0; i < DNS_TABLE_SIZE; ++i) {
+    if ((dns_table[i].state == DNS_STATE_DONE) &&
+        (strcmp(name, dns_table[i].name) == 0)) {
+      LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name));
+      ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr));
+      LWIP_DEBUGF(DNS_DEBUG, ("\n"));
+      return ip4_addr_get_u32(&dns_table[i].ipaddr);
+    }
+  }
+
+  return IPADDR_NONE;
+}
+
+#if DNS_DOES_NAME_CHECK
+/**
+ * Compare the "dotted" name "query" with the encoded name "response"
+ * to make sure an answer from the DNS server matches the current dns_table
+ * entry (otherwise, answers might arrive late for hostname not on the list
+ * any more).
+ *
+ * @param query hostname (not encoded) from the dns_table
+ * @param response encoded hostname in the DNS response
+ * @return 0: names equal; 1: names differ
+ */
+static u8_t
+dns_compare_name(unsigned char *query, unsigned char *response)
+{
+  unsigned char n;
+
+  do {
+    n = *response++;
+    /** @see RFC 1035 - 4.1.4. Message compression */
+    if ((n & 0xc0) == 0xc0) {
+      /* Compressed name */
+      break;
+    } else {
+      /* Not compressed name */
+      while (n > 0) {
+        if ((*query) != (*response)) {
+          return 1;
+        }
+        ++response;
+        ++query;
+        --n;
+      };
+      ++query;
+    }
+  } while (*response != 0);
+
+  return 0;
+}
+#endif /* DNS_DOES_NAME_CHECK */
+
+/**
+ * Walk through a compact encoded DNS name and return the end of the name.
+ *
+ * @param query encoded DNS name in the DNS server response
+ * @return end of the name
+ */
+static unsigned char *
+dns_parse_name(unsigned char *query)
+{
+  unsigned char n;
+
+  do {
+    n = *query++;
+    /** @see RFC 1035 - 4.1.4. Message compression */
+    if ((n & 0xc0) == 0xc0) {
+      /* Compressed name */
+      break;
+    } else {
+      /* Not compressed name */
+      while (n > 0) {
+        ++query;
+        --n;
+      };
+    }
+  } while (*query != 0);
+
+  return query + 1;
+}
+
+/**
+ * Send a DNS query packet.
+ *
+ * @param numdns index of the DNS server in the dns_servers table
+ * @param name hostname to query
+ * @param id index of the hostname in dns_table, used as transaction ID in the
+ *        DNS query packet
+ * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise
+ */
+static err_t
+dns_send(u8_t numdns, const char* name, u8_t id)
+{
+  err_t err;
+  struct dns_hdr *hdr;
+  struct dns_query qry;
+  struct pbuf *p;
+  char *query, *nptr;
+  const char *pHostname;
+  u8_t n;
+
+  LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n",
+              (u16_t)(numdns), name));
+  LWIP_ASSERT("dns server out of array", numdns < DNS_MAX_SERVERS);
+  LWIP_ASSERT("dns server has no IP address set", !ip_addr_isany(&dns_servers[numdns]));
+
+  /* if here, we have either a new query or a retry on a previous query to process */
+  p = pbuf_alloc(PBUF_TRANSPORT, SIZEOF_DNS_HDR + DNS_MAX_NAME_LENGTH +
+                 SIZEOF_DNS_QUERY, PBUF_RAM);
+  if (p != NULL) {
+    LWIP_ASSERT("pbuf must be in one piece", p->next == NULL);
+    /* fill dns header */
+    hdr = (struct dns_hdr*)p->payload;
+    memset(hdr, 0, SIZEOF_DNS_HDR);
+    hdr->id = htons(id);
+    hdr->flags1 = DNS_FLAG1_RD;
+    hdr->numquestions = PP_HTONS(1);
+    query = (char*)hdr + SIZEOF_DNS_HDR;
+    pHostname = name;
+    --pHostname;
+
+    /* convert hostname into suitable query format. */
+    do {
+      ++pHostname;
+      nptr = query;
+      ++query;
+      for(n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
+        *query = *pHostname;
+        ++query;
+        ++n;
+      }
+      *nptr = n;
+    } while(*pHostname != 0);
+    *query++='\0';
+
+    /* fill dns query */
+    qry.type = PP_HTONS(DNS_RRTYPE_A);
+    qry.cls = PP_HTONS(DNS_RRCLASS_IN);
+    SMEMCPY(query, &qry, SIZEOF_DNS_QUERY);
+
+    /* resize pbuf to the exact dns query */
+    pbuf_realloc(p, (u16_t)((query + SIZEOF_DNS_QUERY) - ((char*)(p->payload))));
+
+    /* connect to the server for faster receiving */
+    udp_connect(dns_pcb, &dns_servers[numdns], DNS_SERVER_PORT);
+    /* send dns packet */
+    err = udp_sendto(dns_pcb, p, &dns_servers[numdns], DNS_SERVER_PORT);
+
+    /* free pbuf */
+    pbuf_free(p);
+  } else {
+    err = ERR_MEM;
+  }
+
+  return err;
+}
+
+/**
+ * dns_check_entry() - see if pEntry has not yet been queried and, if so, sends out a query.
+ * Check an entry in the dns_table:
+ * - send out query for new entries
+ * - retry old pending entries on timeout (also with different servers)
+ * - remove completed entries from the table if their TTL has expired
+ *
+ * @param i index of the dns_table entry to check
+ */
+static void
+dns_check_entry(u8_t i)
+{
+  err_t err;
+  struct dns_table_entry *pEntry = &dns_table[i];
+
+  LWIP_ASSERT("array index out of bounds", i < DNS_TABLE_SIZE);
+
+  switch(pEntry->state) {
+
+    case DNS_STATE_NEW: {
+      /* initialize new entry */
+      pEntry->state   = DNS_STATE_ASKING;
+      pEntry->numdns  = 0;
+      pEntry->tmr     = 1;
+      pEntry->retries = 0;
+      
+      /* send DNS packet for this entry */
+      err = dns_send(pEntry->numdns, pEntry->name, i);
+      if (err != ERR_OK) {
+        LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING,
+                    ("dns_send returned error: %d\n", err)); //FIX DG, lwip_strerr is part of lwip/api
+      }
+      break;
+    }
+
+    case DNS_STATE_ASKING: {
+      if (--pEntry->tmr == 0) {
+        if (++pEntry->retries == DNS_MAX_RETRIES) {
+          if ((pEntry->numdns+1<DNS_MAX_SERVERS) && !ip_addr_isany(&dns_servers[pEntry->numdns+1])) {
+            /* change of server */
+            pEntry->numdns++;
+            pEntry->tmr     = 1;
+            pEntry->retries = 0;
+            break;
+          } else {
+            LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": timeout\n", pEntry->name));
+            /* call specified callback function if provided */
+            if (pEntry->found)
+              (*pEntry->found)(pEntry->name, NULL, pEntry->arg);
+            /* flush this entry */
+            pEntry->state   = DNS_STATE_UNUSED;
+            pEntry->found   = NULL;
+            break;
+          }
+        }
+
+        /* wait longer for the next retry */
+        pEntry->tmr = pEntry->retries;
+
+        /* send DNS packet for this entry */
+        err = dns_send(pEntry->numdns, pEntry->name, i);
+        if (err != ERR_OK) {
+          LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING,
+                      ("dns_send returned error: %d\n", err)); //FIX DG, lwip_strerr is part of lwip/api
+        }
+      }
+      break;
+    }
+
+    case DNS_STATE_DONE: {
+      /* if the time to live is nul */
+      if (--pEntry->ttl == 0) {
+        LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": flush\n", pEntry->name));
+        /* flush this entry */
+        pEntry->state = DNS_STATE_UNUSED;
+        pEntry->found = NULL;
+      }
+      break;
+    }
+    case DNS_STATE_UNUSED:
+      /* nothing to do */
+      break;
+    default:
+      LWIP_ASSERT("unknown dns_table entry state:", 0);
+      break;
+  }
+}
+
+/**
+ * Call dns_check_entry for each entry in dns_table - check all entries.
+ */
+static void
+dns_check_entries(void)
+{
+  u8_t i;
+
+  for (i = 0; i < DNS_TABLE_SIZE; ++i) {
+    dns_check_entry(i);
+  }
+}
+
+/**
+ * Receive input function for DNS response packets arriving for the dns UDP pcb.
+ *
+ * @params see udp.h
+ */
+static void
+dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
+{
+  u16_t i;
+  char *pHostname;
+  struct dns_hdr *hdr;
+  struct dns_answer ans;
+  struct dns_table_entry *pEntry;
+  u16_t nquestions, nanswers;
+
+  LWIP_UNUSED_ARG(arg);
+  LWIP_UNUSED_ARG(pcb);
+  LWIP_UNUSED_ARG(addr);
+  LWIP_UNUSED_ARG(port);
+
+  /* is the dns message too big ? */
+  if (p->tot_len > DNS_MSG_SIZE) {
+    LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too big\n"));
+    /* free pbuf and return */
+    goto memerr;
+  }
+
+  /* is the dns message big enough ? */
+  if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + SIZEOF_DNS_ANSWER)) {
+    LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n"));
+    /* free pbuf and return */
+    goto memerr;
+  }
+
+  /* copy dns payload inside static buffer for processing */ 
+  if (pbuf_copy_partial(p, dns_payload, p->tot_len, 0) == p->tot_len) {
+    /* The ID in the DNS header should be our entry into the name table. */
+    hdr = (struct dns_hdr*)dns_payload;
+    i = htons(hdr->id);
+    if (i < DNS_TABLE_SIZE) {
+      pEntry = &dns_table[i];
+      if(pEntry->state == DNS_STATE_ASKING) {
+        /* This entry is now completed. */
+        pEntry->state = DNS_STATE_DONE;
+        pEntry->err   = hdr->flags2 & DNS_FLAG2_ERR_MASK;
+
+        /* We only care about the question(s) and the answers. The authrr
+           and the extrarr are simply discarded. */
+        nquestions = htons(hdr->numquestions);
+        nanswers   = htons(hdr->numanswers);
+
+        /* Check for error. If so, call callback to inform. */
+        if (((hdr->flags1 & DNS_FLAG1_RESPONSE) == 0) || (pEntry->err != 0) || (nquestions != 1)) {
+          LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in flags\n", pEntry->name));
+          /* call callback to indicate error, clean up memory and return */
+          goto responseerr;
+        }
+
+#if DNS_DOES_NAME_CHECK
+        /* Check if the name in the "question" part match with the name in the entry. */
+        if (dns_compare_name((unsigned char *)(pEntry->name), (unsigned char *)dns_payload + SIZEOF_DNS_HDR) != 0) {
+          LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", pEntry->name));
+          /* call callback to indicate error, clean up memory and return */
+          goto responseerr;
+        }
+#endif /* DNS_DOES_NAME_CHECK */
+
+        /* Skip the name in the "question" part */
+        pHostname = (char *) dns_parse_name((unsigned char *)dns_payload + SIZEOF_DNS_HDR) + SIZEOF_DNS_QUERY;
+
+        while (nanswers > 0) {
+          /* skip answer resource record's host name */
+          pHostname = (char *) dns_parse_name((unsigned char *)pHostname);
+
+          /* Check for IP address type and Internet class. Others are discarded. */
+          SMEMCPY(&ans, pHostname, SIZEOF_DNS_ANSWER);
+          if((ans.type == PP_HTONS(DNS_RRTYPE_A)) && (ans.cls == PP_HTONS(DNS_RRCLASS_IN)) &&
+             (ans.len == PP_HTONS(sizeof(ip_addr_t))) ) {
+            /* read the answer resource record's TTL, and maximize it if needed */
+            pEntry->ttl = ntohl(ans.ttl);
+            if (pEntry->ttl > DNS_MAX_TTL) {
+              pEntry->ttl = DNS_MAX_TTL;
+            }
+            /* read the IP address after answer resource record's header */
+            SMEMCPY(&(pEntry->ipaddr), (pHostname+SIZEOF_DNS_ANSWER), sizeof(ip_addr_t));
+            LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", pEntry->name));
+            ip_addr_debug_print(DNS_DEBUG, (&(pEntry->ipaddr)));
+            LWIP_DEBUGF(DNS_DEBUG, ("\n"));
+            /* call specified callback function if provided */
+            if (pEntry->found) {
+              (*pEntry->found)(pEntry->name, &pEntry->ipaddr, pEntry->arg);
+            }
+            /* deallocate memory and return */
+            goto memerr;
+          } else {
+            pHostname = pHostname + SIZEOF_DNS_ANSWER + htons(ans.len);
+          }
+          --nanswers;
+        }
+        LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in response\n", pEntry->name));
+        /* call callback to indicate error, clean up memory and return */
+        goto responseerr;
+      }
+    }
+  }
+
+  /* deallocate memory and return */
+  goto memerr;
+
+responseerr:
+  /* ERROR: call specified callback function with NULL as name to indicate an error */
+  if (pEntry->found) {
+    (*pEntry->found)(pEntry->name, NULL, pEntry->arg);
+  }
+  /* flush this entry */
+  pEntry->state = DNS_STATE_UNUSED;
+  pEntry->found = NULL;
+
+memerr:
+  /* free pbuf */
+  pbuf_free(p);
+  return;
+}
+
+/**
+ * Queues a new hostname to resolve and sends out a DNS query for that hostname
+ *
+ * @param name the hostname that is to be queried
+ * @param found a callback founction to be called on success, failure or timeout
+ * @param callback_arg argument to pass to the callback function
+ * @return @return a err_t return code.
+ */
+static err_t
+dns_enqueue(const char *name, dns_found_callback found, void *callback_arg)
+{
+  u8_t i;
+  u8_t lseq, lseqi;
+  struct dns_table_entry *pEntry = NULL;
+  size_t namelen;
+
+  /* search an unused entry, or the oldest one */
+  lseq = lseqi = 0;
+  for (i = 0; i < DNS_TABLE_SIZE; ++i) {
+    pEntry = &dns_table[i];
+    /* is it an unused entry ? */
+    if (pEntry->state == DNS_STATE_UNUSED)
+      break;
+
+    /* check if this is the oldest completed entry */
+    if (pEntry->state == DNS_STATE_DONE) {
+      if ((dns_seqno - pEntry->seqno) > lseq) {
+        lseq = dns_seqno - pEntry->seqno;
+        lseqi = i;
+      }
+    }
+  }
+
+  /* if we don't have found an unused entry, use the oldest completed one */
+  if (i == DNS_TABLE_SIZE) {
+    if ((lseqi >= DNS_TABLE_SIZE) || (dns_table[lseqi].state != DNS_STATE_DONE)) {
+      /* no entry can't be used now, table is full */
+      LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS entries table is full\n", name));
+      return ERR_MEM;
+    } else {
+      /* use the oldest completed one */
+      i = lseqi;
+      pEntry = &dns_table[i];
+    }
+  }
+
+  /* use this entry */
+  LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS entry %"U16_F"\n", name, (u16_t)(i)));
+
+  /* fill the entry */
+  pEntry->state = DNS_STATE_NEW;
+  pEntry->seqno = dns_seqno++;
+  pEntry->found = found;
+  pEntry->arg   = callback_arg;
+  namelen = LWIP_MIN(strlen(name), DNS_MAX_NAME_LENGTH-1);
+  MEMCPY(pEntry->name, name, namelen);
+  pEntry->name[namelen] = 0;
+
+  /* force to send query without waiting timer */
+  dns_check_entry(i);
+
+  /* dns query is enqueued */
+  return ERR_INPROGRESS;
+}
+
+/**
+ * Resolve a hostname (string) into an IP address.
+ * NON-BLOCKING callback version for use with raw API!!!
+ *
+ * Returns immediately with one of err_t return codes:
+ * - ERR_OK if hostname is a valid IP address string or the host
+ *   name is already in the local names table.
+ * - ERR_INPROGRESS enqueue a request to be sent to the DNS server
+ *   for resolution if no errors are present.
+ *
+ * @param hostname the hostname that is to be queried
+ * @param addr pointer to a ip_addr_t where to store the address if it is already
+ *             cached in the dns_table (only valid if ERR_OK is returned!)
+ * @param found a callback function to be called on success, failure or timeout (only if
+ *              ERR_INPROGRESS is returned!)
+ * @param callback_arg argument to pass to the callback function
+ * @return a err_t return code.
+ */
+err_t
+dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found,
+                  void *callback_arg)
+{
+  u32_t ipaddr;
+  /* not initialized or no valid server yet, or invalid addr pointer
+   * or invalid hostname or invalid hostname length */
+  if ((dns_pcb == NULL) || (addr == NULL) ||
+      (!hostname) || (!hostname[0]) ||
+      (strlen(hostname) >= DNS_MAX_NAME_LENGTH)) {
+    return ERR_VAL;
+  }
+
+#if LWIP_HAVE_LOOPIF
+  if (strcmp(hostname, "localhost")==0) {
+    ip_addr_set_loopback(addr);
+    return ERR_OK;
+  }
+#endif /* LWIP_HAVE_LOOPIF */
+
+  /* host name already in octet notation? set ip addr and return ERR_OK */
+  ipaddr = ipaddr_addr(hostname);
+  if (ipaddr == IPADDR_NONE) {
+    /* already have this address cached? */
+    ipaddr = dns_lookup(hostname);
+  }
+  if (ipaddr != IPADDR_NONE) {
+    ip4_addr_set_u32(addr, ipaddr);
+    return ERR_OK;
+  }
+
+  /* queue query with specified callback */
+  return dns_enqueue(hostname, found, callback_arg);
+}
+
+#endif /* LWIP_DNS */
--- a/lwip/core/init.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/core/init.c	Tue Jul 27 15:59:42 2010 +0000
@@ -81,12 +81,12 @@
 #if (!LWIP_UDP && LWIP_IGMP)
   #error "If you want to use IGMP, you have to define LWIP_UDP=1 in your lwipopts.h"
 #endif
+#if (!LWIP_UDP && LWIP_SNMP)
+  #error "If you want to use SNMP, you have to define LWIP_UDP=1 in your lwipopts.h"
+#endif
 #if (!LWIP_UDP && LWIP_DNS)
   #error "If you want to use DNS, you have to define LWIP_UDP=1 in your lwipopts.h"
 #endif
-#if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f))
-  #error "If you want to use ARP, ARP_TABLE_SIZE must fit in an s8_t, so, you have to reduce it in your lwipopts.h"
-#endif
 #if (LWIP_ARP && ARP_QUEUEING && (MEMP_NUM_ARP_QUEUE<=0))
   #error "If you want to use ARP Queueing, you have to define MEMP_NUM_ARP_QUEUE>=1 in your lwipopts.h"
 #endif
@@ -145,7 +145,7 @@
   #error "One and exactly one of LWIP_EVENT_API and LWIP_CALLBACK_API has to be enabled in your lwipopts.h"
 #endif
 /* There must be sufficient timeouts, taking into account requirements of the subsystems. */
-#if (MEMP_NUM_SYS_TIMEOUT < (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT))
+#if LWIP_TIMERS && (MEMP_NUM_SYS_TIMEOUT < (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT))
   #error "MEMP_NUM_SYS_TIMEOUT is too low to accomodate all required timeouts"
 #endif
 #if (IP_REASSEMBLY && (MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS))
@@ -178,8 +178,11 @@
 #if LWIP_TCPIP_CORE_LOCKING_INPUT && !LWIP_TCPIP_CORE_LOCKING
   #error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too"
 #endif
-#if LWIP_TCP && LWIP_NETIF_TX_SINGLE_PBUF && (TCP_OVERSIZE < TCP_MSS)
-  #error "LWIP_NETIF_TX_SINGLE_PBUF needs TCP_OVERSIZE == TCP_MSS to create single-pbuf TCP packets"
+#if LWIP_TCP && LWIP_NETIF_TX_SINGLE_PBUF && !TCP_OVERSIZE
+  #error "LWIP_NETIF_TX_SINGLE_PBUF needs TCP_OVERSIZE enabled to create single-pbuf TCP packets"
+#endif
+#if IP_FRAG && IP_FRAG_USES_STATIC_BUF && LWIP_NETIF_TX_SINGLE_PBUF
+  #error "LWIP_NETIF_TX_SINGLE_PBUF does not work with IP_FRAG_USES_STATIC_BUF==1 as that creates pbuf queues"
 #endif
 
 
@@ -203,11 +206,6 @@
 #ifdef ETHARP_ALWAYS_INSERT
   #error "ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h."
 #endif
-#if SO_REUSE
-/* I removed the lot since this was an ugly hack. It broke the raw-API.
-   It also came with many ugly goto's, Christiaan Simons. */
-  #error "SO_REUSE currently unavailable, this was a hack"
-#endif
 
 #ifdef LWIP_DEBUG
 static void
@@ -234,6 +232,19 @@
   if (TCP_WND < TCP_MSS)
     LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_WND is smaller than MSS\n"));
 #endif /* LWIP_TCP */
+#if LWIP_SOCKET
+  /* Check that the SO_* socket options and SOF_* lwIP-internal flags match */
+  if (SO_ACCEPTCONN != SOF_ACCEPTCONN)
+    LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: SO_ACCEPTCONN != SOF_ACCEPTCONN\n"));
+  if (SO_REUSEADDR != SOF_REUSEADDR)
+    LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: SO_REUSEADDR != SOF_REUSEADDR\n"));
+  if (SO_KEEPALIVE != SOF_KEEPALIVE)
+    LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: SO_KEEPALIVE != SOF_KEEPALIVE\n"));
+  if (SO_BROADCAST != SOF_BROADCAST)
+    LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: SO_BROADCAST != SOF_BROADCAST\n"));
+  if (SO_LINGER != SOF_LINGER)
+    LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: SO_LINGER != SOF_LINGER\n"));
+#endif /* LWIP_SOCKET */
 }
 #else  /* LWIP_DEBUG */
 #define lwip_sanity_check()
@@ -250,7 +261,9 @@
 
   /* Modules initialization */
   stats_init();
+#if !NO_SYS
   sys_init();
+#endif /* !NO_SYS */
   mem_init();
   memp_init();
   pbuf_init();
@@ -284,5 +297,7 @@
   dns_init();
 #endif /* LWIP_DNS */
 
+#if LWIP_TIMERS
   sys_timeouts_init();
+#endif /* LWIP_TIMERS */
 }
--- a/lwip/core/ipv4/autoip.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/core/ipv4/autoip.c	Tue Jul 27 15:59:42 2010 +0000
@@ -150,6 +150,17 @@
   netif->autoip = autoip;
 }
 
+/** Restart AutoIP client and check the next address (conflict detected)
+ *
+ * @param netif The netif under AutoIP control
+ */
+static void
+autoip_restart(struct netif *netif)
+{
+  netif->autoip->tried_llipaddr++;
+  autoip_start(netif);
+}
+
 /**
  * Handle a IP address conflict after an ARP conflict detection
  */
@@ -168,7 +179,7 @@
         ("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n"));
 
       /* TODO: close all TCP sessions */
-      autoip_start(netif);
+      autoip_restart(netif);
     } else {
       LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
         ("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n"));
@@ -179,7 +190,7 @@
     LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
       ("autoip_handle_arp_conflict(): we do not defend, retreating\n"));
     /* TODO: close all TCP sessions */
-    autoip_start(netif);
+    autoip_restart(netif);
   }
 }
 
@@ -308,7 +319,7 @@
         ("autoip_start(): could not allocate autoip\n"));
       return ERR_MEM;
     }
-    memset( autoip, 0, sizeof(struct autoip));
+    memset(autoip, 0, sizeof(struct autoip));
     /* store this AutoIP client in the netif */
     netif->autoip = autoip;
     LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip"));
@@ -316,12 +327,11 @@
     autoip->state = AUTOIP_STATE_OFF;
     autoip->ttw = 0;
     autoip->sent_num = 0;
-    memset(&autoip->llipaddr, 0, sizeof(ip_addr_t));
+    ip_addr_set_zero(&autoip->llipaddr);
     autoip->lastconflict = 0;
   }
 
   autoip_create_addr(netif, &(autoip->llipaddr));
-  autoip->tried_llipaddr++;
   autoip_start_probing(netif);
 
   return result;
@@ -494,8 +504,8 @@
     /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
      * structure packing (not using structure copy which breaks strict-aliasing rules).
      */
-    SMEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr));
-    SMEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr));
+    IPADDR2_COPY(&sipaddr, &hdr->sipaddr);
+    IPADDR2_COPY(&dipaddr, &hdr->dipaddr);
       
     if ((netif->autoip->state == AUTOIP_STATE_PROBING) ||
         ((netif->autoip->state == AUTOIP_STATE_ANNOUNCING) &&
@@ -511,7 +521,7 @@
            !eth_addr_cmp(&netifaddr, &hdr->shwaddr))) {
         LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
           ("autoip_arp_reply(): Probe Conflict detected\n"));
-        autoip_start(netif);
+        autoip_restart(netif);
       }
     } else {
      /* RFC 3927 Section 2.5:
--- a/lwip/core/ipv4/icmp.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/core/ipv4/icmp.c	Tue Jul 27 15:59:42 2010 +0000
@@ -82,7 +82,6 @@
 #endif /* LWIP_DEBUG */
   struct icmp_echo_hdr *iecho;
   struct ip_hdr *iphdr;
-  ip_addr_t tmpaddr;
   s16_t hlen;
 
   ICMP_STATS_INC(icmp.recv);
@@ -111,13 +110,13 @@
       int accepted = 1;
 #if !LWIP_MULTICAST_PING
       /* multicast destination address? */
-      if (ip_addr_ismulticast(&iphdr->dest)) {
+      if (ip_addr_ismulticast(&current_iphdr_dest)) {
         accepted = 0;
       }
 #endif /* LWIP_MULTICAST_PING */
 #if !LWIP_BROADCAST_PING
       /* broadcast destination address? */
-      if (ip_addr_isbroadcast(&iphdr->dest, inp)) {
+      if (ip_addr_isbroadcast(&current_iphdr_dest, inp)) {
         accepted = 0;
       }
 #endif /* LWIP_BROADCAST_PING */
@@ -188,15 +187,14 @@
     /* We generate an answer by switching the dest and src ip addresses,
      * setting the icmp type to ECHO_RESPONSE and updating the checksum. */
     iecho = (struct icmp_echo_hdr *)p->payload;
-    ip_addr_copy(tmpaddr, iphdr->src);
-    ip_addr_copy(iphdr->src, iphdr->dest);
-    ip_addr_copy(iphdr->dest, tmpaddr);
+    ip_addr_copy(iphdr->src, *ip_current_dest_addr());
+    ip_addr_copy(iphdr->dest, *ip_current_src_addr());
     ICMPH_TYPE_SET(iecho, ICMP_ER);
     /* adjust the checksum */
-    if (iecho->chksum >= htons(0xffff - (ICMP_ECHO << 8))) {
-      iecho->chksum += htons(ICMP_ECHO << 8) + 1;
+    if (iecho->chksum >= PP_HTONS(0xffff - (ICMP_ECHO << 8))) {
+      iecho->chksum += PP_HTONS(ICMP_ECHO << 8) + 1;
     } else {
-      iecho->chksum += htons(ICMP_ECHO << 8);
+      iecho->chksum += PP_HTONS(ICMP_ECHO << 8);
     }
 
     /* Set the correct TTL and recalculate the header checksum. */
@@ -216,7 +214,8 @@
       LWIP_ASSERT("Can't move over header in packet", 0);
     } else {
       err_t ret;
-      ret = ip_output_if(p, &(iphdr->src), IP_HDRINCL,
+      /* send an ICMP packet, src addr is the dest addr of the curren packet */
+      ret = ip_output_if(p, ip_current_dest_addr(), IP_HDRINCL,
                    ICMP_TTL, 0, IP_PROTO_ICMP, inp);
       if (ret != ERR_OK) {
         LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ip_output_if returned an error: %c.\n", ret));
@@ -291,6 +290,7 @@
   struct ip_hdr *iphdr;
   /* we can use the echo header here */
   struct icmp_echo_hdr *icmphdr;
+  ip_addr_t iphdr_src;
 
   /* ICMP header + IP header + 8 bytes of data */
   q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE,
@@ -327,7 +327,8 @@
   snmp_inc_icmpoutmsgs();
   /* increase number of destination unreachable messages attempted to send */
   snmp_inc_icmpouttimeexcds();
-  ip_output(q, NULL, &(iphdr->src), ICMP_TTL, 0, IP_PROTO_ICMP);
+  ip_addr_copy(iphdr_src, iphdr->src);
+  ip_output(q, NULL, &iphdr_src, ICMP_TTL, 0, IP_PROTO_ICMP);
   pbuf_free(q);
 }
 
--- a/lwip/core/ipv4/igmp.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/core/ipv4/igmp.c	Tue Jul 27 15:59:42 2010 +0000
@@ -127,7 +127,7 @@
  PACK_STRUCT_FIELD(u8_t           igmp_msgtype);
  PACK_STRUCT_FIELD(u8_t           igmp_maxresp);
  PACK_STRUCT_FIELD(u16_t          igmp_checksum);
- PACK_STRUCT_FIELD(ip_addr_t      igmp_group_address);
+ PACK_STRUCT_FIELD(ip_addr_p_t    igmp_group_address);
 } PACK_STRUCT_STRUCT;
 PACK_STRUCT_END
 #ifdef PACK_STRUCT_USE_INCLUDES
@@ -326,7 +326,7 @@
   }
 
   /* Group doesn't exist yet, create a new one */
-  group = memp_malloc(MEMP_IGMP_GROUP);
+  group = (struct igmp_group *)memp_malloc(MEMP_IGMP_GROUP);
   if (group != NULL) {
     group->netif              = ifp;
     ip_addr_set(&(group->group_address), addr);
@@ -397,7 +397,7 @@
   IGMP_STATS_INC(igmp.recv);
 
   /* Note that the length CAN be greater than 8 but only 8 are used - All are included in the checksum */    
-  iphdr = p->payload;
+  iphdr = (struct ip_hdr *)p->payload;
   if (pbuf_header(p, -(s16_t)(IPH_HL(iphdr) * 4)) || (p->len < IGMP_MINLEN)) {
     pbuf_free(p);
     IGMP_STATS_INC(igmp.lenerr);
@@ -443,8 +443,7 @@
          IGMP_STATS_INC(igmp.rx_v1);
          LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: got an all hosts query with time== 0 - this is V1 and not implemented - treat as v2\n"));
          igmp->igmp_maxresp = IGMP_V1_DELAYING_MEMBER_TMR;
-       }
-       else {
+       } else {
          IGMP_STATS_INC(igmp.rx_general);
        }
 
@@ -462,9 +461,11 @@
          LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_MEMB_QUERY to a specific group "));
          ip_addr_debug_print(IGMP_DEBUG, &igmp->igmp_group_address);
          if (ip_addr_cmp(dest, &allsystems)) {
+           ip_addr_t groupaddr;
            LWIP_DEBUGF(IGMP_DEBUG, (" using \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp)));
-           /* we first need to re-lookfor the group since we used dest last time */
-           group = igmp_lookfor_group(inp, &igmp->igmp_group_address);
+           /* we first need to re-look for the group since we used dest last time */
+           ip_addr_copy(groupaddr, igmp->igmp_group_address);
+           group = igmp_lookfor_group(inp, &groupaddr);
          } else {
            LWIP_DEBUGF(IGMP_DEBUG, (" with the group address as destination [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp)));
          }
@@ -472,12 +473,10 @@
          if (group != NULL) {
            IGMP_STATS_INC(igmp.rx_group);
            igmp_delaying_member(group, igmp->igmp_maxresp);
-         }
-         else {
+         } else {
            IGMP_STATS_INC(igmp.drop);
          }
-       }
-       else {
+       } else {
          IGMP_STATS_INC(igmp.proterr);
        }
      }
@@ -715,7 +714,7 @@
 static void
 igmp_stop_timer(struct igmp_group *group)
 {
-	  group->timer = 0;
+  group->timer = 0;
 }
 
 /**
@@ -759,7 +758,7 @@
 {
   /* This is the "router alert" option */
   u16_t ra[2];
-  ra[0] = htons(ROUTER_ALERT);
+  ra[0] = PP_HTONS(ROUTER_ALERT);
   ra[1] = 0x0000; /* Router shall examine packet */
   IGMP_STATS_INC(igmp.xmit);
   return ip_output_if_opt(p, src, dest, IGMP_TTL, 0, IP_PROTO_IGMP, netif, ra, ROUTER_ALERTLEN);
@@ -783,7 +782,7 @@
   p = pbuf_alloc(PBUF_TRANSPORT, IGMP_MINLEN, PBUF_RAM);
   
   if (p) {
-    igmp = p->payload;
+    igmp = (struct igmp_msg *)p->payload;
     LWIP_ASSERT("igmp_send: check that first pbuf can hold struct igmp_msg",
                (p->len >= sizeof(struct igmp_msg)));
     ip_addr_copy(src, group->netif->ip_addr);
--- a/lwip/core/ipv4/ip.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/core/ipv4/ip.c	Tue Jul 27 15:59:42 2010 +0000
@@ -58,6 +58,41 @@
 
 #include <string.h>
 
+/** Set this to 0 in the rare case of wanting to call an extra function to
+ * generate the IP checksum (in contrast to calculating it on-the-fly). */
+#ifndef LWIP_INLINE_IP_CHKSUM
+#define LWIP_INLINE_IP_CHKSUM   1
+#endif
+#if LWIP_INLINE_IP_CHKSUM && CHECKSUM_GEN_IP
+#define CHECKSUM_GEN_IP_INLINE  1
+#else
+#define CHECKSUM_GEN_IP_INLINE  0
+#endif
+
+#if LWIP_DHCP || defined(LWIP_IP_ACCEPT_UDP_PORT)
+#define IP_ACCEPT_LINK_LAYER_ADDRESSING 1
+
+/** Some defines for DHCP to let link-layer-addressed packets through while the
+ * netif is down.
+ * To use this in your own application/protocol, define LWIP_IP_ACCEPT_UDP_PORT
+ * to return 1 if the port is accepted and 0 if the port is not accepted.
+ */
+#if LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT)
+/* accept DHCP client port and custom port */
+#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (((port) == PP_NTOHS(DHCP_CLIENT_PORT)) \
+         || (LWIP_IP_ACCEPT_UDP_PORT(port)))
+#elif defined(LWIP_IP_ACCEPT_UDP_PORT) /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */
+/* accept custom port only */
+#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (LWIP_IP_ACCEPT_UDP_PORT(dst_port))
+#else /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */
+/* accept DHCP client port only */
+#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) ((port) == PP_NTOHS(DHCP_CLIENT_PORT))
+#endif /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */
+
+#else /* LWIP_DHCP */
+#define IP_ACCEPT_LINK_LAYER_ADDRESSING 0
+#endif /* LWIP_DHCP */
+
 /**
  * The interface that provided the packet for the current callback
  * invocation.
@@ -68,6 +103,13 @@
  * Header of the input packet currently being processed.
  */
 const struct ip_hdr *current_header;
+/** Source IP address of current_header */
+ip_addr_t current_iphdr_src;
+/** Destination IP address of current_header */
+ip_addr_t current_iphdr_dest;
+
+/** The IP header ID of the next outgoing IP packet */
+static u16_t ip_id;
 
 /**
  * Finds the appropriate network interface for a given IP address. It
@@ -113,39 +155,35 @@
  * @param p the packet to forward (p->payload points to IP header)
  * @param iphdr the IP header of the input packet
  * @param inp the netif on which this packet was received
- * @return the netif on which the packet was sent (NULL if it wasn't sent)
  */
-static struct netif *
+static void
 ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
 {
   struct netif *netif;
-  ip_addr_t dest;
 
   PERF_START;
-  dest = iphdr->dest;
 
   /* RFC3927 2.7: do not forward link-local addresses */
-  if (ip_addr_islinklocal(&dest)) {
+  if (ip_addr_islinklocal(&current_iphdr_dest)) {
     LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not forwarding LLA %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
-      ip4_addr1_16(&dest), ip4_addr2_16(&dest), ip4_addr3_16(&dest), ip4_addr4_16(&dest)));
-    snmp_inc_ipoutnoroutes();
-    return (struct netif *)NULL;
+      ip4_addr1_16(&current_iphdr_dest), ip4_addr2_16(&current_iphdr_dest),
+      ip4_addr3_16(&current_iphdr_dest), ip4_addr4_16(&current_iphdr_dest)));
+    goto return_noroute;
   }
 
   /* Find network interface where to forward this IP packet to. */
-  netif = ip_route(&dest);
+  netif = ip_route(&current_iphdr_dest);
   if (netif == NULL) {
     LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for %"U16_F".%"U16_F".%"U16_F".%"U16_F" found\n",
-      ip4_addr1_16(&dest), ip4_addr2_16(&dest), ip4_addr3_16(&dest), ip4_addr4_16(&dest)));
-    snmp_inc_ipoutnoroutes();
-    return (struct netif *)NULL;
+      ip4_addr1_16(&current_iphdr_dest), ip4_addr2_16(&current_iphdr_dest),
+      ip4_addr3_16(&current_iphdr_dest), ip4_addr4_16(&current_iphdr_dest)));
+    goto return_noroute;
   }
   /* Do not forward packets onto the same network interface on which
    * they arrived. */
   if (netif == inp) {
     LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n"));
-    snmp_inc_ipoutnoroutes();
-    return (struct netif *)NULL;
+    goto return_noroute;
   }
 
   /* decrement TTL */
@@ -159,18 +197,19 @@
       icmp_time_exceeded(p, ICMP_TE_TTL);
     }
 #endif /* LWIP_ICMP */
-    return (struct netif *)NULL;
+    return;
   }
 
   /* Incrementally update the IP checksum. */
-  if (IPH_CHKSUM(iphdr) >= htons(0xffff - 0x100)) {
-    IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100) + 1);
+  if (IPH_CHKSUM(iphdr) >= PP_HTONS(0xffff - 0x100)) {
+    IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100) + 1);
   } else {
-    IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100));
+    IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100));
   }
 
   LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
-    ip4_addr1_16(&dest), ip4_addr2_16(&dest), ip4_addr3_16(&dest), ip4_addr4_16(&dest)));
+    ip4_addr1_16(&current_iphdr_dest), ip4_addr2_16(&current_iphdr_dest),
+    ip4_addr3_16(&current_iphdr_dest), ip4_addr4_16(&current_iphdr_dest)));
 
   IP_STATS_INC(ip.fw);
   IP_STATS_INC(ip.xmit);
@@ -178,8 +217,10 @@
 
   PERF_STOP("ip_forward");
   /* transmit pbuf on chosen interface */
-  netif->output(netif, p, &dest);
-  return netif;
+  netif->output(netif, p, &current_iphdr_dest);
+  return;
+return_noroute:
+  snmp_inc_ipoutnoroutes();
 }
 #endif /* IP_FORWARD */
 
@@ -204,9 +245,9 @@
   struct netif *netif;
   u16_t iphdr_hlen;
   u16_t iphdr_len;
-#if LWIP_DHCP
+#if IP_ACCEPT_LINK_LAYER_ADDRESSING
   int check_ip_src=1;
-#endif /* LWIP_DHCP */
+#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
 
   IP_STATS_INC(ip.recv);
   snmp_inc_ipinreceives();
@@ -269,10 +310,14 @@
    * but we'll do it anyway just to be sure that its done. */
   pbuf_realloc(p, iphdr_len);
 
+  /* copy IP addresses to aligned ip_addr_t */
+  ip_addr_copy(current_iphdr_dest, iphdr->dest);
+  ip_addr_copy(current_iphdr_src, iphdr->src);
+
   /* match packet against an interface, i.e. is this packet for us? */
 #if LWIP_IGMP
-  if (ip_addr_ismulticast(&(iphdr->dest))) {
-    if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, &(iphdr->dest)))) {
+  if (ip_addr_ismulticast(&current_iphdr_dest)) {
+    if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, &current_iphdr_dest))) {
       netif = inp;
     } else {
       netif = NULL;
@@ -295,9 +340,9 @@
       /* interface is up and configured? */
       if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr)))) {
         /* unicast to this interface address? */
-        if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) ||
+        if (ip_addr_cmp(&current_iphdr_dest, &(netif->ip_addr)) ||
             /* or broadcast on this interface network address? */
-            ip_addr_isbroadcast(&(iphdr->dest), netif)) {
+            ip_addr_isbroadcast(&current_iphdr_dest, netif)) {
           LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
               netif->name[0], netif->name[1]));
           /* break out of for loop */
@@ -307,7 +352,7 @@
         /* connections to link-local addresses must persist after changing
            the netif's address (RFC3927 ch. 1.9) */
         if ((netif->autoip != NULL) &&
-            ip_addr_cmp(&(iphdr->dest), &(netif->autoip->llipaddr))) {
+            ip_addr_cmp(&current_iphdr_dest, &(netif->autoip->llipaddr))) {
           LWIP_DEBUGF(IP_DEBUG, ("ip_input: LLA packet accepted on interface %c%c\n",
               netif->name[0], netif->name[1]));
           /* break out of for loop */
@@ -327,32 +372,38 @@
     } while(netif != NULL);
   }
 
-#if LWIP_DHCP
+#if IP_ACCEPT_LINK_LAYER_ADDRESSING
   /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed
    * using link layer addressing (such as Ethernet MAC) so we must not filter on IP.
    * According to RFC 1542 section 3.1.1, referred by RFC 2131).
+   *
+   * If you want to accept private broadcast communication while a netif is down,
+   * define LWIP_IP_ACCEPT_UDP_PORT(dst_port), e.g.:
+   *
+   * #define LWIP_IP_ACCEPT_UDP_PORT(dst_port) ((dst_port) == PP_NTOHS(12345))
    */
   if (netif == NULL) {
     /* remote port is DHCP server? */
     if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
+      struct udp_hdr *udphdr = (struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen);
       LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: UDP packet to DHCP client port %"U16_F"\n",
-        ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen))->dest)));
-      if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen))->dest) == DHCP_CLIENT_PORT) {
+        ntohs(udphdr->dest)));
+      if (IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(udphdr->dest)) {
         LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: DHCP packet accepted.\n"));
         netif = inp;
         check_ip_src = 0;
       }
     }
   }
-#endif /* LWIP_DHCP */
+#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
 
   /* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */
-#if LWIP_DHCP
+#if IP_ACCEPT_LINK_LAYER_ADDRESSING
   /* DHCP servers need 0.0.0.0 to be allowed as source address (RFC 1.1.2.2: 3.2.1.3/a) */
-  if (check_ip_src && !ip_addr_isany(&iphdr->src))
-#endif /* LWIP_DHCP */
-  {  if ((ip_addr_isbroadcast(&(iphdr->src), inp)) ||
-         (ip_addr_ismulticast(&(iphdr->src)))) {
+  if (check_ip_src && !ip_addr_isany(&current_iphdr_src))
+#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
+  {  if ((ip_addr_isbroadcast(&current_iphdr_src, inp)) ||
+         (ip_addr_ismulticast(&current_iphdr_src))) {
       /* packet source is not valid */
       LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ip_input: packet source is not valid.\n"));
       /* free (drop) packet pbufs */
@@ -370,7 +421,7 @@
     LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: packet not for us.\n"));
 #if IP_FORWARD
     /* non-broadcast packet? */
-    if (!ip_addr_isbroadcast(&(iphdr->dest), inp)) {
+    if (!ip_addr_isbroadcast(&current_iphdr_dest, inp)) {
       /* try to forward IP packet on (other) interfaces */
       ip_forward(p, iphdr, inp);
     } else
@@ -383,10 +434,10 @@
     return ERR_OK;
   }
   /* packet consists of multiple fragments? */
-  if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
+  if ((IPH_OFFSET(iphdr) & PP_HTONS(IP_OFFMASK | IP_MF)) != 0) {
 #if IP_REASSEMBLY /* packet fragment reassembly code present? */
     LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip_reass()\n",
-      ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & htons(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8));
+      ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & PP_HTONS(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8));
     /* reassemble the packet*/
     p = ip_reass(p);
     /* packet not fully reassembled yet? */
@@ -462,14 +513,14 @@
 #endif /* LWIP_ICMP */
 #if LWIP_IGMP
     case IP_PROTO_IGMP:
-      igmp_input(p,inp,&(iphdr->dest));
+      igmp_input(p, inp, &current_iphdr_dest);
       break;
 #endif /* LWIP_IGMP */
     default:
 #if LWIP_ICMP
       /* send ICMP destination protocol unreachable unless is was a broadcast */
-      if (!ip_addr_isbroadcast(&(iphdr->dest), inp) &&
-          !ip_addr_ismulticast(&(iphdr->dest))) {
+      if (!ip_addr_isbroadcast(&current_iphdr_dest, inp) &&
+          !ip_addr_ismulticast(&current_iphdr_dest)) {
         p->payload = iphdr;
         icmp_dest_unreach(p, ICMP_DUR_PROTO);
       }
@@ -486,6 +537,8 @@
 
   current_netif = NULL;
   current_header = NULL;
+  ip_addr_set_any(&current_iphdr_src);
+  ip_addr_set_any(&current_iphdr_dest);
 
   return ERR_OK;
 }
@@ -536,7 +589,10 @@
 {
 #endif /* IP_OPTIONS_SEND */
   struct ip_hdr *iphdr;
-  static u16_t ip_id = 0;
+  ip_addr_t dest_addr;
+#if CHECKSUM_GEN_IP_INLINE
+  u32_t chk_sum = 0;
+#endif /* CHECKSUM_GEN_IP_INLINE */
 
   /* pbufs passed to IP must have a ref-count of 1 as their payload pointer
      gets altered as the packet is passed down the stack */
@@ -550,6 +606,9 @@
 #if IP_OPTIONS_SEND
     u16_t optlen_aligned = 0;
     if (optlen != 0) {
+#if CHECKSUM_GEN_IP_INLINE
+      int i;
+#endif /* CHECKSUM_GEN_IP_INLINE */
       /* round up to a multiple of 4 */
       optlen_aligned = ((optlen + 3) & ~3);
       ip_hlen += optlen_aligned;
@@ -565,6 +624,11 @@
         /* zero the remaining bytes */
         memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen);
       }
+#if CHECKSUM_GEN_IP_INLINE
+      for (i = 0; i < optlen_aligned; i += sizeof(u16_t)) {
+        chk_sum += ((u16_t*)p->payload)[i];
+      }
+#endif /* CHECKSUM_GEN_IP_INLINE */
     }
 #endif /* IP_OPTIONS_SEND */
     /* generate IP header */
@@ -582,14 +646,30 @@
 
     IPH_TTL_SET(iphdr, ttl);
     IPH_PROTO_SET(iphdr, proto);
+#if CHECKSUM_GEN_IP_INLINE
+    chk_sum += LWIP_MAKE_U16(proto, ttl);
+#endif /* CHECKSUM_GEN_IP_INLINE */
 
     /* dest cannot be NULL here */
     ip_addr_copy(iphdr->dest, *dest);
+#if CHECKSUM_GEN_IP_INLINE
+    chk_sum += ip4_addr_get_u32(&iphdr->dest) & 0xFFFF;
+    chk_sum += ip4_addr_get_u32(&iphdr->dest) >> 16;
+#endif /* CHECKSUM_GEN_IP_INLINE */
 
     IPH_VHLTOS_SET(iphdr, 4, ip_hlen / 4, tos);
+#if CHECKSUM_GEN_IP_INLINE
+    chk_sum += iphdr->_v_hl_tos;
+#endif /* CHECKSUM_GEN_IP_INLINE */
     IPH_LEN_SET(iphdr, htons(p->tot_len));
+#if CHECKSUM_GEN_IP_INLINE
+    chk_sum += iphdr->_len;
+#endif /* CHECKSUM_GEN_IP_INLINE */
     IPH_OFFSET_SET(iphdr, 0);
     IPH_ID_SET(iphdr, htons(ip_id));
+#if CHECKSUM_GEN_IP_INLINE
+    chk_sum += iphdr->_id;
+#endif /* CHECKSUM_GEN_IP_INLINE */
     ++ip_id;
 
     if (ip_addr_isany(src)) {
@@ -599,14 +679,24 @@
       ip_addr_copy(iphdr->src, *src);
     }
 
+#if CHECKSUM_GEN_IP_INLINE
+    chk_sum += ip4_addr_get_u32(&iphdr->src) & 0xFFFF;
+    chk_sum += ip4_addr_get_u32(&iphdr->src) >> 16;
+    chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF);
+    chk_sum = (chk_sum >> 16) + chk_sum;
+    chk_sum = ~chk_sum;
+    iphdr->_chksum = chk_sum; /* network order */
+#else /* CHECKSUM_GEN_IP_INLINE */
     IPH_CHKSUM_SET(iphdr, 0);
 #if CHECKSUM_GEN_IP
     IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen));
 #endif
+#endif /* CHECKSUM_GEN_IP_INLINE */
   } else {
     /* IP header already included in p */
     iphdr = (struct ip_hdr *)p->payload;
-    dest = &(iphdr->dest);
+    ip_addr_copy(dest_addr, iphdr->dest);
+    dest = &dest_addr;
   }
 
   IP_STATS_INC(ip.xmit);
@@ -620,13 +710,18 @@
     LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()"));
     return netif_loop_output(netif, p, dest);
   }
+#if LWIP_IGMP
+  if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) {
+    netif_loop_output(netif, p, dest);
+  }
+#endif /* LWIP_IGMP */
 #endif /* ENABLE_LOOPBACK */
 #if IP_FRAG
   /* don't fragment if interface has mtu set to 0 [loopif] */
   if (netif->mtu && (p->tot_len > netif->mtu)) {
-    return ip_frag(p,netif,dest);
+    return ip_frag(p, netif, dest);
   }
-#endif
+#endif /* IP_FRAG */
 
   LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
   return netif->output(netif, p, dest);
@@ -721,7 +816,7 @@
 void
 ip_debug_print(struct pbuf *p)
 {
-  struct ip_hdr *iphdr = (struct ip_hdr *) p->payload;
+  struct ip_hdr *iphdr = (struct ip_hdr *)p->payload;
   u8_t *payload;
 
   payload = (u8_t *)iphdr + IP_HLEN;
--- a/lwip/core/ipv4/ip_addr.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/core/ipv4/ip_addr.c	Tue Jul 27 15:59:42 2010 +0000
@@ -51,32 +51,62 @@
  * @param netif the network interface against which the address is checked
  * @return returns non-zero if the address is a broadcast address
  */
-u8_t ip_addr_isbroadcast(ip_addr_t *addr, struct netif *netif)
+u8_t
+ip4_addr_isbroadcast(u32_t addr, const struct netif *netif)
 {
-  u32_t addr2test;
+  ip_addr_t ipaddr;
+  ip4_addr_set_u32(&ipaddr, addr);
 
-  addr2test = ip4_addr_get_u32(addr);
   /* all ones (broadcast) or all zeroes (old skool broadcast) */
-  if ((~addr2test == IPADDR_ANY) ||
-      (addr2test == IPADDR_ANY))
+  if ((~addr == IPADDR_ANY) ||
+      (addr == IPADDR_ANY)) {
     return 1;
   /* no broadcast support on this network interface? */
-  else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0)
+  } else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0) {
     /* the given address cannot be a broadcast address
      * nor can we check against any broadcast addresses */
     return 0;
   /* address matches network interface address exactly? => no broadcast */
-  else if (addr2test == ip4_addr_get_u32(&netif->ip_addr))
+  } else if (addr == ip4_addr_get_u32(&netif->ip_addr)) {
     return 0;
   /*  on the same (sub) network... */
-  else if (ip_addr_netcmp(addr, &(netif->ip_addr), &(netif->netmask))
+  } else if (ip_addr_netcmp(&ipaddr, &(netif->ip_addr), &(netif->netmask))
          /* ...and host identifier bits are all ones? =>... */
-          && ((addr2test & ~ip4_addr_get_u32(&netif->netmask)) ==
-           (IPADDR_BROADCAST & ~ip4_addr_get_u32(&netif->netmask))))
+          && ((addr & ~ip4_addr_get_u32(&netif->netmask)) ==
+           (IPADDR_BROADCAST & ~ip4_addr_get_u32(&netif->netmask)))) {
     /* => network broadcast address */
     return 1;
-  else
+  } else {
     return 0;
+  }
+}
+
+/** Checks if a netmask is valid (starting with ones, then only zeros)
+ *
+ * @param netmask the IPv4 netmask to check (in network byte order!)
+ * @return 1 if the netmask is valid, 0 if it is not
+ */
+u8_t
+ip4_addr_netmask_valid(u32_t netmask)
+{
+  u32_t mask;
+  u32_t nm_hostorder = lwip_htonl(netmask);
+
+  /* first, check for the first zero */
+  for (mask = 1U << 31 ; mask != 0; mask >>= 1) {
+    if ((nm_hostorder & mask) == 0) {
+      break;
+    }
+  }
+  /* then check that there is no one */
+  for (; mask != 0; mask >>= 1) {
+    if ((nm_hostorder & mask) != 0) {
+      /* there is a one after the first zero -> invalid */
+      return 0;
+    }
+  }
+  /* no one after the first zero -> valid */
+  return 1;
 }
 
 /* Here for now until needed in other places in lwIP */
@@ -87,8 +117,8 @@
 #define isxdigit(c)          (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
 #define islower(c)           in_range(c, 'a', 'z')
 #define isspace(c)           (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
-#endif    
-    
+#endif
+
 /**
  * Ascii internet address interpretation routine.
  * The value returned is in network order.
@@ -163,8 +193,9 @@
        *  a.b.c   (with c treated as 16 bits)
        *  a.b (with b treated as 24 bits)
        */
-      if (pp >= parts + 3)
+      if (pp >= parts + 3) {
         return (0);
+      }
       *pp++ = val;
       c = *++cp;
     } else
@@ -173,8 +204,9 @@
   /*
    * Check for trailing characters.
    */
-  if (c != '\0' && !isspace(c))
+  if (c != '\0' && !isspace(c)) {
     return (0);
+  }
   /*
    * Concoct the address according to
    * the number of parts specified.
@@ -188,22 +220,28 @@
     break;
 
   case 2:             /* a.b -- 8.24 bits */
-    if (val > 0xffffffUL)
+    if (val > 0xffffffUL) {
       return (0);
+    }
     val |= parts[0] << 24;
     break;
 
   case 3:             /* a.b.c -- 8.8.16 bits */
-    if (val > 0xffff)
+    if (val > 0xffff) {
       return (0);
+    }
     val |= (parts[0] << 24) | (parts[1] << 16);
     break;
 
   case 4:             /* a.b.c.d -- 8.8.8.8 bits */
-    if (val > 0xff)
+    if (val > 0xff) {
       return (0);
+    }
     val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
     break;
+  default:
+    LWIP_ASSERT("unhandled", 0);
+    break;
   }
   if (addr) {
     ip4_addr_set_u32(addr, htonl(val));
@@ -220,7 +258,7 @@
  *         represenation of addr
  */
 char *
-ipaddr_ntoa(ip_addr_t *addr)
+ipaddr_ntoa(const ip_addr_t *addr)
 {
   static char str[16];
   return ipaddr_ntoa_r(addr, str, 16);
@@ -235,7 +273,7 @@
  * @return either pointer to buf which now holds the ASCII
  *         representation of addr or NULL if buf was too small
  */
-char *ipaddr_ntoa_r(ip_addr_t *addr, char *buf, int buflen)
+char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen)
 {
   u32_t s_addr;
   char inv[3];
--- a/lwip/core/ipv4/ip_frag.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/core/ipv4/ip_frag.c	Tue Jul 27 15:59:42 2010 +0000
@@ -80,7 +80,10 @@
 /** This is a helper struct which holds the starting
  * offset and the ending offset of this fragment to
  * easily chain the fragments.
- * It has to be packed since it has to fit inside the IP header.
+ * It has the same packing requirements as the IP header, since it replaces
+ * the IP header in memory in incoming fragments (after copying it) to keep
+ * track of the various fragments. (-> If the IP header doesn't need packing,
+ * this struct doesn't need packing, too.)
  */
 #ifdef PACK_STRUCT_USE_INCLUDES
 #  include "arch/bpstruct.h"
@@ -267,11 +270,11 @@
 {
   struct ip_reassdata* ipr;
   /* No matching previous fragment found, allocate a new reassdata struct */
-  ipr = (struct ip_reassdata*) memp_malloc(MEMP_REASSDATA);
+  ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA);
   if (ipr == NULL) {
 #if IP_REASS_FREE_OLDEST
     if (ip_reass_remove_oldest_datagram(fraghdr, clen) >= clen) {
-      ipr =  (struct ip_reassdata*) memp_malloc(MEMP_REASSDATA);
+      ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA);
     }
     if (ipr == NULL)
 #endif /* IP_REASS_FREE_OLDEST */
@@ -552,7 +555,7 @@
    * to an existing one */
 
   /* check for 'no more fragments', and update queue entry*/
-  if ((ntohs(IPH_OFFSET(fraghdr)) & IP_MF) == 0) {
+  if ((IPH_OFFSET(fraghdr) & PP_NTOHS(IP_MF)) == 0) {
     ipr->flags |= IP_REASS_FLAG_LASTFRAG;
     ipr->datagram_len = offset + len;
     LWIP_DEBUGF(IP_REASS_DEBUG,
@@ -613,6 +616,38 @@
 #if IP_FRAG
 #if IP_FRAG_USES_STATIC_BUF
 static u8_t buf[LWIP_MEM_ALIGN_SIZE(IP_FRAG_MAX_MTU + MEM_ALIGNMENT - 1)];
+#else /* IP_FRAG_USES_STATIC_BUF */
+
+#if !LWIP_NETIF_TX_SINGLE_PBUF
+/** Allocate a new struct pbuf_custom_ref */
+static struct pbuf_custom_ref*
+ip_frag_alloc_pbuf_custom_ref(void)
+{
+  return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF);
+}
+
+/** Free a struct pbuf_custom_ref */
+static void
+ip_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p)
+{
+  LWIP_ASSERT("p != NULL", p != NULL);
+  memp_free(MEMP_FRAG_PBUF, p);
+}
+
+/** Free-callback function to free a 'struct pbuf_custom_ref', called by
+ * pbuf_free. */
+static void
+ipfrag_free_pbuf_custom(struct pbuf *p)
+{
+  struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p;
+  LWIP_ASSERT("pcr != NULL", pcr != NULL);
+  LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p);
+  if (pcr->original != NULL) {
+    pbuf_free(pcr->original);
+  }
+  ip_frag_free_pbuf_custom_ref(pcr);
+}
+#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */
 #endif /* IP_FRAG_USES_STATIC_BUF */
 
 /**
@@ -635,7 +670,9 @@
 #if IP_FRAG_USES_STATIC_BUF
   struct pbuf *header;
 #else
+#if !LWIP_NETIF_TX_SINGLE_PBUF
   struct pbuf *newpbuf;
+#endif
   struct ip_hdr *original_iphdr;
 #endif
   struct ip_hdr *iphdr;
@@ -646,7 +683,7 @@
   u16_t last;
   u16_t poff = IP_HLEN;
   u16_t tmp;
-#if !IP_FRAG_USES_STATIC_BUF
+#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF
   u16_t newpbuflen = 0;
   u16_t left_to_copy;
 #endif
@@ -666,10 +703,10 @@
   rambuf->payload = LWIP_MEM_ALIGN((void *)buf);
 
   /* Copy the IP header in it */
-  iphdr = (struct ip_hdr*) rambuf->payload;
+  iphdr = (struct ip_hdr *)rambuf->payload;
   SMEMCPY(iphdr, p->payload, IP_HLEN);
 #else /* IP_FRAG_USES_STATIC_BUF */
-  original_iphdr = (struct ip_hdr*) p->payload;
+  original_iphdr = (struct ip_hdr *)p->payload;
   iphdr = original_iphdr;
 #endif /* IP_FRAG_USES_STATIC_BUF */
 
@@ -697,6 +734,23 @@
 #if IP_FRAG_USES_STATIC_BUF
     poff += pbuf_copy_partial(p, (u8_t*)iphdr + IP_HLEN, cop, poff);
 #else /* IP_FRAG_USES_STATIC_BUF */
+#if LWIP_NETIF_TX_SINGLE_PBUF
+    rambuf = pbuf_alloc(PBUF_IP, cop, PBUF_RAM);
+    if (rambuf == NULL) {
+      return ERR_MEM;
+    }
+    LWIP_ASSERT("this needs a pbuf in one piece!",
+      (rambuf->len == rambuf->tot_len) && (rambuf->next == NULL));
+    poff += pbuf_copy_partial(p, rambuf->payload, cop, poff);
+    /* make room for the IP header */
+    if(pbuf_header(rambuf, IP_HLEN)) {
+      pbuf_free(rambuf);
+      return ERR_MEM;
+    }
+    /* fill in the IP header */
+    SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN);
+    iphdr = rambuf->payload;
+#else /* LWIP_NETIF_TX_SINGLE_PBUF */
     /* When not using a static buffer, create a chain of pbufs.
      * The first will be a PBUF_RAM holding the link and IP header.
      * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged,
@@ -709,7 +763,7 @@
     LWIP_ASSERT("this needs a pbuf in one piece!",
                 (p->len >= (IP_HLEN)));
     SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN);
-    iphdr = (struct ip_hdr*) rambuf->payload;
+    iphdr = (struct ip_hdr *)rambuf->payload;
 
     /* Can just adjust p directly for needed offset. */
     p->payload = (u8_t *)p->payload + poff;
@@ -717,20 +771,29 @@
 
     left_to_copy = cop;
     while (left_to_copy) {
+      struct pbuf_custom_ref *pcr;
       newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len;
       /* Is this pbuf already empty? */
       if (!newpbuflen) {
         p = p->next;
         continue;
       }
-      newpbuf = pbuf_alloc(PBUF_RAW, 0, PBUF_REF);
-      if (newpbuf == NULL) {
+      pcr = ip_frag_alloc_pbuf_custom_ref();
+      if (pcr == NULL) {
         pbuf_free(rambuf);
         return ERR_MEM;
       }
       /* Mirror this pbuf, although we might not need all of it. */
-      newpbuf->payload = p->payload;
-      newpbuf->len = newpbuf->tot_len = newpbuflen;
+      newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen);
+      if (newpbuf == NULL) {
+        ip_frag_free_pbuf_custom_ref(pcr);
+        pbuf_free(rambuf);
+        return ERR_MEM;
+      }
+      pbuf_ref(p);
+      pcr->original = p;
+      pcr->pc.custom_free_function = ipfrag_free_pbuf_custom;
+
       /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain
        * so that it is removed when pbuf_dechain is later called on rambuf.
        */
@@ -741,6 +804,7 @@
       }
     }
     poff = newpbuflen;
+#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
 #endif /* IP_FRAG_USES_STATIC_BUF */
 
     /* Correct header */
--- a/lwip/core/mem.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/core/mem.c	Tue Jul 27 15:59:42 2010 +0000
@@ -82,7 +82,7 @@
   memp_t poolnr;
   mem_size_t required_size = size + sizeof(struct memp_malloc_helper);
 
-  for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr++) {
+  for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr = (memp_t)(poolnr + 1)) {
 #if MEM_USE_POOLS_TRY_BIGGER_POOL
 again:
 #endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */
@@ -178,7 +178,7 @@
  * how that space is calculated). */
 #ifndef LWIP_RAM_HEAP_POINTER
 /** the heap. we need one struct mem at the end and some room for alignment */
-u8_t ram_heap[MEM_SIZE_ALIGNED + (2*SIZEOF_STRUCT_MEM) + MEM_ALIGNMENT] MEM_POSITION;
+u8_t ram_heap[MEM_SIZE_ALIGNED + (2*SIZEOF_STRUCT_MEM) + MEM_ALIGNMENT];
 #define LWIP_RAM_HEAP_POINTER ram_heap
 #endif /* LWIP_RAM_HEAP_POINTER */
 
@@ -189,10 +189,8 @@
 /** pointer to the lowest free block, this is used for faster search */
 static struct mem *lfree;
 
-#if (NO_SYS==0) //Pointless if monothreaded app
 /** concurrent access protection */
 static sys_mutex_t mem_mutex;
-#endif
 
 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
 
--- a/lwip/core/memp.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/core/memp.c	Tue Jul 27 15:59:42 2010 +0000
@@ -57,6 +57,7 @@
 #include "lwip/snmp_structs.h"
 #include "lwip/snmp_msg.h"
 #include "lwip/dns.h"
+#include "netif/ppp_oe.h"
 
 #include <string.h>
 
@@ -113,7 +114,7 @@
 
 /** This array holds the first free element of each pool.
  *  Elements form a linked list. */
-static struct memp *memp_tab[MEMP_MAX] MEM_POSITION;
+static struct memp *memp_tab[MEMP_MAX];
 
 #else /* MEMP_MEM_MALLOC */
 
@@ -161,7 +162,7 @@
 static u8_t *const memp_bases[] = { 
 #define LWIP_MEMPOOL(name,num,size,desc) memp_memory_ ## name ## _base,   
 #include "lwip/memp_std.h"
-} MEM_POSITION;
+};
 
 #else /* MEMP_SEPARATE_POOLS */
 
@@ -169,7 +170,7 @@
 static u8_t memp_memory[MEM_ALIGNMENT - 1 
 #define LWIP_MEMPOOL(name,num,size,desc) + ( (num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size) ) )
 #include "lwip/memp_std.h"
-] MEM_POSITION;
+];
 
 #endif /* MEMP_SEPARATE_POOLS */
 
@@ -197,15 +198,55 @@
 }
 #endif /* MEMP_SANITY_CHECK*/
 #if MEMP_OVERFLOW_CHECK
+#if defined(LWIP_DEBUG) && MEMP_STATS
+static const char * memp_overflow_names[] = {
+#define LWIP_MEMPOOL(name,num,size,desc) "/"desc,
+#include "lwip/memp_std.h"
+  };
+#endif
+
 /**
  * Check if a memp element was victim of an overflow
  * (e.g. the restricted area after it has been altered)
  *
  * @param p the memp element to check
- * @param memp_size the element size of the pool p comes from
+ * @param memp_type the pool p comes from
  */
 static void
-memp_overflow_check_element(struct memp *p, u16_t memp_size)
+memp_overflow_check_element_overflow(struct memp *p, u16_t memp_type)
+{
+  u16_t k;
+  u8_t *m;
+#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0
+  m = (u8_t*)p + MEMP_SIZE + memp_sizes[memp_type];
+  for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) {
+    if (m[k] != 0xcd) {
+      char errstr[128] = "detected memp overflow in pool ";
+      char digit[] = "0";
+      if(memp_type >= 10) {
+        digit[0] = '0' + (memp_type/10);
+        strcat(errstr, digit);
+      }
+      digit[0] = '0' + (memp_type%10);
+      strcat(errstr, digit);
+#if defined(LWIP_DEBUG) && MEMP_STATS
+      strcat(errstr, memp_overflow_names[memp_type]);
+#endif
+      LWIP_ASSERT(errstr, 0);
+    }
+  }
+#endif
+}
+
+/**
+ * Check if a memp element was victim of an underflow
+ * (e.g. the restricted area before it has been altered)
+ *
+ * @param p the memp element to check
+ * @param memp_type the pool p comes from
+ */
+static void
+memp_overflow_check_element_underflow(struct memp *p, u16_t memp_type)
 {
   u16_t k;
   u8_t *m;
@@ -213,15 +254,18 @@
   m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED;
   for (k = 0; k < MEMP_SANITY_REGION_BEFORE_ALIGNED; k++) {
     if (m[k] != 0xcd) {
-      LWIP_ASSERT("detected memp underflow!", 0);
-    }
-  }
+      char errstr[128] = "detected memp underflow in pool ";
+      char digit[] = "0";
+      if(memp_type >= 10) {
+        digit[0] = '0' + (memp_type/10);
+        strcat(errstr, digit);
+      }
+      digit[0] = '0' + (memp_type%10);
+      strcat(errstr, digit);
+#if defined(LWIP_DEBUG) && MEMP_STATS
+      strcat(errstr, memp_overflow_names[memp_type]);
 #endif
-#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0
-  m = (u8_t*)p + MEMP_SIZE + memp_size;
-  for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) {
-    if (m[k] != 0xcd) {
-      LWIP_ASSERT("detected memp overflow!", 0);
+      LWIP_ASSERT(errstr, 0);
     }
   }
 #endif
@@ -238,11 +282,19 @@
   u16_t i, j;
   struct memp *p;
 
-  p = LWIP_MEM_ALIGN(memp_memory);
+  p = (struct memp *)LWIP_MEM_ALIGN(memp_memory);
   for (i = 0; i < MEMP_MAX; ++i) {
     p = p;
     for (j = 0; j < memp_num[i]; ++j) {
-      memp_overflow_check_element(p, memp_sizes[i]);
+      memp_overflow_check_element_overflow(p, i);
+      p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED);
+    }
+  }
+  p = (struct memp *)LWIP_MEM_ALIGN(memp_memory);
+  for (i = 0; i < MEMP_MAX; ++i) {
+    p = p;
+    for (j = 0; j < memp_num[i]; ++j) {
+      memp_overflow_check_element_underflow(p, i);
       p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED);
     }
   }
@@ -258,7 +310,7 @@
   struct memp *p;
   u8_t *m;
 
-  p = LWIP_MEM_ALIGN(memp_memory);
+  p = (struct memp *)LWIP_MEM_ALIGN(memp_memory);
   for (i = 0; i < MEMP_MAX; ++i) {
     p = p;
     for (j = 0; j < memp_num[i]; ++j) {
@@ -397,7 +449,8 @@
 #if MEMP_OVERFLOW_CHECK >= 2
   memp_overflow_check_all();
 #else
-  memp_overflow_check_element(memp, memp_sizes[type]);
+  memp_overflow_check_element_overflow(memp, type);
+  memp_overflow_check_element_underflow(memp, type);
 #endif /* MEMP_OVERFLOW_CHECK >= 2 */
 #endif /* MEMP_OVERFLOW_CHECK */
 
--- a/lwip/core/pbuf.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/core/pbuf.c	Tue Jul 27 15:59:42 2010 +0000
@@ -73,6 +73,9 @@
 #if TCP_QUEUE_OOSEQ
 #include "lwip/tcp_impl.h"
 #endif
+#if LWIP_CHECKSUM_ON_COPY
+#include "lwip/inet_chksum.h"
+#endif
 
 #include <string.h>
 
@@ -81,9 +84,9 @@
    aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */
 #define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE)
 
-#if !TCP_QUEUE_OOSEQ || NO_SYS
+#if !LWIP_TCP || !TCP_QUEUE_OOSEQ || NO_SYS
 #define PBUF_POOL_IS_EMPTY()
-#else /* !TCP_QUEUE_OOSEQ || NO_SYS */
+#else /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || NO_SYS */
 /** Define this to 0 to prevent freeing ooseq pbufs when the PBUF_POOL is empty */
 #ifndef PBUF_POOL_FREE_OOSEQ
 #define PBUF_POOL_FREE_OOSEQ 1
@@ -145,7 +148,7 @@
   }
 }
 #endif /* PBUF_POOL_FREE_OOSEQ */
-#endif /* !TCP_QUEUE_OOSEQ || NO_SYS */
+#endif /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || NO_SYS */
 
 /**
  * Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type).
@@ -323,6 +326,67 @@
   return p;
 }
 
+#if LWIP_SUPPORT_CUSTOM_PBUF
+/** Initialize a custom pbuf (already allocated).
+ *
+ * @param layer flag to define header size
+ * @param length size of the pbuf's payload
+ * @param type type of the pbuf (only used to treat the pbuf accordingly, as
+ *        this function allocates no memory)
+ * @param p pointer to the custom pbuf to initialize (already allocated)
+ * @param payload_mem pointer to the buffer that is used for payload and headers,
+ *        must be at least big enough to hold 'length' plus the header size,
+ *        may be NULL if set later
+ * @param payload_mem_len the size of the 'payload_mem' buffer, must be at least
+ *        big enough to hold 'length' plus the header size
+ */
+struct pbuf*
+pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, struct pbuf_custom *p,
+                    void *payload_mem, u16_t payload_mem_len)
+{
+  u16_t offset;
+  LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloced_custom(length=%"U16_F")\n", length));
+
+  /* determine header offset */
+  offset = 0;
+  switch (l) {
+  case PBUF_TRANSPORT:
+    /* add room for transport (often TCP) layer header */
+    offset += PBUF_TRANSPORT_HLEN;
+    /* FALLTHROUGH */
+  case PBUF_IP:
+    /* add room for IP layer header */
+    offset += PBUF_IP_HLEN;
+    /* FALLTHROUGH */
+  case PBUF_LINK:
+    /* add room for link layer header */
+    offset += PBUF_LINK_HLEN;
+    break;
+  case PBUF_RAW:
+    break;
+  default:
+    LWIP_ASSERT("pbuf_alloced_custom: bad pbuf layer", 0);
+    return NULL;
+  }
+
+  if (LWIP_MEM_ALIGN_SIZE(offset) + length < payload_mem_len) {
+    LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_WARNING, ("pbuf_alloced_custom(length=%"U16_F") buffer too short\n", length));
+    return NULL;
+  }
+
+  p->pbuf.next = NULL;
+  if (payload_mem != NULL) {
+    p->pbuf.payload = LWIP_MEM_ALIGN((void *)((u8_t *)payload_mem + offset));
+  } else {
+    p->pbuf.payload = NULL;
+  }
+  p->pbuf.flags = PBUF_FLAG_IS_CUSTOM;
+  p->pbuf.len = p->pbuf.tot_len = length;
+  p->pbuf.type = type;
+  p->pbuf.ref = 1;
+  return &p->pbuf;
+}
+#endif /* LWIP_SUPPORT_CUSTOM_PBUF */
 
 /**
  * Shrink a pbuf chain to a desired length.
@@ -428,8 +492,9 @@
   u16_t increment_magnitude;
 
   LWIP_ASSERT("p != NULL", p != NULL);
-  if ((header_size_increment == 0) || (p == NULL))
+  if ((header_size_increment == 0) || (p == NULL)) {
     return 0;
+  }
  
   if (header_size_increment < 0){
     increment_magnitude = -header_size_increment;
@@ -478,8 +543,7 @@
        * bail out unsuccesfully */
       return 1;
     }
-  }
-  else {
+  } else {
     /* Unknown type */
     LWIP_ASSERT("bad pbuf type", 0);
     return 1;
@@ -570,15 +634,25 @@
       q = p->next;
       LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: deallocating %p\n", (void *)p));
       type = p->type;
-      /* is this a pbuf from the pool? */
-      if (type == PBUF_POOL) {
-        memp_free(MEMP_PBUF_POOL, p);
-      /* is this a ROM or RAM referencing pbuf? */
-      } else if (type == PBUF_ROM || type == PBUF_REF) {
-        memp_free(MEMP_PBUF, p);
-      /* type == PBUF_RAM */
-      } else {
-        mem_free(p);
+#if LWIP_SUPPORT_CUSTOM_PBUF
+      /* is this a custom pbuf? */
+      if ((p->flags & PBUF_FLAG_IS_CUSTOM) != 0) {
+        struct pbuf_custom *pc = (struct pbuf_custom*)p;
+        LWIP_ASSERT("pc->custom_free_function != NULL", pc->custom_free_function != NULL);
+        pc->custom_free_function(p);
+      } else
+#endif /* LWIP_SUPPORT_CUSTOM_PBUF */
+      {
+        /* is this a pbuf from the pool? */
+        if (type == PBUF_POOL) {
+          memp_free(MEMP_PBUF_POOL, p);
+        /* is this a ROM or RAM referencing pbuf? */
+        } else if (type == PBUF_ROM || type == PBUF_REF) {
+          memp_free(MEMP_PBUF, p);
+        /* type == PBUF_RAM */
+        } else {
+          mem_free(p);
+        }
       }
       count++;
       /* proceed to next pbuf */
@@ -900,8 +974,8 @@
 /**
  * Creates a single pbuf out of a queue of pbufs.
  *
- * @remark: The source pbuf 'p' is not freed by this function because that can
- *          be illegal in some places!
+ * @remark: Either the source pbuf 'p' is freed by this function or the original
+ *          pbuf 'p' is returned, therefore the caller has to check the result!
  *
  * @param p the source pbuf
  * @param layer pbuf_layer of the new pbuf
@@ -927,3 +1001,156 @@
   pbuf_free(p);
   return q;
 }
+
+#if LWIP_CHECKSUM_ON_COPY
+/**
+ * Copies data into a single pbuf (*not* into a pbuf queue!) and updates
+ * the checksum while copying
+ *
+ * @param p the pbuf to copy data into
+ * @param start_offset offset of p->payload where to copy the data to
+ * @param dataptr data to copy into the pbuf
+ * @param len length of data to copy into the pbuf
+ * @param chksum pointer to the checksum which is updated
+ * @return ERR_OK if successful, another error if the data does not fit
+ *         within the (first) pbuf (no pbuf queues!)
+ */
+err_t
+pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr,
+                 u16_t len, u16_t *chksum)
+{
+  u32_t acc;
+  u16_t copy_chksum;
+  char *dst_ptr;
+  LWIP_ASSERT("p != NULL", p != NULL);
+  LWIP_ASSERT("dataptr != NULL", dataptr != NULL);
+  LWIP_ASSERT("chksum != NULL", chksum != NULL);
+  LWIP_ASSERT("len != 0", len != 0);
+
+  if ((start_offset >= p->len) || (start_offset + len > p->len)) {
+    return ERR_ARG;
+  }
+
+  dst_ptr = ((char*)p->payload) + start_offset;
+  copy_chksum = LWIP_CHKSUM_COPY(dst_ptr, dataptr, len);
+  if ((start_offset & 1) != 0) {
+    copy_chksum = SWAP_BYTES_IN_WORD(copy_chksum);
+  }
+  acc = *chksum;
+  acc += copy_chksum;
+  *chksum = FOLD_U32T(acc);
+  return ERR_OK;
+}
+#endif /* LWIP_CHECKSUM_ON_COPY */
+
+ /** Get one byte from the specified position in a pbuf
+ * WARNING: returns zero for offset >= p->tot_len
+ *
+ * @param p pbuf to parse
+ * @param offset offset into p of the byte to return
+ * @return byte at an offset into p OR ZERO IF 'offset' >= p->tot_len
+ */
+u8_t
+pbuf_get_at(struct pbuf* p, u16_t offset)
+{
+  u16_t copy_from = offset;
+  struct pbuf* q = p;
+
+  /* get the correct pbuf */
+  while ((q != NULL) && (q->len <= copy_from)) {
+    copy_from -= q->len;
+    q = q->next;
+  }
+  /* return requested data if pbuf is OK */
+  if ((q != NULL) && (q->len > copy_from)) {
+    return ((u8_t*)q->payload)[copy_from];
+  }
+  return 0;
+}
+
+/** Compare pbuf contents at specified offset with memory s2, both of length n
+ *
+ * @param p pbuf to compare
+ * @param offset offset into p at wich to start comparing
+ * @param s2 buffer to compare
+ * @param n length of buffer to compare
+ * @return zero if equal, nonzero otherwise
+ *         (0xffff if p is too short, diffoffset+1 otherwise)
+ */
+u16_t
+pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n)
+{
+  u16_t start = offset;
+  struct pbuf* q = p;
+
+  /* get the correct pbuf */
+  while ((q != NULL) && (q->len <= start)) {
+    start -= q->len;
+    q = q->next;
+  }
+  /* return requested data if pbuf is OK */
+  if ((q != NULL) && (q->len > start)) {
+    u16_t i;
+    for(i = 0; i < n; i++) {
+      u8_t a = pbuf_get_at(q, start + i);
+      u8_t b = ((u8_t*)s2)[i];
+      if (a != b) {
+        return i+1;
+      }
+    }
+    return 0;
+  }
+  return 0xffff;
+}
+
+/** Find occurrence of mem (with length mem_len) in pbuf p, starting at offset
+ * start_offset.
+ *
+ * @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as
+ *        return value 'not found'
+ * @param mem search for the contents of this buffer
+ * @param mem_len length of 'mem'
+ * @param start_offset offset into p at which to start searching
+ * @return 0xFFFF if substr was not found in p or the index where it was found
+ */
+u16_t
+pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset)
+{
+  u16_t i;
+  u16_t max = p->tot_len - mem_len;
+  if (p->tot_len >= mem_len + start_offset) {
+    for(i = start_offset; i <= max; ) {
+      u16_t plus = pbuf_memcmp(p, i, mem, mem_len);
+      if (plus == 0) {
+        return i;
+      } else {
+        i += plus;
+      }
+    }
+  }
+  return 0xFFFF;
+}
+
+/** Find occurrence of substr with length substr_len in pbuf p, start at offset
+ * start_offset
+ * WARNING: in contrast to strstr(), this one does not stop at the first \0 in
+ * the pbuf/source string!
+ *
+ * @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as
+ *        return value 'not found'
+ * @param substr string to search for in p, maximum length is 0xFFFE
+ * @return 0xFFFF if substr was not found in p or the index where it was found
+ */
+u16_t
+pbuf_strstr(struct pbuf* p, const char* substr)
+{
+  size_t substr_len;
+  if ((substr == NULL) || (substr[0] == 0) || (p->tot_len == 0xFFFF)) {
+    return 0xFFFF;
+  }
+  substr_len = strlen(substr);
+  if (substr_len >= 0xFFFF) {
+    return 0xFFFF;
+  }
+  return pbuf_memfind(p, substr, (u16_t)substr_len, 0);
+}
--- a/lwip/core/raw.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/core/raw.c	Tue Jul 27 15:59:42 2010 +0000
@@ -92,16 +92,16 @@
   while ((eaten == 0) && (pcb != NULL)) {
     if ((pcb->protocol == proto) &&
         (ip_addr_isany(&pcb->local_ip) ||
-         ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
+         ip_addr_cmp(&(pcb->local_ip), &current_iphdr_dest))) {
 #if IP_SOF_BROADCAST_RECV
       /* broadcast filter? */
-      if ((pcb->so_options & SOF_BROADCAST) || !ip_addr_isbroadcast(&(iphdr->dest), inp))
+      if ((pcb->so_options & SOF_BROADCAST) || !ip_addr_isbroadcast(&current_iphdr_dest, inp))
 #endif /* IP_SOF_BROADCAST_RECV */
       {
         /* receive callback function available? */
         if (pcb->recv != NULL) {
           /* the receive callback function did not eat the packet? */
-          if (pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src)) != 0) {
+          if (pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr()) != 0) {
             /* receive function ate the packet */
             p = NULL;
             eaten = 1;
--- a/lwip/core/snmp/mib2.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/core/snmp/mib2.c	Tue Jul 27 15:59:42 2010 +0000
@@ -131,20 +131,20 @@
   17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30
 };
 struct mib_node* const snmp_nodes[28] = {
-  (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar,
-  (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar,
-  (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar,
-  (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar,
-  (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar,
-  (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar,
-  (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar,
-  (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar,
-  (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar,
-  (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar,
-  (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar,
-  (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar,
-  (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar,
-  (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar
+  (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
+  (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
+  (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
+  (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
+  (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
+  (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
+  (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
+  (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
+  (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
+  (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
+  (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
+  (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
+  (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
+  (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar
 };
 const struct mib_array_node snmp = {
   &noleafs_get_object_def,
@@ -176,7 +176,7 @@
 };
 const s32_t udpentry_ids[2] = { 1, 2 };
 struct mib_node* const udpentry_nodes[2] = {
-  (struct mib_node* const)&udp_root, (struct mib_node* const)&udp_root,
+  (struct mib_node*)&udp_root, (struct mib_node*)&udp_root,
 };
 const struct mib_array_node udpentry = {
   &noleafs_get_object_def,
@@ -190,7 +190,7 @@
 };
 
 s32_t udptable_id = 1;
-struct mib_node* udptable_node = (struct mib_node* const)&udpentry;
+struct mib_node* udptable_node = (struct mib_node*)&udpentry;
 struct mib_ram_array_node udptable = {
   &noleafs_get_object_def,
   &noleafs_get_value,
@@ -212,9 +212,9 @@
 };
 const s32_t udp_ids[5] = { 1, 2, 3, 4, 5 };
 struct mib_node* const udp_nodes[5] = {
-  (struct mib_node* const)&udp_scalar, (struct mib_node* const)&udp_scalar,
-  (struct mib_node* const)&udp_scalar, (struct mib_node* const)&udp_scalar,
-  (struct mib_node* const)&udptable
+  (struct mib_node*)&udp_scalar, (struct mib_node*)&udp_scalar,
+  (struct mib_node*)&udp_scalar, (struct mib_node*)&udp_scalar,
+  (struct mib_node*)&udptable
 };
 const struct mib_array_node udp = {
   &noleafs_get_object_def,
@@ -244,9 +244,9 @@
 };
 const s32_t tcpconnentry_ids[5] = { 1, 2, 3, 4, 5 };
 struct mib_node* const tcpconnentry_nodes[5] = {
-  (struct mib_node* const)&tcpconntree_root, (struct mib_node* const)&tcpconntree_root,
-  (struct mib_node* const)&tcpconntree_root, (struct mib_node* const)&tcpconntree_root,
-  (struct mib_node* const)&tcpconntree_root
+  (struct mib_node*)&tcpconntree_root, (struct mib_node*)&tcpconntree_root,
+  (struct mib_node*)&tcpconntree_root, (struct mib_node*)&tcpconntree_root,
+  (struct mib_node*)&tcpconntree_root
 };
 const struct mib_array_node tcpconnentry = {
   &noleafs_get_object_def,
@@ -260,7 +260,7 @@
 };
 
 s32_t tcpconntable_id = 1;
-struct mib_node* tcpconntable_node = (struct mib_node* const)&tcpconnentry;
+struct mib_node* tcpconntable_node = (struct mib_node*)&tcpconnentry;
 struct mib_ram_array_node tcpconntable = {
   &noleafs_get_object_def,
   &noleafs_get_value,
@@ -284,14 +284,14 @@
 };
 const s32_t tcp_ids[15] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
 struct mib_node* const tcp_nodes[15] = {
-  (struct mib_node* const)&tcp_scalar, (struct mib_node* const)&tcp_scalar,
-  (struct mib_node* const)&tcp_scalar, (struct mib_node* const)&tcp_scalar,
-  (struct mib_node* const)&tcp_scalar, (struct mib_node* const)&tcp_scalar,
-  (struct mib_node* const)&tcp_scalar, (struct mib_node* const)&tcp_scalar,
-  (struct mib_node* const)&tcp_scalar, (struct mib_node* const)&tcp_scalar,
-  (struct mib_node* const)&tcp_scalar, (struct mib_node* const)&tcp_scalar,
-  (struct mib_node* const)&tcpconntable, (struct mib_node* const)&tcp_scalar,
-  (struct mib_node* const)&tcp_scalar
+  (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar,
+  (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar,
+  (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar,
+  (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar,
+  (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar,
+  (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar,
+  (struct mib_node*)&tcpconntable, (struct mib_node*)&tcp_scalar,
+  (struct mib_node*)&tcp_scalar
 };
 const struct mib_array_node tcp = {
   &noleafs_get_object_def,
@@ -316,19 +316,19 @@
 };
 const s32_t icmp_ids[26] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 };
 struct mib_node* const icmp_nodes[26] = {
-  (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar,
-  (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar,
-  (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar,
-  (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar,
-  (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar,
-  (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar,
-  (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar,
-  (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar,
-  (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar,
-  (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar,
-  (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar,
-  (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar,
-  (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar
+  (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
+  (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
+  (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
+  (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
+  (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
+  (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
+  (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
+  (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
+  (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
+  (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
+  (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
+  (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
+  (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar
 };
 const struct mib_array_node icmp = {
   &noleafs_get_object_def,
@@ -355,8 +355,8 @@
 };
 const s32_t ipntomentry_ids[4] = { 1, 2, 3, 4 };
 struct mib_node* const ipntomentry_nodes[4] = {
-  (struct mib_node* const)&ipntomtree_root, (struct mib_node* const)&ipntomtree_root,
-  (struct mib_node* const)&ipntomtree_root, (struct mib_node* const)&ipntomtree_root
+  (struct mib_node*)&ipntomtree_root, (struct mib_node*)&ipntomtree_root,
+  (struct mib_node*)&ipntomtree_root, (struct mib_node*)&ipntomtree_root
 };
 const struct mib_array_node ipntomentry = {
   &noleafs_get_object_def,
@@ -370,7 +370,7 @@
 };
 
 s32_t ipntomtable_id = 1;
-struct mib_node* ipntomtable_node = (struct mib_node* const)&ipntomentry;
+struct mib_node* ipntomtable_node = (struct mib_node*)&ipntomentry;
 struct mib_ram_array_node ipntomtable = {
   &noleafs_get_object_def,
   &noleafs_get_value,
@@ -396,13 +396,13 @@
 };
 const s32_t iprteentry_ids[13] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };
 struct mib_node* const iprteentry_nodes[13] = {
-  (struct mib_node* const)&iprtetree_root, (struct mib_node* const)&iprtetree_root,
-  (struct mib_node* const)&iprtetree_root, (struct mib_node* const)&iprtetree_root,
-  (struct mib_node* const)&iprtetree_root, (struct mib_node* const)&iprtetree_root,
-  (struct mib_node* const)&iprtetree_root, (struct mib_node* const)&iprtetree_root,
-  (struct mib_node* const)&iprtetree_root, (struct mib_node* const)&iprtetree_root,
-  (struct mib_node* const)&iprtetree_root, (struct mib_node* const)&iprtetree_root,
-  (struct mib_node* const)&iprtetree_root
+  (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root,
+  (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root,
+  (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root,
+  (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root,
+  (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root,
+  (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root,
+  (struct mib_node*)&iprtetree_root
 };
 const struct mib_array_node iprteentry = {
   &noleafs_get_object_def,
@@ -416,7 +416,7 @@
 };
 
 s32_t iprtetable_id = 1;
-struct mib_node* iprtetable_node = (struct mib_node* const)&iprteentry;
+struct mib_node* iprtetable_node = (struct mib_node*)&iprteentry;
 struct mib_ram_array_node iprtetable = {
   &noleafs_get_object_def,
   &noleafs_get_value,
@@ -442,11 +442,11 @@
 };
 const s32_t ipaddrentry_ids[5] = { 1, 2, 3, 4, 5 };
 struct mib_node* const ipaddrentry_nodes[5] = {
-  (struct mib_node* const)&ipaddrtree_root,
-  (struct mib_node* const)&ipaddrtree_root,
-  (struct mib_node* const)&ipaddrtree_root,
-  (struct mib_node* const)&ipaddrtree_root,
-  (struct mib_node* const)&ipaddrtree_root
+  (struct mib_node*)&ipaddrtree_root,
+  (struct mib_node*)&ipaddrtree_root,
+  (struct mib_node*)&ipaddrtree_root,
+  (struct mib_node*)&ipaddrtree_root,
+  (struct mib_node*)&ipaddrtree_root
 };
 const struct mib_array_node ipaddrentry = {
   &noleafs_get_object_def,
@@ -460,7 +460,7 @@
 };
 
 s32_t ipaddrtable_id = 1;
-struct mib_node* ipaddrtable_node = (struct mib_node* const)&ipaddrentry;
+struct mib_node* ipaddrtable_node = (struct mib_node*)&ipaddrentry;
 struct mib_ram_array_node ipaddrtable = {
   &noleafs_get_object_def,
   &noleafs_get_value,
@@ -483,18 +483,18 @@
 };
 const s32_t ip_ids[23] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 };
 struct mib_node* const ip_nodes[23] = {
-  (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar,
-  (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar,
-  (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar,
-  (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar,
-  (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar,
-  (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar,
-  (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar,
-  (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar,
-  (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar,
-  (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ipaddrtable,
-  (struct mib_node* const)&iprtetable, (struct mib_node* const)&ipntomtable,
-  (struct mib_node* const)&ip_scalar
+  (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
+  (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
+  (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
+  (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
+  (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
+  (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
+  (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
+  (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
+  (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
+  (struct mib_node*)&ip_scalar, (struct mib_node*)&ipaddrtable,
+  (struct mib_node*)&iprtetable, (struct mib_node*)&ipntomtable,
+  (struct mib_node*)&ip_scalar
 };
 const struct mib_array_node mib2_ip = {
   &noleafs_get_object_def,
@@ -521,9 +521,9 @@
 };
 const s32_t atentry_ids[3] = { 1, 2, 3 };
 struct mib_node* const atentry_nodes[3] = {
-  (struct mib_node* const)&arptree_root,
-  (struct mib_node* const)&arptree_root,
-  (struct mib_node* const)&arptree_root
+  (struct mib_node*)&arptree_root,
+  (struct mib_node*)&arptree_root,
+  (struct mib_node*)&arptree_root
 };
 const struct mib_array_node atentry = {
   &noleafs_get_object_def,
@@ -537,7 +537,7 @@
 };
 
 const s32_t attable_id = 1;
-struct mib_node* const attable_node = (struct mib_node* const)&atentry;
+struct mib_node* const attable_node = (struct mib_node*)&atentry;
 const struct mib_array_node attable = {
   &noleafs_get_object_def,
   &noleafs_get_value,
@@ -551,7 +551,7 @@
 
 /* at .1.3.6.1.2.1.3 */
 s32_t at_id = 1;
-struct mib_node* mib2_at_node = (struct mib_node* const)&attable;
+struct mib_node* mib2_at_node = (struct mib_node*)&attable;
 struct mib_ram_array_node at = {
   &noleafs_get_object_def,
   &noleafs_get_value,
@@ -582,17 +582,17 @@
 };
 const s32_t ifentry_ids[22] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 };
 struct mib_node* const ifentry_nodes[22] = {
-  (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root,
-  (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root,
-  (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root,
-  (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root,
-  (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root,
-  (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root,
-  (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root,
-  (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root,
-  (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root,
-  (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root,
-  (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root
+  (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
+  (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
+  (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
+  (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
+  (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
+  (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
+  (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
+  (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
+  (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
+  (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
+  (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root
 };
 const struct mib_array_node ifentry = {
   &noleafs_get_object_def,
@@ -606,7 +606,7 @@
 };
 
 s32_t iftable_id = 1;
-struct mib_node* iftable_node = (struct mib_node* const)&ifentry;
+struct mib_node* iftable_node = (struct mib_node*)&ifentry;
 struct mib_ram_array_node iftable = {
   &noleafs_get_object_def,
   &noleafs_get_value,
@@ -629,7 +629,7 @@
 };
 const s32_t interfaces_ids[2] = { 1, 2 };
 struct mib_node* const interfaces_nodes[2] = {
-  (struct mib_node* const)&interfaces_scalar, (struct mib_node* const)&iftable
+  (struct mib_node*)&interfaces_scalar, (struct mib_node*)&iftable
 };
 const struct mib_array_node interfaces = {
   &noleafs_get_object_def,
@@ -655,10 +655,10 @@
 };
 const s32_t sys_tem_ids[7] = { 1, 2, 3, 4, 5, 6, 7 };
 struct mib_node* const sys_tem_nodes[7] = {
-  (struct mib_node* const)&sys_tem_scalar, (struct mib_node* const)&sys_tem_scalar,
-  (struct mib_node* const)&sys_tem_scalar, (struct mib_node* const)&sys_tem_scalar,
-  (struct mib_node* const)&sys_tem_scalar, (struct mib_node* const)&sys_tem_scalar,
-  (struct mib_node* const)&sys_tem_scalar
+  (struct mib_node*)&sys_tem_scalar, (struct mib_node*)&sys_tem_scalar,
+  (struct mib_node*)&sys_tem_scalar, (struct mib_node*)&sys_tem_scalar,
+  (struct mib_node*)&sys_tem_scalar, (struct mib_node*)&sys_tem_scalar,
+  (struct mib_node*)&sys_tem_scalar
 };
 /* work around name issue with 'sys_tem', some compiler(s?) seem to reserve 'system' */
 const struct mib_array_node sys_tem = {
@@ -692,16 +692,16 @@
   11
 };
 struct mib_node* const mib2_nodes[MIB2_GROUPS] = {
-  (struct mib_node* const)&sys_tem,
-  (struct mib_node* const)&interfaces,
-  (struct mib_node* const)&at,
-  (struct mib_node* const)&mib2_ip,
-  (struct mib_node* const)&icmp,
+  (struct mib_node*)&sys_tem,
+  (struct mib_node*)&interfaces,
+  (struct mib_node*)&at,
+  (struct mib_node*)&mib2_ip,
+  (struct mib_node*)&icmp,
 #if LWIP_TCP
-  (struct mib_node* const)&tcp,
+  (struct mib_node*)&tcp,
 #endif
-  (struct mib_node* const)&udp,
-  (struct mib_node* const)&snmp
+  (struct mib_node*)&udp,
+  (struct mib_node*)&snmp
 };
 
 const struct mib_array_node mib2 = {
@@ -717,7 +717,7 @@
 
 /* mgmt .1.3.6.1.2 */
 const s32_t mgmt_ids[1] = { 1 };
-struct mib_node* const mgmt_nodes[1] = { (struct mib_node* const)&mib2 };
+struct mib_node* const mgmt_nodes[1] = { (struct mib_node*)&mib2 };
 const struct mib_array_node mgmt = {
   &noleafs_get_object_def,
   &noleafs_get_value,
@@ -734,7 +734,7 @@
 /* When using a private MIB, you have to create a file 'private_mib.h' that contains
  * a 'struct mib_array_node mib_private' which contains your MIB. */
 s32_t internet_ids[2] = { 2, 4 };
-struct mib_node* const internet_nodes[2] = { (struct mib_node* const)&mgmt, (struct mib_node* const)&mib_private };
+struct mib_node* const internet_nodes[2] = { (struct mib_node*)&mgmt, (struct mib_node*)&mib_private };
 const struct mib_array_node internet = {
   &noleafs_get_object_def,
   &noleafs_get_value,
@@ -747,7 +747,7 @@
 };
 #else
 const s32_t internet_ids[1] = { 2 };
-struct mib_node* const internet_nodes[1] = { (struct mib_node* const)&mgmt };
+struct mib_node* const internet_nodes[1] = { (struct mib_node*)&mgmt };
 const struct mib_array_node internet = {
   &noleafs_get_object_def,
   &noleafs_get_value,
--- a/lwip/core/snmp/mib_structs.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/core/snmp/mib_structs.c	Tue Jul 27 15:59:42 2010 +0000
@@ -445,7 +445,7 @@
  * @param node points to the root of the tree ('.internet')
  * @param ident_len the length of the supplied object identifier
  * @param ident points to the array of sub identifiers
- * @param np points to the found object instance (rerurn)
+ * @param np points to the found object instance (return)
  * @return pointer to the requested parent (!) node if success, NULL otherwise
  */
 struct mib_node *
--- a/lwip/core/snmp/msg_out.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/core/snmp/msg_out.c	Tue Jul 27 15:59:42 2010 +0000
@@ -96,7 +96,7 @@
 {
   if (dst_idx < SNMP_TRAP_DESTINATIONS)
   {
-    ip_addr_set_hton(&trap_dst[dst_idx].dip, dst);
+    ip_addr_set(&trap_dst[dst_idx].dip, dst);
   }
 }
 
@@ -270,11 +270,8 @@
         snmp_inc_snmpouttraps();
         snmp_inc_snmpoutpkts();
 
-        /** connect to the TRAP destination */
-        udp_connect(trap_msg.pcb, &trap_msg.dip, SNMP_TRAP_PORT);
-        udp_send(trap_msg.pcb, p);
-        /** disassociate remote address and port with this pcb */
-        udp_disconnect(trap_msg.pcb);
+        /** send to the TRAP destination */
+        udp_sendto(trap_msg.pcb, p, &trap_msg.dip, SNMP_TRAP_PORT);
 
         pbuf_free(p);
       }
--- a/lwip/core/stats.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/core/stats.c	Tue Jul 27 15:59:42 2010 +0000
@@ -48,11 +48,11 @@
 
 struct stats_ lwip_stats;
 
-void stats_init()
+void stats_init(void)
 {
 #ifdef LWIP_DEBUG
 #if MEMP_STATS
-  char * memp_names[] = {
+  const char * memp_names[] = {
 #define LWIP_MEMPOOL(name,num,size,desc) desc,
 #include "lwip/memp_std.h"
   };
--- a/lwip/core/tcp.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/core/tcp.c	Tue Jul 27 15:59:42 2010 +0000
@@ -55,7 +55,7 @@
 
 #include <string.h>
 
-const char *tcp_state_str[] = {
+const char * const tcp_state_str[] = {
   "CLOSED",      
   "LISTEN",      
   "SYN_SENT",    
@@ -88,6 +88,12 @@
 /** List of all TCP PCBs in TIME-WAIT state */
 struct tcp_pcb *tcp_tw_pcbs;
 
+#define NUM_TCP_PCB_LISTS               4
+#define NUM_TCP_PCB_LISTS_NO_TIME_WAIT  3
+/** An array with all (non-temporary) PCB lists, mainly used for smaller code size */
+struct tcp_pcb **tcp_pcb_lists[] = {&tcp_listen_pcbs.pcbs, &tcp_bound_pcbs,
+  &tcp_active_pcbs, &tcp_tw_pcbs};
+
 /** Only used for temporary storage. */
 struct tcp_pcb *tcp_tmp_pcb;
 
@@ -134,11 +140,26 @@
   err_t err;
 
   if (rst_on_unacked_data && (pcb->state != LISTEN)) {
-    if ((pcb->refused_data != NULL) ||  (pcb->rcv_wnd != TCP_WND)) {
+    if ((pcb->refused_data != NULL) || (pcb->rcv_wnd != TCP_WND)) {
       /* Not all data received by application, send RST to tell the remote
          side about this. */
+      LWIP_ASSERT("pcb->flags & TF_RXCLOSED", pcb->flags & TF_RXCLOSED);
+
+      /* don't call tcp_abort here: we must not deallocate the pcb since
+         that might not be expected when calling tcp_close */
       tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
         pcb->local_port, pcb->remote_port);
+
+      tcp_pcb_purge(pcb);
+
+      /* TODO: to which state do we move now? */
+
+      /* move to TIME_WAIT since we close actively */
+      TCP_RMV(&tcp_active_pcbs, pcb);
+      pcb->state = TIME_WAIT;
+      TCP_REG(&tcp_tw_pcbs, pcb);
+
+      return ERR_OK;
     }
   }
 
@@ -158,7 +179,7 @@
     break;
   case LISTEN:
     err = ERR_OK;
-    tcp_pcb_remove((struct tcp_pcb **)&tcp_listen_pcbs.pcbs, pcb);
+    tcp_pcb_remove(&tcp_listen_pcbs.pcbs, pcb);
     memp_free(MEMP_TCP_PCB_LISTEN, pcb);
     pcb = NULL;
     break;
@@ -302,7 +323,9 @@
 #endif /* LWIP_CALLBACK_API */
   void *errf_arg;
 
-  
+  /* pcb->state LISTEN not allowed here */
+  LWIP_ASSERT("don't call tcp_abort/tcp_abandon for listen-pcbs",
+    pcb->state != LISTEN);
   /* Figure out on which TCP PCB list we are, and remove us. If we
      are in an active state, call the receive function associated with
      the PCB with a NULL argument, and send an RST to the remote end. */
@@ -310,7 +333,6 @@
     tcp_pcb_remove(&tcp_tw_pcbs, pcb);
     memp_free(MEMP_TCP_PCB, pcb);
   } else {
-    /* @todo: pcb->state, LISTEN not allowed */
     seqno = pcb->snd_nxt;
     ackno = pcb->rcv_nxt;
     ip_addr_copy(local_ip, pcb->local_ip);
@@ -374,55 +396,46 @@
 err_t
 tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
 {
+  int i;
+  int max_pcb_list = NUM_TCP_PCB_LISTS;
   struct tcp_pcb *cpcb;
 
   LWIP_ERROR("tcp_bind: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_ISCONN);
 
+#if SO_REUSE
+  /* Unless the REUSEADDR flag is set,
+     we have to check the pcbs in TIME-WAIT state, also.
+     We do not dump TIME_WAIT pcb's; they can still be matched by incoming
+     packets using both local and remote IP addresses and ports to distinguish.
+   */
+#if SO_REUSE
+  if ((pcb->so_options & SOF_REUSEADDR) != 0) {
+    max_pcb_list = NUM_TCP_PCB_LISTS_NO_TIME_WAIT;
+  }
+#endif /* SO_REUSE */
+#endif /* SO_REUSE */
+
   if (port == 0) {
     port = tcp_new_port();
   }
-  /* Check if the address already is in use. */
-  /* Check the listen pcbs. */
-  for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs;
-      cpcb != NULL; cpcb = cpcb->next) {
-    if (cpcb->local_port == port) {
-      if (ip_addr_isany(&(cpcb->local_ip)) ||
-          ip_addr_isany(ipaddr) ||
-          ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
-        return ERR_USE;
-      }
-    }
-  }
-  /* Check the connected pcbs. */
-  for(cpcb = tcp_active_pcbs;
-      cpcb != NULL; cpcb = cpcb->next) {
-    if (cpcb->local_port == port) {
-      if (ip_addr_isany(&(cpcb->local_ip)) ||
-          ip_addr_isany(ipaddr) ||
-          ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
-        return ERR_USE;
-      }
-    }
-  }
-  /* Check the bound, not yet connected pcbs. */
-  for(cpcb = tcp_bound_pcbs; cpcb != NULL; cpcb = cpcb->next) {
-    if (cpcb->local_port == port) {
-      if (ip_addr_isany(&(cpcb->local_ip)) ||
-          ip_addr_isany(ipaddr) ||
-          ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
-        return ERR_USE;
-      }
-    }
-  }
-  /* Unless the REUSEADDR flag is set,
-   * we have to check the pcbs in TIME-WAIT state, also: */
-  if ((pcb->so_options & SOF_REUSEADDR) == 0) {
-    for(cpcb = tcp_tw_pcbs; cpcb != NULL; cpcb = cpcb->next) {
+
+  /* Check if the address already is in use (on all lists) */
+  for (i = 0; i < max_pcb_list; i++) {
+    for(cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) {
       if (cpcb->local_port == port) {
-        if (ip_addr_isany(&(cpcb->local_ip)) ||
-            ip_addr_isany(ipaddr) ||
-            ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
-          return ERR_USE;
+#if SO_REUSE
+        /* Omit checking for the same port if both pcbs have REUSEADDR set.
+           For SO_REUSEADDR, the duplicate-check for a 5-tuple is done in
+           tcp_connect. */
+        if (((pcb->so_options & SOF_REUSEADDR) == 0) ||
+          ((cpcb->so_options & SOF_REUSEADDR) == 0))
+#endif /* SO_REUSE */
+        {
+          if (ip_addr_isany(&(cpcb->local_ip)) ||
+              ip_addr_isany(ipaddr) ||
+              ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
+            return ERR_USE;
+          }
         }
       }
     }
@@ -477,6 +490,21 @@
   if (pcb->state == LISTEN) {
     return pcb;
   }
+#if SO_REUSE
+  if ((pcb->so_options & SOF_REUSEADDR) != 0) {
+    /* Since SOF_REUSEADDR allows reusing a local address before the pcb's usage
+       is declared (listen-/connection-pcb), we have to make sure now that
+       this port is only used once for every local IP. */
+    for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
+      if (lpcb->local_port == pcb->local_port) {
+        if (ip_addr_cmp(&lpcb->local_ip, &pcb->local_ip)) {
+          /* this address/port is already used */
+          return NULL;
+        }
+      }
+    }
+  }
+#endif /* SO_REUSE */
   lpcb = (struct tcp_pcb_listen *)memp_malloc(MEMP_TCP_PCB_LISTEN);
   if (lpcb == NULL) {
     return NULL;
@@ -484,6 +512,7 @@
   lpcb->callback_arg = pcb->callback_arg;
   lpcb->local_port = pcb->local_port;
   lpcb->state = LISTEN;
+  lpcb->prio = pcb->prio;
   lpcb->so_options = pcb->so_options;
   lpcb->so_options |= SOF_ACCEPTCONN;
   lpcb->ttl = pcb->ttl;
@@ -498,7 +527,7 @@
   lpcb->accepts_pending = 0;
   lpcb->backlog = (backlog ? backlog : 1);
 #endif /* TCP_LISTEN_BACKLOG */
-  TCP_REG(&tcp_listen_pcbs.listen_pcbs, lpcb);
+  TCP_REG(&tcp_listen_pcbs.pcbs, (struct tcp_pcb *)lpcb);
   return (struct tcp_pcb *)lpcb;
 }
 
@@ -576,6 +605,7 @@
 static u16_t
 tcp_new_port(void)
 {
+  int i;
   struct tcp_pcb *pcb;
 #ifndef TCP_LOCAL_PORT_RANGE_START
 #define TCP_LOCAL_PORT_RANGE_START 4096
@@ -587,20 +617,12 @@
   if (++port > TCP_LOCAL_PORT_RANGE_END) {
     port = TCP_LOCAL_PORT_RANGE_START;
   }
-  
-  for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
-    if (pcb->local_port == port) {
-      goto again;
-    }
-  }
-  for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
-    if (pcb->local_port == port) {
-      goto again;
-    }
-  }
-  for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {
-    if (pcb->local_port == port) {
-      goto again;
+  /* Check all PCB lists. */
+  for (i = 1; i < NUM_TCP_PCB_LISTS; i++) {  
+    for(pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) {
+      if (pcb->local_port == port) {
+        goto again;
+      }
     }
   }
   return port;
@@ -634,9 +656,43 @@
     return ERR_VAL;
   }
   pcb->remote_port = port;
+
+  /* check if we have a route to the remote host */
+  if (ip_addr_isany(&(pcb->local_ip))) {
+    /* no local IP address set, yet. */
+    struct netif *netif = ip_route(&(pcb->remote_ip));
+    if (netif == NULL) {
+      /* Don't even try to send a SYN packet if we have no route
+         since that will fail. */
+      return ERR_RTE;
+    }
+    /* Use the netif's IP address as local address. */
+    ip_addr_copy(pcb->local_ip, netif->ip_addr);
+  }
+
   if (pcb->local_port == 0) {
     pcb->local_port = tcp_new_port();
   }
+#if SO_REUSE
+  if ((pcb->so_options & SOF_REUSEADDR) != 0) {
+    /* Since SOF_REUSEADDR allows reusing a local address, we have to make sure
+       now that the 5-tuple is unique. */
+    struct tcp_pcb *cpcb;
+    int i;
+    /* Don't check listen PCBs, check bound-, active- and TIME-WAIT PCBs. */
+    for (i = 1; i < NUM_TCP_PCB_LISTS; i++) {
+      for(cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) {
+        if ((cpcb->local_port == pcb->local_port) &&
+            (cpcb->remote_port == port) &&
+            ip_addr_cmp(&cpcb->local_ip, &pcb->local_ip) &&
+            ip_addr_cmp(&cpcb->remote_ip, ipaddr)) {
+          /* linux returns EISCONN here, but ERR_USE should be OK for us */
+          return ERR_USE;
+        }
+      }
+    }
+  }
+#endif /* SO_REUSE */
   iss = tcp_next_iss();
   pcb->rcv_nxt = 0;
   pcb->snd_nxt = iss;
@@ -656,8 +712,12 @@
   pcb->ssthresh = pcb->mss * 10;
 #if LWIP_CALLBACK_API
   pcb->connected = connected;
+#else /* LWIP_CALLBACK_API */  
+  LWIP_UNUSED_ARG(connected);
 #endif /* LWIP_CALLBACK_API */
 
+  LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect: tcp_ticks=%"U32_F" iss=%"U32_F"\n", tcp_ticks, iss));
+
   /* Send a SYN together with the MSS option. */
   ret = tcp_enqueue_flags(pcb, TCP_SYN);
   if (ret == ERR_OK) {
@@ -687,10 +747,13 @@
   u8_t pcb_remove;      /* flag if a PCB should be removed */
   u8_t pcb_reset;       /* flag if a RST should be sent when removing */
   err_t err;
+  
+  tcp_debug_print_pcbs(); //DG
 
   err = ERR_OK;
 
   ++tcp_ticks;
+  LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: tcp_ticks=%"U32_F"\n", tcp_ticks));
 
   /* Steps through all of the active PCBs. */
   prev = NULL;
@@ -998,8 +1061,8 @@
 {
   pcb->prio = prio;
 }
+
 #if TCP_QUEUE_OOSEQ
-
 /**
  * Returns a copy of the given TCP segment.
  * The pbuf and data are not copied, only the pointers
@@ -1020,7 +1083,7 @@
   pbuf_ref(cseg->p);
   return cseg;
 }
-#endif
+#endif /* TCP_QUEUE_OOSEQ */
 
 #if LWIP_CALLBACK_API
 /**
@@ -1072,7 +1135,7 @@
     LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n",
            (void *)inactive, inactivity));
     tcp_abort(inactive);
-  }      
+  }
 }
 
 /**
@@ -1098,7 +1161,7 @@
     LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n",
            (void *)inactive, inactivity));
     tcp_abort(inactive);
-  }      
+  }
 }
 
 /**
@@ -1159,6 +1222,8 @@
     pcb->lastack = iss;
     pcb->snd_lbb = iss;   
     pcb->tmr = tcp_ticks;
+    
+    LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: tcp_ticks=%"U32_F" iss=%"U32_F"\n", tcp_ticks, iss));
 
     pcb->polltmr = 0;
 
@@ -1278,6 +1343,8 @@
 {
 #if LWIP_CALLBACK_API
   pcb->poll = poll;
+#else /* LWIP_CALLBACK_API */  
+  LWIP_UNUSED_ARG(poll);
 #endif /* LWIP_CALLBACK_API */  
   pcb->pollinterval = interval;
 }
@@ -1329,7 +1396,7 @@
     if (pcb->unacked != NULL) {
       LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->unacked\n"));
     }
-#if TCP_QUEUE_OOSEQ /* LW */
+#if TCP_QUEUE_OOSEQ
     if (pcb->ooseq != NULL) {
       LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n"));
     }
--- a/lwip/core/tcp_in.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/core/tcp_in.c	Tue Jul 27 15:59:42 2010 +0000
@@ -93,6 +93,10 @@
 {
   struct tcp_pcb *pcb, *prev;
   struct tcp_pcb_listen *lpcb;
+#if SO_REUSE
+  struct tcp_pcb *lpcb_prev = NULL;
+  struct tcp_pcb_listen *lpcb_any = NULL;
+#endif /* SO_REUSE */
   u8_t hdrlen;
   err_t err;
 
@@ -120,8 +124,8 @@
   }
 
   /* Don't even process incoming broadcasts/multicasts. */
-  if (ip_addr_isbroadcast(&(iphdr->dest), inp) ||
-      ip_addr_ismulticast(&(iphdr->dest))) {
+  if (ip_addr_isbroadcast(&current_iphdr_dest, inp) ||
+      ip_addr_ismulticast(&current_iphdr_dest)) {
     TCP_STATS_INC(tcp.proterr);
     TCP_STATS_INC(tcp.drop);
     snmp_inc_tcpinerrs();
@@ -131,10 +135,10 @@
 
 #if CHECKSUM_CHECK_TCP
   /* Verify TCP checksum. */
-  if (inet_chksum_pseudo(p, &iphdr->src, &iphdr->dest,
+  if (inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(),
       IP_PROTO_TCP, p->tot_len) != 0) {
       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n",
-        inet_chksum_pseudo(p, &iphdr->src, &iphdr->dest,
+        inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(),
       IP_PROTO_TCP, p->tot_len)));
 #if TCP_DEBUG
     tcp_debug_print(tcphdr);
@@ -181,8 +185,8 @@
     LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
     if (pcb->remote_port == tcphdr->src &&
        pcb->local_port == tcphdr->dest &&
-       ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
-       ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
+       ip_addr_cmp(&(pcb->remote_ip), &current_iphdr_src) &&
+       ip_addr_cmp(&(pcb->local_ip), &current_iphdr_dest)) {
 
       /* Move this PCB to the front of the list so that subsequent
          lookups will be faster (we exploit locality in TCP segment
@@ -206,8 +210,8 @@
       LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
       if (pcb->remote_port == tcphdr->src &&
          pcb->local_port == tcphdr->dest &&
-         ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
-         ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
+         ip_addr_cmp(&(pcb->remote_ip), &current_iphdr_src) &&
+         ip_addr_cmp(&(pcb->local_ip), &current_iphdr_dest)) {
         /* We don't really care enough to move this PCB to the front
            of the list since we are not very likely to receive that
            many segments for connections in TIME-WAIT. */
@@ -218,31 +222,55 @@
       }
     }
 
-  /* Finally, if we still did not get a match, we check all PCBs that
-     are LISTENing for incoming connections. */
+    /* Finally, if we still did not get a match, we check all PCBs that
+       are LISTENing for incoming connections. */
     prev = NULL;
     for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
-      if ((ip_addr_isany(&(lpcb->local_ip)) ||
-        ip_addr_cmp(&(lpcb->local_ip), &(iphdr->dest))) &&
-        lpcb->local_port == tcphdr->dest) {
-        /* Move this PCB to the front of the list so that subsequent
-           lookups will be faster (we exploit locality in TCP segment
-           arrivals). */
-        if (prev != NULL) {
-          ((struct tcp_pcb_listen *)prev)->next = lpcb->next;
-                /* our successor is the remainder of the listening list */
-          lpcb->next = tcp_listen_pcbs.listen_pcbs;
-                /* put this listening pcb at the head of the listening list */
-          tcp_listen_pcbs.listen_pcbs = lpcb;
+      if (lpcb->local_port == tcphdr->dest) {
+#if SO_REUSE
+        if (ip_addr_cmp(&(lpcb->local_ip), &current_iphdr_dest)) {
+          /* found an exact match */
+          break;
+        } else if(ip_addr_isany(&(lpcb->local_ip))) {
+          /* found an ANY-match */
+          lpcb_any = lpcb;
+          lpcb_prev = prev;
         }
-      
-        LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));
-        tcp_listen_input(lpcb);
-        pbuf_free(p);
-        return;
+#else /* SO_REUSE */
+        if (ip_addr_cmp(&(lpcb->local_ip), &current_iphdr_dest) ||
+            ip_addr_isany(&(lpcb->local_ip))) {
+          /* found a match */
+          break;
+        }
+#endif /* SO_REUSE */
       }
       prev = (struct tcp_pcb *)lpcb;
     }
+#if SO_REUSE
+    /* first try specific local IP */
+    if (lpcb == NULL) {
+      /* only pass to ANY if no specific local IP has been found */
+      lpcb = lpcb_any;
+      prev = lpcb_prev;
+    }
+#endif /* SO_REUSE */
+    if (lpcb != NULL) {
+      /* Move this PCB to the front of the list so that subsequent
+         lookups will be faster (we exploit locality in TCP segment
+         arrivals). */
+      if (prev != NULL) {
+        ((struct tcp_pcb_listen *)prev)->next = lpcb->next;
+              /* our successor is the remainder of the listening list */
+        lpcb->next = tcp_listen_pcbs.listen_pcbs;
+              /* put this listening pcb at the head of the listening list */
+        tcp_listen_pcbs.listen_pcbs = lpcb;
+      }
+    
+      LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));
+      tcp_listen_input(lpcb);
+      pbuf_free(p);
+      return;
+    }
   }
 
 #if TCP_INPUT_DEBUG
@@ -318,7 +346,14 @@
         }
 
         if (recv_data != NULL) {
-          if(flags & TCP_PSH) {
+          if (pcb->flags & TF_RXCLOSED) {
+            /* received data although already closed -> abort (send RST) to
+               notify the remote host that not all data has been processed */
+            pbuf_free(recv_data);
+            tcp_abort(pcb);
+            goto aborted;
+          }
+          if (flags & TCP_PSH) {
             recv_data->flags |= PBUF_FLAG_PUSH;
           }
 
@@ -343,7 +378,7 @@
           if (pcb->rcv_wnd != TCP_WND) {
             pcb->rcv_wnd++;
           }
-          TCP_EVENT_RECV(pcb, NULL, ERR_OK, err);
+          TCP_EVENT_CLOSED(pcb, err);
           if (err == ERR_ABRT) {
             goto aborted;
           }
@@ -363,7 +398,7 @@
        Below this line, 'pcb' may not be dereferenced! */
 aborted:
     tcp_input_pcb = NULL;
-
+    recv_data = NULL;
 
     /* give up our reference to inseg.p */
     if (inseg.p != NULL)
@@ -380,7 +415,7 @@
       TCP_STATS_INC(tcp.proterr);
       TCP_STATS_INC(tcp.drop);
       tcp_rst(ackno, seqno + tcplen,
-        &(iphdr->dest), &(iphdr->src),
+        ip_current_dest_addr(), ip_current_src_addr(),
         tcphdr->dest, tcphdr->src);
     }
     pbuf_free(p);
@@ -415,7 +450,7 @@
        RST. */
     LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
     tcp_rst(ackno + 1, seqno + tcplen,
-      &(iphdr->dest), &(iphdr->src),
+      ip_current_dest_addr(), ip_current_src_addr(),
       tcphdr->dest, tcphdr->src);
   } else if (flags & TCP_SYN) {
     LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
@@ -438,9 +473,9 @@
     pcb->accepts_pending++;
 #endif /* TCP_LISTEN_BACKLOG */
     /* Set up the new PCB. */
-    ip_addr_copy(npcb->local_ip, iphdr->dest);
+    ip_addr_copy(npcb->local_ip, current_iphdr_dest);
     npcb->local_port = pcb->local_port;
-    ip_addr_copy(npcb->remote_ip, iphdr->src);
+    ip_addr_copy(npcb->remote_ip, current_iphdr_src);
     npcb->remote_port = tcphdr->src;
     npcb->state = SYN_RCVD;
     npcb->rcv_nxt = seqno + 1;
@@ -453,7 +488,7 @@
     npcb->accept = pcb->accept;
 #endif /* LWIP_CALLBACK_API */
     /* inherit socket options */
-    npcb->so_options = pcb->so_options & (SOF_DEBUG|SOF_DONTROUTE|SOF_KEEPALIVE|SOF_OOBINLINE|SOF_LINGER);
+    npcb->so_options = pcb->so_options & SOF_INHERITED;
     /* Register the new PCB so that we can begin receiving segments
        for it. */
     TCP_REG(&tcp_active_pcbs, npcb);
@@ -503,7 +538,7 @@
        should be sent in reply */
     if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) {
       /* If the SYN is in the window it is an error, send a reset */
-      tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
+      tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
         tcphdr->dest, tcphdr->src);
       return ERR_OK;
     }
@@ -637,7 +672,7 @@
     /* received ACK? possibly a half-open connection */
     else if (flags & TCP_ACK) {
       /* send a RST to bring the other side in a non-synchronized state. */
-      tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
+      tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
         tcphdr->dest, tcphdr->src);
     }
     break;
@@ -680,7 +715,7 @@
         }
       } else {
         /* incorrect ACK number, send RST */
-        tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
+        tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
                 tcphdr->dest, tcphdr->src);
       }
     } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) {
@@ -1402,6 +1437,24 @@
                     next->len = (u16_t)(seqno - next->tcphdr->seqno);
                     pbuf_realloc(next->p, next->len);
                   }
+                  /* check if the remote side overruns our receive window */
+                  if ((u32_t)tcplen + seqno > pcb->rcv_nxt + (u32_t)pcb->rcv_wnd) {
+                    LWIP_DEBUGF(TCP_INPUT_DEBUG, 
+                                ("tcp_receive: other end overran receive window"
+                                 "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n",
+                                 seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
+                    if (TCPH_FLAGS(next->next->tcphdr) & TCP_FIN) {
+                      /* Must remove the FIN from the header as we're trimming 
+                       * that byte of sequence-space from the packet */
+                      TCPH_FLAGS_SET(next->next->tcphdr, TCPH_FLAGS(next->next->tcphdr) &~ TCP_FIN);
+                    }
+                    /* Adjust length of segment to fit in the window. */
+                    next->next->len = pcb->rcv_nxt + pcb->rcv_wnd - seqno;
+                    pbuf_realloc(next->next->p, next->next->len);
+                    tcplen = TCP_TCPLEN(next->next);
+                    LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n",
+                                (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd));
+                  }
                 }
                 break;
               }
--- a/lwip/core/tcp_out.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/core/tcp_out.c	Tue Jul 27 15:59:42 2010 +0000
@@ -221,6 +221,14 @@
   struct pbuf *p;
   u16_t alloc = length;
 
+#if LWIP_NETIF_TX_SINGLE_PBUF
+  LWIP_UNUSED_ARG(max_length);
+  LWIP_UNUSED_ARG(pcb);
+  LWIP_UNUSED_ARG(apiflags);
+  LWIP_UNUSED_ARG(first_seg);
+  /* always create MSS-sized pbufs */
+  alloc = TCP_MSS;
+#else /* LWIP_NETIF_TX_SINGLE_PBUF */
   if (length < max_length) {
     /* Should we allocate an oversized pbuf, or just the minimum
      * length required? If tcp_write is going to be called again
@@ -241,6 +249,7 @@
       alloc = LWIP_MIN(max_length, LWIP_MEM_ALIGN_SIZE(length + TCP_OVERSIZE));
     }
   }
+#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
   p = pbuf_alloc(layer, alloc, PBUF_RAM);
   if (p == NULL) {
     return NULL;
@@ -273,6 +282,56 @@
 }
 #endif /* TCP_CHECKSUM_ON_COPY */
 
+/** Checks if tcp_write is allowed or not (checks state, snd_buf and snd_queuelen).
+ *
+ * @param pcb the tcp pcb to check for
+ * @param len length of data to send (checked agains snd_buf)
+ * @return ERR_OK if tcp_write is allowed to proceed, another err_t otherwise
+ */
+static err_t
+tcp_write_checks(struct tcp_pcb *pcb, u16_t len)
+{
+  /* connection is in invalid state for data transmission? */
+  if ((pcb->state != ESTABLISHED) &&
+      (pcb->state != CLOSE_WAIT) &&
+      (pcb->state != SYN_SENT) &&
+      (pcb->state != SYN_RCVD)) {
+    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n"));
+    return ERR_CONN;
+  } else if (len == 0) {
+    return ERR_OK;
+  }
+
+  /* fail on too much data */
+  if (len > pcb->snd_buf) {
+    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_write: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n",
+      len, pcb->snd_buf));
+    pcb->flags |= TF_NAGLEMEMERR;
+    return ERR_MEM;
+  }
+
+  LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen));
+
+  /* If total number of pbufs on the unsent/unacked queues exceeds the
+   * configured maximum, return an error */
+  /* check for configured max queuelen and possible overflow */
+  if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
+    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_write: too long queue %"U16_F" (max %"U16_F")\n",
+      pcb->snd_queuelen, TCP_SND_QUEUELEN));
+    TCP_STATS_INC(tcp.memerr);
+    pcb->flags |= TF_NAGLEMEMERR;
+    return ERR_MEM;
+  }
+  if (pcb->snd_queuelen != 0) {
+    LWIP_ASSERT("tcp_write: pbufs on queue => at least one queue non-empty",
+      pcb->unacked != NULL || pcb->unsent != NULL);
+  } else {
+    LWIP_ASSERT("tcp_write: no pbufs on queue => both queues empty",
+      pcb->unacked == NULL && pcb->unsent == NULL);
+  }
+  return ERR_OK;
+}
+
 /**
  * Write data for sending (but does not send it immediately).
  *
@@ -307,6 +366,7 @@
   u8_t concat_chksum_swapped = 0;
   u16_t concat_chksummed = 0;
 #endif /* TCP_CHECKSUM_ON_COPY */
+  err_t err;
 
 #if LWIP_NETIF_TX_SINGLE_PBUF
   /* Always copy to try to create single pbufs for TX */
@@ -315,50 +375,14 @@
 
   LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n",
     (void *)pcb, arg, len, (u16_t)apiflags));
-  /* connection is in invalid state for data transmission? */
-  if ((pcb->state != ESTABLISHED) &&
-      (pcb->state != CLOSE_WAIT) &&
-      (pcb->state != SYN_SENT) &&
-      (pcb->state != SYN_RCVD)) {
-    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n"));
-    return ERR_CONN;
-  } else if (len == 0) {
-    return ERR_OK;
-  }
-
-  LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, arg=%p, len=%"U16_F", apiflags=%"U16_F")\n",
-    (void *)pcb, arg, len, (u16_t)apiflags));
   LWIP_ERROR("tcp_write: arg == NULL (programmer violates API)", 
              arg != NULL, return ERR_ARG;);
 
-  /* fail on too much data */
-  if (len > pcb->snd_buf) {
-    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_write: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n",
-      len, pcb->snd_buf));
-    pcb->flags |= TF_NAGLEMEMERR;
-    return ERR_MEM;
+  err = tcp_write_checks(pcb, len);
+  if (err != ERR_OK) {
+    return err;
   }
-
-  LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen));
-
-  /* If total number of pbufs on the unsent/unacked queues exceeds the
-   * configured maximum, return an error */
   queuelen = pcb->snd_queuelen;
-  /* check for configured max queuelen and possible overflow */
-  if ((queuelen >= TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
-    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_write: too long queue %"U16_F" (max %"U16_F")\n",
-      queuelen, TCP_SND_QUEUELEN));
-    TCP_STATS_INC(tcp.memerr);
-    pcb->flags |= TF_NAGLEMEMERR;
-    return ERR_MEM;
-  }
-  if (queuelen != 0) {
-    LWIP_ASSERT("tcp_write: pbufs on queue => at least one queue non-empty",
-      pcb->unacked != NULL || pcb->unsent != NULL);
-  } else {
-    LWIP_ASSERT("tcp_write: no pbufs on queue => both queues empty",
-      pcb->unacked == NULL && pcb->unsent == NULL);
-  }
 
 #if LWIP_TCP_TIMESTAMPS
   if ((pcb->flags & TF_TIMESTAMP)) {
@@ -802,7 +826,7 @@
 tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts)
 {
   /* Pad with two NOP options to make everything nicely aligned */
-  opts[0] = htonl(0x0101080A);
+  opts[0] = PP_HTONL(0x0101080A);
   opts[1] = htonl(sys_now());
   opts[2] = htonl(pcb->ts_recent);
 }
@@ -961,7 +985,12 @@
     }
 
     tcp_output_segment(seg, pcb);
+       
     snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
+    
+    LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: pcb->snd_nxt was %"U32_F" seqno=%"U32_F" len=%"U32_F" new snd_nxt=%"U32_F"\n", //DG
+                                    pcb->snd_nxt, ntohl(seg->tcphdr->seqno), TCP_TCPLEN(seg), snd_nxt));
+    
     if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
       pcb->snd_nxt = snd_nxt;
     }
@@ -1132,6 +1161,9 @@
 #endif /* TCP_CHECKSUM_ON_COPY */
 #endif /* CHECKSUM_GEN_TCP */
   TCP_STATS_INC(tcp.xmit);
+  
+  LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: Before ip_out seqno = %"U32_F"\n",
+        htonl(seg->tcphdr->seqno))); //DG
 
 #if LWIP_NETIF_HWADDRHINT
   ip_output_hinted(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
@@ -1140,6 +1172,11 @@
   ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
       IP_PROTO_TCP);
 #endif /* LWIP_NETIF_HWADDRHINT*/
+
+  LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: After ip_out seqno = %"U32_F"\n",
+        htonl(seg->tcphdr->seqno))); //DG
+
+
 }
 
 /**
@@ -1183,7 +1220,7 @@
   tcphdr->seqno = htonl(seqno);
   tcphdr->ackno = htonl(ackno);
   TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK);
-  tcphdr->wnd = htons(TCP_WND);
+  tcphdr->wnd = PP_HTONS(TCP_WND);
   tcphdr->chksum = 0;
   tcphdr->urgp = 0;
 
--- a/lwip/core/timers.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/core/timers.c	Tue Jul 27 15:59:42 2010 +0000
@@ -42,6 +42,9 @@
 #include "lwip/opt.h"
 
 #include "lwip/timers.h"
+
+#if LWIP_TIMERS
+
 #include "lwip/def.h"
 #include "lwip/memp.h"
 #include "lwip/tcpip.h"
@@ -250,15 +253,15 @@
  * - by calling sys_check_timeouts() (NO_SYS==1 only)
  *
  * @param msecs time in milliseconds after that the timer should expire
- * @param h callback function to call when msecs have elapsed
+ * @param handler callback function to call when msecs have elapsed
  * @param arg argument to pass to the callback function
  */
 #if LWIP_DEBUG_TIMERNAMES
 void
-sys_timeout_debug(u32_t msecs, sys_timeout_handler h, void *arg, const char* handler_name)
+sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name)
 #else /* LWIP_DEBUG_TIMERNAMES */
 void
-sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
+sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg)
 #endif /* LWIP_DEBUG_TIMERNAMES */
 {
   struct sys_timeo *timeout, *t;
@@ -269,19 +272,13 @@
     return;
   }
   timeout->next = NULL;
-  timeout->h = h;
+  timeout->h = handler;
   timeout->arg = arg;
   timeout->time = msecs;
 #if LWIP_DEBUG_TIMERNAMES
   timeout->handler_name = handler_name;
-#endif /* LWIP_DEBUG_TIMERNAMES */
-
-#if LWIP_DEBUG_TIMERNAMES
-  LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" h=%p arg=%p name=%s\n",
-    (void *)timeout, msecs, *(void**)&h, (void *)arg, handler_name));
-#else /* LWIP_DEBUG_TIMERNAMES */
-  LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" h=%p arg=%p\n",
-    (void *)timeout, msecs, *(void**)&h, (void *)arg));
+  LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" handler=%s arg=%p\n",
+    (void *)timeout, msecs, handler_name, (void *)arg));
 #endif /* LWIP_DEBUG_TIMERNAMES */
 
   if (next_timeout == NULL) {
@@ -313,13 +310,13 @@
  * entry, even though the timeout has not triggered yet.
  *
  * @note This function only works as expected if there is only one timeout
- * calling 'h' in the list of timeouts.
+ * calling 'handler' in the list of timeouts.
  *
- * @param h callback function that would be called by the timeout
- * @param arg callback argument that would be passed to h
+ * @param handler callback function that would be called by the timeout
+ * @param arg callback argument that would be passed to handler
 */
 void
-sys_untimeout(sys_timeout_handler h, void *arg)
+sys_untimeout(sys_timeout_handler handler, void *arg)
 {
   struct sys_timeo *prev_t, *t;
 
@@ -328,7 +325,7 @@
   }
 
   for (t = next_timeout, prev_t = NULL; t != NULL; prev_t = t, t = t->next) {
-    if ((t->h == h) && (t->arg == arg)) {
+    if ((t->h == handler) && (t->arg == arg)) {
       /* We have a match */
       /* Unlink from previous in list */
       if (prev_t == NULL) {
@@ -360,18 +357,15 @@
 {
   struct sys_timeo *tmptimeout;
   u32_t diff;
-  sys_timeout_handler h;
+  sys_timeout_handler handler;
   void *arg;
   int had_one;
   u32_t now;
-#if LWIP_DEBUG_TIMERNAMES
-  const char *handler_name;
-#endif /* LWIP_DEBUG_TIMERNAMES */
 
   now = sys_now();
   if (next_timeout) {
-    /* @todo: wrap around? */
-    diff = now - timeouts_last_time;
+    /* this cares for wraparounds */
+    diff = LWIP_U32_DIFF(now, timeouts_last_time);
     do
     {
       had_one = 0;
@@ -382,19 +376,17 @@
         timeouts_last_time = now;
         diff -= tmptimeout->time;
         next_timeout = tmptimeout->next;
-        h   = tmptimeout->h;
+        handler = tmptimeout->h;
         arg = tmptimeout->arg;
 #if LWIP_DEBUG_TIMERNAMES
-        handler_name = tmptimeout->handler_name;
+        if (handler != NULL) {
+          LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s arg=%p\n",
+            tmptimeout->handler_name, arg));
+        }
 #endif /* LWIP_DEBUG_TIMERNAMES */
         memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
-        if (h != NULL) {
-#if LWIP_DEBUG_TIMERNAMES
-          LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%p(%p) (%s)\n", *(void**)&h, arg, handler_name));
-#else /* LWIP_DEBUG_TIMERNAMES */
-          LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%p(%p)\n", *(void**)&h, arg));
-#endif /* LWIP_DEBUG_TIMERNAMES */
-          h(arg);
+        if (handler != NULL) {
+          handler(arg);
         }
       }
     /* repeat until all expired timers have been called */
@@ -427,11 +419,8 @@
 {
   u32_t time_needed;
   struct sys_timeo *tmptimeout;
-  sys_timeout_handler h;
+  sys_timeout_handler handler;
   void *arg;
-#if LWIP_DEBUG_TIMERNAMES
-  const char *handler_name;
-#endif /* LWIP_DEBUG_TIMERNAMES */
 
  again:
   if (!next_timeout) {
@@ -449,24 +438,23 @@
          deallocate the memory allocated for the timeout. */
       tmptimeout = next_timeout;
       next_timeout = tmptimeout->next;
-      h   = tmptimeout->h;
+      handler = tmptimeout->h;
       arg = tmptimeout->arg;
 #if LWIP_DEBUG_TIMERNAMES
-      handler_name = tmptimeout->handler_name;
+      if (handler != NULL) {
+        LWIP_DEBUGF(TIMERS_DEBUG, ("stmf calling h=%s arg=%p\n",
+          tmptimeout->handler_name, arg));
+      }
 #endif /* LWIP_DEBUG_TIMERNAMES */
       memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
-      if (h != NULL) {
-#if LWIP_DEBUG_TIMERNAMES
-        LWIP_DEBUGF(TIMERS_DEBUG, ("stmf calling h=%p(%p) (%s)\n", *(void**)&h, arg, handler_name));
-#else /* LWIP_DEBUG_TIMERNAMES */
-        LWIP_DEBUGF(TIMERS_DEBUG, ("stmf calling h=%p(%p)\n", *(void**)&h, arg));
-#endif /* LWIP_DEBUG_TIMERNAMES */
+      if (handler != NULL) {
         /* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the
            timeout handler function. */
         LOCK_TCPIP_CORE();
-        h(arg);
+        handler(arg);
         UNLOCK_TCPIP_CORE();
       }
+      LWIP_TCPIP_THREAD_ALIVE();
 
       /* We try again to fetch a message from the mbox. */
       goto again;
@@ -484,3 +472,11 @@
 }
 
 #endif /* NO_SYS */
+
+#else /* LWIP_TIMERS */
+/* Satisfy the TCP code which calls this function */
+void
+tcp_timer_needed(void)
+{
+}
+#endif /* LWIP_TIMERS */
--- a/lwip/core/udp.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/core/udp.c	Tue Jul 27 15:59:42 2010 +0000
@@ -113,7 +113,7 @@
   udphdr = (struct udp_hdr *)p->payload;
 
   /* is broadcast packet ? */
-  broadcast = ip_addr_isbroadcast(&(iphdr->dest), inp);
+  broadcast = ip_addr_isbroadcast(&current_iphdr_dest, inp);
 
   LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len));
 
@@ -144,7 +144,7 @@
            (- broadcast or directed to us) -> DHCP is link-layer-addressed, local ip is always ANY!
            - inp->dhcp->pcb->remote == ANY or iphdr->src */
         if ((ip_addr_isany(&inp->dhcp->pcb->remote_ip) ||
-           ip_addr_cmp(&(inp->dhcp->pcb->remote_ip), &(iphdr->src)))) {
+           ip_addr_cmp(&(inp->dhcp->pcb->remote_ip), &current_iphdr_src))) {
           pcb = inp->dhcp->pcb;
         }
       }
@@ -173,9 +173,9 @@
       /* compare PCB local addr+port to UDP destination addr+port */
       if ((pcb->local_port == dest) &&
           ((!broadcast && ip_addr_isany(&pcb->local_ip)) ||
-           ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)) ||
+           ip_addr_cmp(&(pcb->local_ip), &current_iphdr_dest) ||
 #if LWIP_IGMP
-           ip_addr_ismulticast(&(iphdr->dest)) ||
+           ip_addr_ismulticast(&current_iphdr_dest) ||
 #endif /* LWIP_IGMP */
 #if IP_SOF_BROADCAST_RECV
            (broadcast && (pcb->so_options & SOF_BROADCAST)))) {
@@ -193,7 +193,7 @@
       if ((local_match != 0) &&
           (pcb->remote_port == src) &&
           (ip_addr_isany(&pcb->remote_ip) ||
-           ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)))) {
+           ip_addr_cmp(&(pcb->remote_ip), &current_iphdr_src))) {
         /* the first fully matching PCB */
         if (prev != NULL) {
           /* move the pcb to the front of udp_pcbs so that is
@@ -215,7 +215,7 @@
   }
 
   /* Check checksum if this is a match or if it was directed at us. */
-  if (pcb != NULL || ip_addr_cmp(&inp->ip_addr, &iphdr->dest)) {
+  if (pcb != NULL || ip_addr_cmp(&inp->ip_addr, &current_iphdr_dest)) {
     LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: calculating checksum\n"));
 #if LWIP_UDPLITE
     if (IPH_PROTO(iphdr) == IP_PROTO_UDPLITE) {
@@ -237,7 +237,7 @@
           goto end;
         }
       }
-      if (inet_chksum_pseudo_partial(p, &iphdr->src, &iphdr->dest,
+      if (inet_chksum_pseudo_partial(p, &current_iphdr_src, &current_iphdr_dest,
                              IP_PROTO_UDPLITE, p->tot_len, chklen) != 0) {
        LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
                    ("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
@@ -253,7 +253,7 @@
     {
 #if CHECKSUM_CHECK_UDP
       if (udphdr->chksum != 0) {
-        if (inet_chksum_pseudo(p, &iphdr->src, &iphdr->dest,
+        if (inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(),
                                IP_PROTO_UDP, p->tot_len) != 0) {
           LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
                       ("udp_input: UDP datagram discarded due to failing checksum\n"));
@@ -276,10 +276,58 @@
     }
     if (pcb != NULL) {
       snmp_inc_udpindatagrams();
+#if SO_REUSE && SO_REUSE_RXTOALL
+      if ((broadcast || ip_addr_ismulticast(&current_iphdr_dest)) &&
+          ((pcb->so_options & SOF_REUSEADDR) != 0)) {
+        /* pass broadcast- or multicast packets to all multicast pcbs
+           if SOF_REUSEADDR is set on the first match */
+        struct udp_pcb *mpcb;
+        u8_t p_header_changed = 0;
+        for (mpcb = udp_pcbs; mpcb != NULL; mpcb = mpcb->next) {
+          if (mpcb != pcb) {
+            /* compare PCB local addr+port to UDP destination addr+port */
+            if ((mpcb->local_port == dest) &&
+                ((!broadcast && ip_addr_isany(&mpcb->local_ip)) ||
+                 ip_addr_cmp(&(mpcb->local_ip), &current_iphdr_dest) ||
+#if LWIP_IGMP
+                 ip_addr_ismulticast(&current_iphdr_dest) ||
+#endif /* LWIP_IGMP */
+#if IP_SOF_BROADCAST_RECV
+                 (broadcast && (mpcb->so_options & SOF_BROADCAST)))) {
+#else  /* IP_SOF_BROADCAST_RECV */
+                 (broadcast))) {
+#endif /* IP_SOF_BROADCAST_RECV */
+              /* pass a copy of the packet to all local matches */
+              if (mpcb->recv != NULL) {
+                struct pbuf *q;
+                /* for that, move payload to IP header again */
+                if (p_header_changed == 0) {
+                  pbuf_header(p, (s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
+                  p_header_changed = 1;
+                }
+                q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
+                if (q != NULL) {
+                  err_t err = pbuf_copy(q, p);
+                  if (err == ERR_OK) {
+                    /* move payload to UDP data */
+                    pbuf_header(q, -(s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
+                    mpcb->recv(mpcb->recv_arg, mpcb, q, ip_current_src_addr(), src);
+                  }
+                }
+              }
+            }
+          }
+        }
+        if (p_header_changed) {
+          /* and move payload to UDP data again */
+          pbuf_header(p, -(s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
+        }
+      }
+#endif /* SO_REUSE && SO_REUSE_RXTOALL */
       /* callback */
       if (pcb->recv != NULL) {
         /* now the recv function is responsible for freeing p */
-        pcb->recv(pcb->recv_arg, pcb, p, &iphdr->src, src);
+        pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr(), src);
       } else {
         /* no recv function registered? then we have to free the pbuf! */
         pbuf_free(p);
@@ -292,7 +340,7 @@
       /* No match was found, send ICMP destination port unreachable unless
          destination address was broadcast/multicast. */
       if (!broadcast &&
-          !ip_addr_ismulticast(&iphdr->dest)) {
+          !ip_addr_ismulticast(&current_iphdr_dest)) {
         /* move payload pointer back to ip header */
         pbuf_header(p, (IPH_HL(iphdr) * 4) + UDP_HLEN);
         LWIP_ASSERT("p->payload == iphdr", (p->payload == iphdr));
@@ -336,6 +384,19 @@
   return udp_sendto(pcb, p, &pcb->remote_ip, pcb->remote_port);
 }
 
+#if LWIP_CHECKSUM_ON_COPY
+/** Same as udp_send() but with checksum
+ */
+err_t
+udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p,
+                u8_t have_chksum, u16_t chksum)
+{
+  /* send to the packet using remote ip and port stored in the pcb */
+  return udp_sendto_chksum(pcb, p, &pcb->remote_ip, pcb->remote_port,
+    have_chksum, chksum);
+}
+#endif /* LWIP_CHECKSUM_ON_COPY */
+
 /**
  * Send data to a specified address using UDP.
  *
@@ -357,6 +418,16 @@
 udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
   ip_addr_t *dst_ip, u16_t dst_port)
 {
+#if LWIP_CHECKSUM_ON_COPY
+  return udp_sendto_chksum(pcb, p, dst_ip, dst_port, 0, 0);
+}
+
+/** Same as udp_sendto(), but with checksum */
+err_t
+udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
+                  u16_t dst_port, u8_t have_chksum, u16_t chksum)
+{
+#endif /* LWIP_CHECKSUM_ON_COPY */
   struct netif *netif;
 
   LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n"));
@@ -375,7 +446,11 @@
     UDP_STATS_INC(udp.rterr);
     return ERR_RTE;
   }
+#if LWIP_CHECKSUM_ON_COPY
+  return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum);
+#else /* LWIP_CHECKSUM_ON_COPY */
   return udp_sendto_if(pcb, p, dst_ip, dst_port, netif);
+#endif /* LWIP_CHECKSUM_ON_COPY */
 }
 
 /**
@@ -401,6 +476,17 @@
 udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
   ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif)
 {
+#if LWIP_CHECKSUM_ON_COPY
+  return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0);
+}
+
+/** Same as udp_sendto_if(), but with checksum */
+err_t
+udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
+                     u16_t dst_port, struct netif *netif, u8_t have_chksum,
+                     u16_t chksum)
+{
+#endif /* LWIP_CHECKSUM_ON_COPY */
   struct udp_hdr *udphdr;
   ip_addr_t *src_ip;
   err_t err;
@@ -454,6 +540,14 @@
   /* in UDP, 0 checksum means 'no checksum' */
   udphdr->chksum = 0x0000; 
 
+  /* Multicast Loop? */
+#if LWIP_IGMP
+  if (ip_addr_ismulticast(dst_ip) && ((pcb->flags & UDP_FLAGS_MULTICAST_LOOP) != 0)) {
+    q->flags |= PBUF_FLAG_MCASTLOOP;
+  }
+#endif /* LWIP_IGMP */
+
+
   /* PCB local address is IP_ANY_ADDR? */
   if (ip_addr_isany(&pcb->local_ip)) {
     /* use outgoing network interface IP address as source address */
@@ -501,7 +595,18 @@
     /* calculate checksum */
 #if CHECKSUM_GEN_UDP
     udphdr->chksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip,
-                                        IP_PROTO_UDPLITE, q->tot_len, chklen);
+      IP_PROTO_UDPLITE, q->tot_len,
+#if !LWIP_CHECKSUM_ON_COPY
+      chklen);
+#else /* !LWIP_CHECKSUM_ON_COPY */
+      (have_chksum ? UDP_HLEN : chklen));
+    if (have_chksum) {
+      u32_t acc;
+      acc = udphdr->chksum + (u16_t)~(chksum);
+      udphdr->chksum = FOLD_U32T(acc);
+    }
+#endif /* !LWIP_CHECKSUM_ON_COPY */
+
     /* chksum zero must become 0xffff, as zero means 'no checksum' */
     if (udphdr->chksum == 0x0000) {
       udphdr->chksum = 0xffff;
@@ -524,11 +629,25 @@
     /* calculate checksum */
 #if CHECKSUM_GEN_UDP
     if ((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
-      udphdr->chksum = inet_chksum_pseudo(q, src_ip, dst_ip, IP_PROTO_UDP, q->tot_len);
+      u16_t udpchksum;
+#if LWIP_CHECKSUM_ON_COPY
+      if (have_chksum) {
+        u32_t acc;
+        udpchksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip, IP_PROTO_UDP,
+          q->tot_len, UDP_HLEN);
+        acc = udpchksum + (u16_t)~(chksum);
+        udpchksum = FOLD_U32T(acc);
+      } else
+#endif /* LWIP_CHECKSUM_ON_COPY */
+      {
+        udpchksum = inet_chksum_pseudo(q, src_ip, dst_ip, IP_PROTO_UDP, q->tot_len);
+      }
+
       /* chksum zero must become 0xffff, as zero means 'no checksum' */
-      if (udphdr->chksum == 0x0000) {
-        udphdr->chksum = 0xffff;
+      if (udpchksum == 0x0000) {
+        udpchksum = 0xffff;
       }
+      udphdr->chksum = udpchksum;
     }
 #endif /* CHECKSUM_GEN_UDP */
     LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum));
@@ -597,13 +716,16 @@
       rebind = 1;
     }
 
-    /* this code does not allow upper layer to share a UDP port for
-       listening to broadcast or multicast traffic (See SO_REUSEADDR and
-       SO_REUSEPORT under *BSD). TODO: See where it fits instead, OR
-       combine with implementation of UDP PCB flags. Leon Woestenberg. */
-#ifdef LWIP_UDP_TODO
-    /* port matches that of PCB in list? */
+    /* By default, we don't allow to bind to a port that any other udp
+       PCB is alread bound to, unless *all* PCBs with that port have tha
+       REUSEADDR flag set. */
+#if SO_REUSE
+    else if (((pcb->so_options & SOF_REUSEADDR) == 0) &&
+             ((ipcb->so_options & SOF_REUSEADDR) == 0)) {
+#else /* SO_REUSE */
+    /* port matches that of PCB in list and REUSEADDR not set -> reject */
     else {
+#endif /* SO_REUSE */
       if ((ipcb->local_port == port) &&
           /* IP address matches, or one is IP_ADDR_ANY? */
           (ip_addr_isany(&(ipcb->local_ip)) ||
@@ -615,7 +737,6 @@
         return ERR_USE;
       }
     }
-#endif
   }
 
   ip_addr_set(&pcb->local_ip, ipaddr);
--- a/lwip/include/ipv4/lwip/autoip.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/ipv4/lwip/autoip.h	Tue Jul 27 15:59:42 2010 +0000
@@ -80,7 +80,7 @@
 
 struct autoip
 {
-  ip_addr_t llipaddr;  /* the currently selected, probed, announced or used LL IP-Address */
+  ip_addr_t llipaddr;       /* the currently selected, probed, announced or used LL IP-Address */
   u8_t state;               /* current AutoIP state machine state */
   u8_t sent_num;            /* sent number of probes or announces, dependent on state */
   u16_t ttw;                /* ticks to wait, tick is AUTOIP_TMR_INTERVAL long */
--- a/lwip/include/ipv4/lwip/icmp.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/ipv4/lwip/icmp.h	Tue Jul 27 15:59:42 2010 +0000
@@ -70,7 +70,7 @@
 #ifdef PACK_STRUCT_USE_INCLUDES
 #  include "arch/bpstruct.h"
 #endif
-/** This is the standard ICMP header only that the u32_t data
+/*  This is the standard ICMP header only that the u32_t data
  *  is splitted to two u16_t like ICMP echo needs it.
  *  This header is also used for other ICMP types that do not
  *  use the data part.
@@ -91,7 +91,7 @@
 #define ICMPH_TYPE(hdr) ((hdr)->type)
 #define ICMPH_CODE(hdr) ((hdr)->code)
 
-/** Combines type and code to an u16_t */
+/*  Combines type and code to an u16_t */
 #define ICMPH_TYPE_SET(hdr, t) ((hdr)->type = (t))
 #define ICMPH_CODE_SET(hdr, c) ((hdr)->code = (c))
 
--- a/lwip/include/ipv4/lwip/inet.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/ipv4/lwip/inet.h	Tue Jul 27 15:59:42 2010 +0000
@@ -40,7 +40,7 @@
 extern "C" {
 #endif
 
-/** For compatibility with BSD code */
+/*  For compatibility with BSD code */
 struct in_addr {
   u32_t s_addr;
 };
@@ -91,6 +91,8 @@
 
 #define inet_addr_from_ipaddr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr))
 #define inet_addr_to_ipaddr(target_ipaddr, source_inaddr)   (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr))
+/* ATTENTION: the next define only works because both s_addr and ip_addr_t are an u32_t effectively! */
+#define inet_addr_to_ipaddr_p(target_ipaddr_p, source_inaddr)   ((target_ipaddr_p) = (ip_addr_t*)&((source_inaddr)->s_addr))
 
 /* directly map this to the lwip internal functions */
 #define inet_addr(cp)         ipaddr_addr(cp)
--- a/lwip/include/ipv4/lwip/ip.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/ipv4/lwip/ip.h	Tue Jul 27 15:59:42 2010 +0000
@@ -78,7 +78,7 @@
   ip_addr_t local_ip; \
   ip_addr_t remote_ip; \
    /* Socket options */  \
-  u16_t so_options;      \
+  u8_t so_options;      \
    /* Type Of Service */ \
   u8_t tos;              \
   /* Time To Live */     \
@@ -94,16 +94,19 @@
 /*
  * Option flags per-socket. These are the same like SO_XXX.
  */
-#define SOF_DEBUG       (u16_t)0x0001U    /* turn on debugging info recording */
-#define SOF_ACCEPTCONN  (u16_t)0x0002U    /* socket has had listen() */
-#define SOF_REUSEADDR   (u16_t)0x0004U    /* allow local address reuse */
-#define SOF_KEEPALIVE   (u16_t)0x0008U    /* keep connections alive */
-#define SOF_DONTROUTE   (u16_t)0x0010U    /* just use interface addresses */
-#define SOF_BROADCAST   (u16_t)0x0020U    /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */
-#define SOF_USELOOPBACK (u16_t)0x0040U    /* bypass hardware when possible */
-#define SOF_LINGER      (u16_t)0x0080U    /* linger on close if data present */
-#define SOF_OOBINLINE   (u16_t)0x0100U    /* leave received OOB data in line */
-#define SOF_REUSEPORT   (u16_t)0x0200U    /* allow local address & port reuse */
+/*#define SOF_DEBUG       (u8_t)0x01U     Unimplemented: turn on debugging info recording */
+#define SOF_ACCEPTCONN    (u8_t)0x02U  /* socket has had listen() */
+#define SOF_REUSEADDR     (u8_t)0x04U  /* allow local address reuse */
+#define SOF_KEEPALIVE     (u8_t)0x08U  /* keep connections alive */
+/*#define SOF_DONTROUTE   (u8_t)0x10U     Unimplemented: just use interface addresses */
+#define SOF_BROADCAST     (u8_t)0x20U  /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */
+/*#define SOF_USELOOPBACK (u8_t)0x40U     Unimplemented: bypass hardware when possible */
+#define SOF_LINGER        (u8_t)0x80U  /* linger on close if data present */
+/*#define SOF_OOBINLINE   (u16_t)0x0100U     Unimplemented: leave received OOB data in line */
+/*#define SOF_REUSEPORT   (u16_t)0x0200U     Unimplemented: allow local address & port reuse */
+
+/* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */
+#define SOF_INHERITED   (SOF_REUSEADDR|SOF_KEEPALIVE|SOF_LINGER/*|SOF_DEBUG|SOF_DONTROUTE|SOF_OOBINLINE*/)
 
 
 #ifdef PACK_STRUCT_USE_INCLUDES
@@ -130,8 +133,8 @@
   /* checksum */
   PACK_STRUCT_FIELD(u16_t _chksum);
   /* source and destination IP addresses */
-  PACK_STRUCT_FIELD(ip_addr_t src);
-  PACK_STRUCT_FIELD(ip_addr_t dest); 
+  PACK_STRUCT_FIELD(ip_addr_p_t src);
+  PACK_STRUCT_FIELD(ip_addr_p_t dest); 
 } PACK_STRUCT_STRUCT;
 PACK_STRUCT_END
 #ifdef PACK_STRUCT_USE_INCLUDES
@@ -160,6 +163,10 @@
 extern struct netif *current_netif;
 /** Header of the input packet currently being processed. */
 extern const struct ip_hdr *current_header;
+/** Source IP address of current_header */
+extern ip_addr_t current_iphdr_src;
+/** Destination IP address of current_header */
+extern ip_addr_t current_iphdr_dest;
 
 #define ip_init() /* Compatibility define, not init needed. */
 struct netif *ip_route(ip_addr_t *dest);
@@ -186,6 +193,11 @@
  * This function must only be called from a receive callback (udp_recv,
  * raw_recv, tcp_accept). It will return NULL otherwise. */
 #define ip_current_header() (current_header)
+/** Source IP address of current_header */
+#define ip_current_src_addr()  (&current_iphdr_src)
+/** Destination IP address of current_header */
+#define ip_current_dest_addr() (&current_iphdr_dest)
+
 #if IP_DEBUG
 void ip_debug_print(struct pbuf *p);
 #else
--- a/lwip/include/ipv4/lwip/ip_addr.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/ipv4/lwip/ip_addr.h	Tue Jul 27 15:59:42 2010 +0000
@@ -39,11 +39,19 @@
 extern "C" {
 #endif
 
+/* This is the aligned version of ip_addr_t,
+   used as local variable, on the stack, etc. */
+struct ip_addr {
+  u32_t addr;
+};
+
+/* This is the packed version of ip_addr_t,
+   used in network headers that are itself packed */
 #ifdef PACK_STRUCT_USE_INCLUDES
 #  include "arch/bpstruct.h"
 #endif
 PACK_STRUCT_BEGIN
-struct _ip_addr {
+struct ip_addr_packed {
   PACK_STRUCT_FIELD(u32_t addr);
 } PACK_STRUCT_STRUCT;
 PACK_STRUCT_END
@@ -51,7 +59,10 @@
 #  include "arch/epstruct.h"
 #endif
 
-typedef struct _ip_addr ip_addr_t;
+/** ip_addr_t uses a struct for convenience only, so that the same defines can
+ * operate both on ip_addr_t as well as on ip_addr_p_t. */
+typedef struct ip_addr ip_addr_t;
+typedef struct ip_addr_packed ip_addr_p_t;
 
 /*
  * struct ipaddr2 is used in the definition of the ARP packet format in
@@ -140,6 +151,13 @@
                           (u32_t)((a) & 0xff)
 #endif
 
+/** MEMCPY-like copying of IP addresses where addresses are known to be
+ * 16-bit-aligned if the port is correctly configured (so a port could define
+ * this to copying 2 u16_t's) - no NULL-pointer-checking needed. */
+#ifndef IPADDR2_COPY
+#define IPADDR2_COPY(dest, src) SMEMCPY(dest, src, sizeof(ip_addr_t))
+#endif
+
 /** Copy IP address - faster than ip_addr_set: no NULL check */
 #define ip_addr_copy(dest, src) ((dest).addr = (src).addr)
 /** Safely copy one IP address to another (src may be NULL) */
@@ -151,7 +169,7 @@
 /** Set address to IPADDR_ANY (no need for htonl()) */
 #define ip_addr_set_any(ipaddr)       ((ipaddr)->addr = IPADDR_ANY)
 /** Set address to loopback address */
-#define ip_addr_set_loopback(ipaddr)  ((ipaddr)->addr = htonl(IPADDR_LOOPBACK))
+#define ip_addr_set_loopback(ipaddr)  ((ipaddr)->addr = PP_HTONL(IPADDR_LOOPBACK))
 /** Safely copy one IP address to another and change byte order
  * from host- to network-order. */
 #define ip_addr_set_hton(dest, src) ((dest)->addr = \
@@ -181,11 +199,15 @@
 
 #define ip_addr_isany(addr1) ((addr1) == NULL || (addr1)->addr == IPADDR_ANY)
 
-u8_t ip_addr_isbroadcast(ip_addr_t *, struct netif *);
+#define ip_addr_isbroadcast(ipaddr, netif) ip4_addr_isbroadcast((ipaddr)->addr, (netif))
+u8_t ip4_addr_isbroadcast(u32_t addr, const struct netif *netif);
 
-#define ip_addr_ismulticast(addr1) (((addr1)->addr & ntohl(0xf0000000UL)) == ntohl(0xe0000000UL))
+#define ip_addr_netmask_valid(netmask) ip4_addr_netmask_valid((netmask)->addr)
+u8_t ip4_addr_netmask_valid(u32_t netmask);
 
-#define ip_addr_islinklocal(addr1) (((addr1)->addr & ntohl(0xffff0000UL)) == ntohl(0xa9fe0000UL))
+#define ip_addr_ismulticast(addr1) (((addr1)->addr & PP_HTONL(0xf0000000UL)) == PP_HTONL(0xe0000000UL))
+
+#define ip_addr_islinklocal(addr1) (((addr1)->addr & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xa9fe0000UL))
 
 #define ip_addr_debug_print(debug, ipaddr) \
   LWIP_DEBUGF(debug, ("%"U16_F".%"U16_F".%"U16_F".%"U16_F,             \
@@ -212,8 +234,8 @@
 u32_t ipaddr_addr(const char *cp);
 int ipaddr_aton(const char *cp, ip_addr_t *addr);
 /** returns ptr to static buffer; not reentrant! */
-char *ipaddr_ntoa(ip_addr_t *addr);
-char *ipaddr_ntoa_r(ip_addr_t *addr, char *buf, int buflen);
+char *ipaddr_ntoa(const ip_addr_t *addr);
+char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen);
 
 #ifdef __cplusplus
 }
--- a/lwip/include/ipv4/lwip/ip_frag.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/ipv4/lwip/ip_frag.h	Tue Jul 27 15:59:42 2010 +0000
@@ -66,6 +66,18 @@
 #endif /* IP_REASSEMBLY */
 
 #if IP_FRAG
+#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF
+/** A custom pbuf that holds a reference to another pbuf, which is freed
+ * when this custom pbuf is freed. This is used to create a custom PBUF_REF
+ * that points into the original pbuf. */
+struct pbuf_custom_ref {
+  /** 'base class' */
+  struct pbuf_custom pc;
+  /** pointer to the original pbuf that is referenced */
+  struct pbuf *original;
+};
+#endif /* !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */
+
 err_t ip_frag(struct pbuf *p, struct netif *netif, ip_addr_t *dest);
 #endif /* IP_FRAG */
 
--- a/lwip/include/lwip/api.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/lwip/api.h	Tue Jul 27 15:59:42 2010 +0000
@@ -150,9 +150,11 @@
   /** mbox where received packets are stored until they are fetched
       by the netconn application thread (can grow quite big) */
   sys_mbox_t recvmbox;
+#if LWIP_TCP
   /** mbox where new connections are stored until processed
       by the application thread */
   sys_mbox_t acceptmbox;
+#endif /* LWIP_TCP */
   /** only used for socket layer */
 #if LWIP_SOCKET
   int socket;
@@ -232,6 +234,7 @@
 err_t   netconn_write(struct netconn *conn, const void *dataptr, size_t size,
                       u8_t apiflags);
 err_t   netconn_close(struct netconn *conn);
+err_t   netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx);
 
 #if LWIP_IGMP
 err_t   netconn_join_leave_group(struct netconn *conn, ip_addr_t *multiaddr,
@@ -261,9 +264,9 @@
 #define netconn_get_noautorecved(conn)        (((conn)->flags & NETCONN_FLAG_NO_AUTO_RECVED) != 0)
 
 #if LWIP_SO_RCVTIMEO
-/** Set the receive timeout in miliseconds */
+/** Set the receive timeout in milliseconds */
 #define netconn_set_recvtimeout(conn, timeout)      ((conn)->recv_timeout = (timeout))
-/** Get the receive timeout in miliseconds */
+/** Get the receive timeout in milliseconds */
 #define netconn_get_recvtimeout(conn)               ((conn)->recv_timeout)
 #endif /* LWIP_SO_RCVTIMEO */
 #if LWIP_SO_RCVBUF
--- a/lwip/include/lwip/api_msg.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/lwip/api_msg.h	Tue Jul 27 15:59:42 2010 +0000
@@ -48,6 +48,10 @@
 extern "C" {
 #endif
 
+#define NETCONN_SHUT_RD   1
+#define NETCONN_SHUT_WR   2
+#define NETCONN_SHUT_RDWR 3
+
 /* IP addresses and port numbers are expected to be in
  * the same byte order as in the corresponding pcb.
  */
@@ -89,6 +93,10 @@
     struct {
       u32_t len;
     } r;
+    /** used for do_close (/shutdown) */
+    struct {
+      u8_t shut;
+    } sd;
 #if LWIP_IGMP
     /** used for do_join_leave_group */
     struct {
@@ -144,6 +152,7 @@
 void do_write           ( struct api_msg_msg *msg);
 void do_getaddr         ( struct api_msg_msg *msg);
 void do_close           ( struct api_msg_msg *msg);
+void do_shutdown        ( struct api_msg_msg *msg);
 #if LWIP_IGMP
 void do_join_leave_group( struct api_msg_msg *msg);
 #endif /* LWIP_IGMP */
--- a/lwip/include/lwip/def.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/lwip/def.h	Tue Jul 27 15:59:42 2010 +0000
@@ -39,6 +39,7 @@
 #ifdef __cplusplus
 extern "C" {
 #endif
+
 #define LWIP_MAX(x , y)  (((x) > (y)) ? (x) : (y))
 #define LWIP_MIN(x , y)  (((x) < (y)) ? (x) : (y))
 
--- a/lwip/include/lwip/dhcp.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/lwip/dhcp.h	Tue Jul 27 15:59:42 2010 +0000
@@ -80,10 +80,10 @@
   PACK_STRUCT_FIELD(u32_t xid);
   PACK_STRUCT_FIELD(u16_t secs);
   PACK_STRUCT_FIELD(u16_t flags);
-  PACK_STRUCT_FIELD(ip_addr_t ciaddr);
-  PACK_STRUCT_FIELD(ip_addr_t yiaddr);
-  PACK_STRUCT_FIELD(ip_addr_t siaddr);
-  PACK_STRUCT_FIELD(ip_addr_t giaddr);
+  PACK_STRUCT_FIELD(ip_addr_p_t ciaddr);
+  PACK_STRUCT_FIELD(ip_addr_p_t yiaddr);
+  PACK_STRUCT_FIELD(ip_addr_p_t siaddr);
+  PACK_STRUCT_FIELD(ip_addr_p_t giaddr);
   PACK_STRUCT_FIELD(u8_t chaddr[DHCP_CHADDR_LEN]);
   PACK_STRUCT_FIELD(u8_t sname[DHCP_SNAME_LEN]);
   PACK_STRUCT_FIELD(u8_t file[DHCP_FILE_LEN]);
--- a/lwip/include/lwip/dns.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/lwip/dns.h	Tue Jul 27 15:59:42 2010 +0000
@@ -1,116 +1,116 @@
-/**
- * lwip DNS resolver header file.
-
- * Author: Jim Pettinato 
- *   April 2007
-
- * ported from uIP resolv.c Copyright (c) 2002-2003, Adam Dunkels.
- *
- * 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. The name of the author may not be used to endorse or promote
- *    products derived from this software without specific prior
- *    written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
- */
-
-#ifndef __LWIP_DNS_H__
-#define __LWIP_DNS_H__
-
-#include "lwip/opt.h"
-
-#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
-
-/** DNS timer period */
-#define DNS_TMR_INTERVAL          1000
-
-/** DNS field TYPE used for "Resource Records" */
-#define DNS_RRTYPE_A              1     /* a host address */
-#define DNS_RRTYPE_NS             2     /* an authoritative name server */
-#define DNS_RRTYPE_MD             3     /* a mail destination (Obsolete - use MX) */
-#define DNS_RRTYPE_MF             4     /* a mail forwarder (Obsolete - use MX) */
-#define DNS_RRTYPE_CNAME          5     /* the canonical name for an alias */
-#define DNS_RRTYPE_SOA            6     /* marks the start of a zone of authority */
-#define DNS_RRTYPE_MB             7     /* a mailbox domain name (EXPERIMENTAL) */
-#define DNS_RRTYPE_MG             8     /* a mail group member (EXPERIMENTAL) */
-#define DNS_RRTYPE_MR             9     /* a mail rename domain name (EXPERIMENTAL) */
-#define DNS_RRTYPE_NULL           10    /* a null RR (EXPERIMENTAL) */
-#define DNS_RRTYPE_WKS            11    /* a well known service description */
-#define DNS_RRTYPE_PTR            12    /* a domain name pointer */
-#define DNS_RRTYPE_HINFO          13    /* host information */
-#define DNS_RRTYPE_MINFO          14    /* mailbox or mail list information */
-#define DNS_RRTYPE_MX             15    /* mail exchange */
-#define DNS_RRTYPE_TXT            16    /* text strings */
-
-/** DNS field CLASS used for "Resource Records" */
-#define DNS_RRCLASS_IN            1     /* the Internet */
-#define DNS_RRCLASS_CS            2     /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */
-#define DNS_RRCLASS_CH            3     /* the CHAOS class */
-#define DNS_RRCLASS_HS            4     /* Hesiod [Dyer 87] */
-#define DNS_RRCLASS_FLUSH         0x800 /* Flush bit */
-
-/* The size used for the next line is rather a hack, but it prevents including socket.h in all files
-   that include memp.h, and that would possibly break portability (since socket.h defines some types
-   and constants possibly already define by the OS).
-   Calculation rule:
-   sizeof(struct addrinfo) + sizeof(struct sockaddr_in) + DNS_MAX_NAME_LENGTH + 1 byte zero-termination */
-#define NETDB_ELEM_SIZE           (32 + 16 + DNS_MAX_NAME_LENGTH + 1)
-
-#if DNS_LOCAL_HOSTLIST
-/** struct used for local host-list */
-struct local_hostlist_entry {
-  /** static hostname */
-  const char *name;
-  /** static host address in network byteorder */
-  ip_addr_t addr;
-  struct local_hostlist_entry *next;
-};
-#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
-#ifndef DNS_LOCAL_HOSTLIST_MAX_NAMELEN
-#define DNS_LOCAL_HOSTLIST_MAX_NAMELEN  DNS_MAX_NAME_LENGTH
-#endif
-#define LOCALHOSTLIST_ELEM_SIZE ((sizeof(struct local_hostlist_entry) + DNS_LOCAL_HOSTLIST_MAX_NAMELEN + 1))
-#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
-#endif /* DNS_LOCAL_HOSTLIST */
-
-/** Callback which is invoked when a hostname is found.
- * A function of this type must be implemented by the application using the DNS resolver.
- * @param name pointer to the name that was looked up.
- * @param ipaddr pointer to an ip_addr_t containing the IP address of the hostname,
- *        or NULL if the name could not be found (or on any other error).
- * @param callback_arg a user-specified callback argument passed to dns_gethostbyname
-*/
-typedef void (*dns_found_callback)(const char *name, ip_addr_t *ipaddr, void *callback_arg);
-
-void           dns_init(void);
-void           dns_tmr(void);
-void           dns_setserver(u8_t numdns, ip_addr_t *dnsserver);
-ip_addr_t      dns_getserver(u8_t numdns);
-err_t          dns_gethostbyname(const char *hostname, ip_addr_t *addr,
-                                 dns_found_callback found, void *callback_arg);
-
-#if DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC
-int            dns_local_removehost(const char *hostname, const ip_addr_t *addr);
-err_t          dns_local_addhost(const char *hostname, const ip_addr_t *addr);
-#endif /* DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
-
-#endif /* LWIP_DNS */
-
-#endif /* __LWIP_DNS_H__ */
+/**
+ * lwip DNS resolver header file.
+
+ * Author: Jim Pettinato 
+ *   April 2007
+
+ * ported from uIP resolv.c Copyright (c) 2002-2003, Adam Dunkels.
+ *
+ * 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. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+#ifndef __LWIP_DNS_H__
+#define __LWIP_DNS_H__
+
+#include "lwip/opt.h"
+
+#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
+
+/** DNS timer period */
+#define DNS_TMR_INTERVAL          1000
+
+/** DNS field TYPE used for "Resource Records" */
+#define DNS_RRTYPE_A              1     /* a host address */
+#define DNS_RRTYPE_NS             2     /* an authoritative name server */
+#define DNS_RRTYPE_MD             3     /* a mail destination (Obsolete - use MX) */
+#define DNS_RRTYPE_MF             4     /* a mail forwarder (Obsolete - use MX) */
+#define DNS_RRTYPE_CNAME          5     /* the canonical name for an alias */
+#define DNS_RRTYPE_SOA            6     /* marks the start of a zone of authority */
+#define DNS_RRTYPE_MB             7     /* a mailbox domain name (EXPERIMENTAL) */
+#define DNS_RRTYPE_MG             8     /* a mail group member (EXPERIMENTAL) */
+#define DNS_RRTYPE_MR             9     /* a mail rename domain name (EXPERIMENTAL) */
+#define DNS_RRTYPE_NULL           10    /* a null RR (EXPERIMENTAL) */
+#define DNS_RRTYPE_WKS            11    /* a well known service description */
+#define DNS_RRTYPE_PTR            12    /* a domain name pointer */
+#define DNS_RRTYPE_HINFO          13    /* host information */
+#define DNS_RRTYPE_MINFO          14    /* mailbox or mail list information */
+#define DNS_RRTYPE_MX             15    /* mail exchange */
+#define DNS_RRTYPE_TXT            16    /* text strings */
+
+/** DNS field CLASS used for "Resource Records" */
+#define DNS_RRCLASS_IN            1     /* the Internet */
+#define DNS_RRCLASS_CS            2     /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */
+#define DNS_RRCLASS_CH            3     /* the CHAOS class */
+#define DNS_RRCLASS_HS            4     /* Hesiod [Dyer 87] */
+#define DNS_RRCLASS_FLUSH         0x800 /* Flush bit */
+
+/* The size used for the next line is rather a hack, but it prevents including socket.h in all files
+   that include memp.h, and that would possibly break portability (since socket.h defines some types
+   and constants possibly already define by the OS).
+   Calculation rule:
+   sizeof(struct addrinfo) + sizeof(struct sockaddr_in) + DNS_MAX_NAME_LENGTH + 1 byte zero-termination */
+#define NETDB_ELEM_SIZE           (32 + 16 + DNS_MAX_NAME_LENGTH + 1)
+
+#if DNS_LOCAL_HOSTLIST
+/** struct used for local host-list */
+struct local_hostlist_entry {
+  /** static hostname */
+  const char *name;
+  /** static host address in network byteorder */
+  ip_addr_t addr;
+  struct local_hostlist_entry *next;
+};
+#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
+#ifndef DNS_LOCAL_HOSTLIST_MAX_NAMELEN
+#define DNS_LOCAL_HOSTLIST_MAX_NAMELEN  DNS_MAX_NAME_LENGTH
+#endif
+#define LOCALHOSTLIST_ELEM_SIZE ((sizeof(struct local_hostlist_entry) + DNS_LOCAL_HOSTLIST_MAX_NAMELEN + 1))
+#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
+#endif /* DNS_LOCAL_HOSTLIST */
+
+/** Callback which is invoked when a hostname is found.
+ * A function of this type must be implemented by the application using the DNS resolver.
+ * @param name pointer to the name that was looked up.
+ * @param ipaddr pointer to an ip_addr_t containing the IP address of the hostname,
+ *        or NULL if the name could not be found (or on any other error).
+ * @param callback_arg a user-specified callback argument passed to dns_gethostbyname
+*/
+typedef void (*dns_found_callback)(const char *name, ip_addr_t *ipaddr, void *callback_arg);
+
+void           dns_init(void);
+void           dns_tmr(void);
+void           dns_setserver(u8_t numdns, ip_addr_t *dnsserver);
+ip_addr_t      dns_getserver(u8_t numdns);
+err_t          dns_gethostbyname(const char *hostname, ip_addr_t *addr,
+                                 dns_found_callback found, void *callback_arg);
+
+#if DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC
+int            dns_local_removehost(const char *hostname, const ip_addr_t *addr);
+err_t          dns_local_addhost(const char *hostname, const ip_addr_t *addr);
+#endif /* DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
+
+#endif /* LWIP_DNS */
+
+#endif /* __LWIP_DNS_H__ */
--- a/lwip/include/lwip/err.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/lwip/err.h	Tue Jul 27 15:59:42 2010 +0000
@@ -56,7 +56,7 @@
 #define ERR_RTE        -4    /* Routing problem.         */
 #define ERR_INPROGRESS -5    /* Operation in progress    */
 #define ERR_VAL        -6    /* Illegal value.           */
-#define ERR_WOULBLOCK  -7    /* Operation would block.   */
+#define ERR_WOULDBLOCK -7    /* Operation would block.   */
 
 #define ERR_IS_FATAL(e) ((e) < ERR_VAL)
 
--- a/lwip/include/lwip/init.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/lwip/init.h	Tue Jul 27 15:59:42 2010 +0000
@@ -47,7 +47,7 @@
 /** For release candidates, this is set to 1..254
   * For official releases, this is set to 255 (LWIP_RC_RELEASE)
   * For development versions (CVS), this is set to 0 (LWIP_RC_DEVELOPMENT) */
-#define LWIP_VERSION_RC         0U
+#define LWIP_VERSION_RC         1U
 
 /** LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases */
 #define LWIP_RC_RELEASE         255U
--- a/lwip/include/lwip/mem.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/lwip/mem.h	Tue Jul 27 15:59:42 2010 +0000
@@ -70,8 +70,10 @@
  */
 #if MEM_SIZE > 64000l
 typedef u32_t mem_size_t;
+#define MEM_SIZE_F U32_F
 #else
 typedef u16_t mem_size_t;
+#define MEM_SIZE_F U16_F
 #endif /* MEM_SIZE > 64000 */
 
 #if MEM_USE_POOLS
--- a/lwip/include/lwip/memp_std.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/lwip/memp_std.h	Tue Jul 27 15:59:42 2010 +0000
@@ -47,6 +47,9 @@
 #if IP_REASSEMBLY
 LWIP_MEMPOOL(REASSDATA,      MEMP_NUM_REASSDATA,       sizeof(struct ip_reassdata),   "REASSDATA")
 #endif /* IP_REASSEMBLY */
+#if IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF
+LWIP_MEMPOOL(FRAG_PBUF,      MEMP_NUM_FRAG_PBUF,       sizeof(struct pbuf_custom_ref),"FRAG_PBUF")
+#endif /* IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */
 
 #if LWIP_NETCONN
 LWIP_MEMPOOL(NETBUF,         MEMP_NUM_NETBUF,          sizeof(struct netbuf),         "NETBUF")
@@ -55,7 +58,9 @@
 
 #if NO_SYS==0
 LWIP_MEMPOOL(TCPIP_MSG_API,  MEMP_NUM_TCPIP_MSG_API,   sizeof(struct tcpip_msg),      "TCPIP_MSG_API")
+#if !LWIP_TCPIP_CORE_LOCKING_INPUT
 LWIP_MEMPOOL(TCPIP_MSG_INPKT,MEMP_NUM_TCPIP_MSG_INPKT, sizeof(struct tcpip_msg),      "TCPIP_MSG_INPKT")
+#endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */
 #endif /* NO_SYS==0 */
 
 #if ARP_QUEUEING
@@ -66,7 +71,9 @@
 LWIP_MEMPOOL(IGMP_GROUP,     MEMP_NUM_IGMP_GROUP,      sizeof(struct igmp_group),     "IGMP_GROUP")
 #endif /* LWIP_IGMP */
 
+#if (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) /* LWIP_TIMERS */
 LWIP_MEMPOOL(SYS_TIMEOUT,    MEMP_NUM_SYS_TIMEOUT,     sizeof(struct sys_timeo),      "SYS_TIMEOUT")
+#endif /* LWIP_TIMERS */
 
 #if LWIP_SNMP
 LWIP_MEMPOOL(SNMP_ROOTNODE,  MEMP_NUM_SNMP_ROOTNODE,   sizeof(struct mib_list_rootnode), "SNMP_ROOTNODE")
@@ -77,6 +84,12 @@
 #if LWIP_DNS && LWIP_SOCKET
 LWIP_MEMPOOL(NETDB,          MEMP_NUM_NETDB,           NETDB_ELEM_SIZE,               "NETDB")
 #endif /* LWIP_DNS && LWIP_SOCKET */
+#if LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC
+LWIP_MEMPOOL(LOCALHOSTLIST,  MEMP_NUM_LOCALHOSTLIST,   LOCALHOSTLIST_ELEM_SIZE,       "LOCALHOSTLIST")
+#endif /* LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
+#if PPP_SUPPORT && PPPOE_SUPPORT
+LWIP_MEMPOOL(PPPOE_IF,      MEMP_NUM_PPPOE_INTERFACES, sizeof(struct pppoe_softc),    "PPPOE_IF")
+#endif /* PPP_SUPPORT && PPPOE_SUPPORT */
 
 /*
  * A list of pools of pbuf's used by LWIP.
--- a/lwip/include/lwip/netbuf.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/lwip/netbuf.h	Tue Jul 27 15:59:42 2010 +0000
@@ -40,14 +40,24 @@
 extern "C" {
 #endif
 
+/** This netbuf has dest-addr/port set */
+#define NETBUF_FLAG_DESTADDR    0x01
+/** This netbuf includes a checksum */
+#define NETBUF_FLAG_CHKSUM      0x02
+
 struct netbuf {
   struct pbuf *p, *ptr;
-  ip_addr_t *addr;
+  ip_addr_t addr;
   u16_t port;
+#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY
+#if LWIP_CHECKSUM_ON_COPY
+  u8_t flags;
+#endif /* LWIP_CHECKSUM_ON_COPY */
+  u16_t toport_chksum;
 #if LWIP_NETBUF_RECVINFO
-  ip_addr_t *toaddr;
-  u16_t toport;
+  ip_addr_t toaddr;
 #endif /* LWIP_NETBUF_RECVINFO */
+#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */
 };
 
 /* Network buffer functions: */
@@ -56,12 +66,12 @@
 void *            netbuf_alloc    (struct netbuf *buf, u16_t size);
 void              netbuf_free     (struct netbuf *buf);
 err_t             netbuf_ref      (struct netbuf *buf,
-           const void *dataptr, u16_t size);
+                                   const void *dataptr, u16_t size);
 void              netbuf_chain    (struct netbuf *head,
            struct netbuf *tail);
 
 err_t             netbuf_data     (struct netbuf *buf,
-           void **dataptr, u16_t *len);
+                                   void **dataptr, u16_t *len);
 s8_t              netbuf_next     (struct netbuf *buf);
 void              netbuf_first    (struct netbuf *buf);
 
@@ -71,12 +81,18 @@
 #define netbuf_copy(buf,dataptr,len) netbuf_copy_partial(buf, dataptr, len, 0)
 #define netbuf_take(buf, dataptr, len) pbuf_take((buf)->p, dataptr, len)
 #define netbuf_len(buf)              ((buf)->p->tot_len)
-#define netbuf_fromaddr(buf)         ((buf)->addr)
+#define netbuf_fromaddr(buf)         (&((buf)->addr))
+#define netbuf_set_fromaddr(buf, fromaddr) ip_addr_set((&(buf)->addr), fromaddr)
 #define netbuf_fromport(buf)         ((buf)->port)
 #if LWIP_NETBUF_RECVINFO
-#define netbuf_destaddr(buf)         ((buf)->toaddr)
-#define netbuf_destport(buf)         ((buf)->toport)
+#define netbuf_destaddr(buf)         (&((buf)->toaddr))
+#define netbuf_set_destaddr(buf, destaddr) ip_addr_set((&(buf)->addr), destaddr)
+#define netbuf_destport(buf)         (((buf)->flags & NETBUF_FLAG_DESTADDR) ? (buf)->toport_chksum : 0)
 #endif /* LWIP_NETBUF_RECVINFO */
+#if LWIP_CHECKSUM_ON_COPY
+#define netbuf_set_chksum(buf, chksum) do { (buf)->flags = NETBUF_FLAG_CHKSUM; \
+                                            (buf)->toport_chksum = chksum; } while(0)
+#endif /* LWIP_CHECKSUM_ON_COPY */
 
 #ifdef __cplusplus
 }
--- a/lwip/include/lwip/netif.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/lwip/netif.h	Tue Jul 27 15:59:42 2010 +0000
@@ -56,58 +56,58 @@
 /* Throughout this file, IP addresses are expected to be in
  * the same byte order as in IP_PCB. */
 
-/** must be the maximum of all used hardware address lengths
+/*  must be the maximum of all used hardware address lengths
     across all types of interfaces in use */
 #define NETIF_MAX_HWADDR_LEN 6U
 
-/** Whether the network interface is 'up'. This is
+/*  Whether the network interface is 'up'. This is
  * a software flag used to control whether this network
  * interface is enabled and processes traffic.
  * It is set by the startup code (for static IP configuration) or
  * by dhcp/autoip when an address has been assigned.
  */
 #define NETIF_FLAG_UP           0x01U
-/** If set, the netif has broadcast capability.
+/*  If set, the netif has broadcast capability.
  * Set by the netif driver in its init function. */
 #define NETIF_FLAG_BROADCAST    0x02U
-/** If set, the netif is one end of a point-to-point connection.
+/*  If set, the netif is one end of a point-to-point connection.
  * Set by the netif driver in its init function. */
 #define NETIF_FLAG_POINTTOPOINT 0x04U
-/** If set, the interface is configured using DHCP.
+/*  If set, the interface is configured using DHCP.
  * Set by the DHCP code when starting or stopping DHCP. */
 #define NETIF_FLAG_DHCP         0x08U
-/** If set, the interface has an active link
+/*  If set, the interface has an active link
  *  (set by the network interface driver).
  * Either set by the netif driver in its init function (if the link
  * is up at that time) or at a later point once the link comes up
  * (if link detection is supported by the hardware). */
 #define NETIF_FLAG_LINK_UP      0x10U
-/** If set, the netif is an ethernet device using ARP.
+/*  If set, the netif is an ethernet device using ARP.
  * Set by the netif driver in its init function.
  * Used to check input packet types and use of DHCP. */
 #define NETIF_FLAG_ETHARP       0x20U
-/** If set, the netif is an ethernet device. It might not use
+/*  If set, the netif is an ethernet device. It might not use
  * ARP or TCP/IP if it is used for PPPoE only.
  */
 #define NETIF_FLAG_ETHERNET     0x40U
-/** If set, the netif has IGMP capability.
+/*  If set, the netif has IGMP capability.
  * Set by the netif driver in its init function. */
 #define NETIF_FLAG_IGMP         0x80U
 
-/** Function prototype for netif init functions. Set up flags and output/linkoutput
+/*  Function prototype for netif init functions. Set up flags and output/linkoutput
  * callback functions in this function.
  *
  * @param netif The netif to initialize
  */
 typedef err_t (*netif_init_fn)(struct netif *netif);
-/** Function prototype for netif->input functions. This function is saved as 'input'
+/*  Function prototype for netif->input functions. This function is saved as 'input'
  * callback function in the netif struct. Call it when a packet has been received.
  *
  * @param p The received packet, copied into a pbuf
  * @param inp The netif which received the packet
  */
 typedef err_t (*netif_input_fn)(struct pbuf *p, struct netif *inp);
-/** Function prototype for netif->output functions. Called by lwIP when a packet
+/*  Function prototype for netif->output functions. Called by lwIP when a packet
  * shall be sent. For ethernet netif, set this to 'etharp_output' and set
  * 'linkoutput'.
  *
@@ -117,87 +117,87 @@
  */
 typedef err_t (*netif_output_fn)(struct netif *netif, struct pbuf *p,
        ip_addr_t *ipaddr);
-/** Function prototype for netif->linkoutput functions. Only used for ethernet
+/*  Function prototype for netif->linkoutput functions. Only used for ethernet
  * netifs. This function is called by ARP when a packet shall be sent.
  *
  * @param netif The netif which shall send a packet
  * @param p The packet to send (raw ethernet packet)
  */
 typedef err_t (*netif_linkoutput_fn)(struct netif *netif, struct pbuf *p);
-/** Function prototype for netif status- or link-callback functions. */
+/*  Function prototype for netif status- or link-callback functions. */
 typedef void (*netif_status_callback_fn)(struct netif *netif);
-/** Function prototype for netif igmp_mac_filter functions */
+/*  Function prototype for netif igmp_mac_filter functions */
 typedef err_t (*netif_igmp_mac_filter_fn)(struct netif *netif,
        ip_addr_t *group, u8_t action);
 
-/** Generic data structure used for all lwIP network interfaces.
+/*  Generic data structure used for all lwIP network interfaces.
  *  The following fields should be filled in by the initialization
  *  function for the device driver: hwaddr_len, hwaddr[], mtu, flags */
 struct netif {
-  /** pointer to next in linked list */
+  /*  pointer to next in linked list */
   struct netif *next;
 
-  /** IP address configuration in network byte order */
+  /*  IP address configuration in network byte order */
   ip_addr_t ip_addr;
   ip_addr_t netmask;
   ip_addr_t gw;
 
-  /** This function is called by the network device driver
+  /*  This function is called by the network device driver
    *  to pass a packet up the TCP/IP stack. */
   netif_input_fn input;
-  /** This function is called by the IP module when it wants
+  /*  This function is called by the IP module when it wants
    *  to send a packet on the interface. This function typically
    *  first resolves the hardware address, then sends the packet. */
   netif_output_fn output;
-  /** This function is called by the ARP module when it wants
+  /*  This function is called by the ARP module when it wants
    *  to send a packet on the interface. This function outputs
    *  the pbuf as-is on the link medium. */
   netif_linkoutput_fn linkoutput;
 #if LWIP_NETIF_STATUS_CALLBACK
-  /** This function is called when the netif state is set to up or down
+  /*  This function is called when the netif state is set to up or down
    */
   netif_status_callback_fn status_callback;
 #endif /* LWIP_NETIF_STATUS_CALLBACK */
 #if LWIP_NETIF_LINK_CALLBACK
-  /** This function is called when the netif link is set to up or down
+  /*  This function is called when the netif link is set to up or down
    */
   netif_status_callback_fn link_callback;
 #endif /* LWIP_NETIF_LINK_CALLBACK */
-  /** This field can be set by the device driver and could point
+  /*  This field can be set by the device driver and could point
    *  to state information for the device. */
   void *state;
 #if LWIP_DHCP
-  /** the DHCP client state information for this netif */
+  /*  the DHCP client state information for this netif */
   struct dhcp *dhcp;
 #endif /* LWIP_DHCP */
 #if LWIP_AUTOIP
-  /** the AutoIP client state information for this netif */
+  /*  the AutoIP client state information for this netif */
   struct autoip *autoip;
 #endif
 #if LWIP_NETIF_HOSTNAME
   /* the hostname for this netif, NULL is a valid value */
   char*  hostname;
 #endif /* LWIP_NETIF_HOSTNAME */
-  /** maximum transfer unit (in bytes) */
+  /*  maximum transfer unit (in bytes) */
   u16_t mtu;
-  /** number of bytes used in hwaddr */
+  /*  number of bytes used in hwaddr */
   u8_t hwaddr_len;
-  /** link level hardware address of this interface */
+  /*  link level hardware address of this interface */
   u8_t hwaddr[NETIF_MAX_HWADDR_LEN];
-  /** flags (see NETIF_FLAG_ above) */
+  /*  flags (see NETIF_FLAG_ above) */
   u8_t flags;
-  /** descriptive abbreviation */
+  /*  descriptive abbreviation */
   char name[2];
-  /** number of this interface */
+  /*  number of this interface */
   u8_t num;
 #if LWIP_SNMP
-  /** link type (from "snmp_ifType" enum from snmp.h) */
+  /*  link type (from "snmp_ifType" enum from snmp.h) */
   u8_t link_type;
-  /** (estimate) link speed */
+  /*  (estimate) link speed */
   u32_t link_speed;
-  /** timestamp at last change made (up/down) */
+  /*  timestamp at last change made (up/down) */
   u32_t ts;
-  /** counters */
+  /*  counters */
   u32_t ifinoctets;
   u32_t ifinucastpkts;
   u32_t ifinnucastpkts;
@@ -208,7 +208,7 @@
   u32_t ifoutdiscards;
 #endif /* LWIP_SNMP */
 #if LWIP_IGMP
-  /** This function could be called to add or delete a entry in the multicast
+  /*  This function could be called to add or delete a entry in the multicast
       filter table of the ethernet MAC.*/
   netif_igmp_mac_filter_fn igmp_mac_filter;
 #endif /* LWIP_IGMP */
@@ -245,9 +245,9 @@
 #endif /* LWIP_SNMP */
 
 
-/** The list of network interfaces. */
+/*  The list of network interfaces. */
 extern struct netif *netif_list;
-/** The default network interface. */
+/*  The default network interface. */
 extern struct netif *netif_default;
 
 void netif_init(void);
@@ -274,7 +274,7 @@
 
 void netif_set_up(struct netif *netif);
 void netif_set_down(struct netif *netif);
-/** Ask if an interface is up */
+/*  Ask if an interface is up */
 #define netif_is_up(netif) (((netif)->flags & NETIF_FLAG_UP) ? (u8_t)1 : (u8_t)0)
 
 #if LWIP_NETIF_STATUS_CALLBACK
@@ -283,7 +283,7 @@
 
 void netif_set_link_up(struct netif *netif);
 void netif_set_link_down(struct netif *netif);
-/** Ask if a link is up */ 
+/*  Ask if a link is up */ 
 #define netif_is_link_up(netif) (((netif)->flags & NETIF_FLAG_LINK_UP) ? (u8_t)1 : (u8_t)0)
 
 #if LWIP_NETIF_LINK_CALLBACK
--- a/lwip/include/lwip/opt.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/lwip/opt.h	Tue Jul 27 15:59:42 2010 +0000
@@ -69,6 +69,14 @@
 #endif
 
 /**
+ * NO_SYS_NO_TIMERS==1: Drop support for sys_timeout when NO_SYS==1
+ * Mainly for compatibility to old versions.
+ */
+#ifndef NO_SYS_NO_TIMERS
+#define NO_SYS_NO_TIMERS                0
+#endif
+
+/**
  * MEMCPY: override this if you have a faster implementation at hand than the
  * one included in your C library
  */
@@ -260,7 +268,7 @@
 #endif
 
 /**
- * MEMP_NUM_REASSDATA: the number of simultaneously IP packets queued for
+ * MEMP_NUM_REASSDATA: the number of IP packets simultaneously queued for
  * reassembly (whole packets, not fragments!)
  */
 #ifndef MEMP_NUM_REASSDATA
@@ -268,6 +276,17 @@
 #endif
 
 /**
+ * MEMP_NUM_FRAG_PBUF: the number of IP fragments simultaneously sent
+ * (fragments, not whole packets!).
+ * This is only used with IP_FRAG_USES_STATIC_BUF==0 and
+ * LWIP_NETIF_TX_SINGLE_PBUF==0 and only has to be > 1 with DMA-enabled MACs
+ * where the packet is not yet sent when netif->output returns.
+ */
+#ifndef MEMP_NUM_FRAG_PBUF
+#define MEMP_NUM_FRAG_PBUF              15
+#endif
+
+/**
  * MEMP_NUM_ARP_QUEUE: the number of simulateously queued outgoing
  * packets (pbufs) that are waiting for an ARP request (to resolve
  * their destination address) to finish.
@@ -371,6 +390,22 @@
 #endif
 
 /**
+ * MEMP_NUM_LOCALHOSTLIST: the number of host entries in the local host list
+ * if DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1.
+ */
+#ifndef MEMP_NUM_LOCALHOSTLIST
+#define MEMP_NUM_LOCALHOSTLIST          1
+#endif
+
+/**
+ * MEMP_NUM_PPPOE_INTERFACES: the number of concurrently active PPPoE
+ * interfaces (only used with PPPOE_SUPPORT==1)
+ */
+#ifndef MEMP_NUM_PPPOE_INTERFACES
+#define MEMP_NUM_PPPOE_INTERFACES       1
+#endif
+
+/**
  * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. 
  */
 #ifndef PBUF_POOL_SIZE
@@ -444,6 +479,14 @@
 #define ETH_PAD_SIZE                    0
 #endif
 
+/** ETHARP_SUPPORT_STATIC_ENTRIES==1: enable code to support static ARP table
+ * entries (using etharp_add_static_entry/etharp_remove_static_entry).
+ */
+#ifndef ETHARP_SUPPORT_STATIC_ENTRIES
+#define ETHARP_SUPPORT_STATIC_ENTRIES   0
+#endif
+
+
 /*
    --------------------------------
    ---------- IP options ----------
@@ -507,10 +550,12 @@
 /**
  * IP_FRAG_USES_STATIC_BUF==1: Use a static MTU-sized buffer for IP
  * fragmentation. Otherwise pbufs are allocated and reference the original
- * packet data to be fragmented.
+ * packet data to be fragmented (or with LWIP_NETIF_TX_SINGLE_PBUF==1,
+ * new PBUF_RAM pbufs are used for fragments).
+ * ATTENTION: IP_FRAG_USES_STATIC_BUF==1 may not be used for DMA-enabled MACs!
  */
 #ifndef IP_FRAG_USES_STATIC_BUF
-#define IP_FRAG_USES_STATIC_BUF         1
+#define IP_FRAG_USES_STATIC_BUF         0
 #endif
 
 /**
@@ -1313,6 +1358,13 @@
 #define LWIP_NETCONN                    1
 #endif
 
+/** LWIP_TCPIP_TIMEOUT==1: Enable tcpip_timeout/tcpip_untimeout tod create
+ * timers running in tcpip_thread from another thread.
+ */
+#ifndef LWIP_TCPIP_TIMEOUT
+#define LWIP_TCPIP_TIMEOUT              1
+#endif
+
 /*
    ------------------------------------
    ---------- Socket options ----------
@@ -1373,12 +1425,21 @@
 #endif
 
 /**
- * SO_REUSE==1: Enable SO_REUSEADDR and SO_REUSEPORT options. DO NOT USE!
+ * SO_REUSE==1: Enable SO_REUSEADDR option.
  */
 #ifndef SO_REUSE
 #define SO_REUSE                        0
 #endif
 
+/**
+ * SO_REUSE_RXTOALL==1: Pass a copy of incoming broadcast/multicast packets
+ * to all local matches if SO_REUSEADDR is turned on.
+ * WARNING: Adds a memcpy for every packet if passing to more than one pcb!
+ */
+#ifndef SO_REUSE_RXTOALL
+#define SO_REUSE_RXTOALL                0
+#endif
+
 /*
    ----------------------------------------
    ---------- Statistics options ----------
--- a/lwip/include/lwip/pbuf.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/lwip/pbuf.h	Tue Jul 27 15:59:42 2010 +0000
@@ -40,6 +40,10 @@
 extern "C" {
 #endif
 
+/* Currently, the pbuf_custom code is only needed for one specific configuration
+ * of IP_FRAG */
+#define LWIP_SUPPORT_CUSTOM_PBUF (IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF)
+
 #define PBUF_TRANSPORT_HLEN 20
 #define PBUF_IP_HLEN        20
 
@@ -58,16 +62,21 @@
 } pbuf_type;
 
 
-/** indicates this packet's data should be immediately passed to the application */
-#define PBUF_FLAG_PUSH 0x01U
+/* indicates this packet's data should be immediately passed to the application */
+#define PBUF_FLAG_PUSH      0x01U
+/* indicates this is a custom pbuf: pbuf_free and pbuf_header handle such a
+    a pbuf differently */
+#define PBUF_FLAG_IS_CUSTOM 0x02U
+/* indicates this pbuf is UDP multicast to be looped back */
+#define PBUF_FLAG_MCASTLOOP 0x04U
 
 struct pbuf {
-  /** next pbuf in singly linked pbuf chain */
+  /* next pbuf in singly linked pbuf chain */
   struct pbuf *next;
 
-  /** pointer to the actual data in the buffer */
+  /* pointer to the actual data in the buffer */
   void *payload;
-  
+
   /**
    * total length of this buffer and all next buffers in chain
    * belonging to the same packet.
@@ -76,14 +85,14 @@
    * p->tot_len == p->len + (p->next? p->next->tot_len: 0)
    */
   u16_t tot_len;
-  
-  /** length of this buffer */
-  u16_t len;  
 
-  /** pbuf_type as u8_t instead of enum to save space */
+  /* length of this buffer */
+  u16_t len;
+
+  /* pbuf_type as u8_t instead of enum to save space */
   u8_t /*pbuf_type*/ type;
 
-  /** misc flags */
+  /* misc flags */
   u8_t flags;
 
   /**
@@ -92,17 +101,33 @@
    * the stack itself, or pbuf->next pointers from a chain.
    */
   u16_t ref;
-  
 };
 
+#if LWIP_SUPPORT_CUSTOM_PBUF
+/* Prototype for a function to free a custom pbuf */
+typedef void (*pbuf_free_custom_fn)(struct pbuf *p);
+
+/* A custom pbuf: like a pbuf, but following a function pointer to free it. */
+struct pbuf_custom {
+  /* The actual pbuf */
+  struct pbuf pbuf;
+  /* This function is called when pbuf_free deallocates this pbuf(_custom) */
+  pbuf_free_custom_fn custom_free_function;
+};
+#endif /* LWIP_SUPPORT_CUSTOM_PBUF */
+
 /* Initializes the pbuf module. This call is empty for now, but may not be in future. */
 #define pbuf_init()
 
-struct pbuf *pbuf_alloc(pbuf_layer l, u16_t size, pbuf_type type);
+struct pbuf *pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type);
+#if LWIP_SUPPORT_CUSTOM_PBUF
+struct pbuf *pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type,
+                                 struct pbuf_custom *p, void *payload_mem,
+                                 u16_t payload_mem_len);
+#endif /* LWIP_SUPPORT_CUSTOM_PBUF */
 void pbuf_realloc(struct pbuf *p, u16_t size); 
 u8_t pbuf_header(struct pbuf *p, s16_t header_size);
 void pbuf_ref(struct pbuf *p);
-void pbuf_ref_chain(struct pbuf *p);
 u8_t pbuf_free(struct pbuf *p);
 u8_t pbuf_clen(struct pbuf *p);  
 void pbuf_cat(struct pbuf *head, struct pbuf *tail);
@@ -112,6 +137,15 @@
 u16_t pbuf_copy_partial(struct pbuf *p, void *dataptr, u16_t len, u16_t offset);
 err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len);
 struct pbuf *pbuf_coalesce(struct pbuf *p, pbuf_layer layer);
+#if LWIP_CHECKSUM_ON_COPY
+err_t pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr,
+                       u16_t len, u16_t *chksum);
+#endif /* LWIP_CHECKSUM_ON_COPY */
+
+u8_t pbuf_get_at(struct pbuf* p, u16_t offset);
+u16_t pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n);
+u16_t pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset);
+u16_t pbuf_strstr(struct pbuf* p, const char* substr);
 
 #ifdef __cplusplus
 }
--- a/lwip/include/lwip/snmp_asn1.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/lwip/snmp_asn1.h	Tue Jul 27 15:59:42 2010 +0000
@@ -46,12 +46,12 @@
 extern "C" {
 #endif
 
-#define SNMP_ASN1_UNIV   (!0x80 | !0x40)
-#define SNMP_ASN1_APPLIC (!0x80 |  0x40)
-#define SNMP_ASN1_CONTXT ( 0x80 | !0x40)
+#define SNMP_ASN1_UNIV   (0)    /* (!0x80 | !0x40) */
+#define SNMP_ASN1_APPLIC (0x40) /* (!0x80 |  0x40) */
+#define SNMP_ASN1_CONTXT (0x80) /* ( 0x80 | !0x40) */
 
-#define SNMP_ASN1_CONSTR (0x20)
-#define SNMP_ASN1_PRIMIT (!0x20)
+#define SNMP_ASN1_CONSTR (0x20) /* ( 0x20) */
+#define SNMP_ASN1_PRIMIT (0)    /* (!0x20) */
 
 /* universal tags */
 #define SNMP_ASN1_INTEG  2
--- a/lwip/include/lwip/snmp_structs.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/lwip/snmp_structs.h	Tue Jul 27 15:59:42 2010 +0000
@@ -136,7 +136,7 @@
   u8_t node_type;
   u16_t maxlength;
 
-  /* aditional struct members */
+  /* additional struct members */
   const s32_t *objid;
   struct mib_node* const *nptr;
 };
@@ -180,7 +180,7 @@
   u8_t node_type;
   u16_t maxlength;
 
-  /* aditional struct members */
+  /* additional struct members */
   struct mib_list_node *head;
   struct mib_list_node *tail;
   /* counts list nodes in list  */
@@ -200,8 +200,8 @@
   u8_t node_type;
   u16_t maxlength;
 
-  /* aditional struct members */
-  /** points to an extenal (in memory) record of some sort of addressing
+  /* additional struct members */
+  /** points to an external (in memory) record of some sort of addressing
       information, passed to and interpreted by the funtions below */
   void* addr_inf;
   /** tree levels under this node */
--- a/lwip/include/lwip/sockets.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/lwip/sockets.h	Tue Jul 27 15:59:42 2010 +0000
@@ -72,11 +72,11 @@
 #define SOCK_RAW        3
 
 /*
- * Option flags per-socket. These must match the SOF_ flags in ip.h!
+ * Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c)
  */
 #define  SO_DEBUG       0x0001 /* Unimplemented: turn on debugging info recording */
 #define  SO_ACCEPTCONN  0x0002 /* socket has had listen() */
-#define  SO_REUSEADDR   0x0004 /* Unimplemented: allow local address reuse */
+#define  SO_REUSEADDR   0x0004 /* Allow local address reuse */
 #define  SO_KEEPALIVE   0x0008 /* keep connections alive */
 #define  SO_DONTROUTE   0x0010 /* Unimplemented: just use interface addresses */
 #define  SO_BROADCAST   0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */
@@ -279,6 +279,12 @@
 #define O_NDELAY    1 /* same as O_NONBLOCK, for compatibility */
 #endif
 
+#ifndef SHUT_RD
+  #define SHUT_RD   1
+  #define SHUT_WR   2
+  #define SHUT_RDWR 3
+#endif
+
 /* FD_SET used for lwip_select */
 #ifndef FD_SET
   #undef  FD_SETSIZE
--- a/lwip/include/lwip/stats.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/lwip/stats.h	Tue Jul 27 15:59:42 2010 +0000
@@ -148,7 +148,7 @@
 
 extern struct stats_ lwip_stats;
 
-void stats_init();
+void stats_init(void);
 
 #define STATS_INC(x) ++lwip_stats.x
 #define STATS_DEC(x) --lwip_stats.x
@@ -157,7 +157,7 @@
                                     lwip_stats.x.max = lwip_stats.x.used; \
                                 } \
                              } while(0)
-#else
+#else /* LWIP_STATS */
 #define stats_init()
 #define STATS_INC(x)
 #define STATS_DEC(x)
@@ -276,7 +276,7 @@
 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
+#else /* LWIP_STATS_DISPLAY */
 #define stats_display()
 #define stats_display_proto(proto, name)
 #define stats_display_igmp(igmp)
--- a/lwip/include/lwip/sys.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/lwip/sys.h	Tue Jul 27 15:59:42 2010 +0000
@@ -136,8 +136,8 @@
 void sys_sem_signal(sys_sem_t *sem);
 /** Wait for a semaphore for the specified timeout
  * @param sem the semaphore to wait for
- * @param timeout timeout in miliseconds to wait (0 = wait forever)
- * @return time (in miliseconds) waited for the semaphore
+ * @param timeout timeout in milliseconds to wait (0 = wait forever)
+ * @return time (in milliseconds) waited for the semaphore
  *         or SYS_ARCH_TIMEOUT on timeout */
 u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout);
 /** Delete a semaphore
@@ -178,8 +178,8 @@
 /** Wait for a new message to arrive in the mbox
  * @param mbox mbox to get a message from
  * @param msg pointer where the message is stored
- * @param timeout maximum time (in miliseconds) to wait for a message
- * @return time (in miliseconds) waited for a message, may be 0 if not waited
+ * @param timeout maximum time (in milliseconds) to wait for a message
+ * @return time (in milliseconds) waited for a message, may be 0 if not waited
            or SYS_ARCH_TIMEOUT on timeout
  *         The returned time has to be accurate to prevent timer jitter! */
 u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout);
@@ -188,8 +188,8 @@
 /** Wait for a new message to arrive in the mbox
  * @param mbox mbox to get a message from
  * @param msg pointer where the message is stored
- * @param timeout maximum time (in miliseconds) to wait for a message
- * @return 0 (miliseconds) if a message has been received
+ * @param timeout maximum time (in milliseconds) to wait for a message
+ * @return 0 (milliseconds) if a message has been received
  *         or SYS_MBOX_EMPTY if the mailbox is empty */
 u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg);
 #endif
@@ -215,7 +215,7 @@
  * @param arg parameter passed to 'thread'
  * @param stacksize stack size in bytes for the new thread (may be ignored by ports)
  * @param prio priority of the new thread (may be ignored by ports) */
-sys_thread_t sys_thread_new(char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio);
+sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio);
 
 #endif /* NO_SYS */
 
--- a/lwip/include/lwip/tcp_impl.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/lwip/tcp_impl.h	Tue Jul 27 15:59:42 2010 +0000
@@ -176,7 +176,7 @@
 
 #define TCPH_OFFSET_SET(phdr, offset) (phdr)->_hdrlen_rsvd_flags = htons(((offset) << 8) | TCPH_FLAGS(phdr))
 #define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr))
-#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & htons((u16_t)(~(u16_t)(TCP_FLAGS)))) | htons(flags))
+#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & PP_HTONS((u16_t)(~(u16_t)(TCP_FLAGS)))) | htons(flags))
 #define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | (flags))
 
 #define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | htons(flags))
@@ -199,6 +199,8 @@
                    LWIP_EVENT_SENT, NULL, space, ERR_OK)
 #define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
                 LWIP_EVENT_RECV, (p), 0, (err))
+#define TCP_EVENT_CLOSED(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
+                LWIP_EVENT_RECV, NULL, 0, ERR_OK)
 #define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
                 LWIP_EVENT_CONNECTED, NULL, 0, (err))
 #define TCP_EVENT_POLL(pcb,ret)       ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
@@ -222,13 +224,22 @@
     else (ret) = ERR_OK;                                       \
   } while (0)
 
-#define TCP_EVENT_RECV(pcb,p,err,ret)                              \
-  do {                                                             \
-    if(((pcb)->recv != NULL) && (!((pcb)->flags & TF_RXCLOSED))) { \
-      (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err));    \
-    } else {                                                       \
-      (ret) = tcp_recv_null(NULL, (pcb), (p), (err));              \
-    }                                                              \
+#define TCP_EVENT_RECV(pcb,p,err,ret)                          \
+  do {                                                         \
+    if((pcb)->recv != NULL) {                                  \
+      (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err));\
+    } else {                                                   \
+      (ret) = tcp_recv_null(NULL, (pcb), (p), (err));          \
+    }                                                          \
+  } while (0)
+
+#define TCP_EVENT_CLOSED(pcb,ret)                                \
+  do {                                                           \
+    if(((pcb)->recv != NULL)) {                                  \
+      (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),NULL,ERR_OK);\
+    } else {                                                     \
+      (ret) = ERR_OK;                                            \
+    }                                                            \
   } while (0)
 
 #define TCP_EVENT_CONNECTED(pcb,err,ret)                         \
@@ -260,7 +271,7 @@
 #define TCP_OVERSIZE_DBGCHECK 0
 #endif
 
-/** Don't generate chceksum on copy if CHECKSUM_GEN_TCP is disabled */
+/** Don't generate checksum on copy if CHECKSUM_GEN_TCP is disabled */
 #define TCP_CHECKSUM_ON_COPY  (LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_TCP)
 
 /* This structure represents a TCP segment on the unsent, unacked and ooseq queues */
@@ -291,10 +302,10 @@
   (flags & TF_SEG_OPTS_TS  ? 12 : 0)
 
 /** This returns a TCP header option for MSS in an u32_t */
-#define TCP_BUILD_MSS_OPTION(x) (x) = htonl(((u32_t)2 << 24) |          \
-                                            ((u32_t)4 << 16) |          \
-                                            (((u32_t)TCP_MSS / 256) << 8) | \
-                                            (TCP_MSS & 255))
+#define TCP_BUILD_MSS_OPTION(x) (x) = PP_HTONL(((u32_t)2 << 24) |          \
+                                               ((u32_t)4 << 16) |          \
+                                               (((u32_t)TCP_MSS / 256) << 8) | \
+                                               (TCP_MSS & 255))
 
 /* Global variables: */
 extern struct tcp_pcb *tcp_input_pcb;
@@ -305,6 +316,7 @@
   struct tcp_pcb_listen *listen_pcbs; 
   struct tcp_pcb *pcbs;
 };
+extern struct tcp_pcb *tcp_bound_pcbs;
 extern union tcp_listen_pcbs_t tcp_listen_pcbs;
 extern struct tcp_pcb *tcp_active_pcbs;  /* List of all TCP PCBs that are in a
               state in which they accept or send
@@ -321,62 +333,65 @@
 */
 /* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB
    with a PCB list or removes a PCB from a list, respectively. */
-#if 0
+#ifndef TCP_DEBUG_PCB_LISTS
+#define TCP_DEBUG_PCB_LISTS 0
+#endif
+#if TCP_DEBUG_PCB_LISTS
 #define TCP_REG(pcbs, npcb) do {\
-                            LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", npcb, npcb->local_port)); \
-                            for(tcp_tmp_pcb = *pcbs; \
+                            LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", (npcb), (npcb)->local_port)); \
+                            for(tcp_tmp_pcb = *(pcbs); \
           tcp_tmp_pcb != NULL; \
         tcp_tmp_pcb = tcp_tmp_pcb->next) { \
-                                LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != npcb); \
+                                LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != (npcb)); \
                             } \
-                            LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", npcb->state != CLOSED); \
-                            npcb->next = *pcbs; \
-                            LWIP_ASSERT("TCP_REG: npcb->next != npcb", npcb->next != npcb); \
-                            *(pcbs) = npcb; \
+                            LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", ((pcbs) == &tcp_bound_pcbs) || ((npcb)->state != CLOSED)); \
+                            (npcb)->next = *(pcbs); \
+                            LWIP_ASSERT("TCP_REG: npcb->next != npcb", (npcb)->next != (npcb)); \
+                            *(pcbs) = (npcb); \
                             LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
               tcp_timer_needed(); \
                             } while(0)
 #define TCP_RMV(pcbs, npcb) do { \
-                            LWIP_ASSERT("TCP_RMV: pcbs != NULL", *pcbs != NULL); \
-                            LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", npcb, *pcbs)); \
-                            if(*pcbs == npcb) { \
-                               *pcbs = (*pcbs)->next; \
-                            } else for(tcp_tmp_pcb = *pcbs; tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \
-                               if(tcp_tmp_pcb->next == npcb) { \
-                                  tcp_tmp_pcb->next = npcb->next; \
+                            LWIP_ASSERT("TCP_RMV: pcbs != NULL", *(pcbs) != NULL); \
+                            LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", (npcb), *(pcbs))); \
+                            if(*(pcbs) == (npcb)) { \
+                               *(pcbs) = (*pcbs)->next; \
+                            } else for(tcp_tmp_pcb = *(pcbs); tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \
+                               if(tcp_tmp_pcb->next == (npcb)) { \
+                                  tcp_tmp_pcb->next = (npcb)->next; \
                                   break; \
                                } \
                             } \
-                            npcb->next = NULL; \
+                            (npcb)->next = NULL; \
                             LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
-                            LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", npcb, *pcbs)); \
+                            LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", (npcb), *(pcbs))); \
                             } while(0)
 
 #else /* LWIP_DEBUG */
 
 #define TCP_REG(pcbs, npcb)                        \
   do {                                             \
-    npcb->next = *pcbs;                            \
-    *(pcbs) = npcb;                                \
+    (npcb)->next = *pcbs;                          \
+    *(pcbs) = (npcb);                              \
     tcp_timer_needed();                            \
   } while (0)
 
 #define TCP_RMV(pcbs, npcb)                        \
   do {                                             \
-    if(*(pcbs) == npcb) {                          \
+    if(*(pcbs) == (npcb)) {                        \
       (*(pcbs)) = (*pcbs)->next;                   \
     }                                              \
     else {                                         \
-      for(tcp_tmp_pcb = *pcbs;                                         \
-          tcp_tmp_pcb != NULL;                                         \
-          tcp_tmp_pcb = tcp_tmp_pcb->next) {                           \
-        if(tcp_tmp_pcb->next == npcb) {   \
-          tcp_tmp_pcb->next = npcb->next;          \
+      for(tcp_tmp_pcb = *pcbs;                     \
+          tcp_tmp_pcb != NULL;                     \
+          tcp_tmp_pcb = tcp_tmp_pcb->next) {       \
+        if(tcp_tmp_pcb->next == (npcb)) {          \
+          tcp_tmp_pcb->next = (npcb)->next;        \
           break;                                   \
         }                                          \
       }                                            \
     }                                              \
-    npcb->next = NULL;                             \
+    (npcb)->next = NULL;                           \
   } while(0)
 
 #endif /* LWIP_DEBUG */
@@ -448,68 +463,6 @@
 void tcp_timer_needed(void);
 
 
-/* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB
-   with a PCB list or removes a PCB from a list, respectively. */
-#if 0
-#define TCP_REG(pcbs, npcb) do {\
-                            LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", npcb, npcb->local_port)); \
-                            for(tcp_tmp_pcb = *pcbs; \
-          tcp_tmp_pcb != NULL; \
-        tcp_tmp_pcb = tcp_tmp_pcb->next) { \
-                                LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != npcb); \
-                            } \
-                            LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", npcb->state != CLOSED); \
-                            npcb->next = *pcbs; \
-                            LWIP_ASSERT("TCP_REG: npcb->next != npcb", npcb->next != npcb); \
-                            *(pcbs) = npcb; \
-                            LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
-              tcp_timer_needed(); \
-                            } while(0)
-#define TCP_RMV(pcbs, npcb) do { \
-                            LWIP_ASSERT("TCP_RMV: pcbs != NULL", *pcbs != NULL); \
-                            LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", npcb, *pcbs)); \
-                            if(*pcbs == npcb) { \
-                               *pcbs = (*pcbs)->next; \
-                            } else for(tcp_tmp_pcb = *pcbs; tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \
-                               if(tcp_tmp_pcb->next == npcb) { \
-                                  tcp_tmp_pcb->next = npcb->next; \
-                                  break; \
-                               } \
-                            } \
-                            npcb->next = NULL; \
-                            LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
-                            LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", npcb, *pcbs)); \
-                            } while(0)
-
-#else /* LWIP_DEBUG */
-
-#define TCP_REG(pcbs, npcb)                        \
-  do {                                             \
-    npcb->next = *pcbs;                            \
-    *(pcbs) = npcb;                                \
-    tcp_timer_needed();                            \
-  } while (0)
-
-#define TCP_RMV(pcbs, npcb)                        \
-  do {                                             \
-    if(*(pcbs) == npcb) {                          \
-      (*(pcbs)) = (*pcbs)->next;                   \
-    }                                              \
-    else {                                         \
-      for(tcp_tmp_pcb = *pcbs;                                         \
-          tcp_tmp_pcb != NULL;                                         \
-          tcp_tmp_pcb = tcp_tmp_pcb->next) {                           \
-        if(tcp_tmp_pcb->next == npcb) {   \
-          tcp_tmp_pcb->next = npcb->next;          \
-          break;                                   \
-        }                                          \
-      }                                            \
-    }                                              \
-    npcb->next = NULL;                             \
-  } while(0)
-
-#endif /* LWIP_DEBUG */
-
 #ifdef __cplusplus
 }
 #endif
--- a/lwip/include/lwip/tcpip.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/lwip/tcpip.h	Tue Jul 27 15:59:42 2010 +0000
@@ -48,6 +48,12 @@
 extern "C" {
 #endif
 
+/** Define this to something that triggers a watchdog. This is called from
+ * tcpip_thread after processing a message. */
+#ifndef LWIP_TCPIP_THREAD_ALIVE
+#define LWIP_TCPIP_THREAD_ALIVE()
+#endif
+
 #if LWIP_TCPIP_CORE_LOCKING
 /** The global semaphore to lock the stack. */
 extern sys_mutex_t lock_tcpip_core;
@@ -96,8 +102,10 @@
 err_t pbuf_free_callback(struct pbuf *p);
 err_t mem_free_callback(void *m);
 
+#if LWIP_TCPIP_TIMEOUT
 err_t tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg);
 err_t tcpip_untimeout(sys_timeout_handler h, void *arg);
+#endif /* LWIP_TCPIP_TIMEOUT */
 
 enum tcpip_msg_type {
 #if LWIP_NETCONN
@@ -107,9 +115,11 @@
 #if LWIP_NETIF_API
   TCPIP_MSG_NETIFAPI,
 #endif /* LWIP_NETIF_API */
-  TCPIP_MSG_CALLBACK,
+#if LWIP_TCPIP_TIMEOUT
   TCPIP_MSG_TIMEOUT,
-  TCPIP_MSG_UNTIMEOUT
+  TCPIP_MSG_UNTIMEOUT,
+#endif /* LWIP_TCPIP_TIMEOUT */
+  TCPIP_MSG_CALLBACK
 };
 
 struct tcpip_msg {
@@ -130,11 +140,13 @@
       tcpip_callback_fn function;
       void *ctx;
     } cb;
+#if LWIP_TCPIP_TIMEOUT
     struct {
       u32_t msecs;
       sys_timeout_handler h;
       void *arg;
     } tmo;
+#endif /* LWIP_TCPIP_TIMEOUT */
   } msg;
 };
 
--- a/lwip/include/lwip/timers.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/lwip/timers.h	Tue Jul 27 15:59:42 2010 +0000
@@ -35,6 +35,11 @@
 
 #include "lwip/opt.h"
 
+/* Timers are not supported when NO_SYS==1 and NO_SYS_NO_TIMERS==1 */
+#define LWIP_TIMERS (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS))
+
+#if LWIP_TIMERS
+
 #include "lwip/err.h"
 #include "lwip/sys.h"
 
@@ -70,13 +75,13 @@
 void sys_timeouts_init(void);
 
 #if LWIP_DEBUG_TIMERNAMES
-void sys_timeout_debug(u32_t msecs, sys_timeout_handler h, void *arg, const char* handler_name);
+void sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name);
 #define sys_timeout(msecs, handler, arg) sys_timeout_debug(msecs, handler, arg, #handler)
 #else /* LWIP_DEBUG_TIMERNAMES */
-void sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg);
+void sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg);
 #endif /* LWIP_DEBUG_TIMERNAMES */
 
-void sys_untimeout(sys_timeout_handler h, void *arg);
+void sys_untimeout(sys_timeout_handler handler, void *arg);
 #if NO_SYS
 void sys_check_timeouts(void);
 void sys_restart_timeouts(void);
@@ -89,4 +94,5 @@
 }
 #endif
 
+#endif /* LWIP_TIMERS */
 #endif /* __LWIP_TIMERS_H__ */
--- a/lwip/include/lwip/udp.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/lwip/udp.h	Tue Jul 27 15:59:42 2010 +0000
@@ -63,9 +63,10 @@
 #  include "arch/epstruct.h"
 #endif
 
-#define UDP_FLAGS_NOCHKSUM 0x01U
-#define UDP_FLAGS_UDPLITE  0x02U
-#define UDP_FLAGS_CONNECTED  0x04U
+#define UDP_FLAGS_NOCHKSUM       0x01U
+#define UDP_FLAGS_UDPLITE        0x02U
+#define UDP_FLAGS_CONNECTED      0x04U
+#define UDP_FLAGS_MULTICAST_LOOP 0x08U
 
 struct udp_pcb;
 
@@ -135,6 +136,18 @@
                                  ip_addr_t *dst_ip, u16_t dst_port);
 err_t            udp_send       (struct udp_pcb *pcb, struct pbuf *p);
 
+#if LWIP_CHECKSUM_ON_COPY
+err_t            udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p,
+                                 ip_addr_t *dst_ip, u16_t dst_port,
+                                 struct netif *netif, u8_t have_chksum,
+                                 u16_t chksum);
+err_t            udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p,
+                                 ip_addr_t *dst_ip, u16_t dst_port,
+                                 u8_t have_chksum, u16_t chksum);
+err_t            udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p,
+                                 u8_t have_chksum, u16_t chksum);
+#endif /* LWIP_CHECKSUM_ON_COPY */
+
 #define          udp_flags(pcb) ((pcb)->flags)
 #define          udp_setflags(pcb, f)  ((pcb)->flags = (f))
 
--- a/lwip/include/netif/etharp.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/netif/etharp.h	Tue Jul 27 15:59:42 2010 +0000
@@ -68,7 +68,7 @@
 #  include "arch/bpstruct.h"
 #endif
 PACK_STRUCT_BEGIN
-/** Ethernet header */
+/* Ethernet header */
 struct eth_hdr {
 #if ETH_PAD_SIZE
   PACK_STRUCT_FIELD(u8_t padding[ETH_PAD_SIZE]);
@@ -90,7 +90,7 @@
 #  include "arch/bpstruct.h"
 #endif
 PACK_STRUCT_BEGIN
-/** VLAN header inserted between ethernet header and payload
+/* VLAN header inserted between ethernet header and payload
  * if 'type' in ethernet header is ETHTYPE_VLAN.
  * See IEEE802.Q */
 struct eth_vlan_hdr {
@@ -111,11 +111,12 @@
 #  include "arch/bpstruct.h"
 #endif
 PACK_STRUCT_BEGIN
-/** the ARP message, see RFC 826 ("Packet format") */
+/* the ARP message, see RFC 826 ("Packet format") */
 struct etharp_hdr {
   PACK_STRUCT_FIELD(u16_t hwtype);
   PACK_STRUCT_FIELD(u16_t proto);
-  PACK_STRUCT_FIELD(u16_t _hwlen_protolen);
+  PACK_STRUCT_FIELD(u8_t  hwlen);
+  PACK_STRUCT_FIELD(u8_t  protolen);
   PACK_STRUCT_FIELD(u16_t opcode);
   PACK_STRUCT_FIELD(struct eth_addr shwaddr);
   PACK_STRUCT_FIELD(struct ip_addr2 sipaddr);
@@ -130,7 +131,7 @@
 #define SIZEOF_ETHARP_HDR 28
 #define SIZEOF_ETHARP_PACKET (SIZEOF_ETH_HDR + SIZEOF_ETHARP_HDR)
 
-/** 5 seconds period */
+/* 5 seconds period */
 #define ARP_TMR_INTERVAL 5000
 
 #define ETHTYPE_ARP       0x0806
@@ -139,14 +140,36 @@
 #define ETHTYPE_PPPOEDISC 0x8863  /* PPP Over Ethernet Discovery Stage */
 #define ETHTYPE_PPPOE     0x8864  /* PPP Over Ethernet Session Stage */
 
+/* MEMCPY-like macro to copy to/from struct eth_addr's that are local variables
+ * or known to be 32-bit aligned within the protocol header. */
+#ifndef ETHADDR32_COPY
+#define ETHADDR32_COPY(src, dst)  SMEMCPY(src, dst, ETHARP_HWADDR_LEN)
+#endif
+
+/* MEMCPY-like macro to copy to/from struct eth_addr's that are no local
+ * variables and known to be 16-bit aligned within the protocol header. */
+#ifndef ETHADDR16_COPY
+#define ETHADDR16_COPY(src, dst)  SMEMCPY(src, dst, ETHARP_HWADDR_LEN)
+#endif
+
 #if LWIP_ARP /* don't build if not configured for use in lwipopts.h */
 
-/** ARP message types (opcodes) */
+/* ARP message types (opcodes) */
 #define ARP_REQUEST 1
 #define ARP_REPLY   2
 
+/* Define this to 1 and define LWIP_ARP_FILTER_NETIF_FN(pbuf, netif, type)
+ * to a filter function that returns the correct netif when using multiple
+ * netifs on one hardware interface where the netif's low-level receive
+ * routine cannot decide for the correct netif (e.g. when mapping multiple
+ * IP addresses to one hardware interface).
+ */
+#ifndef LWIP_ARP_FILTER_NETIF
+#define LWIP_ARP_FILTER_NETIF 0
+#endif
+
 #if ARP_QUEUEING
-/** struct for queueing outgoing packets for unknown address
+/* struct for queueing outgoing packets for unknown address
   * defined here to be accessed by memp.h
   */
 struct etharp_q_entry {
@@ -162,12 +185,17 @@
 err_t etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr);
 err_t etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q);
 err_t etharp_request(struct netif *netif, ip_addr_t *ipaddr);
-/** For Ethernet network interfaces, we might want to send "gratuitous ARP";
+/* For Ethernet network interfaces, we might want to send "gratuitous ARP";
  *  this is an ARP packet sent by a node in order to spontaneously cause other
  *  nodes to update an entry in their ARP cache.
  *  From RFC 3220 "IP Mobility Support for IPv4" section 4.6. */
 #define etharp_gratuitous(netif) etharp_request((netif), &(netif)->ip_addr)
 
+#if ETHARP_SUPPORT_STATIC_ENTRIES
+err_t etharp_add_static_entry(ip_addr_t *ipaddr, struct eth_addr *ethaddr);
+err_t etharp_remove_static_entry(ip_addr_t *ipaddr);
+#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
+
 #if LWIP_AUTOIP
 err_t etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
                  const struct eth_addr *ethdst_addr,
@@ -176,7 +204,6 @@
                  const u16_t opcode);
 #endif /* LWIP_AUTOIP */
 
-
 #endif /* LWIP_ARP */
 
 err_t ethernet_input(struct pbuf *p, struct netif *netif);
--- a/lwip/include/netif/ppp_oe.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/include/netif/ppp_oe.h	Tue Jul 27 15:59:42 2010 +0000
@@ -140,12 +140,38 @@
 /* two byte PPP protocol discriminator, then IP data */
 #define PPPOE_MAXMTU          (ETHERMTU-PPPOE_HEADERLEN-2)
 
-struct pppoe_softc;
+#ifndef PPPOE_MAX_AC_COOKIE_LEN
+#define PPPOE_MAX_AC_COOKIE_LEN   64
+#endif
+
+struct pppoe_softc {
+  struct pppoe_softc *next;
+  struct netif *sc_ethif;      /* ethernet interface we are using */
+  int sc_pd;                   /* ppp unit number */
+  void (*sc_linkStatusCB)(int pd, int up);
+
+  int sc_state;                /* discovery phase or session connected */
+  struct eth_addr sc_dest;     /* hardware address of concentrator */
+  u16_t sc_session;            /* PPPoE session id */
+
+#ifdef PPPOE_TODO
+  char *sc_service_name;       /* if != NULL: requested name of service */
+  char *sc_concentrator_name;  /* if != NULL: requested concentrator id */
+#endif /* PPPOE_TODO */
+  u8_t sc_ac_cookie[PPPOE_MAX_AC_COOKIE_LEN]; /* content of AC cookie we must echo back */
+  size_t sc_ac_cookie_len;     /* length of cookie data */
+#ifdef PPPOE_SERVER
+  u8_t *sc_hunique;            /* content of host unique we must echo back */
+  size_t sc_hunique_len;       /* length of host unique */
+#endif
+  int sc_padi_retried;         /* number of PADI retries already done */
+  int sc_padr_retried;         /* number of PADR retries already done */
+};
 
 
-void pppoe_init(void);
+#define pppoe_init() /* compatibility define, no initialization needed */
 
-err_t pppoe_create(struct netif *ethernetnetif, int pd, void (*linkStatusCB)(int pd, int up), struct pppoe_softc **scptr);
+err_t pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up), struct pppoe_softc **scptr);
 err_t pppoe_destroy(struct netif *ifp);
 
 int pppoe_connect(struct pppoe_softc *sc);
--- a/lwip/lwipopts.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/lwipopts.h	Tue Jul 27 15:59:42 2010 +0000
@@ -53,24 +53,25 @@
 #define TUNIF_DEBUG LWIP_DBG_OFF
 #define UNIXIF_DEBUG LWIP_DBG_OFF
 #define DELIF_DEBUG LWIP_DBG_OFF
-#define SIO_FIFO_DEBUG LWIP_DBG_OFF
-#define TCPDUMP_DEBUG LWIP_DBG_OFF
+#define SIO_FIFO_DEBUG LWIP_DBG_ON
+#define TCPDUMP_DEBUG LWIP_DBG_ON
 
-#define PPP_DEBUG        LWIP_DBG_ON
+#define PPP_DEBUG        LWIP_DBG_OFF
 #define MEM_DEBUG        LWIP_DBG_OFF
 #define MEMP_DEBUG       LWIP_DBG_OFF
 #define PBUF_DEBUG       LWIP_DBG_OFF
 #define API_LIB_DEBUG    LWIP_DBG_OFF
 #define API_MSG_DEBUG    LWIP_DBG_OFF
-#define TCPIP_DEBUG      LWIP_DBG_OFF
-#define NETIF_DEBUG      LWIP_DBG_OFF
+#define TCPIP_DEBUG      LWIP_DBG_ON
+#define NETIF_DEBUG      LWIP_DBG_ON
 #define SOCKETS_DEBUG    LWIP_DBG_OFF
 #define DEMO_DEBUG       LWIP_DBG_OFF
-#define IP_DEBUG         LWIP_DBG_OFF
-#define IP_REASS_DEBUG   LWIP_DBG_OFF
+#define IP_DEBUG         LWIP_DBG_ON
+#define IP_REASS_DEBUG   LWIP_DBG_ON
 #define RAW_DEBUG        LWIP_DBG_OFF
-#define ICMP_DEBUG       LWIP_DBG_OFF
-#define UDP_DEBUG        LWIP_DBG_OFF
+#define ICMP_DEBUG       LWIP_DBG_ON
+#define IGMP_DEBUG       LWIP_DBG_ON
+#define UDP_DEBUG        LWIP_DBG_ON
 #define TCP_DEBUG        LWIP_DBG_OFF
 #define TCP_INPUT_DEBUG  LWIP_DBG_OFF
 #define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
@@ -80,7 +81,7 @@
 #define TCP_FR_DEBUG     LWIP_DBG_OFF
 #define TCP_QLEN_DEBUG   LWIP_DBG_OFF
 #define TCP_RST_DEBUG    LWIP_DBG_OFF
-#define ETHARP_DEBUG     LWIP_DBG_OFF
+#define ETHARP_DEBUG     LWIP_DBG_ON
 #define DNS_DEBUG        LWIP_DBG_OFF
 
 #endif
@@ -174,30 +175,34 @@
 
 /* ---------- TCP options ---------- */
 #define LWIP_TCP                1
-#define TCP_TTL                 255
+//#define TCP_TTL                 255
 
 /* Controls if TCP should queue segments that arrive out of
    order. Define to 0 if your device is low on memory. */
-#define TCP_QUEUE_OOSEQ         0
+#define TCP_QUEUE_OOSEQ         1
 
 /* TCP Maximum segment size. */
 //#define TCP_MSS                 1024
-#define TCP_MSS                   1024//536//0x276
+#define TCP_MSS                   536//1024//536//0x276
 
 /* TCP sender buffer space (bytes). */
-#define TCP_SND_BUF             2048
+#define TCP_SND_BUF             (3 * TCP_MSS) //2048
 
 /* TCP sender buffer space (pbufs). This must be at least = 2 *
    TCP_SND_BUF/TCP_MSS for things to work. */
-#define TCP_SND_QUEUELEN        (2 * TCP_SND_BUF/TCP_MSS)
+#define TCP_SND_QUEUELEN        (4 * (TCP_SND_BUF)/(TCP_MSS))
 
 /* TCP writable space (bytes). This must be less than or equal
    to TCP_SND_BUF. It is the amount of space which must be
    available in the tcp snd_buf for select to return writable */
-#define TCP_SNDLOWAT        (TCP_SND_BUF/2)
+#define TCP_SNDLOWAT        ((TCP_SND_BUF)/2)
 
+/**
+ * TCP_WND: The size of a TCP window.  This must be at least 
+ * (2 * TCP_MSS) for things to work well
+ */
 /* TCP receive window. */
-#define TCP_WND        1024         //8096
+#define TCP_WND        (4 * TCP_MSS)         //8096
 
 /* Maximum number of retransmissions of data segments. */
 //#define TCP_MAXRTX              12
@@ -272,14 +277,14 @@
 
 /* TCP Maximum segment size. */
 //#define TCP_MSS                 1024
-#define TCP_MSS                   512//0x276//536//0x276
+#define TCP_MSS                   1024//0x276//536//0x276
 
 /* TCP sender buffer space (bytes). */
-#define TCP_SND_BUF             1024//2048
+#define TCP_SND_BUF             2048
 
 /* TCP sender buffer space (pbufs). This must be at least = 2 *
    TCP_SND_BUF/TCP_MSS for things to work. */
-#define TCP_SND_QUEUELEN        (4 * TCP_SND_BUF/TCP_MSS)//(4 * TCP_SND_BUF/TCP_MSS)
+#define TCP_SND_QUEUELEN        (2 * TCP_SND_BUF/TCP_MSS)//(4 * TCP_SND_BUF/TCP_MSS)
 
 /* TCP writable space (bytes). This must be less than or equal
    to TCP_SND_BUF. It is the amount of space which must be
@@ -287,7 +292,7 @@
 #define TCP_SNDLOWAT        (TCP_SND_BUF/2)
 
 /* TCP receive window. */
-#define TCP_WND        512         //8096
+#define TCP_WND        1024         //8096
 
 /* Maximum number of retransmissions of data segments. */
 //#define TCP_MAXRTX              12
@@ -299,8 +304,8 @@
 
 /* ---------- ARP options ---------- */
 #define LWIP_ARP                (NET_ETH | NET_ZG2100)
-#define ARP_TABLE_SIZE          2//4//10
-#define ARP_QUEUEING            0//1
+#define ARP_TABLE_SIZE          4//10
+#define ARP_QUEUEING            0
 #define ETHARP_TRUST_IP_MAC     1
 
 /* ---------- IP options ---------- */
@@ -321,6 +326,9 @@
 /* ---------- ICMP options ---------- */
 #define ICMP_TTL                255
 
+/* ---------- IGMP options ---------- */
+#define LWIP_IGMP               (NET_ETH | NET_ZG2100)
+
 /* ---------- DHCP options ---------- */
 /* Define LWIP_DHCP to 1 if you want DHCP configuration of
    interfaces. */
--- a/lwip/lwipopts_light.h	Fri Jul 09 14:46:47 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,454 +0,0 @@
-/*
- * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
- * 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 notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
- *
- * This file is part of the lwIP TCP/IP stack.
- * 
- * Author: Adam Dunkels <adam@sics.se>
- *
- */
-#ifndef __LWIPOPTS_H__
-#define __LWIPOPTS_H__
-
-#include "netCfg.h"
-#if NET_LWIP_STACK
-
-//#include "arch/sys_arch.h"
-
-/* <sys/time.h> is included in cc.h! */
-#define LWIP_TIMEVAL_PRIVATE 0
-
-//#define __LWIP_DEBUG
-#include "dbg/dbg.h"
-
-#ifdef __LWIP_DEBUG
-
-#define LWIP_DEBUG 1
-
-#define LWIP_DBG_MIN_LEVEL 0
-//#define LWIP_COMPAT_SOCKETS 1
-#define TAPIF_DEBUG LWIP_DBG_OFF
-#define TUNIF_DEBUG LWIP_DBG_OFF
-#define UNIXIF_DEBUG LWIP_DBG_OFF
-#define DELIF_DEBUG LWIP_DBG_OFF
-#define SIO_FIFO_DEBUG LWIP_DBG_OFF
-#define TCPDUMP_DEBUG LWIP_DBG_OFF
-
-#define PPP_DEBUG        LWIP_DBG_OFF
-#define MEM_DEBUG        LWIP_DBG_ON
-#define MEMP_DEBUG       LWIP_DBG_ON
-#define PBUF_DEBUG       LWIP_DBG_ON
-#define API_LIB_DEBUG    LWIP_DBG_OFF
-#define API_MSG_DEBUG    LWIP_DBG_OFF
-#define TCPIP_DEBUG      LWIP_DBG_OFF
-#define NETIF_DEBUG      LWIP_DBG_OFF
-#define SOCKETS_DEBUG    LWIP_DBG_OFF
-#define DEMO_DEBUG       LWIP_DBG_OFF
-#define IP_DEBUG         LWIP_DBG_OFF
-#define IP_REASS_DEBUG   LWIP_DBG_OFF
-#define RAW_DEBUG        LWIP_DBG_OFF
-#define ICMP_DEBUG       LWIP_DBG_OFF
-#define UDP_DEBUG        LWIP_DBG_OFF
-#define TCP_DEBUG        LWIP_DBG_OFF
-#define TCP_INPUT_DEBUG  LWIP_DBG_OFF
-#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
-#define TCP_RTO_DEBUG    LWIP_DBG_OFF
-#define TCP_CWND_DEBUG   LWIP_DBG_OFF
-#define TCP_WND_DEBUG    LWIP_DBG_OFF
-#define TCP_FR_DEBUG     LWIP_DBG_OFF
-#define TCP_QLEN_DEBUG   LWIP_DBG_OFF
-#define TCP_RST_DEBUG    LWIP_DBG_OFF
-#define ETHARP_DEBUG     LWIP_DBG_OFF
-#define DNS_DEBUG        LWIP_DBG_OFF
-
-#endif
-
-/*
-extern unsigned char debug_flags;
-#define LWIP_DBG_TYPES_ON debug_flags
-*/
-#define NO_SYS                     1
-#define LWIP_SOCKET                (NO_SYS==0)
-#define LWIP_NETCONN               (NO_SYS==0)
-
-
-#define IP_FRAG_USES_STATIC_BUF         0
-
-
-
-/* ---------- Memory options ---------- */
-/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
-   lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
-   byte alignment -> define MEM_ALIGNMENT to 2. */
-/* MSVC port: intel processors don't need 4-byte alignment,
-   but are faster that way! */
-#define MEM_ALIGNMENT           4
-
-/* MEM_SIZE: the size of the heap memory. If the application will send
-a lot of data that needs to be copied, this should be set high. */
-//#define MEM_SIZE               10240 
-
-#if TARGET_LPC1768
-
-
-#define MEM_SIZE               2000
-
-///
-
-#define MEM_POSITION __attribute((section("AHBSRAM0")))
-
-/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
-   sends a lot of data out of ROM (or other static memory), this
-   should be set high. */
-#define MEMP_NUM_PBUF           8
-/* MEMP_NUM_RAW_PCB: the number of UDP protocol control blocks. One
-   per active RAW "connection". */
-//#define MEMP_NUM_RAW_PCB        3
-/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
-   per active UDP "connection". */
-#define MEMP_NUM_UDP_PCB        2
-/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
-   connections. */
-#define MEMP_NUM_TCP_PCB        2
-/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
-   connections. */
-#define MEMP_NUM_TCP_PCB_LISTEN 2//4
-/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
-   segments. */
-#define MEMP_NUM_TCP_SEG        8
-/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
-   timeouts. */
-#define MEMP_NUM_SYS_TIMEOUT    12
-
-/* The following four are used only with the sequential API and can be
-   set to 0 if the application only will use the raw API. */
-/* MEMP_NUM_NETBUF: the number of struct netbufs. */
-#define MEMP_NUM_NETBUF         0
-/* MEMP_NUM_NETCONN: the number of struct netconns. */
-#define MEMP_NUM_NETCONN        0
-/* MEMP_NUM_TCPIP_MSG_*: the number of struct tcpip_msg, which is used
-   for sequential API communication and incoming packets. Used in
-   src/api/tcpip.c. */
-#define MEMP_NUM_TCPIP_MSG_API   0
-#define MEMP_NUM_TCPIP_MSG_INPKT 0
-
-/* ---------- Pbuf options ---------- */
-/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
-#define PBUF_POOL_SIZE          16//100
-
-/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
-#define PBUF_POOL_BUFSIZE       128
-
-/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a
-   link level header. */
-//#define PBUF_LINK_HLEN          16 
-
-/** SYS_LIGHTWEIGHT_PROT
- * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection
- * for certain critical regions during buffer allocation, deallocation and memory
- * allocation and deallocation.
- */
-#define SYS_LIGHTWEIGHT_PROT           0 //No sys here
-
-/* ---------- TCP options ---------- */
-#define LWIP_TCP                1
-#define TCP_TTL                 255
-
-/* Controls if TCP should queue segments that arrive out of
-   order. Define to 0 if your device is low on memory. */
-#define TCP_QUEUE_OOSEQ         0
-
-/* TCP Maximum segment size. */
-//#define TCP_MSS                 1024
-#define TCP_MSS                   0x276//536//0x276
-
-/* TCP sender buffer space (bytes). */
-#define TCP_SND_BUF             1024
-
-/* TCP sender buffer space (pbufs). This must be at least = 2 *
-   TCP_SND_BUF/TCP_MSS for things to work. */
-#define TCP_SND_QUEUELEN        (2 * TCP_SND_BUF/TCP_MSS)
-
-/* TCP writable space (bytes). This must be less than or equal
-   to TCP_SND_BUF. It is the amount of space which must be
-   available in the tcp snd_buf for select to return writable */
-#define TCP_SNDLOWAT        (TCP_SND_BUF/2)
-
-/* TCP receive window. */
-#define TCP_WND        1024         //8096
-
-/* Maximum number of retransmissions of data segments. */
-//#define TCP_MAXRTX              12
-
-/* Maximum number of retransmissions of SYN segments. */
-//#define TCP_SYNMAXRTX           4
-
-#elif TARGET_LPC2368
-
-#define MEM_POSITION __attribute((section("AHBSRAM1")))
-
-/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
-   sends a lot of data out of ROM (or other static memory), this
-   should be set high. */
-#define MEMP_NUM_PBUF           8
-/* MEMP_NUM_RAW_PCB: the number of UDP protocol control blocks. One
-   per active RAW "connection". */
-//#define MEMP_NUM_RAW_PCB        3
-/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
-   per active UDP "connection". */
-#define MEMP_NUM_UDP_PCB        2
-/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
-   connections. */
-#define MEMP_NUM_TCP_PCB        2
-/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
-   connections. */
-#define MEMP_NUM_TCP_PCB_LISTEN 2//4
-/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
-   segments. */
-#define MEMP_NUM_TCP_SEG        8
-/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
-   timeouts. */
-#define MEMP_NUM_SYS_TIMEOUT    12
-
-/* The following four are used only with the sequential API and can be
-   set to 0 if the application only will use the raw API. */
-/* MEMP_NUM_NETBUF: the number of struct netbufs. */
-#define MEMP_NUM_NETBUF         0
-/* MEMP_NUM_NETCONN: the number of struct netconns. */
-#define MEMP_NUM_NETCONN        0
-/* MEMP_NUM_TCPIP_MSG_*: the number of struct tcpip_msg, which is used
-   for sequential API communication and incoming packets. Used in
-   src/api/tcpip.c. */
-#define MEMP_NUM_TCPIP_MSG_API   0
-#define MEMP_NUM_TCPIP_MSG_INPKT 0
-
-/* ---------- Pbuf options ---------- */
-/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
-#define PBUF_POOL_SIZE          8//16//100
-
-/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
-//#define PBUF_POOL_BUFSIZE       128
-
-/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a
-   link level header. */
-//#define PBUF_LINK_HLEN          16 
-
-/** SYS_LIGHTWEIGHT_PROT
- * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection
- * for certain critical regions during buffer allocation, deallocation and memory
- * allocation and deallocation.
- */
-#define SYS_LIGHTWEIGHT_PROT           0 //No sys here
-
-/* ---------- TCP options ---------- */
-#define LWIP_TCP                1
-#define TCP_TTL                 255
-
-/* Controls if TCP should queue segments that arrive out of
-   order. Define to 0 if your device is low on memory. */
-#define TCP_QUEUE_OOSEQ         0
-
-/* TCP Maximum segment size. */
-//#define TCP_MSS                 1024
-#define TCP_MSS                   512//0x276//536//0x276
-
-/* TCP sender buffer space (bytes). */
-#define TCP_SND_BUF             1024//2048
-
-/* TCP sender buffer space (pbufs). This must be at least = 2 *
-   TCP_SND_BUF/TCP_MSS for things to work. */
-#define TCP_SND_QUEUELEN        (4 * TCP_SND_BUF/TCP_MSS)//(4 * TCP_SND_BUF/TCP_MSS)
-
-/* TCP writable space (bytes). This must be less than or equal
-   to TCP_SND_BUF. It is the amount of space which must be
-   available in the tcp snd_buf for select to return writable */
-#define TCP_SNDLOWAT        (TCP_SND_BUF/2)
-
-/* TCP receive window. */
-#define TCP_WND        512         //8096
-
-/* Maximum number of retransmissions of data segments. */
-//#define TCP_MAXRTX              12
-
-/* Maximum number of retransmissions of SYN segments. */
-//#define TCP_SYNMAXRTX           4
-
-#endif
-
-/* ---------- ARP options ---------- */
-#define LWIP_ARP                (NET_ETH | NET_ZG2100)
-#define ARP_TABLE_SIZE          2//4//10
-#define ARP_QUEUEING            0//1
-#define ETHARP_TRUST_IP_MAC     1
-
-/* ---------- IP options ---------- */
-/* Define IP_FORWARD to 1 if you wish to have the ability to forward
-   IP packets across network interfaces. If you are going to run lwIP
-   on a device with only one network interface, define this to 0. */
-#define IP_FORWARD              0
-
-
-/* IP reassembly and segmentation.These are orthogonal even
- * if they both deal with IP fragments */
- /*
-#define IP_REASSEMBLY     1
-#define IP_REASS_MAX_PBUFS      10
-#define MEMP_NUM_REASSDATA      10
-#define IP_FRAG           1
-*/
-/* ---------- ICMP options ---------- */
-#define ICMP_TTL                255
-
-/* ---------- DHCP options ---------- */
-/* Define LWIP_DHCP to 1 if you want DHCP configuration of
-   interfaces. */
-#define LWIP_DHCP               (NET_ETH | NET_ZG2100)
-
-/* 1 if you want to do an ARP check on the offered address
-   (recommended if using DHCP). */
-#define DHCP_DOES_ARP_CHECK     (LWIP_DHCP)
-
-/* ---------- AUTOIP options ------- */
-#define LWIP_AUTOIP             0
-
-/* ---------- SNMP options ---------- */
-/** @todo SNMP is experimental for now
-    @note UDP must be available for SNMP transport */
-#ifndef LWIP_SNMP
-#define LWIP_SNMP               0
-#endif
-
-
-#ifndef SNMP_PRIVATE_MIB
-#define SNMP_PRIVATE_MIB        0
-#endif
-
-
-/* ---------- UDP options ---------- */
-#define LWIP_UDP                1
-#define UDP_TTL                 255
-
-/* ---------- DNS options ---------- */
-#define LWIP_DNS                1
-
-/* ---------- RAW options ---------- */
-#define LWIP_RAW                0
-#define RAW_TTL                 255
-
-/* ---------- Statistics options ---------- */
-/* individual STATS options can be turned off by defining them to 0 
- * (e.g #define TCP_STATS 0). All of them are turned off if LWIP_STATS
- * is 0
- * */
-
-#define LWIP_STATS    0
-
-/* ---------- PPP options ---------- */
-
-#define PPP_SUPPORT      NET_PPP      /* Set > 0 for PPP */
-
-#if PPP_SUPPORT > 0
-
-#define NUM_PPP 1           /* Max PPP sessions. */
-
-
-/* Select modules to enable.  Ideally these would be set in the makefile but
- * we're limited by the command line length so you need to modify the settings
- * in this file.
- */
-#define PAP_SUPPORT      1      /* Set > 0 for PAP. */
-#define CHAP_SUPPORT     1      /* Set > 0 for CHAP. */
-#define MSCHAP_SUPPORT   0      /* Set > 0 for MSCHAP (NOT FUNCTIONAL!) */
-#define CBCP_SUPPORT     0      /* Set > 0 for CBCP (NOT FUNCTIONAL!) */
-#define CCP_SUPPORT      0      /* Set > 0 for CCP (NOT FUNCTIONAL!) */
-#define VJ_SUPPORT       1      /* Set > 0 for VJ header compression. */
-#define MD5_SUPPORT      1      /* Set > 0 for MD5 (see also CHAP) */
-
-
-/*
- * Timeouts.
- */
-#define FSM_DEFTIMEOUT        6    /* Timeout time in seconds */
-#define FSM_DEFMAXTERMREQS    2    /* Maximum Terminate-Request transmissions */
-#define FSM_DEFMAXCONFREQS    10    /* Maximum Configure-Request transmissions */
-#define FSM_DEFMAXNAKLOOPS    5    /* Maximum number of nak loops */
-
-#define UPAP_DEFTIMEOUT        6    /* Timeout (seconds) for retransmitting req */
-#define UPAP_DEFREQTIME        30    /* Time to wait for auth-req from peer */
-
-#define CHAP_DEFTIMEOUT        6    /* Timeout time in seconds */
-#define CHAP_DEFTRANSMITS    10    /* max # times to send challenge */
-
-
-/* Interval in seconds between keepalive echo requests, 0 to disable. */
-#if 1
-#define LCP_ECHOINTERVAL 0
-#else
-
-#define LCP_ECHOINTERVAL 10
-#endif
-
-
-/* Number of unanswered echo requests before failure. */
-#define LCP_MAXECHOFAILS 3
-
-/* Max Xmit idle time (in jiffies) before resend flag char. */
-#define PPP_MAXIDLEFLAG 0//Send it every time//100
-
-/*
- * Packet sizes
- *
- * Note - lcp shouldn't be allowed to negotiate stuff outside these
- *    limits.  See lcp.h in the pppd directory.
- * (XXX - these constants should simply be shared by lcp.c instead
- *    of living in lcp.h)
- */
-#define PPP_MTU     1500     /* Default MTU (size of Info field) */
-#if 0
-#define PPP_MAXMTU  65535 - (PPP_HDRLEN + PPP_FCSLEN)
-#else
-
-#define PPP_MAXMTU  1500 /* Largest MTU we allow */
-#endif
-
-#define PPP_MINMTU  64
-#define PPP_MRU     1500     /* default MRU = max length of info field */
-#define PPP_MAXMRU  1500     /* Largest MRU we allow */
-#define PPP_DEFMRU    296        /* Try for this */
-#define PPP_MINMRU    128        /* No MRUs below this */
-
-
-#define MAXNAMELEN      64     /* max length of hostname or name for auth */
-#define MAXSECRETLEN    64     /* max length of password or secret */
-
-#endif /* PPP_SUPPORT > 0 */
-
-//C++ Compat
-#define try vTry
-
-#endif
-
-
-#endif /* __LWIPOPTS_H__ */
--- a/lwip/netif/etharp.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/netif/etharp.c	Tue Jul 27 15:59:42 2010 +0000
@@ -83,12 +83,6 @@
 
 #define HWTYPE_ETHERNET 1
 
-#define ARPH_HWLEN(hdr) (ntohs((hdr)->_hwlen_protolen) >> 8)
-#define ARPH_PROTOLEN(hdr) (ntohs((hdr)->_hwlen_protolen) & 0xff)
-
-#define ARPH_HWLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons(ARPH_PROTOLEN(hdr) | ((len) << 8))
-#define ARPH_PROTOLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons((len) | (ARPH_HWLEN(hdr) << 8))
-
 enum etharp_state {
   ETHARP_STATE_EMPTY = 0,
   ETHARP_STATE_PENDING,
@@ -97,35 +91,38 @@
 
 struct etharp_entry {
 #if ARP_QUEUEING
-  /** 
-   * Pointer to queue of pending outgoing packets on this ARP entry.
-   */
+  /** Pointer to queue of pending outgoing packets on this ARP entry. */
   struct etharp_q_entry *q;
 #endif /* ARP_QUEUEING */
   ip_addr_t ipaddr;
   struct eth_addr ethaddr;
-  enum etharp_state state;
+#if LWIP_SNMP
+  struct netif *netif;
+#endif /* LWIP_SNMP */
+  u8_t state;
   u8_t ctime;
-  struct netif *netif;
+#if ETHARP_SUPPORT_STATIC_ENTRIES
+  u8_t static_entry;
+#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
 };
 
 static struct etharp_entry arp_table[ARP_TABLE_SIZE];
+
 #if !LWIP_NETIF_HWADDRHINT
 static u8_t etharp_cached_entry;
 #endif /* !LWIP_NETIF_HWADDRHINT */
 
-/**
- * Try hard to create a new entry - we want the IP address to appear in
- * the cache (even if this means removing an active entry or so). */
-#define ETHARP_TRY_HARD 1
-#define ETHARP_FIND_ONLY  2
+/** Try hard to create a new entry - we want the IP address to appear in
+    the cache (even if this means removing an active entry or so). */
+#define ETHARP_FLAG_TRY_HARD     1
+#define ETHARP_FLAG_FIND_ONLY    2
+#define ETHARP_FLAG_STATIC_ENTRY 4
 
 #if LWIP_NETIF_HWADDRHINT
-#define NETIF_SET_HINT(netif, hint)  if (((netif) != NULL) && ((netif)->addr_hint != NULL))  \
+#define ETHARP_SET_HINT(netif, hint)  if (((netif) != NULL) && ((netif)->addr_hint != NULL))  \
                                       *((netif)->addr_hint) = (hint);
-static s8_t find_entry(ip_addr_t *ipaddr, u8_t flags, struct netif *netif);
 #else /* LWIP_NETIF_HWADDRHINT */
-static s8_t find_entry(ip_addr_t *ipaddr, u8_t flags);
+#define ETHARP_SET_HINT(netif, hint)  (etharp_cached_entry = (hint))
 #endif /* LWIP_NETIF_HWADDRHINT */
 
 static err_t update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags);
@@ -133,7 +130,7 @@
 
 /* Some checks, instead of etharp_init(): */
 #if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f))
-  #error "If you want to use ARP, ARP_TABLE_SIZE must fit in an s8_t, so, you have to reduce it in your lwipopts.h"
+  #error "ARP_TABLE_SIZE must fit in an s8_t, you have to reduce it in your lwipopts.h"
 #endif
 
 
@@ -159,10 +156,41 @@
 }
 #endif /* ARP_QUEUEING */
 
+/** Clean up ARP table entries */
+static void
+free_entry(int i)
+{
+  /* remove from SNMP ARP index tree */
+  snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr);
+#if ARP_QUEUEING
+  /* and empty packet queue */
+  if (arp_table[i].q != NULL) {
+    /* remove all queued packets */
+    LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q)));
+    free_etharp_q(arp_table[i].q);
+    arp_table[i].q = NULL;
+  }
+#endif /* ARP_QUEUEING */
+  /* recycle entry for re-use */      
+  arp_table[i].state = ETHARP_STATE_EMPTY;
+#if ETHARP_SUPPORT_STATIC_ENTRIES
+  arp_table[i].static_entry = 0;
+#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
+#ifdef LWIP_DEBUG
+  /* for debugging, clean out the complete entry */
+  arp_table[i].ctime = 0;
+#if LWIP_SNMP
+  arp_table[i].netif = NULL;
+#endif /* LWIP_SNMP */
+  ip_addr_set_zero(&arp_table[i].ipaddr);
+  arp_table[i].ethaddr = ethzero;
+#endif /* LWIP_DEBUG */
+}
+
 /**
  * Clears expired entries in the ARP table.
  *
- * This function should be called every ETHARP_TMR_INTERVAL microseconds (5 seconds),
+ * This function should be called every ETHARP_TMR_INTERVAL milliseconds (5 seconds),
  * in order to expire entries in the ARP table.
  */
 void
@@ -173,35 +201,29 @@
   LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n"));
   /* remove expired entries from the ARP table */
   for (i = 0; i < ARP_TABLE_SIZE; ++i) {
-    arp_table[i].ctime++;
-    if (((arp_table[i].state == ETHARP_STATE_STABLE) &&
-         (arp_table[i].ctime >= ARP_MAXAGE)) ||
-        ((arp_table[i].state == ETHARP_STATE_PENDING)  &&
-         (arp_table[i].ctime >= ARP_MAXPENDING))) {
-         /* pending or stable entry has become old! */
-      LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n",
-           arp_table[i].state == ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i));
-      /* clean up entries that have just been expired */
-      /* remove from SNMP ARP index tree */
-      snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr);
+    u8_t state = arp_table[i].state;
+    if (state != ETHARP_STATE_EMPTY
+#if ETHARP_SUPPORT_STATIC_ENTRIES
+      && (arp_table[i].static_entry == 0)
+#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
+      ) {
+      arp_table[i].ctime++;
+      if ((arp_table[i].ctime >= ARP_MAXAGE) ||
+          ((arp_table[i].state == ETHARP_STATE_PENDING)  &&
+           (arp_table[i].ctime >= ARP_MAXPENDING))) {
+        /* pending or stable entry has become old! */
+        LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n",
+             arp_table[i].state == ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i));
+        /* clean up entries that have just been expired */
+        free_entry(i);
+      }
 #if ARP_QUEUEING
-      /* and empty packet queue */
-      if (arp_table[i].q != NULL) {
-        /* remove all queued packets */
-        LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q)));
-        free_etharp_q(arp_table[i].q);
-        arp_table[i].q = NULL;
+      /* still pending entry? (not expired) */
+      if (arp_table[i].state == ETHARP_STATE_PENDING) {
+        /* resend an ARP query here? */
       }
 #endif /* ARP_QUEUEING */
-      /* recycle entry for re-use */      
-      arp_table[i].state = ETHARP_STATE_EMPTY;
     }
-#if ARP_QUEUEING
-    /* still pending entry? (not expired) */
-    if (arp_table[i].state == ETHARP_STATE_PENDING) {
-        /* resend an ARP query here? */
-    }
-#endif /* ARP_QUEUEING */
   }
 }
 
@@ -216,23 +238,18 @@
  * If ipaddr is NULL, return a initialized new entry in state ETHARP_EMPTY.
  * 
  * In all cases, attempt to create new entries from an empty entry. If no
- * empty entries are available and ETHARP_TRY_HARD flag is set, recycle
+ * empty entries are available and ETHARP_FLAG_TRY_HARD flag is set, recycle
  * old entries. Heuristic choose the least important entry for recycling.
  *
  * @param ipaddr IP address to find in ARP cache, or to add if not found.
- * @param flags
- * - ETHARP_TRY_HARD: Try hard to create a entry by allowing recycling of
- * active (stable or pending) entries.
+ * @param flags @see definition of ETHARP_FLAG_*
+ * @param netif netif related to this address (used for NETIF_HWADDRHINT)
  *  
  * @return The ARP entry index that matched or is created, ERR_MEM if no
  * entry is found or could be recycled.
  */
 static s8_t
-#if LWIP_NETIF_HWADDRHINT
-find_entry(ip_addr_t *ipaddr, u8_t flags, struct netif *netif)
-#else /* LWIP_NETIF_HWADDRHINT */
 find_entry(ip_addr_t *ipaddr, u8_t flags)
-#endif /* LWIP_NETIF_HWADDRHINT */
 {
   s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE;
   s8_t empty = ARP_TABLE_SIZE;
@@ -244,35 +261,6 @@
   u8_t age_queue = 0;
 #endif /* ARP_QUEUEING */
 
-  /* First, test if the last call to this function asked for the
-   * same address. If so, we're really fast! */
-  if (ipaddr) {
-    /* ipaddr to search for was given */
-#if LWIP_NETIF_HWADDRHINT
-    if ((netif != NULL) && (netif->addr_hint != NULL)) {
-      /* per-pcb cached entry was given */
-      u8_t per_pcb_cache = *(netif->addr_hint);
-      if ((per_pcb_cache < ARP_TABLE_SIZE) && arp_table[per_pcb_cache].state == ETHARP_STATE_STABLE) {
-        /* the per-pcb-cached entry is stable */
-        if (ip_addr_cmp(ipaddr, &arp_table[per_pcb_cache].ipaddr)) {
-          /* per-pcb cached entry was the right one! */
-          ETHARP_STATS_INC(etharp.cachehit);
-          return per_pcb_cache;
-        }
-      }
-    }
-#else /* #if LWIP_NETIF_HWADDRHINT */
-    if (arp_table[etharp_cached_entry].state == ETHARP_STATE_STABLE) {
-      /* the cached entry is stable */
-      if (ip_addr_cmp(ipaddr, &arp_table[etharp_cached_entry].ipaddr)) {
-        /* cached entry was the right one! */
-        ETHARP_STATS_INC(etharp.cachehit);
-        return etharp_cached_entry;
-      }
-    }
-#endif /* #if LWIP_NETIF_HWADDRHINT */
-  }
-
   /**
    * a) do a search through the cache, remember candidates
    * b) select candidate entry
@@ -289,65 +277,61 @@
    */
 
   for (i = 0; i < ARP_TABLE_SIZE; ++i) {
+    u8_t state = arp_table[i].state;
     /* no empty entry found yet and now we do find one? */
-    if ((empty == ARP_TABLE_SIZE) && (arp_table[i].state == ETHARP_STATE_EMPTY)) {
+    if ((empty == ARP_TABLE_SIZE) && (state == ETHARP_STATE_EMPTY)) {
       LWIP_DEBUGF(ETHARP_DEBUG, ("find_entry: found empty entry %"U16_F"\n", (u16_t)i));
       /* remember first empty entry */
       empty = i;
-    }
-    /* pending entry? */
-    else if (arp_table[i].state == ETHARP_STATE_PENDING) {
+    } else if (state != ETHARP_STATE_EMPTY) {
+      LWIP_ASSERT("state == ETHARP_STATE_PENDING || state == ETHARP_STATE_STABLE",
+        state == ETHARP_STATE_PENDING || state == ETHARP_STATE_STABLE);
       /* if given, does IP address match IP address in ARP entry? */
       if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
-        LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching pending entry %"U16_F"\n", (u16_t)i));
+        LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching entry %"U16_F"\n", (u16_t)i));
         /* found exact IP address match, simply bail out */
-#if LWIP_NETIF_HWADDRHINT
-        NETIF_SET_HINT(netif, i);
-#else /* #if LWIP_NETIF_HWADDRHINT */
-        etharp_cached_entry = i;
-#endif /* #if LWIP_NETIF_HWADDRHINT */
         return i;
+      }
+      /* pending entry? */
+      if (state == ETHARP_STATE_PENDING) {
+        /* pending with queued packets? */
 #if ARP_QUEUEING
-      /* pending with queued packets? */
-      } else if (arp_table[i].q != NULL) {
-        if (arp_table[i].ctime >= age_queue) {
-          old_queue = i;
-          age_queue = arp_table[i].ctime;
-        }
+        if (arp_table[i].q != NULL) {
+          if (arp_table[i].ctime >= age_queue) {
+            old_queue = i;
+            age_queue = arp_table[i].ctime;
+          }
+        } else
 #endif /* ARP_QUEUEING */
-      /* pending without queued packets? */
-      } else {
-        if (arp_table[i].ctime >= age_pending) {
-          old_pending = i;
-          age_pending = arp_table[i].ctime;
+        /* pending without queued packets? */
+        {
+          if (arp_table[i].ctime >= age_pending) {
+            old_pending = i;
+            age_pending = arp_table[i].ctime;
+          }
         }
-      }        
-    }
-    /* stable entry? */
-    else if (arp_table[i].state == ETHARP_STATE_STABLE) {
-      /* if given, does IP address match IP address in ARP entry? */
-      if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
-        LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching stable entry %"U16_F"\n", (u16_t)i));
-        /* found exact IP address match, simply bail out */
-#if LWIP_NETIF_HWADDRHINT
-        NETIF_SET_HINT(netif, i);
-#else /* #if LWIP_NETIF_HWADDRHINT */
-        etharp_cached_entry = i;
-#endif /* #if LWIP_NETIF_HWADDRHINT */
-        return i;
-      /* remember entry with oldest stable entry in oldest, its age in maxtime */
-      } else if (arp_table[i].ctime >= age_stable) {
-        old_stable = i;
-        age_stable = arp_table[i].ctime;
+      /* stable entry? */
+      } else if (state == ETHARP_STATE_STABLE) {
+#if ETHARP_SUPPORT_STATIC_ENTRIES
+        /* don't record old_stable for static entries since they never expire */
+        if (arp_table[i].static_entry == 0)
+#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
+        {
+          /* remember entry with oldest stable entry in oldest, its age in maxtime */
+          if (arp_table[i].ctime >= age_stable) {
+            old_stable = i;
+            age_stable = arp_table[i].ctime;
+          }
+        }
       }
     }
   }
   /* { we have no match } => try to create a new entry */
    
   /* don't create new entry, only search? */
-  if (((flags & ETHARP_FIND_ONLY) != 0) ||
+  if (((flags & ETHARP_FLAG_FIND_ONLY) != 0) ||
       /* or no empty entry found and not allowed to recycle? */
-      ((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_TRY_HARD) == 0))) {
+      ((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_FLAG_TRY_HARD) == 0))) {
     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: no empty entry found and not allowed to recycle\n"));
     return (s8_t)ERR_MEM;
   }
@@ -358,51 +342,49 @@
    * 3) oldest pending entry without queued packets
    * 4) oldest pending entry with queued packets
    * 
-   * { ETHARP_TRY_HARD is set at this point }
+   * { ETHARP_FLAG_TRY_HARD is set at this point }
    */ 
 
   /* 1) empty entry available? */
   if (empty < ARP_TABLE_SIZE) {
     i = empty;
     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting empty entry %"U16_F"\n", (u16_t)i));
-  }
-  /* 2) found recyclable stable entry? */
-  else if (old_stable < ARP_TABLE_SIZE) {
-    /* recycle oldest stable*/
-    i = old_stable;
-    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i));
+  } else {
+    /* 2) found recyclable stable entry? */
+    if (old_stable < ARP_TABLE_SIZE) {
+      /* recycle oldest stable*/
+      i = old_stable;
+      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i));
 #if ARP_QUEUEING
-    /* no queued packets should exist on stable entries */
-    LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL);
+      /* no queued packets should exist on stable entries */
+      LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL);
 #endif /* ARP_QUEUEING */
-  /* 3) found recyclable pending entry without queued packets? */
-  } else if (old_pending < ARP_TABLE_SIZE) {
-    /* recycle oldest pending */
-    i = old_pending;
-    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i));
+    /* 3) found recyclable pending entry without queued packets? */
+    } else if (old_pending < ARP_TABLE_SIZE) {
+      /* recycle oldest pending */
+      i = old_pending;
+      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i));
 #if ARP_QUEUEING
-  /* 4) found recyclable pending entry with queued packets? */
-  } else if (old_queue < ARP_TABLE_SIZE) {
-    /* recycle oldest pending */
-    i = old_queue;
-    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q)));
-    free_etharp_q(arp_table[i].q);
-    arp_table[i].q = NULL;
+    /* 4) found recyclable pending entry with queued packets? */
+    } else if (old_queue < ARP_TABLE_SIZE) {
+      /* recycle oldest pending (queued packets are free in free_entry) */
+      i = old_queue;
+      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q)));
 #endif /* ARP_QUEUEING */
-    /* no empty or recyclable entries found */
-  } else {
-    return (s8_t)ERR_MEM;
+      /* no empty or recyclable entries found */
+    } else {
+      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: no empty or recyclable entries found\n"));
+      return (s8_t)ERR_MEM;
+    }
+
+    /* { empty or recyclable entry found } */
+    LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE);
+    free_entry(i);
   }
 
-  /* { empty or recyclable entry found } */
   LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE);
-
-  if (arp_table[i].state != ETHARP_STATE_EMPTY)
-  {
-    snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr);
-  }
-  /* recycle entry (no-op for an already empty entry) */
-  arp_table[i].state = ETHARP_STATE_EMPTY;
+  LWIP_ASSERT("arp_table[i].state == ETHARP_STATE_EMPTY",
+    arp_table[i].state == ETHARP_STATE_EMPTY);
 
   /* IP address given? */
   if (ipaddr != NULL) {
@@ -410,11 +392,9 @@
     ip_addr_copy(arp_table[i].ipaddr, *ipaddr);
   }
   arp_table[i].ctime = 0;
-#if LWIP_NETIF_HWADDRHINT
-  NETIF_SET_HINT(netif, i);
-#else /* #if LWIP_NETIF_HWADDRHINT */
-  etharp_cached_entry = i;
-#endif /* #if LWIP_NETIF_HWADDRHINT */
+#if ETHARP_SUPPORT_STATIC_ENTRIES
+  arp_table[i].static_entry = 0;
+#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
   return (err_t)i;
 }
 
@@ -432,17 +412,12 @@
 etharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst)
 {
   struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload;
-  u8_t k;
 
   LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
               (netif->hwaddr_len == ETHARP_HWADDR_LEN));
-  k = ETHARP_HWADDR_LEN;
-  while(k > 0) {
-    k--;
-    ethhdr->dest.addr[k] = dst->addr[k];
-    ethhdr->src.addr[k]  = src->addr[k];
-  }
-  ethhdr->type = htons(ETHTYPE_IP);
+  ETHADDR32_COPY(&ethhdr->dest, dst);
+  ETHADDR16_COPY(&ethhdr->src, src);
+  ethhdr->type = PP_HTONS(ETHTYPE_IP);
   LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_send_ip: sending packet %p\n", (void *)p));
   /* send the packet */
   return netif->linkoutput(netif, p);
@@ -454,15 +429,14 @@
  * If a pending entry is resolved, any queued packets will be sent
  * at this point.
  * 
+ * @param netif netif related to this entry (used for NETIF_ADDRHINT)
  * @param ipaddr IP address of the inserted ARP entry.
  * @param ethaddr Ethernet address of the inserted ARP entry.
- * @param flags Defines behaviour:
- * - ETHARP_TRY_HARD Allows ARP to insert this as a new item. If not specified,
- * only existing ARP entries will be updated.
+ * @param flags @see definition of ETHARP_FLAG_*
  *
  * @return
  * - ERR_OK Succesfully updated ARP cache.
- * - ERR_MEM If we could not add a new ARP entry when ETHARP_TRY_HARD was set.
+ * - ERR_MEM If we could not add a new ARP entry when ETHARP_FLAG_TRY_HARD was set.
  * - ERR_ARG Non-unicast address given, those will not appear in ARP cache.
  *
  * @see pbuf_free()
@@ -471,8 +445,6 @@
 update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags)
 {
   s8_t i;
-  u8_t k;
-  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry()\n"));
   LWIP_ASSERT("netif->hwaddr_len == ETHARP_HWADDR_LEN", netif->hwaddr_len == ETHARP_HWADDR_LEN);
   LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n",
     ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr),
@@ -486,30 +458,32 @@
     return ERR_ARG;
   }
   /* find or create ARP entry */
-#if LWIP_NETIF_HWADDRHINT
-  i = find_entry(ipaddr, flags, netif);
-#else /* LWIP_NETIF_HWADDRHINT */
   i = find_entry(ipaddr, flags);
-#endif /* LWIP_NETIF_HWADDRHINT */
   /* bail out if no entry could be found */
-  if (i < 0)
+  if (i < 0) {
     return (err_t)i;
-  
+  }
+
+#if ETHARP_SUPPORT_STATIC_ENTRIES
+  if (flags & ETHARP_FLAG_STATIC_ENTRY) {
+    /* record static type */
+    arp_table[i].static_entry = 1;
+  }
+#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
+
   /* mark it stable */
   arp_table[i].state = ETHARP_STATE_STABLE;
+
+#if LWIP_SNMP
   /* record network interface */
   arp_table[i].netif = netif;
-
+#endif /* LWIP_SNMP */
   /* insert in SNMP ARP index tree */
   snmp_insert_arpidx_tree(netif, &arp_table[i].ipaddr);
 
   LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i));
   /* update address */
-  k = ETHARP_HWADDR_LEN;
-  while (k > 0) {
-    k--;
-    arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
-  }
+  ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr);
   /* reset time stamp */
   arp_table[i].ctime = 0;
 #if ARP_QUEUEING
@@ -533,6 +507,65 @@
   return ERR_OK;
 }
 
+#if ETHARP_SUPPORT_STATIC_ENTRIES
+/** Add a new static entry to the ARP table. If an entry exists for the
+ * specified IP address, this entry is overwritten.
+ * If packets are queued for the specified IP address, they are sent out.
+ *
+ * @param ipaddr IP address for the new static entry
+ * @param ethaddr ethernet address for the new static entry
+ * @return @see return values of etharp_add_static_entry
+ */
+err_t
+etharp_add_static_entry(ip_addr_t *ipaddr, struct eth_addr *ethaddr)
+{
+  struct netif *netif;
+  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_add_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n",
+    ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr),
+    ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2],
+    ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5]));
+
+  netif = ip_route(ipaddr);
+  if (netif == NULL) {
+    return ERR_RTE;
+  }
+
+  return update_arp_entry(netif, ipaddr, ethaddr, ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY);
+}
+
+/** Remove a static entry from the ARP table previously added with a call to
+ * etharp_add_static_entry.
+ *
+ * @param ipaddr IP address of the static entry to remove
+ * @return ERR_OK: entry removed
+ *         ERR_MEM: entry wasn't found
+ *         ERR_ARG: entry wasn't a static entry but a dynamic one
+ */
+err_t
+etharp_remove_static_entry(ip_addr_t *ipaddr)
+{
+  s8_t i;
+  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_remove_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
+    ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));
+
+  /* find or create ARP entry */
+  i = find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY);
+  /* bail out if no entry could be found */
+  if (i < 0) {
+    return (err_t)i;
+  }
+
+  if ((arp_table[i].state != ETHARP_STATE_STABLE) ||
+    (arp_table[i].static_entry == 0)) {
+    /* entry wasn't a static entry, cannot remove it */
+    return ERR_ARG;
+  }
+  /* entry found, free it */
+  free_entry(i);
+  return ERR_OK;
+}
+#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
+
 /**
  * Finds (stable) ethernet/IP address pair from ARP table
  * using interface and IP address index.
@@ -550,13 +583,12 @@
 {
   s8_t i;
 
+  LWIP_ASSERT("eth_ret != NULL && ip_ret != NULL",
+    eth_ret != NULL && ip_ret != NULL);
+
   LWIP_UNUSED_ARG(netif);
 
-#if LWIP_NETIF_HWADDRHINT
-  i = find_entry(ipaddr, ETHARP_FIND_ONLY, NULL);
-#else /* LWIP_NETIF_HWADDRHINT */
-  i = find_entry(ipaddr, ETHARP_FIND_ONLY);
-#endif /* LWIP_NETIF_HWADDRHINT */
+  i = find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY);
   if((i >= 0) && arp_table[i].state == ETHARP_STATE_STABLE) {
       *eth_ret = &arp_table[i].ethaddr;
       *ip_ret = &arp_table[i].ipaddr;
@@ -564,6 +596,7 @@
   }
   return -1;
 }
+
 #if ETHARP_TRUST_IP_MAC
 /**
  * Updates the ARP table using the given IP packet.
@@ -585,6 +618,7 @@
 {
   struct eth_hdr *ethhdr;
   struct ip_hdr *iphdr;
+  ip_addr_t iphdr_src;
   LWIP_ERROR("netif != NULL", (netif != NULL), return;);
 
   /* Only insert an entry if the source IP address of the
@@ -597,17 +631,19 @@
   }
 #endif /* ETHARP_SUPPORT_VLAN */
 
+  ip_addr_copy(iphdr_src, iphdr->src);
+
   /* source is not on the local network? */
-  if (!ip_addr_netcmp(&(iphdr->src), &(netif->ip_addr), &(netif->netmask))) {
+  if (!ip_addr_netcmp(&iphdr_src, &(netif->ip_addr), &(netif->netmask))) {
     /* do nothing */
     return;
   }
 
   LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n"));
   /* update the source IP address in the cache, if present */
-  /* @todo We could use ETHARP_TRY_HARD if we think we are going to talk
+  /* @todo We could use ETHARP_FLAG_TRY_HARD if we think we are going to talk
    * back soon (for example, if the destination IP address is ours. */
-  update_arp_entry(netif, &(iphdr->src), &(ethhdr->src), ETHARP_FIND_ONLY);
+  update_arp_entry(netif, &iphdr_src, &(ethhdr->src), ETHARP_FLAG_FIND_ONLY);
 }
 #endif /* ETHARP_TRUST_IP_MAC */
 
@@ -633,7 +669,6 @@
   struct eth_hdr *ethhdr;
   /* these are aligned properly, whereas the ARP header fields might not be */
   ip_addr_t sipaddr, dipaddr;
-  u8_t i;
   u8_t for_us;
 #if LWIP_AUTOIP
   const u8_t * ethdst_hwaddr;
@@ -662,13 +697,14 @@
 #endif /* ETHARP_SUPPORT_VLAN */
 
   /* RFC 826 "Packet Reception": */
-  if ((hdr->hwtype != htons(HWTYPE_ETHERNET)) ||
-      (hdr->_hwlen_protolen != htons((ETHARP_HWADDR_LEN << 8) | sizeof(ip_addr_t))) ||
-      (hdr->proto != htons(ETHTYPE_IP)) ||
-      (ethhdr->type != htons(ETHTYPE_ARP)))  {
+  if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) ||
+      (hdr->hwlen != ETHARP_HWADDR_LEN) ||
+      (hdr->protolen != sizeof(ip_addr_t)) ||
+      (hdr->proto != PP_HTONS(ETHTYPE_IP)) ||
+      (ethhdr->type != PP_HTONS(ETHTYPE_ARP)))  {
     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
       ("etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
-      hdr->hwtype, ARPH_HWLEN(hdr), hdr->proto, ARPH_PROTOLEN(hdr), ethhdr->type));
+      hdr->hwtype, hdr->hwlen, hdr->proto, hdr->protolen, ethhdr->type));
     ETHARP_STATS_INC(etharp.proterr);
     ETHARP_STATS_INC(etharp.drop);
     pbuf_free(p);
@@ -685,8 +721,8 @@
 
   /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
    * structure packing (not using structure copy which breaks strict-aliasing rules). */
-  SMEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr));
-  SMEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr));
+  IPADDR2_COPY(&sipaddr, &hdr->sipaddr);
+  IPADDR2_COPY(&dipaddr, &hdr->dipaddr);
 
   /* this interface is not configured? */
   if (ip_addr_isany(&netif->ip_addr)) {
@@ -696,21 +732,18 @@
     for_us = (u8_t)ip_addr_cmp(&dipaddr, &(netif->ip_addr));
   }
 
-  /* ARP message directed to us? */
-  if (for_us) {
-    /* add IP address in ARP cache; assume requester wants to talk to us.
-     * can result in directly sending the queued packets for this host. */
-    update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), ETHARP_TRY_HARD);
-  /* ARP message not directed to us? */
-  } else {
-    /* update the source IP address in the cache, if present */
-    update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), ETHARP_FIND_ONLY);
-  }
+  /* ARP message directed to us?
+      -> add IP address in ARP cache; assume requester wants to talk to us,
+         can result in directly sending the queued packets for this host.
+     ARP message not directed to us?
+      ->  update the source IP address in the cache, if present */
+  update_arp_entry(netif, &sipaddr, &(hdr->shwaddr),
+                   for_us ? ETHARP_FLAG_TRY_HARD : ETHARP_FLAG_FIND_ONLY);
 
   /* now act on the message itself */
-  switch (htons(hdr->opcode)) {
+  switch (hdr->opcode) {
   /* ARP request? */
-  case ARP_REQUEST:
+  case PP_HTONS(ARP_REQUEST):
     /* ARP request. If it asked for our address, we send out a
      * reply. In any case, we time-stamp any existing ARP entry,
      * and possiby send out an IP packet that was queued on it. */
@@ -725,12 +758,11 @@
          that would allocate a new pbuf. */
       hdr->opcode = htons(ARP_REPLY);
 
-      SMEMCPY(&hdr->dipaddr, &hdr->sipaddr, sizeof(ip_addr_t));
-      SMEMCPY(&hdr->sipaddr, &netif->ip_addr, sizeof(ip_addr_t));
+      IPADDR2_COPY(&hdr->dipaddr, &hdr->sipaddr);
+      IPADDR2_COPY(&hdr->sipaddr, &netif->ip_addr);
 
       LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
                   (netif->hwaddr_len == ETHARP_HWADDR_LEN));
-      i = ETHARP_HWADDR_LEN;
 #if LWIP_AUTOIP
       /* If we are using Link-Local, all ARP packets that contain a Link-Local
        * 'sender IP address' MUST be sent using link-layer broadcast instead of
@@ -738,17 +770,14 @@
       ethdst_hwaddr = ip_addr_islinklocal(&netif->ip_addr) ? (u8_t*)(ethbroadcast.addr) : hdr->shwaddr.addr;
 #endif /* LWIP_AUTOIP */
 
-      while(i > 0) {
-        i--;
-        hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i];
+      ETHADDR16_COPY(&hdr->dhwaddr, &hdr->shwaddr);
 #if LWIP_AUTOIP
-        ethhdr->dest.addr[i] = ethdst_hwaddr[i];
+      ETHADDR16_COPY(&ethhdr->dest, ethdst_hwaddr);
 #else  /* LWIP_AUTOIP */
-        ethhdr->dest.addr[i] = hdr->shwaddr.addr[i];
+      ETHADDR16_COPY(&ethhdr->dest, &hdr->shwaddr);
 #endif /* LWIP_AUTOIP */
-        hdr->shwaddr.addr[i] = ethaddr->addr[i];
-        ethhdr->src.addr[i] = ethaddr->addr[i];
-      }
+      ETHADDR16_COPY(&hdr->shwaddr, ethaddr);
+      ETHADDR16_COPY(&ethhdr->src, ethaddr);
 
       /* hwtype, hwaddr_len, proto, protolen and the type in the ethernet header
          are already correct, we tested that before */
@@ -765,7 +794,7 @@
       LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP request was not for us.\n"));
     }
     break;
-  case ARP_REPLY:
+  case PP_HTONS(ARP_REPLY):
     /* ARP reply. We already updated the ARP cache earlier. */
     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n"));
 #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
@@ -852,6 +881,23 @@
         return ERR_RTE;
       }
     }
+#if LWIP_NETIF_HWADDRHINT
+    if (netif->addr_hint != NULL) {
+      /* per-pcb cached entry was given */
+      u8_t etharp_cached_entry = *(netif->addr_hint);
+      if (etharp_cached_entry < ARP_TABLE_SIZE) {
+#endif /* LWIP_NETIF_HWADDRHINT */
+        if ((arp_table[etharp_cached_entry].state == ETHARP_STATE_STABLE) &&
+            (ip_addr_cmp(ipaddr, &arp_table[etharp_cached_entry].ipaddr))) {
+          /* the per-pcb-cached entry is stable and the right one! */
+          ETHARP_STATS_INC(etharp.cachehit);
+          return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr),
+            &arp_table[etharp_cached_entry].ethaddr);
+        }
+#if LWIP_NETIF_HWADDRHINT
+      }
+    }
+#endif /* LWIP_NETIF_HWADDRHINT */
     /* queue on destination Ethernet address belonging to ipaddr */
     return etharp_query(netif, ipaddr, q);
   }
@@ -911,11 +957,7 @@
   }
 
   /* find entry in ARP cache, ask to create entry if queueing packet */
-#if LWIP_NETIF_HWADDRHINT
-  i = find_entry(ipaddr, ETHARP_TRY_HARD, netif);
-#else /* LWIP_NETIF_HWADDRHINT */
-  i = find_entry(ipaddr, ETHARP_TRY_HARD);
-#endif /* LWIP_NETIF_HWADDRHINT */
+  i = find_entry(ipaddr, ETHARP_FLAG_TRY_HARD);
 
   /* could not find or create entry? */
   if (i < 0) {
@@ -947,86 +989,89 @@
          since this failure could be temporary, and the next packet calling
          etharp_query again could lead to sending the queued packets. */
     }
+    if (q == NULL) {
+      return result;
+    }
   }
-  
+
   /* packet given? */
-  if (q != NULL) {
-    /* stable entry? */
-    if (arp_table[i].state == ETHARP_STATE_STABLE) {
-      /* we have a valid IP->Ethernet address mapping */
-      /* send the packet */
-      result = etharp_send_ip(netif, q, srcaddr, &(arp_table[i].ethaddr));
-    /* pending entry? (either just created or already pending */
-    } else if (arp_table[i].state == ETHARP_STATE_PENDING) {
+  LWIP_ASSERT("q != NULL", q != NULL);
+  /* stable entry? */
+  if (arp_table[i].state == ETHARP_STATE_STABLE) {
+    /* we have a valid IP->Ethernet address mapping */
+    ETHARP_SET_HINT(netif, i);
+    /* send the packet */
+    result = etharp_send_ip(netif, q, srcaddr, &(arp_table[i].ethaddr));
+  /* pending entry? (either just created or already pending */
+  } else if (arp_table[i].state == ETHARP_STATE_PENDING) {
 #if ARP_QUEUEING /* queue the given q packet */
-      struct pbuf *p;
-      int copy_needed = 0;
-      /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but
-       * to copy the whole queue into a new PBUF_RAM (see bug #11400) 
-       * PBUF_ROMs can be left as they are, since ROM must not get changed. */
+    struct pbuf *p;
+    int copy_needed = 0;
+    /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but
+     * to copy the whole queue into a new PBUF_RAM (see bug #11400) 
+     * PBUF_ROMs can be left as they are, since ROM must not get changed. */
+    p = q;
+    while (p) {
+      LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0));
+      if(p->type != PBUF_ROM) {
+        copy_needed = 1;
+        break;
+      }
+      p = p->next;
+    }
+    if(copy_needed) {
+      /* copy the whole packet into new pbufs */
+      p = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
+      if(p != NULL) {
+        if (pbuf_copy(p, q) != ERR_OK) {
+          pbuf_free(p);
+          p = NULL;
+        }
+      }
+    } else {
+      /* referencing the old pbuf is enough */
       p = q;
-      while (p) {
-        LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0));
-        if(p->type != PBUF_ROM) {
-          copy_needed = 1;
-          break;
+      pbuf_ref(p);
+    }
+    /* packet could be taken over? */
+    if (p != NULL) {
+      /* queue packet ... */
+      struct etharp_q_entry *new_entry;
+      /* allocate a new arp queue entry */
+      new_entry = (struct etharp_q_entry *)memp_malloc(MEMP_ARP_QUEUE);
+      if (new_entry != NULL) {
+        new_entry->next = 0;
+        new_entry->p = p;
+        if(arp_table[i].q != NULL) {
+          /* queue was already existent, append the new entry to the end */
+          struct etharp_q_entry *r;
+          r = arp_table[i].q;
+          while (r->next != NULL) {
+            r = r->next;
+          }
+          r->next = new_entry;
+        } else {
+          /* queue did not exist, first item in queue */
+          arp_table[i].q = new_entry;
         }
-        p = p->next;
-      }
-      if(copy_needed) {
-        /* copy the whole packet into new pbufs */
-        p = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
-        if(p != NULL) {
-          if (pbuf_copy(p, q) != ERR_OK) {
-            pbuf_free(p);
-            p = NULL;
-          }
-        }
+        LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
+        result = ERR_OK;
       } else {
-        /* referencing the old pbuf is enough */
-        p = q;
-        pbuf_ref(p);
-      }
-      /* packet could be taken over? */
-      if (p != NULL) {
-        /* queue packet ... */
-        struct etharp_q_entry *new_entry;
-        /* allocate a new arp queue entry */
-        new_entry = (struct etharp_q_entry *)memp_malloc(MEMP_ARP_QUEUE);
-        if (new_entry != NULL) {
-          new_entry->next = 0;
-          new_entry->p = p;
-          if(arp_table[i].q != NULL) {
-            /* queue was already existent, append the new entry to the end */
-            struct etharp_q_entry *r;
-            r = arp_table[i].q;
-            while (r->next != NULL) {
-              r = r->next;
-            }
-            r->next = new_entry;
-          } else {
-            /* queue did not exist, first item in queue */
-            arp_table[i].q = new_entry;
-          }
-          LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
-          result = ERR_OK;
-        } else {
-          /* the pool MEMP_ARP_QUEUE is empty */
-          pbuf_free(p);
-          LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
-          /* { result == ERR_MEM } through initialization */
-        }
-      } else {
-        ETHARP_STATS_INC(etharp.memerr);
+        /* the pool MEMP_ARP_QUEUE is empty */
+        pbuf_free(p);
         LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
         /* { result == ERR_MEM } through initialization */
       }
-#else /* ARP_QUEUEING */
-      /* q && state == PENDING && ARP_QUEUEING == 0 => result = ERR_MEM */
+    } else {
+      ETHARP_STATS_INC(etharp.memerr);
+      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
       /* { result == ERR_MEM } through initialization */
-      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: Ethernet destination address unknown, queueing disabled, packet %p dropped\n", (void *)q));
+    }
+#else /* ARP_QUEUEING */
+    /* q && state == PENDING && ARP_QUEUEING == 0 => result = ERR_MEM */
+    /* { result == ERR_MEM } through initialization */
+    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: Ethernet destination address unknown, queueing disabled, packet %p dropped\n", (void *)q));
 #endif /* ARP_QUEUEING */
-    }
   }
   return result;
 }
@@ -1058,7 +1103,6 @@
 {
   struct pbuf *p;
   err_t result = ERR_OK;
-  u8_t k; /* ARP entry index */
   struct eth_hdr *ethhdr;
   struct etharp_hdr *hdr;
 #if LWIP_AUTOIP
@@ -1084,38 +1128,34 @@
 
   LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
               (netif->hwaddr_len == ETHARP_HWADDR_LEN));
-  k = ETHARP_HWADDR_LEN;
 #if LWIP_AUTOIP
   /* If we are using Link-Local, all ARP packets that contain a Link-Local
    * 'sender IP address' MUST be sent using link-layer broadcast instead of
    * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */
   ethdst_hwaddr = ip_addr_islinklocal(ipsrc_addr) ? (u8_t*)(ethbroadcast.addr) : ethdst_addr->addr;
 #endif /* LWIP_AUTOIP */
-  /* Write MAC-Addresses (combined loop for both headers) */
-  while(k > 0) {
-    k--;
-    /* Write the ARP MAC-Addresses */
-    hdr->shwaddr.addr[k] = hwsrc_addr->addr[k];
-    hdr->dhwaddr.addr[k] = hwdst_addr->addr[k];
-    /* Write the Ethernet MAC-Addresses */
+  /* Write the ARP MAC-Addresses */
+  ETHADDR16_COPY(&hdr->shwaddr, hwsrc_addr);
+  ETHADDR16_COPY(&hdr->dhwaddr, hwdst_addr);
+  /* Write the Ethernet MAC-Addresses */
 #if LWIP_AUTOIP
-    ethhdr->dest.addr[k] = ethdst_hwaddr[k];
+  ETHADDR16_COPY(&ethhdr->dest, ethdst_hwaddr);
 #else  /* LWIP_AUTOIP */
-    ethhdr->dest.addr[k] = ethdst_addr->addr[k];
+  ETHADDR16_COPY(&ethhdr->dest, ethdst_addr);
 #endif /* LWIP_AUTOIP */
-    ethhdr->src.addr[k]  = ethsrc_addr->addr[k];
-  }
+  ETHADDR16_COPY(&ethhdr->src, ethsrc_addr);
   /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
    * structure packing. */ 
-  SMEMCPY(&hdr->sipaddr, ipsrc_addr, sizeof(ip_addr_t));
-  SMEMCPY(&hdr->dipaddr, ipdst_addr, sizeof(ip_addr_t));
+  IPADDR2_COPY(&hdr->sipaddr, ipsrc_addr);
+  IPADDR2_COPY(&hdr->dipaddr, ipdst_addr);
 
-  hdr->hwtype = htons(HWTYPE_ETHERNET);
-  hdr->proto = htons(ETHTYPE_IP);
-  /* set hwlen and protolen together */
-  hdr->_hwlen_protolen = htons((ETHARP_HWADDR_LEN << 8) | sizeof(ip_addr_t));
+  hdr->hwtype = PP_HTONS(HWTYPE_ETHERNET);
+  hdr->proto = PP_HTONS(ETHTYPE_IP);
+  /* set hwlen and protolen */
+  hdr->hwlen = ETHARP_HWADDR_LEN;
+  hdr->protolen = sizeof(ip_addr_t);
 
-  ethhdr->type = htons(ETHTYPE_ARP);
+  ethhdr->type = PP_HTONS(ETHTYPE_ARP);
   /* send ARP query */
   result = netif->linkoutput(netif, p);
   ETHARP_STATS_INC(etharp.xmit);
@@ -1170,9 +1210,9 @@
      (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5],
      (unsigned)htons(ethhdr->type)));
 
-  type = htons(ethhdr->type);
+  type = ethhdr->type;
 #if ETHARP_SUPPORT_VLAN
-  if (type == ETHTYPE_VLAN) {
+  if (type == PP_HTONS(ETHTYPE_VLAN)) {
     struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR);
 #ifdef ETHARP_VLAN_CHECK /* if not, allow all VLANs */
     if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) {
@@ -1181,14 +1221,18 @@
       return ERR_OK;
     }
 #endif /* ETHARP_VLAN_CHECK */
-    type = htons(vlan->tpid);
+    type = vlan->tpid;
   }
 #endif /* ETHARP_SUPPORT_VLAN */
 
+#if LWIP_ARP_FILTER_NETIF
+  netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, htons(type));
+#endif /* LWIP_ARP_FILTER_NETIF*/
+
   switch (type) {
 #if LWIP_ARP
     /* IP packet? */
-    case ETHTYPE_IP:
+    case PP_HTONS(ETHTYPE_IP):
       if (!(netif->flags & NETIF_FLAG_ETHARP)) {
         goto free_and_return;
       }
@@ -1206,7 +1250,7 @@
       }
       break;
       
-    case ETHTYPE_ARP:
+    case PP_HTONS(ETHTYPE_ARP):
       if (!(netif->flags & NETIF_FLAG_ETHARP)) {
         goto free_and_return;
       }
@@ -1215,11 +1259,11 @@
       break;
 #endif /* LWIP_ARP */
 #if PPPOE_SUPPORT
-    case ETHTYPE_PPPOEDISC: /* PPP Over Ethernet Discovery Stage */
+    case PP_HTONS(ETHTYPE_PPPOEDISC): /* PPP Over Ethernet Discovery Stage */
       pppoe_disc_input(netif, p);
       break;
 
-    case ETHTYPE_PPPOE: /* PPP Over Ethernet Session Stage */
+    case PP_HTONS(ETHTYPE_PPPOE): /* PPP Over Ethernet Session Stage */
       pppoe_data_input(netif, p);
       break;
 #endif /* PPPOE_SUPPORT */
--- a/lwip/netif/ppp/fsm.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/netif/ppp/fsm.c	Tue Jul 27 15:59:42 2010 +0000
@@ -120,11 +120,9 @@
 void
 fsm_lowerup(fsm *f)
 {
-  #if PPP_DEBUG
   int oldState = f->state;
 
   LWIP_UNUSED_ARG(oldState);
-  #endif
 
   switch( f->state ) {
     case LS_INITIAL:
@@ -159,11 +157,9 @@
 void
 fsm_lowerdown(fsm *f)
 {
-  #if PPP_DEBUG
   int oldState = f->state;
 
   LWIP_UNUSED_ARG(oldState);
-  #endif
 
   switch( f->state ) {
     case LS_CLOSED:
@@ -213,11 +209,9 @@
 void
 fsm_open(fsm *f)
 {
-  #if PPP_DEBUG
   int oldState = f->state;
 
   LWIP_UNUSED_ARG(oldState);
-  #endif
 
   switch( f->state ) {
     case LS_INITIAL:
@@ -276,11 +270,9 @@
 void
 fsm_close(fsm *f, char *reason)
 {
-  #if PPP_DEBUG
   int oldState = f->state;
 
   LWIP_UNUSED_ARG(oldState);
-  #endif
 
   f->term_reason = reason;
   f->term_reason_len = (reason == NULL ? 0 : (int)strlen(reason));
--- a/lwip/netif/ppp/ppp.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/netif/ppp/ppp.c	Tue Jul 27 15:59:42 2010 +0000
@@ -249,7 +249,7 @@
 /******************************/
 u_long subnetMask;
 
-static PPPControl pppControl[NUM_PPP]; /* The PPP interface control blocks. */
+static PPPControl pppControl[NUM_PPP] MEM_POSITION; /* The PPP interface control blocks. */
 
 /*
  * PPP Data Link Layer "protocol" table.
@@ -279,7 +279,7 @@
  * Buffers for outgoing packets.  This must be accessed only from the appropriate
  * PPP task so that it doesn't need to be protected to avoid collisions.
  */
-u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN];
+u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN] MEM_POSITION;
 
 
 /*****************************/
@@ -705,7 +705,7 @@
   int c;
 
   for(b = nb; b != NULL; b = b->next) {
-    if((c = sio_write(pc->fd, (u8_t*)b->payload, b->len)) != b->len) {
+    if((c = sio_write(pc->fd, (u8_t *)b->payload, b->len)) != b->len) {
       PPPDEBUG(LOG_WARNING,
                ("PPP nPut: incomplete sio_write(fd:%"SZT_F", len:%d, c: 0x%"X8_F") c = %d\n", (size_t)pc->fd, b->len, c, c));
       LINK_STATS_INC(link.err);
@@ -1579,7 +1579,7 @@
     return p; /* live dangerously */
   }
 
-  for(b = p, pl = (u_char*)q->payload; b != NULL; b = b->next) {
+  for(b = p, pl = (u_char *) q->payload; b != NULL; b = b->next) {
     MEMCPY(pl, b->payload, b->len);
     pl += b->len;
   }
@@ -1690,7 +1690,7 @@
         if (protp->protocol == protocol && protp->enabled_flag) {
           PPPDEBUG(LOG_INFO, ("pppInput[%d]: %s len=%d\n", pd, protp->name, nb->len));
           nb = pppSingleBuf(nb);
-          (*protp->input)(pd, (u_char*)nb->payload, nb->len);
+          (*protp->input)(pd, (u_char *)nb->payload, nb->len);
           PPPDEBUG(LOG_DETAIL, ("pppInput[%d]: packet processed\n", pd));
           goto out;
         }
@@ -1706,7 +1706,7 @@
       protocol = htons(protocol);
       SMEMCPY(nb->payload, &protocol, sizeof(protocol));
 #endif /* BYTE_ORDER == LITTLE_ENDIAN */
-      lcp_sprotrej(pd, (u_char*)nb->payload, nb->len);
+      lcp_sprotrej(pd, (u_char *)nb->payload, nb->len);
     }
     break;
   }
--- a/lwip/netif/ppp/vj.c	Fri Jul 09 14:46:47 2010 +0000
+++ b/lwip/netif/ppp/vj.c	Tue Jul 27 15:59:42 2010 +0000
@@ -608,7 +608,7 @@
       goto bad;
     }
 
-    bufptr = (u8_t*)n0->payload;
+    bufptr = (u8_t *)n0->payload;
     for(q = np; q != NULL; q = q->next) {
       MEMCPY(q->payload, bufptr, q->len);
       bufptr += q->len;
--- a/netCfg.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/netCfg.h	Tue Jul 27 15:59:42 2010 +0000
@@ -1,11 +1,9 @@
 #ifndef NET_CFG_H
-#define NET_TELIT_STACK 0
 #define NET_GPRS 1
 #define NET_PPP 1
-#define NET_ZG2100 0
+#define NET_GPRS_MODULE 1
 #define NET_ETH 1
 #define NET_USB_SERIAL 1
-#define NET_TELIT 1
 #define NET_CFG_H 1
 #define NET_UMTS 1
 #define NET_USB 1
--- a/services/email/smtp/SMTPClient.cpp	Fri Jul 09 14:46:47 2010 +0000
+++ b/services/email/smtp/SMTPClient.cpp	Tue Jul 27 15:59:42 2010 +0000
@@ -23,6 +23,9 @@
 
 #include "SMTPClient.h"
 
+/*
+  Provided as reference only, this code has not been tested.
+*/
 #if 0
 
 #include <stdio.h>
--- a/services/http/client/HTTPClient.cpp	Fri Jul 09 14:46:47 2010 +0000
+++ b/services/http/client/HTTPClient.cpp	Tue Jul 27 15:59:42 2010 +0000
@@ -41,7 +41,7 @@
 {
   setTimeout(HTTP_REQUEST_TIMEOUT);
   m_buf = new char[CHUNK_SIZE];
-  DBG("\r\nNew HTTPClient %p\r\n",this);
+  DBG("New HTTPClient %p\n",this);
 }
 
 HTTPClient::~HTTPClient()
@@ -62,7 +62,7 @@
   decStr += ":";
   decStr += password;
   auth.append( Base64::encode(decStr) );
-  DBG("\r\nAuth str is %s\r\n", auth.c_str());
+  DBG("Auth str is %s\n", auth.c_str());
   m_reqHeaders["Authorization"] = auth; 
 }
 
@@ -164,7 +164,7 @@
     if( m_state == HTTP_DONE ) 
     {
       //All data has been read, close w/ success :)
-      DBG("\r\nDone :)!\r\n");
+      DBG("Done :)!\n");
       onResult(HTTP_OK);
       close();
     }
@@ -267,7 +267,7 @@
     m_server.setPort( HTTP_PORT );
   }
   
-  DBG("\r\nURL parsed,\r\nHost: %s\r\nPort: %d\r\nPath: %s\r\n", url.getHost().c_str(), url.getPort(), url.getPath().c_str());
+  DBG("URL parsed,\r\nHost: %s\r\nPort: %d\r\nPath: %s\n", url.getHost().c_str(), url.getPort(), url.getPath().c_str());
   
   IpAddr ip;
   if( url.getHostIp(&ip) )
@@ -277,11 +277,11 @@
   }
   else
   {
-    DBG("\r\nDNS Query...\r\n");
+    DBG("DNS Query...\n");
     m_pDnsReq = new DNSRequest();
     m_pDnsReq->setOnReply(this, &HTTPClient::onDNSReply);
     m_pDnsReq->resolve(&m_server);
-    DBG("\r\nHTTPClient : DNSRequest %p\r\n", m_pDnsReq);
+    DBG("HTTPClient : DNSRequest %p\n", m_pDnsReq);
   }
   
 }
@@ -289,7 +289,7 @@
 void HTTPClient::connect() //Start Connection
 {
   resetTimeout();
-  DBG("\r\nConnecting...\r\n");
+  DBG("Connecting...\n");
   m_pTCPSocket->connect(m_server);
 }
 
@@ -352,7 +352,7 @@
     m_state = HTTP_DONE;
     return;
   }
-  DBG("\r\nReading response...\r\n");
+  DBG("Reading response...\n");
   int len = 0;
   do
   {
@@ -360,7 +360,7 @@
     {
       if(m_dataLen==0)
       {
-        DBG("\r\nReading chunk length...\r\n");
+        DBG("Reading chunk length...\n");
         //New block
         static char chunkHeader[16];
         //We use m_dataPos to retain the read position in chunkHeader, it has been set to 0 before the first call of readData()
@@ -370,19 +370,19 @@
           if( chunkHeader[strlen(chunkHeader)-1] == 0x0d )
           {
             sscanf(chunkHeader, "%x%*[^\r\n]", &m_dataLen);
-            DBG("\r\nChunk length is %d\r\n", m_dataLen);
+            DBG("Chunk length is %d\n", m_dataLen);
             m_dataPos = 0;
           }
           else
           {
             //Wait for end of line
-            DBG("\r\nWait for CRLF\r\n");
+            DBG("Wait for CRLF\n");
             return;
           }
         }
         else
         {
-          DBG("\r\nWait for data\r\n");
+          DBG("Wait for data\n");
           //Wait for data
           return;
         }
@@ -408,17 +408,17 @@
     {  
       if(m_dataPos >= m_dataLen)
       {
-        DBG("\r\nChunk read, wait for CRLF\r\n");
+        DBG("Chunk read, wait for CRLF\n");
         char chunkTail[3];
         m_dataPos += readLine(chunkTail, 3);
       }
       
       if(m_dataPos >= m_dataLen + 1) //1 == strlen("\n"),
       {
-        DBG("\r\nEnd of chunk\r\n");
+        DBG("End of chunk\n");
         if(m_dataLen==0)
         {
-          DBG("\r\nEnd of file\r\n");
+          DBG("End of file\n");
           //End of file
           m_state = HTTP_DONE; //Done
         }
@@ -432,7 +432,7 @@
   
   if(!m_dataChunked && (m_dataPos >= m_dataLen)) //All Data has been received
   {
-    DBG("\r\nEnd of file\r\n");
+    DBG("End of file\n");
     m_state = HTTP_DONE; //Done
   }
 }
@@ -450,7 +450,7 @@
   {
     //Write chunk header
     char chunkHeader[16];
-    sprintf(chunkHeader, "%d\r\n", len);
+    sprintf(chunkHeader, "%d\n", len);
     int ret = m_pTCPSocket->send(chunkHeader, strlen(chunkHeader));
     if(ret < 0)//Error
     {
@@ -462,7 +462,7 @@
   m_dataPos+=len;
   if( m_dataChunked )
   {
-    m_pTCPSocket->send("\r\n", 2); //Chunk terminating CRLF
+    m_pTCPSocket->send("", 2); //Chunk terminating CRLF
   }
   if( ( !m_dataChunked && (m_dataPos >= m_dataLen) )
     || ( m_dataChunked && !len ) ) //All Data has been sent
@@ -474,11 +474,11 @@
   
 void HTTPClient::onTCPSocketEvent(TCPSocketEvent e)
 {
-  DBG("\r\nEvent %d in HTTPClient::onTCPSocketEvent()\r\n", e);
+  DBG("Event %d in HTTPClient::onTCPSocketEvent()\n", e);
 
   if(m_closed)
   {
-    DBG("\r\nWARN: Discarded\r\n");
+    DBG("WARN: Discarded\n");
     return;
   }
 
@@ -501,18 +501,18 @@
           m_dataChunked = true;
           m_dataPos = 0;
           m_dataLen = 0; 
-          DBG("\r\nEncoding is chunked, Content-Type is %s\r\n", m_respHeaders["Content-Type"].c_str() );
+          DBG("Encoding is chunked, Content-Type is %s\n", m_respHeaders["Content-Type"].c_str() );
         }
         else
         {    
           m_dataChunked = false;
           int len = 0;
-          //DBG("\r\nPreparing read... len = %s\r\n", m_respHeaders["Content-Length"].c_str());
+          //DBG("Preparing read... len = %s\n", m_respHeaders["Content-Length"].c_str());
           sscanf(m_respHeaders["Content-Length"].c_str(), "%d", &len);
           m_pDataIn->setDataLen( len );
           m_dataPos = 0;
           m_dataLen = len; 
-          DBG("\r\nContent-Length is %d, Content-Type is %s\r\n", len, m_respHeaders["Content-Type"].c_str() );
+          DBG("Content-Length is %d, Content-Type is %s\n", len, m_respHeaders["Content-Type"].c_str() );
         }
         m_pDataIn->setDataType( m_respHeaders["Content-Type"] );
       }
@@ -528,7 +528,7 @@
  //All data has been read, close w/ success :)
     if( m_state == HTTP_DONE ) 
     {
-      DBG("\r\nDone :)!\r\n");
+      DBG("Done :)!\n");
       onResult(HTTP_OK);
     }
     break;
@@ -584,7 +584,7 @@
   case TCPSOCKET_CONRST:
   case TCPSOCKET_CONABRT:
   case TCPSOCKET_ERROR:
-    DBG("\r\nConnection error.\r\n");
+    DBG("Connection error.\n");
     onResult(HTTP_CONN);
   case TCPSOCKET_DISCONNECTED:
     //There might still be some data available for reading
@@ -593,7 +593,7 @@
     {
       onResult(HTTP_CONN);
     }
-    DBG("\r\nConnection closed by remote host.\r\n");
+    DBG("Connection closed by remote host.\n");
     break;
   }
 }
@@ -602,18 +602,18 @@
 {
   if(m_closed)
   {
-    DBG("\r\nWARN: Discarded\r\n");
+    DBG("WARN: Discarded\n");
     return;
   }
   
   if( r != DNS_FOUND )
   {
-    DBG("\r\nCould not resolve hostname.\r\n");
+    DBG("Could not resolve hostname.\n");
     onResult(HTTP_DNS);
     return;
   }
   
-  DBG("\r\nDNS Resolved to %d.%d.%d.%d.\r\n",m_server.getIp()[0],m_server.getIp()[1],m_server.getIp()[2],m_server.getIp()[3]);
+  DBG("DNS Resolved to %d.%d.%d.%d.\n",m_server.getIp()[0],m_server.getIp()[1],m_server.getIp()[2],m_server.getIp()[3]);
   //If no error, m_server has been updated by m_pDnsReq so we're set to go !
   m_pDnsReq->close();
   delete m_pDnsReq;
@@ -633,7 +633,7 @@
 
 void HTTPClient::onTimeout() //Connection has timed out
 {
-  DBG("\r\nTimed out.\n");
+  DBG("Timed out.\n");
   onResult(HTTP_TIMEOUT);
   close();
 }
@@ -671,7 +671,7 @@
       if( sscanf(line, "HTTP/%*d.%*d %d %*[^\r\n]", &m_httpResponseCode) != 1 )
       {
         //Cannot match string, error
-        DBG("\r\nNot a correct HTTP answer : %s\r\n", line);
+        DBG("Not a correct HTTP answer : %s\n", line);
         onResult(HTTP_PRTCL);
         close();
         return false;
@@ -679,7 +679,7 @@
       
       if(m_httpResponseCode != 200)
       {
-        DBG("\r\nResponse: error code %d\r\n", m_httpResponseCode);
+        DBG("Response: error code %d\n", m_httpResponseCode);
         HTTPResult res = HTTP_ERROR;
         switch(m_httpResponseCode)
         {
@@ -696,12 +696,12 @@
         close();
         return false;
       }
-      DBG("\r\nResponse OK\r\n");
+      DBG("Response OK\n");
     }
     else
     {
       //Empty packet, weird!
-      DBG("\r\nEmpty packet!\r\n");
+      DBG("Empty packet!\n");
       onResult(HTTP_PRTCL);
       close();
       return false;
@@ -714,7 +714,7 @@
     m_dataLen = 0;
     if( readLen <= 2 ) //if == 1 or 2, it is an empty line = end of headers
     {
-      DBG("\r\nAll headers read.\r\n");
+      DBG("All headers read.\n");
       m_state = HTTP_READ_DATA;
       break;
     }
@@ -723,11 +723,11 @@
       m_dataLen = readLen;//Sets data length available in buffer
       return false;
     }
-    //DBG("\r\nHeader : %s\r\n", line);
+    //DBG("Header : %s\n", line);
     int n = sscanf(line, "%[^:] : %[^\r\n]", key, value);
     if ( n == 2 )
     {
-      DBG("\r\nRead header : %s: %s\r\n", key, value);
+      DBG("Read header : %s: %s\n", key, value);
       m_respHeaders[key] = value;
     }
     //TODO: Impl n==1 case (part 2 of previous header)
@@ -742,19 +742,19 @@
   const char* HTTP_METH_STR[] = {"GET", "POST", "HEAD"};
   
   //Req
-  sprintf(line, "%s %s HTTP/1.1\r\nHost: %s\r\n", HTTP_METH_STR[m_meth], m_path.c_str(), m_server.getName()); //Write request
+  sprintf(line, "%s %s HTTP/1.1\r\nHost: %s\n", HTTP_METH_STR[m_meth], m_path.c_str(), m_server.getName()); //Write request
   m_pTCPSocket->send(line, strlen(line));
-  DBG("\r\nRequest: %s\r\n", line);
+  DBG("Request: %s\n", line);
   
-  DBG("\r\nWriting headers:\r\n");
+  DBG("Writing headers:\n");
   map<string,string>::iterator it;
   for( it = m_reqHeaders.begin(); it != m_reqHeaders.end(); it++ )
   {
-    sprintf(line, "%s: %s\r\n", (*it).first.c_str(), (*it).second.c_str() );
-    DBG("\r\n%s", line);
+    sprintf(line, "%s: %s\n", (*it).first.c_str(), (*it).second.c_str() );
+    DBG("%s", line);
     m_pTCPSocket->send(line, strlen(line));
   }
-  m_pTCPSocket->send("\r\n",2); //End of head
+  m_pTCPSocket->send("",2); //End of head
   m_state = HTTP_WRITE_DATA;
   return true;
 }
--- a/services/http/client/HTTPClient.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/services/http/client/HTTPClient.h	Tue Jul 27 15:59:42 2010 +0000
@@ -38,33 +38,66 @@
 #include <map>
 using std::map;
 
+///HTTP client results
 enum HTTPResult
 {
   HTTP_OK,
   HTTP_PROCESSING,
-  HTTP_PARSE, //URI Parse error
-  HTTP_DNS, //Could not resolve name
-  HTTP_PRTCL, //Protocol error
-  HTTP_NOTFOUND, //404 Error
-  HTTP_REFUSED, //403 Error
-  HTTP_ERROR, //xxx error
-  HTTP_TIMEOUT, //Connection timeout
-  HTTP_CONN //Connection error
+  HTTP_PARSE, ///URI Parse error
+  HTTP_DNS, ///Could not resolve name
+  HTTP_PRTCL, ///Protocol error
+  HTTP_NOTFOUND, ///HTTP 404 Error
+  HTTP_REFUSED, ///HTTP 403 Error
+  HTTP_ERROR, ///HTTP xxx error
+  HTTP_TIMEOUT, ///Connection timeout
+  HTTP_CONN ///Connection error
 };
 
-
-
+///A simple HTTP Client
+/**
+The HTTPClient is composed of:
+- The actual client (HTTPClient)
+- Classes that act as a data repository, each of which deriving from the HTTPData class (HTTPText for short text content, HTTPFile for file I/O, HTTPMap for key/value pairs, and HTTPStream for streaming purposes)
+*/
 class HTTPClient : protected NetService
 {
 public:
+  ///Instantiates the HTTP client
   HTTPClient();
   virtual ~HTTPClient();
   
+  ///Provides a basic authentification feature (Base64 encoded username and password)
   void basicAuth(const char* user, const char* password); //Basic Authentification
   
   //High Level setup functions
+  ///Executes a GET Request (blocking)
+  /**
+  Executes a GET request on the URI uri
+  @param uri : URI on which to execute the request
+  @param pDataIn : pointer to an HTTPData instance that will collect the data returned by the request, can be NULL
+  Blocks until completion
+  */
   HTTPResult get(const char* uri, HTTPData* pDataIn); //Blocking
+  
+  ///Executes a GET Request (non blocking)
+  /**
+  Executes a GET request on the URI uri
+  @param uri : URI on which to execute the request
+  @param pDataIn : pointer to an HTTPData instance that will collect the data returned by the request, can be NULL
+  @param pMethod : callback function
+  The function returns immediately and calls the callback on completion or error
+  */
   HTTPResult get(const char* uri, HTTPData* pDataIn, void (*pMethod)(HTTPResult)); //Non blocking
+  
+  ///Executes a GET Request (non blocking)
+  /**
+  Executes a GET request on the URI uri
+  @param uri : URI on which to execute the request
+  @param pDataIn : pointer to an HTTPData instance that will collect the data returned by the request, can be NULL
+  @param pItem : instance of class on which to execute the callback method
+  @param pMethod : callback method
+  The function returns immediately and calls the callback on completion or error
+  */
   template<class T> 
   HTTPResult get(const char* uri, HTTPData* pDataIn, T* pItem, void (T::*pMethod)(HTTPResult)) //Non blocking
   {
@@ -73,8 +106,37 @@
     return HTTP_PROCESSING;
   }
   
+  ///Executes a POST Request (blocking)
+  /**
+  Executes a POST request on the URI uri
+  @param uri : URI on which to execute the request
+  @param dataOut : a HTTPData instance that contains the data that will be posted
+  @param pDataIn : pointer to an HTTPData instance that will collect the data returned by the request, can be NULL
+  Blocks until completion
+  */
   HTTPResult post(const char* uri, const HTTPData& dataOut, HTTPData* pDataIn); //Blocking
+  
+  ///Executes a POST Request (non blocking)
+  /**
+  Executes a POST request on the URI uri
+  @param uri : URI on which to execute the request
+  @param dataOut : a HTTPData instance that contains the data that will be posted
+  @param pDataIn : pointer to an HTTPData instance that will collect the data returned by the request, can be NULL
+  @param pMethod : callback function
+  The function returns immediately and calls the callback on completion or error
+  */
   HTTPResult post(const char* uri, const HTTPData& dataOut, HTTPData* pDataIn, void (*pMethod)(HTTPResult)); //Non blocking
+  
+  ///Executes a POST Request (non blocking)
+  /**
+  Executes a POST request on the URI uri
+  @param uri : URI on which to execute the request
+  @param dataOut : a HTTPData instance that contains the data that will be posted
+  @param pDataIn : pointer to an HTTPData instance that will collect the data returned by the request, can be NULL
+  @param pItem : instance of class on which to execute the callback method
+  @param pMethod : callback method
+  The function returns immediately and calls the callback on completion or error
+  */
   template<class T> 
   HTTPResult post(const char* uri, const HTTPData& dataOut, HTTPData* pDataIn, T* pItem, void (T::*pMethod)(HTTPResult)) //Non blocking  
   {
@@ -82,28 +144,68 @@
     doPost(uri, dataOut, pDataIn);
     return HTTP_PROCESSING;
   }
+
+  ///Executes a GET Request (non blocking)
+  /**
+  Executes a GET request on the URI uri
+  @param uri : URI on which to execute the request
+  @param pDataIn : pointer to an HTTPData instance that will collect the data returned by the request, can be NULL
+  The function returns immediately and calls the previously set callback on completion or error
+  */  
+  void doGet(const char* uri, HTTPData* pDataIn);  
   
-  void doGet(const char* uri, HTTPData* pDataIn);  
+  ///Executes a POST Request (non blocking)
+  /**
+  Executes a POST request on the URI uri
+  @param uri : URI on which to execute the request
+  @param dataOut : a HTTPData instance that contains the data that will be posted
+  @param pDataIn : pointer to an HTTPData instance that will collect the data returned by the request, can be NULL
+  @param pMethod : callback function
+  The function returns immediately and calls the previously set callback on completion or error
+  */
   void doPost(const char* uri, const HTTPData& dataOut, HTTPData* pDataIn); 
   
+  ///Setups the result callback
+  /**
+  @param pMethod : callback function
+  */
   void setOnResult( void (*pMethod)(HTTPResult) );
+  
+  ///Setups the result callback
+  /**
+  @param pItem : instance of class on which to execute the callback method
+  @param pMethod : callback method
+  */
   class CDummy;
   template<class T> 
-  //Linker bug : Must be defined here :(
   void setOnResult( T* pItem, void (T::*pMethod)(HTTPResult) )
   {
     m_pCb = NULL;
     m_pCbItem = (CDummy*) pItem;
     m_pCbMeth = (void (CDummy::*)(HTTPResult)) pMethod;
   }
-  
+
+  ///Setups timeout
+  /**
+  @param ms : time of connection inactivity in ms after which the request should timeout
+  */
   void setTimeout(int ms);
   
   virtual void poll(); //Called by NetServices
   
+  ///Gets last request's HTTP response code
+  /**
+  @return The HTTP response code of the last request
+  */
   int getHTTPResponseCode();
+  
+  ///Sets a specific request header
   void setRequestHeader(const string& header, const string& value);
+  
+  ///Gets a response header
   string& getResponseHeader(const string& header);
+  
+  ///Clears request headers
   void resetRequestHeaders();
   
 protected:
--- a/services/http/server/HTTPServer.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/services/http/server/HTTPServer.h	Tue Jul 27 15:59:42 2010 +0000
@@ -37,9 +37,17 @@
 #include <map>
 using std::map;
 
+///A simple HTTP server implementation
+/**
+The HTTPServer is composed of:
+- The actual server (HTTPServer)
+- A request dispatcher, instanciated on each request (HTTPRequestDispatcher)
+- Request handlers instanciated by the dispatcher(deriving from HTTPRequestHandler) 
+*/
 class HTTPServer
 {
 public:
+  ///Instantiates the HTTP Server
   HTTPServer();
   ~HTTPServer();
   
@@ -57,10 +65,21 @@
     }
   };
 
+  ///Adds a handler
+  /**
+  Appends a handler to the handlers list
+  @param T : class which will be instanciated to serve these requests
+  @param path : requests starting with this path will be served using this handler
+  */
   template<typename T>
   void addHandler(const char* path) //Template decl in header
   { m_lpHandlers[path] = &T::inst; }
   
+  ///Starts listening
+  /**
+  Binds server to a specific port and starts listening
+  @param port : port on which to listen for incoming connections
+  */
   void bind(int port = 80);
   
 private:
--- a/services/mysql/MySQLClient.cpp	Fri Jul 09 14:46:47 2010 +0000
+++ b/services/mysql/MySQLClient.cpp	Tue Jul 27 15:59:42 2010 +0000
@@ -28,7 +28,7 @@
 //#define __DEBUG
 #include "dbg/dbg.h"
 
-#define MYSQL_TIMEOUT_MS 15000
+#define MYSQL_TIMEOUT_MS 45000
 #define MYSQL_PORT 3306
 
 #define BUF_SIZE 256
@@ -188,26 +188,25 @@
   m_password = password;
   
   m_db = db;
-  
-  IpAddr ip;
+
   if( !host.getIp().isNull() )
   {
     connect();
   }
   else //Need to do a DNS Query...
   {
-    DBG("\r\nDNS Query...\r\n");
+    DBG("DNS Query...\n");
     m_pDnsReq = new DNSRequest();
     m_pDnsReq->setOnReply(this, &MySQLClient::onDNSReply);
     m_pDnsReq->resolve(&m_host);
-    DBG("\r\nMySQLClient : DNSRequest %p\r\n", m_pDnsReq);
+    DBG("MySQLClient : DNSRequest %p\n", m_pDnsReq);
   }
 }
 
 void MySQLClient::connect() //Start Connection
 {
   resetTimeout();
-  DBG("\r\nConnecting...\r\n");
+  DBG("Connecting...\n");
   m_pTCPSocket->connect(m_host);
   m_packetId = 0;
 }
@@ -442,11 +441,11 @@
 
 void MySQLClient::onTCPSocketEvent(TCPSocketEvent e)
 {
-  DBG("\r\nEvent %d in MySQLClient::onTCPSocketEvent()\r\n", e);
+  DBG("Event %d in MySQLClient::onTCPSocketEvent()\n", e);
 
   if(m_closed)
   {
-    DBG("\r\nWARN: Discarded\r\n");
+    DBG("WARN: Discarded\n");
     return;
   }
   
@@ -471,7 +470,7 @@
   case TCPSOCKET_CONRST:
   case TCPSOCKET_CONABRT:
   case TCPSOCKET_ERROR:
-    DBG("\r\nConnection error.\r\n");
+    DBG("Connection error.\n");
     onResult(MYSQL_CONN);
   case TCPSOCKET_DISCONNECTED:
     //There might still be some data available for reading
@@ -480,7 +479,7 @@
     {
       onResult(MYSQL_CONN);
     }
-    DBG("\r\nConnection closed by remote host.\r\n");
+    DBG("Connection closed by remote host.\n");
     break;
   }
 }
@@ -489,18 +488,18 @@
 {
   if(m_closed)
   {
-    DBG("\r\nWARN: Discarded\r\n");
+    DBG("WARN: Discarded\n");
     return;
   }
   
   if( r != DNS_FOUND )
   {
-    DBG("\r\nCould not resolve hostname.\r\n");
+    DBG("Could not resolve hostname.\n");
     onResult(MYSQL_DNS);
     return;
   }
   
-  DBG("\r\nDNS Resolved to %d.%d.%d.%d.\r\n",m_host.getIp()[0],m_host.getIp()[1],m_host.getIp()[2],m_host.getIp()[3]);
+  DBG("DNS Resolved to %d.%d.%d.%d.\n",m_host.getIp()[0],m_host.getIp()[1],m_host.getIp()[2],m_host.getIp()[3]);
   //If no error, m_host has been updated by m_pDnsReq so we're set to go !
   m_pDnsReq->close();
   delete m_pDnsReq;
@@ -521,7 +520,7 @@
 
 void MySQLClient::onTimeout() //Connection has timed out
 {
-  DBG("\r\nTimed out.\n");
-  onResult(MYSQL_DNS);
+  DBG("Timed out.\n");
+  onResult(MYSQL_TIMEOUT);
   close();
 }
--- a/services/mysql/MySQLClient.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/services/mysql/MySQLClient.h	Tue Jul 27 15:59:42 2010 +0000
@@ -37,28 +37,55 @@
 
 typedef unsigned char byte;
 
+///MySQL client results
 enum MySQLResult
 {
   MYSQL_OK,
   MYSQL_PROCESSING,
   MYSQL_PRTCL,
-  MYSQL_SETUP, //Not properly configured
-  MYSQL_DNS, //Could not resolve name
-  MYSQL_AUTHFAILED, //Auth failure
-  MYSQL_READY, //Ready to send commands
-  MYSQL_SQL, //SQL Error
-  MYSQL_TIMEOUT, //Connection timeout
-  MYSQL_CONN //Connection error
+  MYSQL_SETUP, ///Not properly configured
+  MYSQL_DNS, ///Could not resolve name
+  MYSQL_AUTHFAILED, ///Auth failure
+  MYSQL_READY, ///Ready to send commands
+  MYSQL_SQL, ///SQL Error
+  MYSQL_TIMEOUT, ///Connection timeout
+  MYSQL_CONN ///Connection error
 };
 
+///A MySQL Client
+/**
+This MySQL client implements a limited subset of the MySQL internal client/server protocol (including authentication), for server versions 4.1 and newer.
+*/
 class MySQLClient : protected NetService
 {
 public:
+  ///Instantiates the MySQL client
   MySQLClient();
   virtual ~MySQLClient();
   
   //High Level setup functions
+  
+  ///Opens a connection to a server
+  /**
+  Opens a connection to the server host using the provided username, password passowrd and selecting database
+  On completion of this call (and any further one), the callback set in parameter is fired with the result of that command in parameter
+  @param host : server
+  @param user : username
+  @param db : database to use
+  @param pMethod : callback to call on each request completion
+  */
   MySQLResult open(Host& host, const string& user, const string& password, const string& db, void (*pMethod)(MySQLResult)); //Non blocking
+  
+  ///Opens a connection to a server
+  /**
+  Opens a connection to the server host using the provided username, password passowrd and selecting database
+  On completion of this call (and any further one), the callback set in parameter is fired with the result of that command in parameter
+  @param host : server
+  @param user : username
+  @param db : database to use
+  @param pItem : callback's class instance
+  @param pMethod : callback's method to call on each request completion
+  */
   template<class T> 
   MySQLResult open(Host& host, const string& user, const string& password, const string& db, T* pItem, void (T::*pMethod)(MySQLResult)) //Non blocking
   {
@@ -67,8 +94,17 @@
     return MYSQL_PROCESSING;
   }
   
+  
+  ///Executes an SQL command
+  /**
+  Executes an SQL request on the SQL server
+  This is a non-blocking function
+  On completion, the callback set in the open function is fired with the result of the command in parameter
+  @param sqlCommand SQL request to execute
+  */
   MySQLResult sql(string& sqlCommand);
   
+  ///Closes the connection to the server
   MySQLResult exit();
       
   void setOnResult( void (*pMethod)(MySQLResult) );
@@ -81,6 +117,10 @@
     m_pCbMeth = (void (CDummy::*)(MySQLResult)) pMethod;
   }
   
+  ///Setups timeout
+  /**
+  @param ms : time of connection inactivity in ms after which the request should timeout
+  */
   void setTimeout(int ms);
   
   virtual void poll(); //Called by NetServices
--- a/services/mysql/sha1.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/services/mysql/sha1.h	Tue Jul 27 15:59:42 2010 +0000
@@ -1,4 +1,4 @@
-/**
+/* 
  * \file sha1.h
  *
  *  Copyright (C) 2006-2010, Paul Bakker <polarssl_maintainer at polarssl.org>
@@ -21,7 +21,7 @@
 #ifndef POLARSSL_SHA1_H
 #define POLARSSL_SHA1_H
 
-/**
+/* 
  * \brief          SHA-1 context structure
  */
 typedef struct
@@ -39,14 +39,14 @@
 extern "C" {
 #endif
 
-/**
+/* 
  * \brief          SHA-1 context setup
  *
  * \param ctx      context to be initialized
  */
 void sha1_starts( sha1_context *ctx );
 
-/**
+/* 
  * \brief          SHA-1 process buffer
  *
  * \param ctx      SHA-1 context
@@ -55,7 +55,7 @@
  */
 void sha1_update( sha1_context *ctx, const unsigned char *input, int ilen );
 
-/**
+/* 
  * \brief          SHA-1 final digest
  *
  * \param ctx      SHA-1 context
@@ -63,7 +63,7 @@
  */
 void sha1_finish( sha1_context *ctx, unsigned char output[20] );
 
-/**
+/* 
  * \brief          Output = SHA-1( input buffer )
  *
  * \param input    buffer holding the  data
@@ -73,7 +73,7 @@
 void sha1( const unsigned char *input, int ilen, unsigned char output[20] );
 
 #if 0 //No need for that
-/**
+/* 
  * \brief          Output = SHA-1( file contents )
  *
  * \param path     input file name
@@ -85,7 +85,7 @@
 int sha1_file( const char *path, unsigned char output[20] );
 #endif
 
-/**
+/* 
  * \brief          SHA-1 HMAC context setup
  *
  * \param ctx      HMAC context to be initialized
@@ -94,7 +94,7 @@
  */
 void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, int keylen );
 
-/**
+/* 
  * \brief          SHA-1 HMAC process buffer
  *
  * \param ctx      HMAC context
@@ -103,7 +103,7 @@
  */
 void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, int ilen );
 
-/**
+/* 
  * \brief          SHA-1 HMAC final digest
  *
  * \param ctx      HMAC context
@@ -111,14 +111,14 @@
  */
 void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] );
 
-/**
+/* 
  * \brief          SHA-1 HMAC context reset
  *
  * \param ctx      HMAC context to be reset
  */
 void sha1_hmac_reset( sha1_context *ctx );
 
-/**
+/* 
  * \brief          Output = HMAC-SHA-1( hmac key, input buffer )
  *
  * \param key      HMAC secret key
@@ -131,7 +131,7 @@
                 const unsigned char *input, int ilen,
                 unsigned char output[20] );
 
-/**
+/* 
  * \brief          Checkup routine
  *
  * \return         0 if successful, or 1 if the test failed
--- a/services/ntp/NTPClient.cpp	Fri Jul 09 14:46:47 2010 +0000
+++ b/services/ntp/NTPClient.cpp	Tue Jul 27 15:59:42 2010 +0000
@@ -145,7 +145,7 @@
   resetTimeout();
   DBG("Opening connection\n");
   m_state = NTP_PING;
-  Host localhost(IpAddr(127,0,0,1), NTP_CLIENT_PORT, "localhost");
+  Host localhost(IpAddr(), NTP_CLIENT_PORT, "localhost"); //Any local address
   m_pUDPSocket->bind(localhost);
   set_time( 1280000000 ); //End of July 2010... just there to limit offset range
   process();
@@ -180,6 +180,7 @@
     
     m_pkt.refTm_f = m_pkt.origTm_f = m_pkt.rxTm_f = m_pkt.txTm_f = 0;
     
+    #ifdef __DEBUG
     //Hex Dump:
     DBG("\r\nDump Tx:\r\n");
     for(int i = 0; i< sizeof(NTPPacket); i++)
@@ -187,6 +188,7 @@
       DBG("%02x ", *((char*)&m_pkt + i));
     }
     DBG("\r\n\r\n");
+    #endif
     
     len = m_pUDPSocket->sendto( (char*)&m_pkt, sizeof(NTPPacket), &m_host );
     if(len < sizeof(NTPPacket))
@@ -217,6 +219,7 @@
     if(len < sizeof(NTPPacket)) //TODO: Accept chunks
       { onResult(NTP_PRTCL); close(); return; }
       
+    #ifdef __DEBUG
     //Hex Dump:
     DBG("\r\nDump Rx:\r\n");
     for(int i = 0; i< sizeof(NTPPacket); i++)
@@ -224,6 +227,7 @@
       DBG("%02x ", *((char*)&m_pkt + i));
     }
     DBG("\r\n\r\n");
+    #endif
       
     if( m_pkt.stratum == 0)  //Kiss of death message : Not good !
     {
--- a/services/ntp/NTPClient.h	Fri Jul 09 14:46:47 2010 +0000
+++ b/services/ntp/NTPClient.h	Tue Jul 27 15:59:42 2010 +0000
@@ -29,24 +29,56 @@
 #include "api/DNSRequest.h"
 #include "mbed.h"
 
+///NTP Client results
 enum NTPResult
 {
   NTP_OK,
   NTP_PROCESSING,
-  NTP_PRTCL, //Protocol error
-  NTP_TIMEOUT, //Connection timeout
-  NTP_DNS //Could not resolve DNS Addr
+  NTP_PRTCL, ///Protocol error
+  NTP_TIMEOUT, ///Connection timeout
+  NTP_DNS ///Could not resolve DNS Addr
 };
 
+///A NTP Client
+/**
+The NTP client is a simple UDP client that will update the mbed's RTC
+*/
 class NTPClient : protected NetService
 {
 public:
+  /**
+  Instantiates the NTP client
+  */
   NTPClient();
   virtual ~NTPClient();
   
   //High level setup functions
+  
+  ///Gets current time (blocking)
+  /**
+  Updates the time using the server host
+  Blocks until completion
+  @param host : NTP server
+  */
   NTPResult setTime(const Host& host); //Blocking
+  
+  ///Gets current time (non-blocking)
+  /**
+  Updates the time using the server host
+  The function returns immediately and calls the callback on completion or error
+  @param host : NTP server
+  @param pMethod : callback function
+  */
   NTPResult setTime(const Host& host, void (*pMethod)(NTPResult)); //Non blocking
+  
+  ///Gets current time (non-blocking)
+  /**
+  Updates the time
+  @param host : NTP server
+  @param pItem : instance of class on which to execute the callback method
+  @param pMethod : callback method
+  The function returns immediately and calls the callback on completion or error
+  */
   template<class T> 
   NTPResult setTime(const Host& host, T* pItem, void (T::*pMethod)(NTPResult)) //Non blocking
   {
@@ -55,9 +87,25 @@
     return NTP_PROCESSING;
   }
   
+  ///Gets current time (non-blocking)
+  /**
+  Updates the time using the server host
+  The function returns immediately and calls the previously set callback on completion or error
+  @param host : NTP server
+  */
   void doSetTime(const Host& host);
   
+  ///Setups the result callback
+  /**
+  @param pMethod : callback function
+  */
   void setOnResult( void (*pMethod)(NTPResult) );
+  
+  ///Setups the result callback
+  /**
+  @param pItem : instance of class on which to execute the callback method
+  @param pMethod : callback method
+  */
   class CDummy;
   template<class T> 
   void setOnResult( T* pItem, void (T::*pMethod)(NTPResult) )