EthernetNetIf Compatibility.
Dependents: XBeeWiFi_SPI_example
Fork of NetServicesSource by
Revision 5:dd63a1e02b1b, committed 2010-07-27
- Comitter:
- donatien
- 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); + + int sc_state; /* discovery phase or session connected */ + struct eth_addr sc_dest; /* hardware address of concentrator */ + u16_t sc_session; /* PPPoE session id */ + +#ifdef PPPOE_TODO + char *sc_service_name; /* if != NULL: requested name of service */ + char *sc_concentrator_name; /* if != NULL: requested concentrator id */ +#endif /* PPPOE_TODO */ + u8_t sc_ac_cookie[PPPOE_MAX_AC_COOKIE_LEN]; /* content of AC cookie we must echo back */ + size_t sc_ac_cookie_len; /* length of cookie data */ +#ifdef PPPOE_SERVER + u8_t *sc_hunique; /* content of host unique we must echo back */ + size_t sc_hunique_len; /* length of host unique */ +#endif + int sc_padi_retried; /* number of PADI retries already done */ + int sc_padr_retried; /* number of PADR retries already done */ +}; -void pppoe_init(void); +#define pppoe_init() /* compatibility define, no initialization needed */ -err_t pppoe_create(struct netif *ethernetnetif, int pd, void (*linkStatusCB)(int pd, int up), struct pppoe_softc **scptr); +err_t pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up), struct pppoe_softc **scptr); err_t pppoe_destroy(struct netif *ifp); int pppoe_connect(struct pppoe_softc *sc);
--- a/lwip/lwipopts.h Fri Jul 09 14:46:47 2010 +0000 +++ b/lwip/lwipopts.h Tue Jul 27 15:59:42 2010 +0000 @@ -53,24 +53,25 @@ #define TUNIF_DEBUG LWIP_DBG_OFF #define UNIXIF_DEBUG LWIP_DBG_OFF #define DELIF_DEBUG LWIP_DBG_OFF -#define SIO_FIFO_DEBUG LWIP_DBG_OFF -#define TCPDUMP_DEBUG LWIP_DBG_OFF +#define SIO_FIFO_DEBUG LWIP_DBG_ON +#define TCPDUMP_DEBUG LWIP_DBG_ON -#define PPP_DEBUG LWIP_DBG_ON +#define PPP_DEBUG LWIP_DBG_OFF #define MEM_DEBUG LWIP_DBG_OFF #define MEMP_DEBUG LWIP_DBG_OFF #define PBUF_DEBUG LWIP_DBG_OFF #define API_LIB_DEBUG LWIP_DBG_OFF #define API_MSG_DEBUG LWIP_DBG_OFF -#define TCPIP_DEBUG LWIP_DBG_OFF -#define NETIF_DEBUG LWIP_DBG_OFF +#define TCPIP_DEBUG LWIP_DBG_ON +#define NETIF_DEBUG LWIP_DBG_ON #define SOCKETS_DEBUG LWIP_DBG_OFF #define DEMO_DEBUG LWIP_DBG_OFF -#define IP_DEBUG LWIP_DBG_OFF -#define IP_REASS_DEBUG LWIP_DBG_OFF +#define IP_DEBUG LWIP_DBG_ON +#define IP_REASS_DEBUG LWIP_DBG_ON #define RAW_DEBUG LWIP_DBG_OFF -#define ICMP_DEBUG LWIP_DBG_OFF -#define UDP_DEBUG LWIP_DBG_OFF +#define ICMP_DEBUG LWIP_DBG_ON +#define IGMP_DEBUG LWIP_DBG_ON +#define UDP_DEBUG LWIP_DBG_ON #define TCP_DEBUG LWIP_DBG_OFF #define TCP_INPUT_DEBUG LWIP_DBG_OFF #define TCP_OUTPUT_DEBUG LWIP_DBG_OFF @@ -80,7 +81,7 @@ #define TCP_FR_DEBUG LWIP_DBG_OFF #define TCP_QLEN_DEBUG LWIP_DBG_OFF #define TCP_RST_DEBUG LWIP_DBG_OFF -#define ETHARP_DEBUG LWIP_DBG_OFF +#define ETHARP_DEBUG LWIP_DBG_ON #define DNS_DEBUG LWIP_DBG_OFF #endif @@ -174,30 +175,34 @@ /* ---------- TCP options ---------- */ #define LWIP_TCP 1 -#define TCP_TTL 255 +//#define TCP_TTL 255 /* Controls if TCP should queue segments that arrive out of order. Define to 0 if your device is low on memory. */ -#define TCP_QUEUE_OOSEQ 0 +#define TCP_QUEUE_OOSEQ 1 /* TCP Maximum segment size. */ //#define TCP_MSS 1024 -#define TCP_MSS 1024//536//0x276 +#define TCP_MSS 536//1024//536//0x276 /* TCP sender buffer space (bytes). */ -#define TCP_SND_BUF 2048 +#define TCP_SND_BUF (3 * TCP_MSS) //2048 /* TCP sender buffer space (pbufs). This must be at least = 2 * TCP_SND_BUF/TCP_MSS for things to work. */ -#define TCP_SND_QUEUELEN (2 * TCP_SND_BUF/TCP_MSS) +#define TCP_SND_QUEUELEN (4 * (TCP_SND_BUF)/(TCP_MSS)) /* TCP writable space (bytes). This must be less than or equal to TCP_SND_BUF. It is the amount of space which must be available in the tcp snd_buf for select to return writable */ -#define TCP_SNDLOWAT (TCP_SND_BUF/2) +#define TCP_SNDLOWAT ((TCP_SND_BUF)/2) +/** + * TCP_WND: The size of a TCP window. This must be at least + * (2 * TCP_MSS) for things to work well + */ /* TCP receive window. */ -#define TCP_WND 1024 //8096 +#define TCP_WND (4 * TCP_MSS) //8096 /* Maximum number of retransmissions of data segments. */ //#define TCP_MAXRTX 12 @@ -272,14 +277,14 @@ /* TCP Maximum segment size. */ //#define TCP_MSS 1024 -#define TCP_MSS 512//0x276//536//0x276 +#define TCP_MSS 1024//0x276//536//0x276 /* TCP sender buffer space (bytes). */ -#define TCP_SND_BUF 1024//2048 +#define TCP_SND_BUF 2048 /* TCP sender buffer space (pbufs). This must be at least = 2 * TCP_SND_BUF/TCP_MSS for things to work. */ -#define TCP_SND_QUEUELEN (4 * TCP_SND_BUF/TCP_MSS)//(4 * TCP_SND_BUF/TCP_MSS) +#define TCP_SND_QUEUELEN (2 * TCP_SND_BUF/TCP_MSS)//(4 * TCP_SND_BUF/TCP_MSS) /* TCP writable space (bytes). This must be less than or equal to TCP_SND_BUF. It is the amount of space which must be @@ -287,7 +292,7 @@ #define TCP_SNDLOWAT (TCP_SND_BUF/2) /* TCP receive window. */ -#define TCP_WND 512 //8096 +#define TCP_WND 1024 //8096 /* Maximum number of retransmissions of data segments. */ //#define TCP_MAXRTX 12 @@ -299,8 +304,8 @@ /* ---------- ARP options ---------- */ #define LWIP_ARP (NET_ETH | NET_ZG2100) -#define ARP_TABLE_SIZE 2//4//10 -#define ARP_QUEUEING 0//1 +#define ARP_TABLE_SIZE 4//10 +#define ARP_QUEUEING 0 #define ETHARP_TRUST_IP_MAC 1 /* ---------- IP options ---------- */ @@ -321,6 +326,9 @@ /* ---------- ICMP options ---------- */ #define ICMP_TTL 255 +/* ---------- IGMP options ---------- */ +#define LWIP_IGMP (NET_ETH | NET_ZG2100) + /* ---------- DHCP options ---------- */ /* Define LWIP_DHCP to 1 if you want DHCP configuration of interfaces. */
--- a/lwip/lwipopts_light.h Fri Jul 09 14:46:47 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,454 +0,0 @@ -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels <adam@sics.se> - * - */ -#ifndef __LWIPOPTS_H__ -#define __LWIPOPTS_H__ - -#include "netCfg.h" -#if NET_LWIP_STACK - -//#include "arch/sys_arch.h" - -/* <sys/time.h> is included in cc.h! */ -#define LWIP_TIMEVAL_PRIVATE 0 - -//#define __LWIP_DEBUG -#include "dbg/dbg.h" - -#ifdef __LWIP_DEBUG - -#define LWIP_DEBUG 1 - -#define LWIP_DBG_MIN_LEVEL 0 -//#define LWIP_COMPAT_SOCKETS 1 -#define TAPIF_DEBUG LWIP_DBG_OFF -#define TUNIF_DEBUG LWIP_DBG_OFF -#define UNIXIF_DEBUG LWIP_DBG_OFF -#define DELIF_DEBUG LWIP_DBG_OFF -#define SIO_FIFO_DEBUG LWIP_DBG_OFF -#define TCPDUMP_DEBUG LWIP_DBG_OFF - -#define PPP_DEBUG LWIP_DBG_OFF -#define MEM_DEBUG LWIP_DBG_ON -#define MEMP_DEBUG LWIP_DBG_ON -#define PBUF_DEBUG LWIP_DBG_ON -#define API_LIB_DEBUG LWIP_DBG_OFF -#define API_MSG_DEBUG LWIP_DBG_OFF -#define TCPIP_DEBUG LWIP_DBG_OFF -#define NETIF_DEBUG LWIP_DBG_OFF -#define SOCKETS_DEBUG LWIP_DBG_OFF -#define DEMO_DEBUG LWIP_DBG_OFF -#define IP_DEBUG LWIP_DBG_OFF -#define IP_REASS_DEBUG LWIP_DBG_OFF -#define RAW_DEBUG LWIP_DBG_OFF -#define ICMP_DEBUG LWIP_DBG_OFF -#define UDP_DEBUG LWIP_DBG_OFF -#define TCP_DEBUG LWIP_DBG_OFF -#define TCP_INPUT_DEBUG LWIP_DBG_OFF -#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF -#define TCP_RTO_DEBUG LWIP_DBG_OFF -#define TCP_CWND_DEBUG LWIP_DBG_OFF -#define TCP_WND_DEBUG LWIP_DBG_OFF -#define TCP_FR_DEBUG LWIP_DBG_OFF -#define TCP_QLEN_DEBUG LWIP_DBG_OFF -#define TCP_RST_DEBUG LWIP_DBG_OFF -#define ETHARP_DEBUG LWIP_DBG_OFF -#define DNS_DEBUG LWIP_DBG_OFF - -#endif - -/* -extern unsigned char debug_flags; -#define LWIP_DBG_TYPES_ON debug_flags -*/ -#define NO_SYS 1 -#define LWIP_SOCKET (NO_SYS==0) -#define LWIP_NETCONN (NO_SYS==0) - - -#define IP_FRAG_USES_STATIC_BUF 0 - - - -/* ---------- Memory options ---------- */ -/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which - lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2 - byte alignment -> define MEM_ALIGNMENT to 2. */ -/* MSVC port: intel processors don't need 4-byte alignment, - but are faster that way! */ -#define MEM_ALIGNMENT 4 - -/* MEM_SIZE: the size of the heap memory. If the application will send -a lot of data that needs to be copied, this should be set high. */ -//#define MEM_SIZE 10240 - -#if TARGET_LPC1768 - - -#define MEM_SIZE 2000 - -/// - -#define MEM_POSITION __attribute((section("AHBSRAM0"))) - -/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application - sends a lot of data out of ROM (or other static memory), this - should be set high. */ -#define MEMP_NUM_PBUF 8 -/* MEMP_NUM_RAW_PCB: the number of UDP protocol control blocks. One - per active RAW "connection". */ -//#define MEMP_NUM_RAW_PCB 3 -/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One - per active UDP "connection". */ -#define MEMP_NUM_UDP_PCB 2 -/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP - connections. */ -#define MEMP_NUM_TCP_PCB 2 -/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP - connections. */ -#define MEMP_NUM_TCP_PCB_LISTEN 2//4 -/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP - segments. */ -#define MEMP_NUM_TCP_SEG 8 -/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active - timeouts. */ -#define MEMP_NUM_SYS_TIMEOUT 12 - -/* The following four are used only with the sequential API and can be - set to 0 if the application only will use the raw API. */ -/* MEMP_NUM_NETBUF: the number of struct netbufs. */ -#define MEMP_NUM_NETBUF 0 -/* MEMP_NUM_NETCONN: the number of struct netconns. */ -#define MEMP_NUM_NETCONN 0 -/* MEMP_NUM_TCPIP_MSG_*: the number of struct tcpip_msg, which is used - for sequential API communication and incoming packets. Used in - src/api/tcpip.c. */ -#define MEMP_NUM_TCPIP_MSG_API 0 -#define MEMP_NUM_TCPIP_MSG_INPKT 0 - -/* ---------- Pbuf options ---------- */ -/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */ -#define PBUF_POOL_SIZE 16//100 - -/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */ -#define PBUF_POOL_BUFSIZE 128 - -/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a - link level header. */ -//#define PBUF_LINK_HLEN 16 - -/** SYS_LIGHTWEIGHT_PROT - * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection - * for certain critical regions during buffer allocation, deallocation and memory - * allocation and deallocation. - */ -#define SYS_LIGHTWEIGHT_PROT 0 //No sys here - -/* ---------- TCP options ---------- */ -#define LWIP_TCP 1 -#define TCP_TTL 255 - -/* Controls if TCP should queue segments that arrive out of - order. Define to 0 if your device is low on memory. */ -#define TCP_QUEUE_OOSEQ 0 - -/* TCP Maximum segment size. */ -//#define TCP_MSS 1024 -#define TCP_MSS 0x276//536//0x276 - -/* TCP sender buffer space (bytes). */ -#define TCP_SND_BUF 1024 - -/* TCP sender buffer space (pbufs). This must be at least = 2 * - TCP_SND_BUF/TCP_MSS for things to work. */ -#define TCP_SND_QUEUELEN (2 * TCP_SND_BUF/TCP_MSS) - -/* TCP writable space (bytes). This must be less than or equal - to TCP_SND_BUF. It is the amount of space which must be - available in the tcp snd_buf for select to return writable */ -#define TCP_SNDLOWAT (TCP_SND_BUF/2) - -/* TCP receive window. */ -#define TCP_WND 1024 //8096 - -/* Maximum number of retransmissions of data segments. */ -//#define TCP_MAXRTX 12 - -/* Maximum number of retransmissions of SYN segments. */ -//#define TCP_SYNMAXRTX 4 - -#elif TARGET_LPC2368 - -#define MEM_POSITION __attribute((section("AHBSRAM1"))) - -/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application - sends a lot of data out of ROM (or other static memory), this - should be set high. */ -#define MEMP_NUM_PBUF 8 -/* MEMP_NUM_RAW_PCB: the number of UDP protocol control blocks. One - per active RAW "connection". */ -//#define MEMP_NUM_RAW_PCB 3 -/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One - per active UDP "connection". */ -#define MEMP_NUM_UDP_PCB 2 -/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP - connections. */ -#define MEMP_NUM_TCP_PCB 2 -/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP - connections. */ -#define MEMP_NUM_TCP_PCB_LISTEN 2//4 -/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP - segments. */ -#define MEMP_NUM_TCP_SEG 8 -/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active - timeouts. */ -#define MEMP_NUM_SYS_TIMEOUT 12 - -/* The following four are used only with the sequential API and can be - set to 0 if the application only will use the raw API. */ -/* MEMP_NUM_NETBUF: the number of struct netbufs. */ -#define MEMP_NUM_NETBUF 0 -/* MEMP_NUM_NETCONN: the number of struct netconns. */ -#define MEMP_NUM_NETCONN 0 -/* MEMP_NUM_TCPIP_MSG_*: the number of struct tcpip_msg, which is used - for sequential API communication and incoming packets. Used in - src/api/tcpip.c. */ -#define MEMP_NUM_TCPIP_MSG_API 0 -#define MEMP_NUM_TCPIP_MSG_INPKT 0 - -/* ---------- Pbuf options ---------- */ -/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */ -#define PBUF_POOL_SIZE 8//16//100 - -/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */ -//#define PBUF_POOL_BUFSIZE 128 - -/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a - link level header. */ -//#define PBUF_LINK_HLEN 16 - -/** SYS_LIGHTWEIGHT_PROT - * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection - * for certain critical regions during buffer allocation, deallocation and memory - * allocation and deallocation. - */ -#define SYS_LIGHTWEIGHT_PROT 0 //No sys here - -/* ---------- TCP options ---------- */ -#define LWIP_TCP 1 -#define TCP_TTL 255 - -/* Controls if TCP should queue segments that arrive out of - order. Define to 0 if your device is low on memory. */ -#define TCP_QUEUE_OOSEQ 0 - -/* TCP Maximum segment size. */ -//#define TCP_MSS 1024 -#define TCP_MSS 512//0x276//536//0x276 - -/* TCP sender buffer space (bytes). */ -#define TCP_SND_BUF 1024//2048 - -/* TCP sender buffer space (pbufs). This must be at least = 2 * - TCP_SND_BUF/TCP_MSS for things to work. */ -#define TCP_SND_QUEUELEN (4 * TCP_SND_BUF/TCP_MSS)//(4 * TCP_SND_BUF/TCP_MSS) - -/* TCP writable space (bytes). This must be less than or equal - to TCP_SND_BUF. It is the amount of space which must be - available in the tcp snd_buf for select to return writable */ -#define TCP_SNDLOWAT (TCP_SND_BUF/2) - -/* TCP receive window. */ -#define TCP_WND 512 //8096 - -/* Maximum number of retransmissions of data segments. */ -//#define TCP_MAXRTX 12 - -/* Maximum number of retransmissions of SYN segments. */ -//#define TCP_SYNMAXRTX 4 - -#endif - -/* ---------- ARP options ---------- */ -#define LWIP_ARP (NET_ETH | NET_ZG2100) -#define ARP_TABLE_SIZE 2//4//10 -#define ARP_QUEUEING 0//1 -#define ETHARP_TRUST_IP_MAC 1 - -/* ---------- IP options ---------- */ -/* Define IP_FORWARD to 1 if you wish to have the ability to forward - IP packets across network interfaces. If you are going to run lwIP - on a device with only one network interface, define this to 0. */ -#define IP_FORWARD 0 - - -/* IP reassembly and segmentation.These are orthogonal even - * if they both deal with IP fragments */ - /* -#define IP_REASSEMBLY 1 -#define IP_REASS_MAX_PBUFS 10 -#define MEMP_NUM_REASSDATA 10 -#define IP_FRAG 1 -*/ -/* ---------- ICMP options ---------- */ -#define ICMP_TTL 255 - -/* ---------- DHCP options ---------- */ -/* Define LWIP_DHCP to 1 if you want DHCP configuration of - interfaces. */ -#define LWIP_DHCP (NET_ETH | NET_ZG2100) - -/* 1 if you want to do an ARP check on the offered address - (recommended if using DHCP). */ -#define DHCP_DOES_ARP_CHECK (LWIP_DHCP) - -/* ---------- AUTOIP options ------- */ -#define LWIP_AUTOIP 0 - -/* ---------- SNMP options ---------- */ -/** @todo SNMP is experimental for now - @note UDP must be available for SNMP transport */ -#ifndef LWIP_SNMP -#define LWIP_SNMP 0 -#endif - - -#ifndef SNMP_PRIVATE_MIB -#define SNMP_PRIVATE_MIB 0 -#endif - - -/* ---------- UDP options ---------- */ -#define LWIP_UDP 1 -#define UDP_TTL 255 - -/* ---------- DNS options ---------- */ -#define LWIP_DNS 1 - -/* ---------- RAW options ---------- */ -#define LWIP_RAW 0 -#define RAW_TTL 255 - -/* ---------- Statistics options ---------- */ -/* individual STATS options can be turned off by defining them to 0 - * (e.g #define TCP_STATS 0). All of them are turned off if LWIP_STATS - * is 0 - * */ - -#define LWIP_STATS 0 - -/* ---------- PPP options ---------- */ - -#define PPP_SUPPORT NET_PPP /* Set > 0 for PPP */ - -#if PPP_SUPPORT > 0 - -#define NUM_PPP 1 /* Max PPP sessions. */ - - -/* Select modules to enable. Ideally these would be set in the makefile but - * we're limited by the command line length so you need to modify the settings - * in this file. - */ -#define PAP_SUPPORT 1 /* Set > 0 for PAP. */ -#define CHAP_SUPPORT 1 /* Set > 0 for CHAP. */ -#define MSCHAP_SUPPORT 0 /* Set > 0 for MSCHAP (NOT FUNCTIONAL!) */ -#define CBCP_SUPPORT 0 /* Set > 0 for CBCP (NOT FUNCTIONAL!) */ -#define CCP_SUPPORT 0 /* Set > 0 for CCP (NOT FUNCTIONAL!) */ -#define VJ_SUPPORT 1 /* Set > 0 for VJ header compression. */ -#define MD5_SUPPORT 1 /* Set > 0 for MD5 (see also CHAP) */ - - -/* - * Timeouts. - */ -#define FSM_DEFTIMEOUT 6 /* Timeout time in seconds */ -#define FSM_DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */ -#define FSM_DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */ -#define FSM_DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */ - -#define UPAP_DEFTIMEOUT 6 /* Timeout (seconds) for retransmitting req */ -#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */ - -#define CHAP_DEFTIMEOUT 6 /* Timeout time in seconds */ -#define CHAP_DEFTRANSMITS 10 /* max # times to send challenge */ - - -/* Interval in seconds between keepalive echo requests, 0 to disable. */ -#if 1 -#define LCP_ECHOINTERVAL 0 -#else - -#define LCP_ECHOINTERVAL 10 -#endif - - -/* Number of unanswered echo requests before failure. */ -#define LCP_MAXECHOFAILS 3 - -/* Max Xmit idle time (in jiffies) before resend flag char. */ -#define PPP_MAXIDLEFLAG 0//Send it every time//100 - -/* - * Packet sizes - * - * Note - lcp shouldn't be allowed to negotiate stuff outside these - * limits. See lcp.h in the pppd directory. - * (XXX - these constants should simply be shared by lcp.c instead - * of living in lcp.h) - */ -#define PPP_MTU 1500 /* Default MTU (size of Info field) */ -#if 0 -#define PPP_MAXMTU 65535 - (PPP_HDRLEN + PPP_FCSLEN) -#else - -#define PPP_MAXMTU 1500 /* Largest MTU we allow */ -#endif - -#define PPP_MINMTU 64 -#define PPP_MRU 1500 /* default MRU = max length of info field */ -#define PPP_MAXMRU 1500 /* Largest MRU we allow */ -#define PPP_DEFMRU 296 /* Try for this */ -#define PPP_MINMRU 128 /* No MRUs below this */ - - -#define MAXNAMELEN 64 /* max length of hostname or name for auth */ -#define MAXSECRETLEN 64 /* max length of password or secret */ - -#endif /* PPP_SUPPORT > 0 */ - -//C++ Compat -#define try vTry - -#endif - - -#endif /* __LWIPOPTS_H__ */
--- a/lwip/netif/etharp.c Fri Jul 09 14:46:47 2010 +0000 +++ b/lwip/netif/etharp.c Tue Jul 27 15:59:42 2010 +0000 @@ -83,12 +83,6 @@ #define HWTYPE_ETHERNET 1 -#define ARPH_HWLEN(hdr) (ntohs((hdr)->_hwlen_protolen) >> 8) -#define ARPH_PROTOLEN(hdr) (ntohs((hdr)->_hwlen_protolen) & 0xff) - -#define ARPH_HWLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons(ARPH_PROTOLEN(hdr) | ((len) << 8)) -#define ARPH_PROTOLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons((len) | (ARPH_HWLEN(hdr) << 8)) - enum etharp_state { ETHARP_STATE_EMPTY = 0, ETHARP_STATE_PENDING, @@ -97,35 +91,38 @@ struct etharp_entry { #if ARP_QUEUEING - /** - * Pointer to queue of pending outgoing packets on this ARP entry. - */ + /** Pointer to queue of pending outgoing packets on this ARP entry. */ struct etharp_q_entry *q; #endif /* ARP_QUEUEING */ ip_addr_t ipaddr; struct eth_addr ethaddr; - enum etharp_state state; +#if LWIP_SNMP + struct netif *netif; +#endif /* LWIP_SNMP */ + u8_t state; u8_t ctime; - struct netif *netif; +#if ETHARP_SUPPORT_STATIC_ENTRIES + u8_t static_entry; +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ }; static struct etharp_entry arp_table[ARP_TABLE_SIZE]; + #if !LWIP_NETIF_HWADDRHINT static u8_t etharp_cached_entry; #endif /* !LWIP_NETIF_HWADDRHINT */ -/** - * Try hard to create a new entry - we want the IP address to appear in - * the cache (even if this means removing an active entry or so). */ -#define ETHARP_TRY_HARD 1 -#define ETHARP_FIND_ONLY 2 +/** Try hard to create a new entry - we want the IP address to appear in + the cache (even if this means removing an active entry or so). */ +#define ETHARP_FLAG_TRY_HARD 1 +#define ETHARP_FLAG_FIND_ONLY 2 +#define ETHARP_FLAG_STATIC_ENTRY 4 #if LWIP_NETIF_HWADDRHINT -#define NETIF_SET_HINT(netif, hint) if (((netif) != NULL) && ((netif)->addr_hint != NULL)) \ +#define ETHARP_SET_HINT(netif, hint) if (((netif) != NULL) && ((netif)->addr_hint != NULL)) \ *((netif)->addr_hint) = (hint); -static s8_t find_entry(ip_addr_t *ipaddr, u8_t flags, struct netif *netif); #else /* LWIP_NETIF_HWADDRHINT */ -static s8_t find_entry(ip_addr_t *ipaddr, u8_t flags); +#define ETHARP_SET_HINT(netif, hint) (etharp_cached_entry = (hint)) #endif /* LWIP_NETIF_HWADDRHINT */ static err_t update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags); @@ -133,7 +130,7 @@ /* Some checks, instead of etharp_init(): */ #if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f)) - #error "If you want to use ARP, ARP_TABLE_SIZE must fit in an s8_t, so, you have to reduce it in your lwipopts.h" + #error "ARP_TABLE_SIZE must fit in an s8_t, you have to reduce it in your lwipopts.h" #endif @@ -159,10 +156,41 @@ } #endif /* ARP_QUEUEING */ +/** Clean up ARP table entries */ +static void +free_entry(int i) +{ + /* remove from SNMP ARP index tree */ + snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr); +#if ARP_QUEUEING + /* and empty packet queue */ + if (arp_table[i].q != NULL) { + /* remove all queued packets */ + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q))); + free_etharp_q(arp_table[i].q); + arp_table[i].q = NULL; + } +#endif /* ARP_QUEUEING */ + /* recycle entry for re-use */ + arp_table[i].state = ETHARP_STATE_EMPTY; +#if ETHARP_SUPPORT_STATIC_ENTRIES + arp_table[i].static_entry = 0; +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ +#ifdef LWIP_DEBUG + /* for debugging, clean out the complete entry */ + arp_table[i].ctime = 0; +#if LWIP_SNMP + arp_table[i].netif = NULL; +#endif /* LWIP_SNMP */ + ip_addr_set_zero(&arp_table[i].ipaddr); + arp_table[i].ethaddr = ethzero; +#endif /* LWIP_DEBUG */ +} + /** * Clears expired entries in the ARP table. * - * This function should be called every ETHARP_TMR_INTERVAL microseconds (5 seconds), + * This function should be called every ETHARP_TMR_INTERVAL milliseconds (5 seconds), * in order to expire entries in the ARP table. */ void @@ -173,35 +201,29 @@ LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n")); /* remove expired entries from the ARP table */ for (i = 0; i < ARP_TABLE_SIZE; ++i) { - arp_table[i].ctime++; - if (((arp_table[i].state == ETHARP_STATE_STABLE) && - (arp_table[i].ctime >= ARP_MAXAGE)) || - ((arp_table[i].state == ETHARP_STATE_PENDING) && - (arp_table[i].ctime >= ARP_MAXPENDING))) { - /* pending or stable entry has become old! */ - LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n", - arp_table[i].state == ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i)); - /* clean up entries that have just been expired */ - /* remove from SNMP ARP index tree */ - snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr); + u8_t state = arp_table[i].state; + if (state != ETHARP_STATE_EMPTY +#if ETHARP_SUPPORT_STATIC_ENTRIES + && (arp_table[i].static_entry == 0) +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + ) { + arp_table[i].ctime++; + if ((arp_table[i].ctime >= ARP_MAXAGE) || + ((arp_table[i].state == ETHARP_STATE_PENDING) && + (arp_table[i].ctime >= ARP_MAXPENDING))) { + /* pending or stable entry has become old! */ + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n", + arp_table[i].state == ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i)); + /* clean up entries that have just been expired */ + free_entry(i); + } #if ARP_QUEUEING - /* and empty packet queue */ - if (arp_table[i].q != NULL) { - /* remove all queued packets */ - LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q))); - free_etharp_q(arp_table[i].q); - arp_table[i].q = NULL; + /* still pending entry? (not expired) */ + if (arp_table[i].state == ETHARP_STATE_PENDING) { + /* resend an ARP query here? */ } #endif /* ARP_QUEUEING */ - /* recycle entry for re-use */ - arp_table[i].state = ETHARP_STATE_EMPTY; } -#if ARP_QUEUEING - /* still pending entry? (not expired) */ - if (arp_table[i].state == ETHARP_STATE_PENDING) { - /* resend an ARP query here? */ - } -#endif /* ARP_QUEUEING */ } } @@ -216,23 +238,18 @@ * If ipaddr is NULL, return a initialized new entry in state ETHARP_EMPTY. * * In all cases, attempt to create new entries from an empty entry. If no - * empty entries are available and ETHARP_TRY_HARD flag is set, recycle + * empty entries are available and ETHARP_FLAG_TRY_HARD flag is set, recycle * old entries. Heuristic choose the least important entry for recycling. * * @param ipaddr IP address to find in ARP cache, or to add if not found. - * @param flags - * - ETHARP_TRY_HARD: Try hard to create a entry by allowing recycling of - * active (stable or pending) entries. + * @param flags @see definition of ETHARP_FLAG_* + * @param netif netif related to this address (used for NETIF_HWADDRHINT) * * @return The ARP entry index that matched or is created, ERR_MEM if no * entry is found or could be recycled. */ static s8_t -#if LWIP_NETIF_HWADDRHINT -find_entry(ip_addr_t *ipaddr, u8_t flags, struct netif *netif) -#else /* LWIP_NETIF_HWADDRHINT */ find_entry(ip_addr_t *ipaddr, u8_t flags) -#endif /* LWIP_NETIF_HWADDRHINT */ { s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE; s8_t empty = ARP_TABLE_SIZE; @@ -244,35 +261,6 @@ u8_t age_queue = 0; #endif /* ARP_QUEUEING */ - /* First, test if the last call to this function asked for the - * same address. If so, we're really fast! */ - if (ipaddr) { - /* ipaddr to search for was given */ -#if LWIP_NETIF_HWADDRHINT - if ((netif != NULL) && (netif->addr_hint != NULL)) { - /* per-pcb cached entry was given */ - u8_t per_pcb_cache = *(netif->addr_hint); - if ((per_pcb_cache < ARP_TABLE_SIZE) && arp_table[per_pcb_cache].state == ETHARP_STATE_STABLE) { - /* the per-pcb-cached entry is stable */ - if (ip_addr_cmp(ipaddr, &arp_table[per_pcb_cache].ipaddr)) { - /* per-pcb cached entry was the right one! */ - ETHARP_STATS_INC(etharp.cachehit); - return per_pcb_cache; - } - } - } -#else /* #if LWIP_NETIF_HWADDRHINT */ - if (arp_table[etharp_cached_entry].state == ETHARP_STATE_STABLE) { - /* the cached entry is stable */ - if (ip_addr_cmp(ipaddr, &arp_table[etharp_cached_entry].ipaddr)) { - /* cached entry was the right one! */ - ETHARP_STATS_INC(etharp.cachehit); - return etharp_cached_entry; - } - } -#endif /* #if LWIP_NETIF_HWADDRHINT */ - } - /** * a) do a search through the cache, remember candidates * b) select candidate entry @@ -289,65 +277,61 @@ */ for (i = 0; i < ARP_TABLE_SIZE; ++i) { + u8_t state = arp_table[i].state; /* no empty entry found yet and now we do find one? */ - if ((empty == ARP_TABLE_SIZE) && (arp_table[i].state == ETHARP_STATE_EMPTY)) { + if ((empty == ARP_TABLE_SIZE) && (state == ETHARP_STATE_EMPTY)) { LWIP_DEBUGF(ETHARP_DEBUG, ("find_entry: found empty entry %"U16_F"\n", (u16_t)i)); /* remember first empty entry */ empty = i; - } - /* pending entry? */ - else if (arp_table[i].state == ETHARP_STATE_PENDING) { + } else if (state != ETHARP_STATE_EMPTY) { + LWIP_ASSERT("state == ETHARP_STATE_PENDING || state == ETHARP_STATE_STABLE", + state == ETHARP_STATE_PENDING || state == ETHARP_STATE_STABLE); /* if given, does IP address match IP address in ARP entry? */ if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching pending entry %"U16_F"\n", (u16_t)i)); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching entry %"U16_F"\n", (u16_t)i)); /* found exact IP address match, simply bail out */ -#if LWIP_NETIF_HWADDRHINT - NETIF_SET_HINT(netif, i); -#else /* #if LWIP_NETIF_HWADDRHINT */ - etharp_cached_entry = i; -#endif /* #if LWIP_NETIF_HWADDRHINT */ return i; + } + /* pending entry? */ + if (state == ETHARP_STATE_PENDING) { + /* pending with queued packets? */ #if ARP_QUEUEING - /* pending with queued packets? */ - } else if (arp_table[i].q != NULL) { - if (arp_table[i].ctime >= age_queue) { - old_queue = i; - age_queue = arp_table[i].ctime; - } + if (arp_table[i].q != NULL) { + if (arp_table[i].ctime >= age_queue) { + old_queue = i; + age_queue = arp_table[i].ctime; + } + } else #endif /* ARP_QUEUEING */ - /* pending without queued packets? */ - } else { - if (arp_table[i].ctime >= age_pending) { - old_pending = i; - age_pending = arp_table[i].ctime; + /* pending without queued packets? */ + { + if (arp_table[i].ctime >= age_pending) { + old_pending = i; + age_pending = arp_table[i].ctime; + } } - } - } - /* stable entry? */ - else if (arp_table[i].state == ETHARP_STATE_STABLE) { - /* if given, does IP address match IP address in ARP entry? */ - if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching stable entry %"U16_F"\n", (u16_t)i)); - /* found exact IP address match, simply bail out */ -#if LWIP_NETIF_HWADDRHINT - NETIF_SET_HINT(netif, i); -#else /* #if LWIP_NETIF_HWADDRHINT */ - etharp_cached_entry = i; -#endif /* #if LWIP_NETIF_HWADDRHINT */ - return i; - /* remember entry with oldest stable entry in oldest, its age in maxtime */ - } else if (arp_table[i].ctime >= age_stable) { - old_stable = i; - age_stable = arp_table[i].ctime; + /* stable entry? */ + } else if (state == ETHARP_STATE_STABLE) { +#if ETHARP_SUPPORT_STATIC_ENTRIES + /* don't record old_stable for static entries since they never expire */ + if (arp_table[i].static_entry == 0) +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + { + /* remember entry with oldest stable entry in oldest, its age in maxtime */ + if (arp_table[i].ctime >= age_stable) { + old_stable = i; + age_stable = arp_table[i].ctime; + } + } } } } /* { we have no match } => try to create a new entry */ /* don't create new entry, only search? */ - if (((flags & ETHARP_FIND_ONLY) != 0) || + if (((flags & ETHARP_FLAG_FIND_ONLY) != 0) || /* or no empty entry found and not allowed to recycle? */ - ((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_TRY_HARD) == 0))) { + ((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_FLAG_TRY_HARD) == 0))) { LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: no empty entry found and not allowed to recycle\n")); return (s8_t)ERR_MEM; } @@ -358,51 +342,49 @@ * 3) oldest pending entry without queued packets * 4) oldest pending entry with queued packets * - * { ETHARP_TRY_HARD is set at this point } + * { ETHARP_FLAG_TRY_HARD is set at this point } */ /* 1) empty entry available? */ if (empty < ARP_TABLE_SIZE) { i = empty; LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting empty entry %"U16_F"\n", (u16_t)i)); - } - /* 2) found recyclable stable entry? */ - else if (old_stable < ARP_TABLE_SIZE) { - /* recycle oldest stable*/ - i = old_stable; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i)); + } else { + /* 2) found recyclable stable entry? */ + if (old_stable < ARP_TABLE_SIZE) { + /* recycle oldest stable*/ + i = old_stable; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i)); #if ARP_QUEUEING - /* no queued packets should exist on stable entries */ - LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL); + /* no queued packets should exist on stable entries */ + LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL); #endif /* ARP_QUEUEING */ - /* 3) found recyclable pending entry without queued packets? */ - } else if (old_pending < ARP_TABLE_SIZE) { - /* recycle oldest pending */ - i = old_pending; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i)); + /* 3) found recyclable pending entry without queued packets? */ + } else if (old_pending < ARP_TABLE_SIZE) { + /* recycle oldest pending */ + i = old_pending; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i)); #if ARP_QUEUEING - /* 4) found recyclable pending entry with queued packets? */ - } else if (old_queue < ARP_TABLE_SIZE) { - /* recycle oldest pending */ - i = old_queue; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q))); - free_etharp_q(arp_table[i].q); - arp_table[i].q = NULL; + /* 4) found recyclable pending entry with queued packets? */ + } else if (old_queue < ARP_TABLE_SIZE) { + /* recycle oldest pending (queued packets are free in free_entry) */ + i = old_queue; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q))); #endif /* ARP_QUEUEING */ - /* no empty or recyclable entries found */ - } else { - return (s8_t)ERR_MEM; + /* no empty or recyclable entries found */ + } else { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: no empty or recyclable entries found\n")); + return (s8_t)ERR_MEM; + } + + /* { empty or recyclable entry found } */ + LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE); + free_entry(i); } - /* { empty or recyclable entry found } */ LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE); - - if (arp_table[i].state != ETHARP_STATE_EMPTY) - { - snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr); - } - /* recycle entry (no-op for an already empty entry) */ - arp_table[i].state = ETHARP_STATE_EMPTY; + LWIP_ASSERT("arp_table[i].state == ETHARP_STATE_EMPTY", + arp_table[i].state == ETHARP_STATE_EMPTY); /* IP address given? */ if (ipaddr != NULL) { @@ -410,11 +392,9 @@ ip_addr_copy(arp_table[i].ipaddr, *ipaddr); } arp_table[i].ctime = 0; -#if LWIP_NETIF_HWADDRHINT - NETIF_SET_HINT(netif, i); -#else /* #if LWIP_NETIF_HWADDRHINT */ - etharp_cached_entry = i; -#endif /* #if LWIP_NETIF_HWADDRHINT */ +#if ETHARP_SUPPORT_STATIC_ENTRIES + arp_table[i].static_entry = 0; +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ return (err_t)i; } @@ -432,17 +412,12 @@ etharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst) { struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload; - u8_t k; LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!", (netif->hwaddr_len == ETHARP_HWADDR_LEN)); - k = ETHARP_HWADDR_LEN; - while(k > 0) { - k--; - ethhdr->dest.addr[k] = dst->addr[k]; - ethhdr->src.addr[k] = src->addr[k]; - } - ethhdr->type = htons(ETHTYPE_IP); + ETHADDR32_COPY(ð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 /* ARP_QUEUEING */ - /* q && state == PENDING && ARP_QUEUEING == 0 => result = ERR_MEM */ + } else { + ETHARP_STATS_INC(etharp.memerr); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); /* { result == ERR_MEM } through initialization */ - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: Ethernet destination address unknown, queueing disabled, packet %p dropped\n", (void *)q)); + } +#else /* ARP_QUEUEING */ + /* q && state == PENDING && ARP_QUEUEING == 0 => result = ERR_MEM */ + /* { result == ERR_MEM } through initialization */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: Ethernet destination address unknown, queueing disabled, packet %p dropped\n", (void *)q)); #endif /* ARP_QUEUEING */ - } } return result; } @@ -1058,7 +1103,6 @@ { struct pbuf *p; err_t result = ERR_OK; - u8_t k; /* ARP entry index */ struct eth_hdr *ethhdr; struct etharp_hdr *hdr; #if LWIP_AUTOIP @@ -1084,38 +1128,34 @@ LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!", (netif->hwaddr_len == ETHARP_HWADDR_LEN)); - k = ETHARP_HWADDR_LEN; #if LWIP_AUTOIP /* If we are using Link-Local, all ARP packets that contain a Link-Local * 'sender IP address' MUST be sent using link-layer broadcast instead of * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */ ethdst_hwaddr = ip_addr_islinklocal(ipsrc_addr) ? (u8_t*)(ethbroadcast.addr) : ethdst_addr->addr; #endif /* LWIP_AUTOIP */ - /* Write MAC-Addresses (combined loop for both headers) */ - while(k > 0) { - k--; - /* Write the ARP MAC-Addresses */ - hdr->shwaddr.addr[k] = hwsrc_addr->addr[k]; - hdr->dhwaddr.addr[k] = hwdst_addr->addr[k]; - /* Write the Ethernet MAC-Addresses */ + /* Write the ARP MAC-Addresses */ + ETHADDR16_COPY(&hdr->shwaddr, hwsrc_addr); + ETHADDR16_COPY(&hdr->dhwaddr, hwdst_addr); + /* Write the Ethernet MAC-Addresses */ #if LWIP_AUTOIP - ethhdr->dest.addr[k] = ethdst_hwaddr[k]; + ETHADDR16_COPY(ð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) )