Last commit 05 Aug 2010
Description: NetServices Stack source
Revision 5:dd63a1e02b1b, committed 27 Jul 2010
- Comitter:
- Date:
- Tue Jul 27 15:59:42 2010 +0000
- Parent:
- 4:fd826cad83c0
- Child:
- 6:b7dd7cde8ad2
- Commit message:
Changed in this revision
--- 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(¤t_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(¤t_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(¤t_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(¤t_iphdr_dest), ip4_addr2_16(¤t_iphdr_dest),
+ ip4_addr3_16(¤t_iphdr_dest), ip4_addr4_16(¤t_iphdr_dest)));
+ goto return_noroute;
}
/* Find network interface where to forward this IP packet to. */
- netif = ip_route(&dest);
+ netif = ip_route(¤t_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(¤t_iphdr_dest), ip4_addr2_16(¤t_iphdr_dest),
+ ip4_addr3_16(¤t_iphdr_dest), ip4_addr4_16(¤t_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(¤t_iphdr_dest), ip4_addr2_16(¤t_iphdr_dest),
+ ip4_addr3_16(¤t_iphdr_dest), ip4_addr4_16(¤t_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, ¤t_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(¤t_iphdr_dest)) {
+ if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, ¤t_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(¤t_iphdr_dest, &(netif->ip_addr)) ||
/* or broadcast on this interface network address? */
- ip_addr_isbroadcast(&(iphdr->dest), netif)) {
+ ip_addr_isbroadcast(¤t_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(¤t_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(¤t_iphdr_src))
+#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
+ { if ((ip_addr_isbroadcast(¤t_iphdr_src, inp)) ||
+ (ip_addr_ismulticast(¤t_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(¤t_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, ¤t_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(¤t_iphdr_dest, inp) &&
+ !ip_addr_ismulticast(¤t_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(¤t_iphdr_src);
+ ip_addr_set_any(¤t_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), ¤t_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(¤t_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(¤t_iphdr_dest, inp) ||
+ ip_addr_ismulticast(¤t_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), ¤t_iphdr_src) &&
+ ip_addr_cmp(&(pcb->local_ip), ¤t_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), ¤t_iphdr_src) &&
+ ip_addr_cmp(&(pcb->local_ip), ¤t_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), ¤t_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), ¤t_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(¤t_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), ¤t_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), ¤t_iphdr_dest) ||
#if LWIP_IGMP
- ip_addr_ismulticast(&(iphdr->dest)) ||
+ ip_addr_ismulticast(¤t_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), ¤t_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, ¤t_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, ¤t_iphdr_src, ¤t_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(¤t_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), ¤t_iphdr_dest) ||
+#if LWIP_IGMP
+ ip_addr_ismulticast(¤t_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(¤t_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() (¤t_iphdr_src)
+/** Destination IP address of current_header */
+#define ip_current_dest_addr() (¤t_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);
-void pppoe_init(void);
+ int sc_state; /* discovery phase or session connected */
+ struct eth_addr sc_dest; /* hardware address of concentrator */
+ u16_t sc_session; /* PPPoE session id */
-err_t pppoe_create(struct netif *ethernetnetif, int pd, void (*linkStatusCB)(int pd, int up), struct pppoe_softc **scptr);
+#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 */
+};
+
+
+#define pppoe_init() /* compatibility define, no initialization needed */
+
+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? */
+ {
+ if (arp_table[i].ctime >= age_pending) {
+ old_pending = i;
+ age_pending = arp_table[i].ctime;
+ }
}
-#endif /* ARP_QUEUEING */
- /* pending without queued packets? */
- } else {
- if (arp_table[i].ctime >= age_pending) {
- old_pending = i;
- age_pending = 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;
+ }
}
- }
- }
- /* 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;
}
}
}
/* { 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(ðhdr->dest, dst);
+ ETHADDR16_COPY(ðhdr->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(ðhdr->dest, ethdst_hwaddr);
#else /* LWIP_AUTOIP */
- ethhdr->dest.addr[i] = hdr->shwaddr.addr[i];
+ ETHADDR16_COPY(ðhdr->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(ðhdr->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 {
+ 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 */
+ }
#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));
+ /* 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(ðhdr->dest, ethdst_hwaddr);
#else /* LWIP_AUTOIP */
- ethhdr->dest.addr[k] = ethdst_addr->addr[k];
+ ETHADDR16_COPY(ðhdr->dest, ethdst_addr);
#endif /* LWIP_AUTOIP */
- ethhdr->src.addr[k] = ethsrc_addr->addr[k];
- }
+ ETHADDR16_COPY(ðhdr->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) )

