Replace the Webserver demo's uIP with the latest code ripped from the Contiki project by Adam Dunkels.

pull/1469/head
Dean Camera 15 years ago
parent 1008260985
commit 84e1241f80

File diff suppressed because one or more lines are too long

@ -127,6 +127,115 @@
* <td bgcolor="#00EE00">Yes</td>
* </tr>
* </table>
*
*
* \section Sec_UsingClassDrivers Using the Class Drivers
* To make the Class drivers easy to integrate into a user application, they all implement a standardized
* design with similarly named/used function, enums, defines and types. The two different modes are implemented
* slightly differently, and thus will be explained separately. For information on a specific class driver, read
* the class driver's module documentation.
*
* \subsection SSec_ClassDriverDevice Device Mode Class Drivers
* Implementing a Device Mode Class Driver in a user application requires a number of steps to be followed. Firstly,
* the module configuration and state structure must be added to the project source. These structures are named in a
* similar manner between classes, that of <i>USB_ClassInfo_<b>{Class Name}</b>_Device_t</i>, and are used to hold the
* complete state and configuration for each class instance. Multiple class instances is where the power of the class
* drivers lie; multiple interfaces of the same class simply require more instances of the Class Driver's ClassInfo
* structure.
*
* Inside the ClassInfo structure lies two sections, a <i>Config</i> section, and a <i>State</i> section. The Config
* section contains the instance's configuration parameters, and <b>must have all fields set by the user application</b>
* before the class driver is used. Each Device mode Class driver typically contains a set of configuration parameters
* for the endpoint size/number of the associated logical USB interface, plus any class-specific configuration parameters.
*
* The <i>State</i> section of the ClassInfo structures are designed to be controlled by the Class Drivers only for
* maintaining the Class Driver instance's state, and should not normally be set by the user application.
*
* The following is an example of a properly initialized instance of the Audio Class Driver structure:
*
* \code
* USB_ClassInfo_Audio_Device_t My_Audio_Interface =
* {
* .Config =
* {
* .StreamingInterfaceNumber = 1,
*
* .DataINEndpointNumber = 1,
* .DataINEndpointSize = 256,
* },
* };
* \endcode
*
* \note The class driver's configuration parameters should match those used in the device's descriptors that are
* sent to the host.
*
* To initialize the Class driver instance, the driver's <i><b>{Class Name}</b>_Device_ConfigureEndpoints()</i> function
* should be called in response to the \ref EVENT_USB_Device_ConfigurationChanged() event. This function will return a
* boolean value if the driver sucessfully initialized the instance. Like all the class driver functions, this function
* takes in the address of the specific instance you wish to initialize - in this manner, multiple seperate instances of
* the same class type can be initialized like thus:
*
* \code
* void EVENT_USB_Device_ConfigurationChanged(void)
* {
* LEDs_SetAllLEDs(LEDMASK_USB_READY);
*
* if (!(Audio_Device_ConfigureEndpoints(&My_Audio_Interface)))
* LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
* }
* \endcode
*
* Once initialized, it is important to maintain the class driver's state by repeatedly calling the Class Driver's
* <i><b>{Class Name}</b>_Device_USBTask()</i> function in the main program loop. The exact implementation of this
* function varies between class drivers, and can be used for any internal class driver purpose to maintain each
* instance. Again, this function uses the address of the instance to operate on, and thus needs to be called for each
* seperate instance, just like the main USB maintenance routine \ref USB_USBTask():
*
* \code
* int main(void)
* {
* SetupHardware();
*
* LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
*
* for (;;)
* {
* Create_And_Process_Samples();
*
* Audio_Device_USBTask(&My_Audio_Interface);
* USB_USBTask();
* }
* }
* \endcode
*
* The final standardized Device Class Driver function is the Control Request handler function
* <i><b>{Class Name}</b>_Device_ProcessControlRequest()</i>, which should be called when the
* \ref EVENT_USB_Device_UnhandledControlRequest() event fires. This function should also be
* called for each class driver instance, using the address of the instance to operate on as
* the function's parameter. The request handler will abort if it is determined that the current
* request is not targeted at the given class driver instance, thus these methods can safely be
* called one-after-another in the event handler with no form of error checking:
*
* \code
* void EVENT_USB_Device_UnhandledControlRequest(void)
* {
* Audio_Device_ProcessControlRequest(&My_Audio_Interface);
* }
* \endcode
*
* Each class driver may also define a set of callback functions (which are prefixed by "CALLBACK_"
* in the function's name) which <b>must</b> also be added to the user application - refer to each
* individual class driver's documentation for mandatory callbacks. In addition, each class driver may
* also define a set of events (identifiable by their prefix of "EVENT_" in the function's name), which
* the user application <b>may</b> choose to implement, or ignore if not needed.
*
* The individual Device Mode Class Driver documentation contains more information on the non-standardized,
* class-specific functions which the user application can then use on the driver instances, such as data
* read and write routines. See each driver's individual documentation for more information on the
* class-specific functions.
*
* \subsection SSec_ClassDriverHost Host Mode Class Drivers
*
*/
#ifndef __USB_H__

@ -66,6 +66,7 @@
* - Mobo 4.3, a USB controlled all band (160-10m) HF SDR transceiver: http://sites.google.com/site/lofturj/mobo4_3
* - SEGA Megadrive/Super Nintendo Cartridge Reader: http://www.snega2usb.com
* - XMEGA Development Board, using LUFA as an On-Board Programmer: http://xmega.mattair.net/
* - Penguino, an Arduino Board With On-Board LUFA Powered Debugger/Programmer: http://wiki.icy.com.au/PenguinoAVR
*
* \section Sec_LUFAPublications Publications Mentioning LUFA
* - Elektor Magazine, "My First AVR-USB" by Antoine Authier (feature), January 2010 Issue

@ -75,7 +75,7 @@ void DHCPApp_Callback(void)
case DHCP_STATE_SendDiscover:
/* Clear all DHCP settings, reset client IP address */
memset(&AppState->DHCPOffer_Data, 0x00, sizeof(AppState->DHCPOffer_Data));
uip_sethostaddr(&AppState->DHCPOffer_Data.AllocatedIP);
uip_sethostaddr((uip_ipaddr_t*)&AppState->DHCPOffer_Data.AllocatedIP);
/* Fill out the DHCP response header */
AppDataSize += DHCPApp_FillDHCPHeader(AppData, DHCP_DISCOVER, AppState);
@ -155,9 +155,9 @@ void DHCPApp_Callback(void)
(RequestResponse_MessageType == DHCP_ACK))
{
/* Set the new network parameters from the DHCP server */
uip_sethostaddr(&AppState->DHCPOffer_Data.AllocatedIP);
uip_setnetmask(&AppState->DHCPOffer_Data.Netmask);
uip_setdraddr(&AppState->DHCPOffer_Data.GatewayIP);
uip_sethostaddr((uip_ipaddr_t*)&AppState->DHCPOffer_Data.AllocatedIP);
uip_setnetmask((uip_ipaddr_t*)&AppState->DHCPOffer_Data.Netmask);
uip_setdraddr((uip_ipaddr_t*)&AppState->DHCPOffer_Data.GatewayIP);
AppState->CurrentState = DHCP_STATE_AddressLeased;
}

@ -59,7 +59,7 @@ char PROGMEM HTTP404Header[] = "HTTP/1.1 404 Not Found\r\n"
/** Default MIME type sent if no other MIME type can be determined */
char PROGMEM DefaultMIMEType[] = "text/plain";
/** List of MIME types for each supported file extension - must be terminated with \ref END_OF_MIME_LIST entry. */
/** List of MIME types for each supported file extension. */
MIME_Type_t PROGMEM MIMETypes[] =
{
{.Extension = "htm", .MIMEType = "text/html"},

@ -52,11 +52,12 @@ void uIPManagement_Init(void)
{
/* uIP Timing Initialization */
clock_init();
timer_set(&ConnectionTimer, CLOCK_SECOND / 10);
timer_set(&ConnectionTimer, CLOCK_SECOND / 8);
timer_set(&ARPTimer, CLOCK_SECOND * 10);
/* uIP Stack Initialization */
uip_init();
uip_arp_init();
/* DHCP/Server IP Settings Initialization */
#if defined(ENABLE_DHCP)

@ -0,0 +1,37 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/sfr_defs.h>
#include "clock.h"
//Counted time
volatile clock_time_t clock_datetime = 0;
//Overflow interrupt
ISR(TIMER1_COMPA_vect)
{
clock_datetime += 1;
}
//Initialise the clock
void clock_init()
{
OCR1A = ((F_CPU / 1024) / 100);
TCCR1B = ((1 << WGM12) | (1 << CS12) | (1 << CS10));
TIMSK1 = (1 << OCIE1A);
}
//Return time
clock_time_t clock_time()
{
clock_time_t time;
cli();
time = clock_datetime;
sei();
return time;
}

@ -1,88 +1,11 @@
/**
* \defgroup clock Clock interface
*
* The clock interface is the interface between the \ref timer "timer library"
* and the platform specific clock functionality. The clock
* interface must be implemented for each platform that uses the \ref
* timer "timer library".
*
* The clock interface does only one this: it measures time. The clock
* interface provides a macro, CLOCK_SECOND, which corresponds to one
* second of system time.
*
* \sa \ref timer "Timer library"
*
* @{
*/
/*
* Copyright (c) 2004, 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. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the uIP TCP/IP stack
*
* Author: Adam Dunkels <adam@sics.se>
*
* $Id: clock.h,v 1.3 2006/06/11 21:46:39 adam Exp $
*/
#ifndef __CLOCK_H__
#define __CLOCK_H__
#include "clock-arch.h"
/**
* Initialize the clock library.
*
* This function initializes the clock library and should be called
* from the main() function of the system.
*
*/
void clock_init(void);
/**
* Get the current clock time.
*
* This function returns the current system clock time.
*
* \return The current clock time, measured in system ticks.
*/
clock_time_t clock_time(void);
/**
* A second, measured in system clock time.
*
* \hideinitializer
*/
#ifdef CLOCK_CONF_SECOND
#define CLOCK_SECOND CLOCK_CONF_SECOND
#else
#define CLOCK_SECOND (clock_time_t)32
#endif
#endif /* __CLOCK_H__ */
/** @} */
#ifndef __CLOCK_ARCH_H__
#define __CLOCK_ARCH_H__
#include <stdint.h>
typedef uint16_t clock_time_t;
#define CLOCK_SECOND 100
void clock_init(void);
clock_time_t clock_time(void);
#endif /* __CLOCK_ARCH_H__ */

@ -1,83 +0,0 @@
/*
* Copyright (c) 2004-2005, 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. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the uIP TCP/IP stack
*
* Author: Adam Dunkels <adam@sics.se>
*
* $Id: lc-addrlabels.h,v 1.3 2006/06/12 08:00:30 adam Exp $
*/
/**
* \addtogroup lc
* @{
*/
/**
* \file
* Implementation of local continuations based on the "Labels as
* values" feature of gcc
* \author
* Adam Dunkels <adam@sics.se>
*
* This implementation of local continuations is based on a special
* feature of the GCC C compiler called "labels as values". This
* feature allows assigning pointers with the address of the code
* corresponding to a particular C label.
*
* For more information, see the GCC documentation:
* http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html
*
* Thanks to dividuum for finding the nice local scope label
* implementation.
*/
#ifndef __LC_ADDRLABELS_H__
#define __LC_ADDRLABELS_H__
/** \hideinitializer */
typedef void * lc_t;
#define LC_INIT(s) s = NULL
#define LC_RESUME(s) \
do { \
if(s != NULL) { \
goto *s; \
} \
} while(0)
#define LC_SET(s) \
do { ({ __label__ resume; resume: (s) = &&resume; }); }while(0)
#define LC_END(s)
#endif /* __LC_ADDRLABELS_H__ */
/** @} */

@ -1,76 +0,0 @@
/*
* Copyright (c) 2004-2005, 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. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the uIP TCP/IP stack
*
* Author: Adam Dunkels <adam@sics.se>
*
* $Id: lc-switch.h,v 1.2 2006/06/12 08:00:30 adam Exp $
*/
/**
* \addtogroup lc
* @{
*/
/**
* \file
* Implementation of local continuations based on switch() statment
* \author Adam Dunkels <adam@sics.se>
*
* This implementation of local continuations uses the C switch()
* statement to resume execution of a function somewhere inside the
* function's body. The implementation is based on the fact that
* switch() statements are able to jump directly into the bodies of
* control structures such as if() or while() statmenets.
*
* This implementation borrows heavily from Simon Tatham's coroutines
* implementation in C:
* http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
*/
#ifndef __LC_SWITCH_H__
#define __LC_SWTICH_H__
/* WARNING! lc implementation using switch() does not work if an
LC_SET() is done within another switch() statement! */
/** \hideinitializer */
typedef unsigned short lc_t;
#define LC_INIT(s) s = 0;
#define LC_RESUME(s) switch(s) { case 0:
#define LC_SET(s) s = __LINE__; case __LINE__:
#define LC_END(s) }
#endif /* __LC_SWITCH_H__ */
/** @} */

@ -1,131 +0,0 @@
/*
* Copyright (c) 2004-2005, 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. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the uIP TCP/IP stack
*
* Author: Adam Dunkels <adam@sics.se>
*
* $Id: lc.h,v 1.2 2006/06/12 08:00:30 adam Exp $
*/
/**
* \addtogroup pt
* @{
*/
/**
* \defgroup lc Local continuations
* @{
*
* Local continuations form the basis for implementing protothreads. A
* local continuation can be <i>set</i> in a specific function to
* capture the state of the function. After a local continuation has
* been set can be <i>resumed</i> in order to restore the state of the
* function at the point where the local continuation was set.
*
*
*/
/**
* \file lc.h
* Local continuations
* \author
* Adam Dunkels <adam@sics.se>
*
*/
#ifdef DOXYGEN
/**
* Initialize a local continuation.
*
* This operation initializes the local continuation, thereby
* unsetting any previously set continuation state.
*
* \hideinitializer
*/
#define LC_INIT(lc)
/**
* Set a local continuation.
*
* The set operation saves the state of the function at the point
* where the operation is executed. As far as the set operation is
* concerned, the state of the function does <b>not</b> include the
* call-stack or local (automatic) variables, but only the program
* counter and such CPU registers that needs to be saved.
*
* \hideinitializer
*/
#define LC_SET(lc)
/**
* Resume a local continuation.
*
* The resume operation resumes a previously set local continuation, thus
* restoring the state in which the function was when the local
* continuation was set. If the local continuation has not been
* previously set, the resume operation does nothing.
*
* \hideinitializer
*/
#define LC_RESUME(lc)
/**
* Mark the end of local continuation usage.
*
* The end operation signifies that local continuations should not be
* used any more in the function. This operation is not needed for
* most implementations of local continuation, but is required by a
* few implementations.
*
* \hideinitializer
*/
#define LC_END(lc)
/**
* \var typedef lc_t;
*
* The local continuation type.
*
* \hideinitializer
*/
#endif /* DOXYGEN */
#ifndef __LC_H__
#define __LC_H__
#ifdef LC_CONF_INCLUDE
#include LC_CONF_INCLUDE
#else
#include "lc-switch.h"
#endif /* LC_CONF_INCLUDE */
#endif /* __LC_H__ */
/** @} */
/** @} */

@ -1,338 +0,0 @@
/*
* Copyright (c) 2004, 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. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the uIP TCP/IP stack
*
* Author: Adam Dunkels <adam@sics.se>
*
* $Id: psock.c,v 1.2 2006/06/12 08:00:30 adam Exp $
*/
#include <stdio.h>
#include <string.h>
#include "uipopt.h"
#include "psock.h"
#include "uip.h"
#define STATE_NONE 0
#define STATE_ACKED 1
#define STATE_READ 2
#define STATE_BLOCKED_NEWDATA 3
#define STATE_BLOCKED_CLOSE 4
#define STATE_BLOCKED_SEND 5
#define STATE_DATA_SENT 6
/*
* Return value of the buffering functions that indicates that a
* buffer was not filled by incoming data.
*
*/
#define BUF_NOT_FULL 0
#define BUF_NOT_FOUND 0
/*
* Return value of the buffering functions that indicates that a
* buffer was completely filled by incoming data.
*
*/
#define BUF_FULL 1
/*
* Return value of the buffering functions that indicates that an
* end-marker byte was found.
*
*/
#define BUF_FOUND 2
/*---------------------------------------------------------------------------*/
static void
buf_setup(struct psock_buf *buf,
u8_t *bufptr, u16_t bufsize)
{
buf->ptr = bufptr;
buf->left = bufsize;
}
/*---------------------------------------------------------------------------*/
static u8_t
buf_bufdata(struct psock_buf *buf, u16_t len,
u8_t **dataptr, u16_t *datalen)
{
if(*datalen < buf->left) {
memcpy(buf->ptr, *dataptr, *datalen);
buf->ptr += *datalen;
buf->left -= *datalen;
*dataptr += *datalen;
*datalen = 0;
return BUF_NOT_FULL;
} else if(*datalen == buf->left) {
memcpy(buf->ptr, *dataptr, *datalen);
buf->ptr += *datalen;
buf->left = 0;
*dataptr += *datalen;
*datalen = 0;
return BUF_FULL;
} else {
memcpy(buf->ptr, *dataptr, buf->left);
buf->ptr += buf->left;
*datalen -= buf->left;
*dataptr += buf->left;
buf->left = 0;
return BUF_FULL;
}
}
/*---------------------------------------------------------------------------*/
static u8_t
buf_bufto(register struct psock_buf *buf, u8_t endmarker,
register u8_t **dataptr, register u16_t *datalen)
{
u8_t c;
while(buf->left > 0 && *datalen > 0) {
c = *buf->ptr = **dataptr;
++*dataptr;
++buf->ptr;
--*datalen;
--buf->left;
if(c == endmarker) {
return BUF_FOUND;
}
}
if(*datalen == 0) {
return BUF_NOT_FOUND;
}
while(*datalen > 0) {
c = **dataptr;
--*datalen;
++*dataptr;
if(c == endmarker) {
return BUF_FOUND | BUF_FULL;
}
}
return BUF_FULL;
}
/*---------------------------------------------------------------------------*/
static char
send_data(register struct psock *s)
{
if(s->state != STATE_DATA_SENT || uip_rexmit()) {
if(s->sendlen > uip_mss()) {
uip_send(s->sendptr, uip_mss());
} else {
uip_send(s->sendptr, s->sendlen);
}
s->state = STATE_DATA_SENT;
return 1;
}
return 0;
}
/*---------------------------------------------------------------------------*/
static char
data_acked(register struct psock *s)
{
if(s->state == STATE_DATA_SENT && uip_acked()) {
if(s->sendlen > uip_mss()) {
s->sendlen -= uip_mss();
s->sendptr += uip_mss();
} else {
s->sendptr += s->sendlen;
s->sendlen = 0;
}
s->state = STATE_ACKED;
return 1;
}
return 0;
}
/*---------------------------------------------------------------------------*/
PT_THREAD(psock_send(register struct psock *s, const char *buf,
unsigned int len))
{
PT_BEGIN(&s->psockpt);
/* If there is no data to send, we exit immediately. */
if(len == 0) {
PT_EXIT(&s->psockpt);
}
/* Save the length of and a pointer to the data that is to be
sent. */
s->sendptr = buf;
s->sendlen = len;
s->state = STATE_NONE;
/* We loop here until all data is sent. The s->sendlen variable is
updated by the data_sent() function. */
while(s->sendlen > 0) {
/*
* The condition for this PT_WAIT_UNTIL is a little tricky: the
* protothread will wait here until all data has been acknowledged
* (data_acked() returns true) and until all data has been sent
* (send_data() returns true). The two functions data_acked() and
* send_data() must be called in succession to ensure that all
* data is sent. Therefore the & operator is used instead of the
* && operator, which would cause only the data_acked() function
* to be called when it returns false.
*/
PT_WAIT_UNTIL(&s->psockpt, data_acked(s) & send_data(s));
}
s->state = STATE_NONE;
PT_END(&s->psockpt);
}
/*---------------------------------------------------------------------------*/
PT_THREAD(psock_generator_send(register struct psock *s,
unsigned short (*generate)(void *), void *arg))
{
PT_BEGIN(&s->psockpt);
/* Ensure that there is a generator function to call. */
if(generate == NULL) {
PT_EXIT(&s->psockpt);
}
/* Call the generator function to generate the data in the
uip_appdata buffer. */
s->sendlen = generate(arg);
s->sendptr = uip_appdata;
s->state = STATE_NONE;
do {
/* Call the generator function again if we are called to perform a
retransmission. */
if(uip_rexmit()) {
generate(arg);
}
/* Wait until all data is sent and acknowledged. */
PT_WAIT_UNTIL(&s->psockpt, data_acked(s) & send_data(s));
} while(s->sendlen > 0);
s->state = STATE_NONE;
PT_END(&s->psockpt);
}
/*---------------------------------------------------------------------------*/
u16_t
psock_datalen(struct psock *psock)
{
return psock->bufsize - psock->buf.left;
}
/*---------------------------------------------------------------------------*/
char
psock_newdata(struct psock *s)
{
if(s->readlen > 0) {
/* There is data in the uip_appdata buffer that has not yet been
read with the PSOCK_READ functions. */
return 1;
} else if(s->state == STATE_READ) {
/* All data in uip_appdata buffer already consumed. */
s->state = STATE_BLOCKED_NEWDATA;
return 0;
} else if(uip_newdata()) {
/* There is new data that has not been consumed. */
return 1;
} else {
/* There is no new data. */
return 0;
}
}
/*---------------------------------------------------------------------------*/
PT_THREAD(psock_readto(register struct psock *psock, unsigned char c))
{
PT_BEGIN(&psock->psockpt);
buf_setup(&psock->buf, psock->bufptr, psock->bufsize);
/* XXX: Should add buf_checkmarker() before do{} loop, if
incoming data has been handled while waiting for a write. */
do {
if(psock->readlen == 0) {
PT_WAIT_UNTIL(&psock->psockpt, psock_newdata(psock));
psock->state = STATE_READ;
psock->readptr = (u8_t *)uip_appdata;
psock->readlen = uip_datalen();
}
} while((buf_bufto(&psock->buf, c,
&psock->readptr,
&psock->readlen) & BUF_FOUND) == 0);
if(psock_datalen(psock) == 0) {
psock->state = STATE_NONE;
PT_RESTART(&psock->psockpt);
}
PT_END(&psock->psockpt);
}
/*---------------------------------------------------------------------------*/
PT_THREAD(psock_readbuf(register struct psock *psock))
{
PT_BEGIN(&psock->psockpt);
buf_setup(&psock->buf, psock->bufptr, psock->bufsize);
/* XXX: Should add buf_checkmarker() before do{} loop, if
incoming data has been handled while waiting for a write. */
do {
if(psock->readlen == 0) {
PT_WAIT_UNTIL(&psock->psockpt, psock_newdata(psock));
printf("Waited for newdata\n");
psock->state = STATE_READ;
psock->readptr = (u8_t *)uip_appdata;
psock->readlen = uip_datalen();
}
} while(buf_bufdata(&psock->buf, psock->bufsize,
&psock->readptr,
&psock->readlen) != BUF_FULL);
if(psock_datalen(psock) == 0) {
psock->state = STATE_NONE;
PT_RESTART(&psock->psockpt);
}
PT_END(&psock->psockpt);
}
/*---------------------------------------------------------------------------*/
void
psock_init(register struct psock *psock, char *buffer, unsigned int buffersize)
{
psock->state = STATE_NONE;
psock->readlen = 0;
psock->bufptr = buffer;
psock->bufsize = buffersize;
buf_setup(&psock->buf, buffer, buffersize);
PT_INIT(&psock->pt);
PT_INIT(&psock->psockpt);
}
/*---------------------------------------------------------------------------*/

@ -1,380 +0,0 @@
/*
* Copyright (c) 2004, 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. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the uIP TCP/IP stack
*
* Author: Adam Dunkels <adam@sics.se>
*
* $Id: psock.h,v 1.3 2006/06/12 08:00:30 adam Exp $
*/
/**
* \defgroup psock Protosockets library
* @{
*
* The protosocket library provides an interface to the uIP stack that is
* similar to the traditional BSD socket interface. Unlike programs
* written for the ordinary uIP event-driven interface, programs
* written with the protosocket library are executed in a sequential
* fashion and does not have to be implemented as explicit state
* machines.
*
* Protosockets only work with TCP connections.
*
* The protosocket library uses \ref pt protothreads to provide
* sequential control flow. This makes the protosockets lightweight in
* terms of memory, but also means that protosockets inherits the
* functional limitations of protothreads. Each protosocket lives only
* within a single function. Automatic variables (stack variables) are
* not retained across a protosocket library function call.
*
* \note Because the protosocket library uses protothreads, local
* variables will not always be saved across a call to a protosocket
* library function. It is therefore advised that local variables are
* used with extreme care.
*
* The protosocket library provides functions for sending data without
* having to deal with retransmissions and acknowledgements, as well
* as functions for reading data without having to deal with data
* being split across more than one TCP segment.
*
* Because each protosocket runs as a protothread, the protosocket has to be
* started with a call to PSOCK_BEGIN() at the start of the function
* in which the protosocket is used. Similarly, the protosocket protothread can
* be terminated by a call to PSOCK_EXIT().
*
*/
/**
* \file
* Protosocket library header file
* \author
* Adam Dunkels <adam@sics.se>
*
*/
#ifndef __PSOCK_H__
#define __PSOCK_H__
#include "uipopt.h"
#include "pt.h"
/*
* The structure that holds the state of a buffer.
*
* This structure holds the state of a uIP buffer. The structure has
* no user-visible elements, but is used through the functions
* provided by the library.
*
*/
struct psock_buf {
u8_t *ptr;
unsigned short left;
};
/**
* The representation of a protosocket.
*
* The protosocket structrure is an opaque structure with no user-visible
* elements.
*/
struct psock {
struct pt pt, psockpt; /* Protothreads - one that's using the psock
functions, and one that runs inside the
psock functions. */
const u8_t *sendptr; /* Pointer to the next data to be sent. */
u8_t *readptr; /* Pointer to the next data to be read. */
char *bufptr; /* Pointer to the buffer used for buffering
incoming data. */
u16_t sendlen; /* The number of bytes left to be sent. */
u16_t readlen; /* The number of bytes left to be read. */
struct psock_buf buf; /* The structure holding the state of the
input buffer. */
unsigned int bufsize; /* The size of the input buffer. */
unsigned char state; /* The state of the protosocket. */
};
void psock_init(struct psock *psock, char *buffer, unsigned int buffersize);
/**
* Initialize a protosocket.
*
* This macro initializes a protosocket and must be called before the
* protosocket is used. The initialization also specifies the input buffer
* for the protosocket.
*
* \param psock (struct psock *) A pointer to the protosocket to be
* initialized
*
* \param buffer (char *) A pointer to the input buffer for the
* protosocket.
*
* \param buffersize (unsigned int) The size of the input buffer.
*
* \hideinitializer
*/
#define PSOCK_INIT(psock, buffer, buffersize) \
psock_init(psock, buffer, buffersize)
/**
* Start the protosocket protothread in a function.
*
* This macro starts the protothread associated with the protosocket and
* must come before other protosocket calls in the function it is used.
*
* \param psock (struct psock *) A pointer to the protosocket to be
* started.
*
* \hideinitializer
*/
#define PSOCK_BEGIN(psock) PT_BEGIN(&((psock)->pt))
PT_THREAD(psock_send(struct psock *psock, const char *buf, unsigned int len));
/**
* Send data.
*
* This macro sends data over a protosocket. The protosocket protothread blocks
* until all data has been sent and is known to have been received by
* the remote end of the TCP connection.
*
* \param psock (struct psock *) A pointer to the protosocket over which
* data is to be sent.
*
* \param data (char *) A pointer to the data that is to be sent.
*
* \param datalen (unsigned int) The length of the data that is to be
* sent.
*
* \hideinitializer
*/
#define PSOCK_SEND(psock, data, datalen) \
PT_WAIT_THREAD(&((psock)->pt), psock_send(psock, data, datalen))
/**
* \brief Send a null-terminated string.
* \param psock Pointer to the protosocket.
* \param str The string to be sent.
*
* This function sends a null-terminated string over the
* protosocket.
*
* \hideinitializer
*/
#define PSOCK_SEND_STR(psock, str) \
PT_WAIT_THREAD(&((psock)->pt), psock_send(psock, str, strlen(str)))
PT_THREAD(psock_generator_send(struct psock *psock,
unsigned short (*f)(void *), void *arg));
/**
* \brief Generate data with a function and send it
* \param psock Pointer to the protosocket.
* \param generator Pointer to the generator function
* \param arg Argument to the generator function
*
* This function generates data and sends it over the
* protosocket. This can be used to dynamically generate
* data for a transmission, instead of generating the data
* in a buffer beforehand. This function reduces the need for
* buffer memory. The generator function is implemented by
* the application, and a pointer to the function is given
* as an argument with the call to PSOCK_GENERATOR_SEND().
*
* The generator function should place the generated data
* directly in the uip_appdata buffer, and return the
* length of the generated data. The generator function is
* called by the protosocket layer when the data first is
* sent, and once for every retransmission that is needed.
*
* \hideinitializer
*/
#define PSOCK_GENERATOR_SEND(psock, generator, arg) \
PT_WAIT_THREAD(&((psock)->pt), \
psock_generator_send(psock, generator, arg))
/**
* Close a protosocket.
*
* This macro closes a protosocket and can only be called from within the
* protothread in which the protosocket lives.
*
* \param psock (struct psock *) A pointer to the protosocket that is to
* be closed.
*
* \hideinitializer
*/
#define PSOCK_CLOSE(psock) uip_close()
PT_THREAD(psock_readbuf(struct psock *psock));
/**
* Read data until the buffer is full.
*
* This macro will block waiting for data and read the data into the
* input buffer specified with the call to PSOCK_INIT(). Data is read
* until the buffer is full..
*
* \param psock (struct psock *) A pointer to the protosocket from which
* data should be read.
*
* \hideinitializer
*/
#define PSOCK_READBUF(psock) \
PT_WAIT_THREAD(&((psock)->pt), psock_readbuf(psock))
PT_THREAD(psock_readto(struct psock *psock, unsigned char c));
/**
* Read data up to a specified character.
*
* This macro will block waiting for data and read the data into the
* input buffer specified with the call to PSOCK_INIT(). Data is only
* read until the specifieed character appears in the data stream.
*
* \param psock (struct psock *) A pointer to the protosocket from which
* data should be read.
*
* \param c (char) The character at which to stop reading.
*
* \hideinitializer
*/
#define PSOCK_READTO(psock, c) \
PT_WAIT_THREAD(&((psock)->pt), psock_readto(psock, c))
/**
* The length of the data that was previously read.
*
* This macro returns the length of the data that was previously read
* using PSOCK_READTO() or PSOCK_READ().
*
* \param psock (struct psock *) A pointer to the protosocket holding the data.
*
* \hideinitializer
*/
#define PSOCK_DATALEN(psock) psock_datalen(psock)
u16_t psock_datalen(struct psock *psock);
/**
* Exit the protosocket's protothread.
*
* This macro terminates the protothread of the protosocket and should
* almost always be used in conjunction with PSOCK_CLOSE().
*
* \sa PSOCK_CLOSE_EXIT()
*
* \param psock (struct psock *) A pointer to the protosocket.
*
* \hideinitializer
*/
#define PSOCK_EXIT(psock) PT_EXIT(&((psock)->pt))
/**
* Close a protosocket and exit the protosocket's protothread.
*
* This macro closes a protosocket and exits the protosocket's protothread.
*
* \param psock (struct psock *) A pointer to the protosocket.
*
* \hideinitializer
*/
#define PSOCK_CLOSE_EXIT(psock) \
do { \
PSOCK_CLOSE(psock); \
PSOCK_EXIT(psock); \
} while(0)
/**
* Declare the end of a protosocket's protothread.
*
* This macro is used for declaring that the protosocket's protothread
* ends. It must always be used together with a matching PSOCK_BEGIN()
* macro.
*
* \param psock (struct psock *) A pointer to the protosocket.
*
* \hideinitializer
*/
#define PSOCK_END(psock) PT_END(&((psock)->pt))
char psock_newdata(struct psock *s);
/**
* Check if new data has arrived on a protosocket.
*
* This macro is used in conjunction with the PSOCK_WAIT_UNTIL()
* macro to check if data has arrived on a protosocket.
*
* \param psock (struct psock *) A pointer to the protosocket.
*
* \hideinitializer
*/
#define PSOCK_NEWDATA(psock) psock_newdata(psock)
/**
* Wait until a condition is true.
*
* This macro blocks the protothread until the specified condition is
* true. The macro PSOCK_NEWDATA() can be used to check if new data
* arrives when the protosocket is waiting.
*
* Typically, this macro is used as follows:
*
\code
PT_THREAD(thread(struct psock *s, struct timer *t))
{
PSOCK_BEGIN(s);
PSOCK_WAIT_UNTIL(s, PSOCK_NEWADATA(s) || timer_expired(t));
if(PSOCK_NEWDATA(s)) {
PSOCK_READTO(s, '\n');
} else {
handle_timed_out(s);
}
PSOCK_END(s);
}
\endcode
*
* \param psock (struct psock *) A pointer to the protosocket.
* \param condition The condition to wait for.
*
* \hideinitializer
*/
#define PSOCK_WAIT_UNTIL(psock, condition) \
PT_WAIT_UNTIL(&((psock)->pt), (condition));
#define PSOCK_WAIT_THREAD(psock, condition) \
PT_WAIT_THREAD(&((psock)->pt), (condition))
#endif /* __PSOCK_H__ */
/** @} */

@ -1,323 +0,0 @@
/*
* Copyright (c) 2004-2005, 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. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the uIP TCP/IP stack
*
* Author: Adam Dunkels <adam@sics.se>
*
* $Id: pt.h,v 1.2 2006/06/12 08:00:30 adam Exp $
*/
/**
* \addtogroup pt
* @{
*/
/**
* \file
* Protothreads implementation.
* \author
* Adam Dunkels <adam@sics.se>
*
*/
#ifndef __PT_H__
#define __PT_H__
#include "lc.h"
struct pt {
lc_t lc;
};
#define PT_WAITING 0
#define PT_EXITED 1
#define PT_ENDED 2
#define PT_YIELDED 3
/**
* \name Initialization
* @{
*/
/**
* Initialize a protothread.
*
* Initializes a protothread. Initialization must be done prior to
* starting to execute the protothread.
*
* \param pt A pointer to the protothread control structure.
*
* \sa PT_SPAWN()
*
* \hideinitializer
*/
#define PT_INIT(pt) LC_INIT((pt)->lc)
/** @} */
/**
* \name Declaration and definition
* @{
*/
/**
* Declaration of a protothread.
*
* This macro is used to declare a protothread. All protothreads must
* be declared with this macro.
*
* \param name_args The name and arguments of the C function
* implementing the protothread.
*
* \hideinitializer
*/
#define PT_THREAD(name_args) char name_args
/**
* Declare the start of a protothread inside the C function
* implementing the protothread.
*
* This macro is used to declare the starting point of a
* protothread. It should be placed at the start of the function in
* which the protothread runs. All C statements above the PT_BEGIN()
* invokation will be executed each time the protothread is scheduled.
*
* \param pt A pointer to the protothread control structure.
*
* \hideinitializer
*/
#define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; LC_RESUME((pt)->lc)
/**
* Declare the end of a protothread.
*
* This macro is used for declaring that a protothread ends. It must
* always be used together with a matching PT_BEGIN() macro.
*
* \param pt A pointer to the protothread control structure.
*
* \hideinitializer
*/
#define PT_END(pt) LC_END((pt)->lc); PT_YIELD_FLAG = 0; \
PT_INIT(pt); return PT_ENDED; }
/** @} */
/**
* \name Blocked wait
* @{
*/
/**
* Block and wait until condition is true.
*
* This macro blocks the protothread until the specified condition is
* true.
*
* \param pt A pointer to the protothread control structure.
* \param condition The condition.
*
* \hideinitializer
*/
#define PT_WAIT_UNTIL(pt, condition) \
do { \
LC_SET((pt)->lc); \
if(!(condition)) { \
return PT_WAITING; \
} \
} while(0)
/**
* Block and wait while condition is true.
*
* This function blocks and waits while condition is true. See
* PT_WAIT_UNTIL().
*
* \param pt A pointer to the protothread control structure.
* \param cond The condition.
*
* \hideinitializer
*/
#define PT_WAIT_WHILE(pt, cond) PT_WAIT_UNTIL((pt), !(cond))
/** @} */
/**
* \name Hierarchical protothreads
* @{
*/
/**
* Block and wait until a child protothread completes.
*
* This macro schedules a child protothread. The current protothread
* will block until the child protothread completes.
*
* \note The child protothread must be manually initialized with the
* PT_INIT() function before this function is used.
*
* \param pt A pointer to the protothread control structure.
* \param thread The child protothread with arguments
*
* \sa PT_SPAWN()
*
* \hideinitializer
*/
#define PT_WAIT_THREAD(pt, thread) PT_WAIT_WHILE((pt), PT_SCHEDULE(thread))
/**
* Spawn a child protothread and wait until it exits.
*
* This macro spawns a child protothread and waits until it exits. The
* macro can only be used within a protothread.
*
* \param pt A pointer to the protothread control structure.
* \param child A pointer to the child protothread's control structure.
* \param thread The child protothread with arguments
*
* \hideinitializer
*/
#define PT_SPAWN(pt, child, thread) \
do { \
PT_INIT((child)); \
PT_WAIT_THREAD((pt), (thread)); \
} while(0)
/** @} */
/**
* \name Exiting and restarting
* @{
*/
/**
* Restart the protothread.
*
* This macro will block and cause the running protothread to restart
* its execution at the place of the PT_BEGIN() call.
*
* \param pt A pointer to the protothread control structure.
*
* \hideinitializer
*/
#define PT_RESTART(pt) \
do { \
PT_INIT(pt); \
return PT_WAITING; \
} while(0)
/**
* Exit the protothread.
*
* This macro causes the protothread to exit. If the protothread was
* spawned by another protothread, the parent protothread will become
* unblocked and can continue to run.
*
* \param pt A pointer to the protothread control structure.
*
* \hideinitializer
*/
#define PT_EXIT(pt) \
do { \
PT_INIT(pt); \
return PT_EXITED; \
} while(0)
/** @} */
/**
* \name Calling a protothread
* @{
*/
/**
* Schedule a protothread.
*
* This function shedules a protothread. The return value of the
* function is non-zero if the protothread is running or zero if the
* protothread has exited.
*
* \param f The call to the C function implementing the protothread to
* be scheduled
*
* \hideinitializer
*/
#define PT_SCHEDULE(f) ((f) == PT_WAITING)
/** @} */
/**
* \name Yielding from a protothread
* @{
*/
/**
* Yield from the current protothread.
*
* This function will yield the protothread, thereby allowing other
* processing to take place in the system.
*
* \param pt A pointer to the protothread control structure.
*
* \hideinitializer
*/
#define PT_YIELD(pt) \
do { \
PT_YIELD_FLAG = 0; \
LC_SET((pt)->lc); \
if(PT_YIELD_FLAG == 0) { \
return PT_YIELDED; \
} \
} while(0)
/**
* \brief Yield from the protothread until a condition occurs.
* \param pt A pointer to the protothread control structure.
* \param cond The condition.
*
* This function will yield the protothread, until the
* specified condition evaluates to true.
*
*
* \hideinitializer
*/
#define PT_YIELD_UNTIL(pt, cond) \
do { \
PT_YIELD_FLAG = 0; \
LC_SET((pt)->lc); \
if((PT_YIELD_FLAG == 0) || !(cond)) { \
return PT_YIELDED; \
} \
} while(0)
/** @} */
#endif /* __PT_H__ */
/** @} */

@ -1,532 +0,0 @@
/*
* Copyright (c) 2004, 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. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the uIP TCP/IP stack
*
* Author: Adam Dunkels <adam@sics.se>
*
* $Id: uip-fw.c,v 1.2 2006/06/12 08:00:30 adam Exp $
*/
/**
* \addtogroup uip
* @{
*/
/**
* \defgroup uipfw uIP packet forwarding
* @{
*
*/
/**
* \file
* uIP packet forwarding.
* \author Adam Dunkels <adam@sics.se>
*
* This file implements a number of simple functions which do packet
* forwarding over multiple network interfaces with uIP.
*
*/
#include "uip.h"
#include "uip_arch.h"
#include "uip-fw.h"
#include <string.h> /* for memcpy() */
/*
* The list of registered network interfaces.
*/
static struct uip_fw_netif *netifs = NULL;
/*
* A pointer to the default network interface.
*/
static struct uip_fw_netif *defaultnetif = NULL;
struct tcpip_hdr {
/* IP header. */
u8_t vhl,
tos;
u16_t len,
ipid,
ipoffset;
u8_t ttl,
proto;
u16_t ipchksum;
u16_t srcipaddr[2],
destipaddr[2];
/* TCP header. */
u16_t srcport,
destport;
u8_t seqno[4],
ackno[4],
tcpoffset,
flags,
wnd[2];
u16_t tcpchksum;
u8_t urgp[2];
u8_t optdata[4];
};
struct icmpip_hdr {
/* IP header. */
u8_t vhl,
tos,
len[2],
ipid[2],
ipoffset[2],
ttl,
proto;
u16_t ipchksum;
u16_t srcipaddr[2],
destipaddr[2];
/* ICMP (echo) header. */
u8_t type, icode;
u16_t icmpchksum;
u16_t id, seqno;
u8_t payload[1];
};
/* ICMP ECHO. */
#define ICMP_ECHO 8
/* ICMP TIME-EXCEEDED. */
#define ICMP_TE 11
/*
* Pointer to the TCP/IP headers of the packet in the uip_buf buffer.
*/
#define BUF ((struct tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
/*
* Pointer to the ICMP/IP headers of the packet in the uip_buf buffer.
*/
#define ICMPBUF ((struct icmpip_hdr *)&uip_buf[UIP_LLH_LEN])
/*
* Certain fields of an IP packet that are used for identifying
* duplicate packets.
*/
struct fwcache_entry {
u16_t timer;
u16_t srcipaddr[2];
u16_t destipaddr[2];
u16_t ipid;
u8_t proto;
u8_t unused;
#if notdef
u16_t payload[2];
#endif
#if UIP_REASSEMBLY > 0
u16_t len, offset;
#endif
};
/*
* The number of packets to remember when looking for duplicates.
*/
#ifdef UIP_CONF_FWCACHE_SIZE
#define FWCACHE_SIZE UIP_CONF_FWCACHE_SIZE
#else
#define FWCACHE_SIZE 2
#endif
/*
* A cache of packet header fields which are used for
* identifying duplicate packets.
*/
static struct fwcache_entry fwcache[FWCACHE_SIZE];
/**
* \internal
* The time that a packet cache is active.
*/
#define FW_TIME 20
/*------------------------------------------------------------------------------*/
/**
* Initialize the uIP packet forwarding module.
*/
/*------------------------------------------------------------------------------*/
void
uip_fw_init(void)
{
struct uip_fw_netif *t;
defaultnetif = NULL;
while(netifs != NULL) {
t = netifs;
netifs = netifs->next;
t->next = NULL;
}
}
/*------------------------------------------------------------------------------*/
/**
* \internal
* Check if an IP address is within the network defined by an IP
* address and a netmask.
*
* \param ipaddr The IP address to be checked.
* \param netipaddr The IP address of the network.
* \param netmask The netmask of the network.
*
* \return Non-zero if IP address is in network, zero otherwise.
*/
/*------------------------------------------------------------------------------*/
static unsigned char
ipaddr_maskcmp(u16_t *ipaddr, u16_t *netipaddr, u16_t *netmask)
{
return (ipaddr[0] & netmask [0]) == (netipaddr[0] & netmask[0]) &&
(ipaddr[1] & netmask[1]) == (netipaddr[1] & netmask[1]);
}
/*------------------------------------------------------------------------------*/
/**
* \internal
* Send out an ICMP TIME-EXCEEDED message.
*
* This function replaces the packet in the uip_buf buffer with the
* ICMP packet.
*/
/*------------------------------------------------------------------------------*/
static void
time_exceeded(void)
{
u16_t tmp16;
/* We don't send out ICMP errors for ICMP messages. */
if(ICMPBUF->proto == UIP_PROTO_ICMP) {
uip_len = 0;
return;
}
/* Copy fields from packet header into payload of this ICMP packet. */
memcpy(&(ICMPBUF->payload[0]), ICMPBUF, 28);
/* Set the ICMP type and code. */
ICMPBUF->type = ICMP_TE;
ICMPBUF->icode = 0;
/* Calculate the ICMP checksum. */
ICMPBUF->icmpchksum = 0;
ICMPBUF->icmpchksum = ~uip_chksum((u16_t *)&(ICMPBUF->type), 36);
/* Set the IP destination address to be the source address of the
original packet. */
tmp16= BUF->destipaddr[0];
BUF->destipaddr[0] = BUF->srcipaddr[0];
BUF->srcipaddr[0] = tmp16;
tmp16 = BUF->destipaddr[1];
BUF->destipaddr[1] = BUF->srcipaddr[1];
BUF->srcipaddr[1] = tmp16;
/* Set our IP address as the source address. */
BUF->srcipaddr[0] = uip_hostaddr[0];
BUF->srcipaddr[1] = uip_hostaddr[1];
/* The size of the ICMP time exceeded packet is 36 + the size of the
IP header (20) = 56. */
uip_len = 56;
ICMPBUF->len[0] = 0;
ICMPBUF->len[1] = uip_len;
/* Fill in the other fields in the IP header. */
ICMPBUF->vhl = 0x45;
ICMPBUF->tos = 0;
ICMPBUF->ipoffset[0] = ICMPBUF->ipoffset[1] = 0;
ICMPBUF->ttl = UIP_TTL;
ICMPBUF->proto = UIP_PROTO_ICMP;
/* Calculate IP checksum. */
ICMPBUF->ipchksum = 0;
ICMPBUF->ipchksum = ~(uip_ipchksum());
}
/*------------------------------------------------------------------------------*/
/**
* \internal
* Register a packet in the forwarding cache so that it won't be
* forwarded again.
*/
/*------------------------------------------------------------------------------*/
static void
fwcache_register(void)
{
struct fwcache_entry *fw;
int i, oldest;
oldest = FW_TIME;
fw = NULL;
/* Find the oldest entry in the cache. */
for(i = 0; i < FWCACHE_SIZE; ++i) {
if(fwcache[i].timer == 0) {
fw = &fwcache[i];
break;
} else if(fwcache[i].timer <= oldest) {
fw = &fwcache[i];
oldest = fwcache[i].timer;
}
}
fw->timer = FW_TIME;
fw->ipid = BUF->ipid;
fw->srcipaddr[0] = BUF->srcipaddr[0];
fw->srcipaddr[1] = BUF->srcipaddr[1];
fw->destipaddr[0] = BUF->destipaddr[0];
fw->destipaddr[1] = BUF->destipaddr[1];
fw->proto = BUF->proto;
#if notdef
fw->payload[0] = BUF->srcport;
fw->payload[1] = BUF->destport;
#endif
#if UIP_REASSEMBLY > 0
fw->len = BUF->len;
fw->offset = BUF->ipoffset;
#endif
}
/*------------------------------------------------------------------------------*/
/**
* \internal
* Find a network interface for the IP packet in uip_buf.
*/
/*------------------------------------------------------------------------------*/
static struct uip_fw_netif *
find_netif(void)
{
struct uip_fw_netif *netif;
/* Walk through every network interface to check for a match. */
for(netif = netifs; netif != NULL; netif = netif->next) {
if(ipaddr_maskcmp(BUF->destipaddr, netif->ipaddr,
netif->netmask)) {
/* If there was a match, we break the loop. */
return netif;
}
}
/* If no matching netif was found, we use default netif. */
return defaultnetif;
}
/*------------------------------------------------------------------------------*/
/**
* Output an IP packet on the correct network interface.
*
* The IP packet should be present in the uip_buf buffer and its
* length in the global uip_len variable.
*
* \retval UIP_FW_ZEROLEN Indicates that a zero-length packet
* transmission was attempted and that no packet was sent.
*
* \retval UIP_FW_NOROUTE No suitable network interface could be found
* for the outbound packet, and the packet was not sent.
*
* \return The return value from the actual network interface output
* function is passed unmodified as a return value.
*/
/*------------------------------------------------------------------------------*/
u8_t
uip_fw_output(void)
{
struct uip_fw_netif *netif;
if(uip_len == 0) {
return UIP_FW_ZEROLEN;
}
fwcache_register();
#if UIP_BROADCAST
/* Link local broadcasts go out on all interfaces. */
if(/*BUF->proto == UIP_PROTO_UDP &&*/
BUF->destipaddr[0] == 0xffff &&
BUF->destipaddr[1] == 0xffff) {
if(defaultnetif != NULL) {
defaultnetif->output();
}
for(netif = netifs; netif != NULL; netif = netif->next) {
netif->output();
}
return UIP_FW_OK;
}
#endif /* UIP_BROADCAST */
netif = find_netif();
/* printf("uip_fw_output: netif %p ->output %p len %d\n", netif,
netif->output,
uip_len);*/
if(netif == NULL) {
return UIP_FW_NOROUTE;
}
/* If we now have found a suitable network interface, we call its
output function to send out the packet. */
return netif->output();
}
/*------------------------------------------------------------------------------*/
/**
* Forward an IP packet in the uip_buf buffer.
*
*
*
* \return UIP_FW_FORWARDED if the packet was forwarded, UIP_FW_LOCAL if
* the packet should be processed locally.
*/
/*------------------------------------------------------------------------------*/
u8_t
uip_fw_forward(void)
{
struct fwcache_entry *fw;
/* First check if the packet is destined for ourselves and return 0
to indicate that the packet should be processed locally. */
if(BUF->destipaddr[0] == uip_hostaddr[0] &&
BUF->destipaddr[1] == uip_hostaddr[1]) {
return UIP_FW_LOCAL;
}
/* If we use ping IP address configuration, and our IP address is
not yet configured, we should intercept all ICMP echo packets. */
#if UIP_PINGADDRCONF
if((uip_hostaddr[0] | uip_hostaddr[1]) == 0 &&
BUF->proto == UIP_PROTO_ICMP &&
ICMPBUF->type == ICMP_ECHO) {
return UIP_FW_LOCAL;
}
#endif /* UIP_PINGADDRCONF */
/* Check if the packet is in the forwarding cache already, and if so
we drop it. */
for(fw = fwcache; fw < &fwcache[FWCACHE_SIZE]; ++fw) {
if(fw->timer != 0 &&
#if UIP_REASSEMBLY > 0
fw->len == BUF->len &&
fw->offset == BUF->ipoffset &&
#endif
fw->ipid == BUF->ipid &&
fw->srcipaddr[0] == BUF->srcipaddr[0] &&
fw->srcipaddr[1] == BUF->srcipaddr[1] &&
fw->destipaddr[0] == BUF->destipaddr[0] &&
fw->destipaddr[1] == BUF->destipaddr[1] &&
#if notdef
fw->payload[0] == BUF->srcport &&
fw->payload[1] == BUF->destport &&
#endif
fw->proto == BUF->proto) {
/* Drop packet. */
return UIP_FW_FORWARDED;
}
}
/* If the TTL reaches zero we produce an ICMP time exceeded message
in the uip_buf buffer and forward that packet back to the sender
of the packet. */
if(BUF->ttl <= 1) {
/* No time exceeded for broadcasts and multicasts! */
if(BUF->destipaddr[0] == 0xffff && BUF->destipaddr[1] == 0xffff) {
return UIP_FW_LOCAL;
}
time_exceeded();
}
/* Decrement the TTL (time-to-live) value in the IP header */
BUF->ttl = BUF->ttl - 1;
/* Update the IP checksum. */
if(BUF->ipchksum >= HTONS(0xffff - 0x0100)) {
BUF->ipchksum = BUF->ipchksum + HTONS(0x0100) + 1;
} else {
BUF->ipchksum = BUF->ipchksum + HTONS(0x0100);
}
if(uip_len > 0) {
uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_TCPIP_HLEN];
uip_fw_output();
}
#if UIP_BROADCAST
if(BUF->destipaddr[0] == 0xffff && BUF->destipaddr[1] == 0xffff) {
return UIP_FW_LOCAL;
}
#endif /* UIP_BROADCAST */
/* Return non-zero to indicate that the packet was forwarded and that no
other processing should be made. */
return UIP_FW_FORWARDED;
}
/*------------------------------------------------------------------------------*/
/**
* Register a network interface with the forwarding module.
*
* \param netif A pointer to the network interface that is to be
* registered.
*/
/*------------------------------------------------------------------------------*/
void
uip_fw_register(struct uip_fw_netif *netif)
{
netif->next = netifs;
netifs = netif;
}
/*------------------------------------------------------------------------------*/
/**
* Register a default network interface.
*
* All packets that don't go out on any of the other interfaces will
* be routed to the default interface.
*
* \param netif A pointer to the network interface that is to be
* registered.
*/
/*------------------------------------------------------------------------------*/
void
uip_fw_default(struct uip_fw_netif *netif)
{
defaultnetif = netif;
}
/*------------------------------------------------------------------------------*/
/**
* Perform periodic processing.
*/
/*------------------------------------------------------------------------------*/
void
uip_fw_periodic(void)
{
struct fwcache_entry *fw;
for(fw = fwcache; fw < &fwcache[FWCACHE_SIZE]; ++fw) {
if(fw->timer > 0) {
--fw->timer;
}
}
}
/*------------------------------------------------------------------------------*/

@ -1,176 +0,0 @@
/**
* \addtogroup uipfw
* @{
*/
/**
* \file
* uIP packet forwarding header file.
* \author Adam Dunkels <adam@sics.se>
*/
/*
* Copyright (c) 2004, 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. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the uIP TCP/IP stack
*
* Author: Adam Dunkels <adam@sics.se>
*
* $Id: uip-fw.h,v 1.2 2006/06/12 08:00:30 adam Exp $
*/
#ifndef __UIP_FW_H__
#define __UIP_FW_H__
#include "uip.h"
/**
* Representation of a uIP network interface.
*/
struct uip_fw_netif {
struct uip_fw_netif *next; /**< Pointer to the next interface when
linked in a list. */
u16_t ipaddr[2]; /**< The IP address of this interface. */
u16_t netmask[2]; /**< The netmask of the interface. */
u8_t (* output)(void);
/**< A pointer to the function that
sends a packet. */
};
/**
* Intantiating macro for a uIP network interface.
*
* Example:
\code
struct uip_fw_netif slipnetif =
{UIP_FW_NETIF(192,168,76,1, 255,255,255,0, slip_output)};
\endcode
* \param ip1,ip2,ip3,ip4 The IP address of the network interface.
*
* \param nm1,nm2,nm3,nm4 The netmask of the network interface.
*
* \param outputfunc A pointer to the output function of the network interface.
*
* \hideinitializer
*/
#define UIP_FW_NETIF(ip1,ip2,ip3,ip4, nm1,nm2,nm3,nm4, outputfunc) \
NULL, \
{HTONS((ip1 << 8) | ip2), HTONS((ip3 << 8) | ip4)}, \
{HTONS((nm1 << 8) | nm2), HTONS((nm3 << 8) | nm4)}, \
outputfunc
/**
* Set the IP address of a network interface.
*
* \param netif A pointer to the uip_fw_netif structure for the network interface.
*
* \param addr A pointer to an IP address.
*
* \hideinitializer
*/
#define uip_fw_setipaddr(netif, addr) \
do { (netif)->ipaddr[0] = ((u16_t *)(addr))[0]; \
(netif)->ipaddr[1] = ((u16_t *)(addr))[1]; } while(0)
/**
* Set the netmask of a network interface.
*
* \param netif A pointer to the uip_fw_netif structure for the network interface.
*
* \param addr A pointer to an IP address representing the netmask.
*
* \hideinitializer
*/
#define uip_fw_setnetmask(netif, addr) \
do { (netif)->netmask[0] = ((u16_t *)(addr))[0]; \
(netif)->netmask[1] = ((u16_t *)(addr))[1]; } while(0)
void uip_fw_init(void);
u8_t uip_fw_forward(void);
u8_t uip_fw_output(void);
void uip_fw_register(struct uip_fw_netif *netif);
void uip_fw_default(struct uip_fw_netif *netif);
void uip_fw_periodic(void);
/**
* A non-error message that indicates that a packet should be
* processed locally.
*
* \hideinitializer
*/
#define UIP_FW_LOCAL 0
/**
* A non-error message that indicates that something went OK.
*
* \hideinitializer
*/
#define UIP_FW_OK 0
/**
* A non-error message that indicates that a packet was forwarded.
*
* \hideinitializer
*/
#define UIP_FW_FORWARDED 1
/**
* A non-error message that indicates that a zero-length packet
* transmission was attempted, and that no packet was sent.
*
* \hideinitializer
*/
#define UIP_FW_ZEROLEN 2
/**
* An error message that indicates that a packet that was too large
* for the outbound network interface was detected.
*
* \hideinitializer
*/
#define UIP_FW_TOOLARGE 3
/**
* An error message that indicates that no suitable interface could be
* found for an outbound packet.
*
* \hideinitializer
*/
#define UIP_FW_NOROUTE 4
/**
* An error message that indicates that a packet that should be
* forwarded or output was dropped.
*
* \hideinitializer
*/
#define UIP_FW_DROPPED 5
#endif /* __UIP_FW_H__ */
/** @} */

@ -1,158 +0,0 @@
/*
* Copyright (c) 2006, 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. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the uIP TCP/IP stack
*
* $Id: uip-neighbor.c,v 1.2 2006/06/12 08:00:30 adam Exp $
*/
/**
* \file
* Database of link-local neighbors, used by IPv6 code and
* to be used by a future ARP code rewrite.
* \author
* Adam Dunkels <adam@sics.se>
*/
#include "uip-neighbor.h"
#include <string.h>
#define MAX_TIME 128
#ifdef UIP_NEIGHBOR_CONF_ENTRIES
#define ENTRIES UIP_NEIGHBOR_CONF_ENTRIES
#else /* UIP_NEIGHBOR_CONF_ENTRIES */
#define ENTRIES 8
#endif /* UIP_NEIGHBOR_CONF_ENTRIES */
struct neighbor_entry {
uip_ipaddr_t ipaddr;
struct uip_neighbor_addr addr;
u8_t time;
};
static struct neighbor_entry entries[ENTRIES];
/*---------------------------------------------------------------------------*/
void
uip_neighbor_init(void)
{
int i;
for(i = 0; i < ENTRIES; ++i) {
entries[i].time = MAX_TIME;
}
}
/*---------------------------------------------------------------------------*/
void
uip_neighbor_periodic(void)
{
int i;
for(i = 0; i < ENTRIES; ++i) {
if(entries[i].time < MAX_TIME) {
entries[i].time++;
}
}
}
/*---------------------------------------------------------------------------*/
void
uip_neighbor_add(uip_ipaddr_t ipaddr, struct uip_neighbor_addr *addr)
{
int i, oldest;
u8_t oldest_time;
printf("Adding neighbor with link address %02x:%02x:%02x:%02x:%02x:%02x\n",
addr->addr.addr[0], addr->addr.addr[1], addr->addr.addr[2], addr->addr.addr[3],
addr->addr.addr[4], addr->addr.addr[5]);
/* Find the first unused entry or the oldest used entry. */
oldest_time = 0;
oldest = 0;
for(i = 0; i < ENTRIES; ++i) {
if(entries[i].time == MAX_TIME) {
oldest = i;
break;
}
if(uip_ipaddr_cmp(entries[i].ipaddr, addr)) {
oldest = i;
break;
}
if(entries[i].time > oldest_time) {
oldest = i;
oldest_time = entries[i].time;
}
}
/* Use the oldest or first free entry (either pointed to by the
"oldest" variable). */
entries[oldest].time = 0;
uip_ipaddr_copy(entries[oldest].ipaddr, ipaddr);
memcpy(&entries[oldest].addr, addr, sizeof(struct uip_neighbor_addr));
}
/*---------------------------------------------------------------------------*/
static struct neighbor_entry *
find_entry(uip_ipaddr_t ipaddr)
{
int i;
for(i = 0; i < ENTRIES; ++i) {
if(uip_ipaddr_cmp(entries[i].ipaddr, ipaddr)) {
return &entries[i];
}
}
return NULL;
}
/*---------------------------------------------------------------------------*/
void
uip_neighbor_update(uip_ipaddr_t ipaddr)
{
struct neighbor_entry *e;
e = find_entry(ipaddr);
if(e != NULL) {
e->time = 0;
}
}
/*---------------------------------------------------------------------------*/
struct uip_neighbor_addr *
uip_neighbor_lookup(uip_ipaddr_t ipaddr)
{
struct neighbor_entry *e;
e = find_entry(ipaddr);
if(e != NULL) {
/* printf("Lookup neighbor with link address %02x:%02x:%02x:%02x:%02x:%02x\n",
e->addr.addr.addr[0], e->addr.addr.addr[1], e->addr.addr.addr[2], e->addr.addr.addr[3],
e->addr.addr.addr[4], e->addr.addr.addr[5]);*/
return &e->addr;
}
return NULL;
}
/*---------------------------------------------------------------------------*/

@ -1,61 +0,0 @@
/*
* Copyright (c) 2006, 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. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the uIP TCP/IP stack
*
* $Id: uip-neighbor.h,v 1.2 2006/06/12 08:00:30 adam Exp $
*/
/**
* \file
* Header file for database of link-local neighbors, used by
* IPv6 code and to be used by future ARP code.
* \author
* Adam Dunkels <adam@sics.se>
*/
#ifndef __UIP_NEIGHBOR_H__
#define __UIP_NEIGHBOR_H__
#include "uip.h"
struct uip_neighbor_addr {
#if UIP_NEIGHBOR_CONF_ADDRTYPE
UIP_NEIGHBOR_CONF_ADDRTYPE addr;
#else
struct uip_eth_addr addr;
#endif
};
void uip_neighbor_init(void);
void uip_neighbor_add(uip_ipaddr_t ipaddr, struct uip_neighbor_addr *addr);
void uip_neighbor_update(uip_ipaddr_t ipaddr);
struct uip_neighbor_addr *uip_neighbor_lookup(uip_ipaddr_t ipaddr);
void uip_neighbor_periodic(void);
#endif /* __UIP-NEIGHBOR_H__ */

@ -1,136 +0,0 @@
/*
* Copyright (c) 2004, 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. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the uIP TCP/IP stack
*
* Author: Adam Dunkels <adam@sics.se>
*
* $Id: uip-split.c,v 1.2 2006/06/12 08:00:30 adam Exp $
*/
#include <string.h>
#include "uip-split.h"
#include "uip.h"
#include "uip-fw.h"
#include "uip_arch.h"
#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
/*-----------------------------------------------------------------------------*/
void
uip_split_output(void)
{
u16_t tcplen, len1, len2;
/* We only try to split maximum sized TCP segments. */
if(BUF->proto == UIP_PROTO_TCP &&
uip_len == UIP_BUFSIZE - UIP_LLH_LEN) {
tcplen = uip_len - UIP_TCPIP_HLEN;
/* Split the segment in two. If the original packet length was
odd, we make the second packet one byte larger. */
len1 = len2 = tcplen / 2;
if(len1 + len2 < tcplen) {
++len2;
}
/* Create the first packet. This is done by altering the length
field of the IP header and updating the checksums. */
uip_len = len1 + UIP_TCPIP_HLEN;
#if UIP_CONF_IPV6
/* For IPv6, the IP length field does not include the IPv6 IP header
length. */
BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
#else /* UIP_CONF_IPV6 */
BUF->len[0] = uip_len >> 8;
BUF->len[1] = uip_len & 0xff;
#endif /* UIP_CONF_IPV6 */
/* Recalculate the TCP checksum. */
BUF->tcpchksum = 0;
BUF->tcpchksum = ~(uip_tcpchksum());
#if !UIP_CONF_IPV6
/* Recalculate the IP checksum. */
BUF->ipchksum = 0;
BUF->ipchksum = ~(uip_ipchksum());
#endif /* UIP_CONF_IPV6 */
/* Transmit the first packet. */
/* uip_fw_output();*/
tcpip_output();
/* Now, create the second packet. To do this, it is not enough to
just alter the length field, but we must also update the TCP
sequence number and point the uip_appdata to a new place in
memory. This place is detemined by the length of the first
packet (len1). */
uip_len = len2 + UIP_TCPIP_HLEN;
#if UIP_CONF_IPV6
/* For IPv6, the IP length field does not include the IPv6 IP header
length. */
BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
#else /* UIP_CONF_IPV6 */
BUF->len[0] = uip_len >> 8;
BUF->len[1] = uip_len & 0xff;
#endif /* UIP_CONF_IPV6 */
/* uip_appdata += len1;*/
memcpy(uip_appdata, (u8_t *)uip_appdata + len1, len2);
uip_add32(BUF->seqno, len1);
BUF->seqno[0] = uip_acc32[0];
BUF->seqno[1] = uip_acc32[1];
BUF->seqno[2] = uip_acc32[2];
BUF->seqno[3] = uip_acc32[3];
/* Recalculate the TCP checksum. */
BUF->tcpchksum = 0;
BUF->tcpchksum = ~(uip_tcpchksum());
#if !UIP_CONF_IPV6
/* Recalculate the IP checksum. */
BUF->ipchksum = 0;
BUF->ipchksum = ~(uip_ipchksum());
#endif /* UIP_CONF_IPV6 */
/* Transmit the second packet. */
/* uip_fw_output();*/
tcpip_output();
} else {
/* uip_fw_output();*/
tcpip_output();
}
}
/*-----------------------------------------------------------------------------*/

@ -1,96 +0,0 @@
/*
* Copyright (c) 2004, 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. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the uIP TCP/IP stack
*
* Author: Adam Dunkels <adam@sics.se>
*
* $Id: uip-split.h,v 1.2 2006/06/12 08:00:30 adam Exp $
*/
/**
* \addtogroup uip
* @{
*/
/**
* \defgroup uipsplit uIP TCP throughput booster hack
* @{
*
* The basic uIP TCP implementation only allows each TCP connection to
* have a single TCP segment in flight at any given time. Because of
* the delayed ACK algorithm employed by most TCP receivers, uIP's
* limit on the amount of in-flight TCP segments seriously reduces the
* maximum achievable throughput for sending data from uIP.
*
* The uip-split module is a hack which tries to remedy this
* situation. By splitting maximum sized outgoing TCP segments into
* two, the delayed ACK algorithm is not invoked at TCP
* receivers. This improves the throughput when sending data from uIP
* by orders of magnitude.
*
* The uip-split module uses the uip-fw module (uIP IP packet
* forwarding) for sending packets. Therefore, the uip-fw module must
* be set up with the appropriate network interfaces for this module
* to work.
*/
/**
* \file
* Module for splitting outbound TCP segments in two to avoid the
* delayed ACK throughput degradation.
* \author
* Adam Dunkels <adam@sics.se>
*
*/
#ifndef __UIP_SPLIT_H__
#define __UIP_SPLIT_H__
/**
* Handle outgoing packets.
*
* This function inspects an outgoing packet in the uip_buf buffer and
* sends it out using the uip_fw_output() function. If the packet is a
* full-sized TCP segment it will be split into two segments and
* transmitted separately. This function should be called instead of
* the actual device driver output function, or the uip_fw_output()
* function.
*
* The headers of the outgoing packet is assumed to be in the uip_buf
* buffer and the payload is assumed to be wherever uip_appdata
* points. The length of the outgoing packet is assumed to be in the
* uip_len variable.
*
*/
void uip_split_output(void);
#endif /* __UIP_SPLIT_H__ */
/** @} */
/** @} */

@ -1,16 +1,8 @@
#define DEBUG_PRINTF(...) /*printf(__VA_ARGS__)*/
/**
* \defgroup uip The uIP TCP/IP stack
* \addtogroup uip
* @{
*
* uIP is an implementation of the TCP/IP protocol stack intended for
* small 8-bit and 16-bit microcontrollers.
*
* uIP provides the necessary protocols for Internet communication,
* with a very small code footprint and RAM requirements - the uIP
* code size is on the order of a few kilobytes and RAM usage is on
* the order of a few hundred bytes.
*/
/**
@ -49,7 +41,7 @@
*
* This file is part of the uIP TCP/IP stack.
*
* $Id: uip.c,v 1.65 2006/06/11 21:46:39 adam Exp $
* $Id: uip.c,v 1.15 2008/10/15 08:08:32 adamdunkels Exp $
*
*/
@ -81,10 +73,16 @@
#include "uip.h"
#include "uipopt.h"
#include "uip_arch.h"
#include "uip_arp.h"
#if !UIP_CONF_IPV6 /* If UIP_CONF_IPV6 is defined, we compile the
uip6.c file instead of this one. Therefore
this #ifndef removes the entire compilation
output of the uip.c file */
#if UIP_CONF_IPV6
#include "uip-neighbor.h"
#include "net/uip-neighbor.h"
#endif /* UIP_CONF_IPV6 */
#include <string.h>
@ -98,31 +96,23 @@
here. Otherwise, the address */
#if UIP_FIXEDADDR > 0
const uip_ipaddr_t uip_hostaddr =
{HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1),
HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)};
{ UIP_IPADDR0, UIP_IPADDR1, UIP_IPADDR2, UIP_IPADDR3 };
const uip_ipaddr_t uip_draddr =
{HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1),
HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)};
{ UIP_DRIPADDR0, UIP_DRIPADDR1, UIP_DRIPADDR2, UIP_DRIPADDR3 };
const uip_ipaddr_t uip_netmask =
{HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1),
HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)};
{ UIP_NETMASK0, UIP_NETMASK1, UIP_NETMASK2, UIP_NETMASK3 };
#else
uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask;
#endif /* UIP_FIXEDADDR */
static const uip_ipaddr_t all_ones_addr =
const uip_ipaddr_t uip_broadcast_addr =
#if UIP_CONF_IPV6
{0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff};
{ { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } };
#else /* UIP_CONF_IPV6 */
{0xffff,0xffff};
{ { 0xff, 0xff, 0xff, 0xff } };
#endif /* UIP_CONF_IPV6 */
static const uip_ipaddr_t all_zeroes_addr =
#if UIP_CONF_IPV6
{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000};
#else /* UIP_CONF_IPV6 */
{0x0000,0x0000};
#endif /* UIP_CONF_IPV6 */
const uip_ipaddr_t uip_all_zeroes_addr = { { 0x0, /* rest is 0 */ } };
#if UIP_FIXEDETHADDR
const struct uip_eth_addr uip_ethaddr = {{UIP_ETHADDR0,
@ -211,6 +201,9 @@ static u16_t tmp16;
#define ICMP_ECHO_REPLY 0
#define ICMP_ECHO 8
#define ICMP_DEST_UNREACHABLE 3
#define ICMP_PORT_UNREACHABLE 3
#define ICMP6_ECHO_REPLY 129
#define ICMP6_ECHO 128
#define ICMP6_NEIGHBOR_SOLICITATION 135
@ -342,7 +335,7 @@ upper_layer_chksum(u8_t proto)
/* IP protocol and length fields. This addition cannot carry. */
sum = upper_layer_len + proto;
/* Sum IP source and destination addresses. */
sum = chksum(sum, (u8_t *)&BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t));
sum = chksum(sum, (u8_t *)&BUF->srcipaddr, 2 * sizeof(uip_ipaddr_t));
/* Sum TCP header and data. */
sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN],
@ -470,7 +463,7 @@ uip_connect(uip_ipaddr_t *ripaddr, u16_t rport)
/*---------------------------------------------------------------------------*/
#if UIP_UDP
struct uip_udp_conn *
uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport)
uip_udp_new(const uip_ipaddr_t *ripaddr, u16_t rport)
{
register struct uip_udp_conn *conn;
@ -504,7 +497,7 @@ uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport)
conn->lport = HTONS(lastport);
conn->rport = rport;
if(ripaddr == NULL) {
memset(conn->ripaddr, 0, sizeof(uip_ipaddr_t));
memset(&conn->ripaddr, 0, sizeof(uip_ipaddr_t));
} else {
uip_ipaddr_copy(&conn->ripaddr, ripaddr);
}
@ -889,7 +882,7 @@ uip_process(u8_t flag)
}
#endif /* UIP_CONF_IPV6 */
if(uip_ipaddr_cmp(uip_hostaddr, all_zeroes_addr)) {
if(uip_ipaddr_cmp(&uip_hostaddr, &uip_all_zeroes_addr)) {
/* If we are configured to use ping IP address configuration and
hasn't been assigned an IP address yet, we accept all ICMP
packets. */
@ -909,7 +902,7 @@ uip_process(u8_t flag)
#if UIP_BROADCAST
DEBUG_PRINTF("UDP IP checksum 0x%04x\n", uip_ipchksum());
if(BUF->proto == UIP_PROTO_UDP &&
uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr)
uip_ipaddr_cmp(&BUF->destipaddr, &uip_broadcast_addr)
/*&&
uip_ipchksum() == 0xffff*/) {
goto udp_input;
@ -918,7 +911,7 @@ uip_process(u8_t flag)
/* Check if the packet is destined for our IP address. */
#if !UIP_CONF_IPV6
if(!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr)) {
if(!uip_ipaddr_cmp(&BUF->destipaddr, &uip_hostaddr)) {
UIP_STAT(++uip_stat.ip.drop);
goto drop;
}
@ -928,8 +921,8 @@ uip_process(u8_t flag)
hosts multicast address, and the solicited-node multicast
address) as well. However, we will cheat here and accept all
multicast packets that are sent to the ff02::/16 addresses. */
if(!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr) &&
BUF->destipaddr[0] != HTONS(0xff02)) {
if(!uip_ipaddr_cmp(&BUF->destipaddr, &uip_hostaddr) &&
BUF->destipaddr.u16[0] != HTONS(0xff02)) {
UIP_STAT(++uip_stat.ip.drop);
goto drop;
}
@ -987,9 +980,8 @@ uip_process(u8_t flag)
the destination IP address of this ping packet and assign it to
ourself. */
#if UIP_PINGADDRCONF
if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) {
uip_hostaddr[0] = BUF->destipaddr[0];
uip_hostaddr[1] = BUF->destipaddr[1];
if(uip_ipaddr_cmp(&uip_hostaddr, &uip_all_zeroes_addr)) {
uip_hostaddr = BUF->destipaddr;
}
#endif /* UIP_PINGADDRCONF */
@ -1002,11 +994,12 @@ uip_process(u8_t flag)
}
/* Swap IP addresses. */
uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
uip_ipaddr_copy(&BUF->destipaddr, &BUF->srcipaddr);
uip_ipaddr_copy(&BUF->srcipaddr, &uip_hostaddr);
UIP_STAT(++uip_stat.icmp.sent);
goto send;
BUF->ttl = UIP_TTL;
goto ip_send_nolen;
/* End of IPv4 input header processing code. */
#else /* !UIP_CONF_IPV6 */
@ -1027,11 +1020,11 @@ uip_process(u8_t flag)
/* If we get a neighbor solicitation for our address we should send
a neighbor advertisement message back. */
if(ICMPBUF->type == ICMP6_NEIGHBOR_SOLICITATION) {
if(uip_ipaddr_cmp(ICMPBUF->icmp6data, uip_hostaddr)) {
if(uip_ipaddr_cmp(&ICMPBUF->icmp6data, &uip_hostaddr)) {
if(ICMPBUF->options[0] == ICMP6_OPTION_SOURCE_LINK_ADDRESS) {
/* Save the sender's address in our neighbor list. */
uip_neighbor_add(ICMPBUF->srcipaddr, &(ICMPBUF->options[2]));
uip_neighbor_add(&ICMPBUF->srcipaddr, &(ICMPBUF->options[2]));
}
/* We should now send a neighbor advertisement back to where the
@ -1041,13 +1034,14 @@ uip_process(u8_t flag)
ICMPBUF->reserved1 = ICMPBUF->reserved2 = ICMPBUF->reserved3 = 0;
uip_ipaddr_copy(ICMPBUF->destipaddr, ICMPBUF->srcipaddr);
uip_ipaddr_copy(ICMPBUF->srcipaddr, uip_hostaddr);
uip_ipaddr_copy(&ICMPBUF->destipaddr, &ICMPBUF->srcipaddr);
uip_ipaddr_copy(&ICMPBUF->srcipaddr, &uip_hostaddr);
ICMPBUF->options[0] = ICMP6_OPTION_TARGET_LINK_ADDRESS;
ICMPBUF->options[1] = 1; /* Options length, 1 = 8 bytes. */
memcpy(&(ICMPBUF->options[2]), &uip_ethaddr, sizeof(uip_ethaddr));
ICMPBUF->icmpchksum = 0;
ICMPBUF->icmpchksum = ~uip_icmp6chksum();
goto send;
}
@ -1059,8 +1053,8 @@ uip_process(u8_t flag)
ICMPBUF->type = ICMP6_ECHO_REPLY;
uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
uip_ipaddr_copy(&BUF->destipaddr, &BUF->srcipaddr);
uip_ipaddr_copy(&BUF->srcipaddr, &uip_hostaddr);
ICMPBUF->icmpchksum = 0;
ICMPBUF->icmpchksum = ~uip_icmp6chksum();
@ -1113,14 +1107,44 @@ uip_process(u8_t flag)
UDPBUF->destport == uip_udp_conn->lport &&
(uip_udp_conn->rport == 0 ||
UDPBUF->srcport == uip_udp_conn->rport) &&
(uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) ||
uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) ||
uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr))) {
(uip_ipaddr_cmp(&uip_udp_conn->ripaddr, &uip_all_zeroes_addr) ||
uip_ipaddr_cmp(&uip_udp_conn->ripaddr, &uip_broadcast_addr) ||
uip_ipaddr_cmp(&BUF->srcipaddr, &uip_udp_conn->ripaddr))) {
goto udp_found;
}
}
UIP_LOG("udp: no matching connection found");
#if UIP_CONF_ICMP_DEST_UNREACH && !UIP_CONF_IPV6
/* Copy fields from packet header into payload of this ICMP packet. */
memcpy(&(ICMPBUF->payload[0]), ICMPBUF, UIP_IPH_LEN + 8);
/* Set the ICMP type and code. */
ICMPBUF->type = ICMP_DEST_UNREACHABLE;
ICMPBUF->icode = ICMP_PORT_UNREACHABLE;
/* Calculate the ICMP checksum. */
ICMPBUF->icmpchksum = 0;
ICMPBUF->icmpchksum = ~uip_chksum((u16_t *)&(ICMPBUF->type), 36);
/* Set the IP destination address to be the source address of the
original packet. */
uip_ipaddr_copy(&BUF->destipaddr, &BUF->srcipaddr);
/* Set our IP address as the source address. */
uip_ipaddr_copy(&BUF->srcipaddr, &uip_hostaddr);
/* The size of the ICMP destination unreachable packet is 36 + the
size of the IP header (20) = 56. */
uip_len = 36 + UIP_IPH_LEN;
ICMPBUF->len[0] = 0;
ICMPBUF->len[1] = (u8_t)uip_len;
ICMPBUF->ttl = UIP_TTL;
ICMPBUF->proto = UIP_PROTO_ICMP;
goto ip_send_nolen;
#else /* UIP_CONF_ICMP_DEST_UNREACH */
goto drop;
#endif /* UIP_CONF_ICMP_DEST_UNREACH */
udp_found:
uip_conn = NULL;
@ -1128,6 +1152,7 @@ uip_process(u8_t flag)
uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
uip_slen = 0;
UIP_UDP_APPCALL();
udp_send:
if(uip_slen == 0) {
goto drop;
@ -1153,8 +1178,8 @@ uip_process(u8_t flag)
BUF->srcport = uip_udp_conn->lport;
BUF->destport = uip_udp_conn->rport;
uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
uip_ipaddr_copy(BUF->destipaddr, uip_udp_conn->ripaddr);
uip_ipaddr_copy(&BUF->srcipaddr, &uip_hostaddr);
uip_ipaddr_copy(&BUF->destipaddr, &uip_udp_conn->ripaddr);
uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN];
@ -1183,7 +1208,6 @@ uip_process(u8_t flag)
goto drop;
}
/* Demultiplex this segment. */
/* First check any active connections. */
for(uip_connr = &uip_conns[0]; uip_connr <= &uip_conns[UIP_CONNS - 1];
@ -1191,7 +1215,7 @@ uip_process(u8_t flag)
if(uip_connr->tcpstateflags != UIP_CLOSED &&
BUF->destport == uip_connr->lport &&
BUF->srcport == uip_connr->rport &&
uip_ipaddr_cmp(BUF->srcipaddr, uip_connr->ripaddr)) {
uip_ipaddr_cmp(&BUF->srcipaddr, &uip_connr->ripaddr)) {
goto found;
}
}
@ -1207,14 +1231,15 @@ uip_process(u8_t flag)
tmp16 = BUF->destport;
/* Next, check listening connections. */
for(c = 0; c < UIP_LISTENPORTS; ++c) {
if(tmp16 == uip_listenports[c])
if(tmp16 == uip_listenports[c]) {
goto found_listen;
}
}
/* No matching connection found, so we send a RST packet. */
UIP_STAT(++uip_stat.tcp.synrst);
reset:
reset:
/* We do not send resets in response to resets. */
if(BUF->flags & TCP_RST) {
goto drop;
@ -1260,8 +1285,8 @@ uip_process(u8_t flag)
BUF->destport = tmp16;
/* Swap IP addresses. */
uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
uip_ipaddr_copy(&BUF->destipaddr, &BUF->srcipaddr);
uip_ipaddr_copy(&BUF->srcipaddr, &uip_hostaddr);
/* And send out the RST packet! */
goto tcp_send_noconn;
@ -1307,7 +1332,7 @@ uip_process(u8_t flag)
uip_connr->nrtx = 0;
uip_connr->lport = BUF->destport;
uip_connr->rport = BUF->srcport;
uip_ipaddr_copy(uip_connr->ripaddr, BUF->srcipaddr);
uip_ipaddr_copy(&uip_connr->ripaddr, &BUF->srcipaddr);
uip_connr->tcpstateflags = UIP_SYN_RCVD;
uip_connr->snd_nxt[0] = iss[0];
@ -1393,7 +1418,7 @@ uip_process(u8_t flag)
UIP_APPCALL();
goto drop;
}
/* Calculated the length of the data, if the application has sent
/* Calculate the length of the data, if the application has sent
any data to us. */
c = (BUF->tcpoffset >> 4) << 2;
/* uip_len will contain the length of the actual TCP data. This is
@ -1432,7 +1457,6 @@ uip_process(u8_t flag)
uip_connr->snd_nxt[2] = uip_acc32[2];
uip_connr->snd_nxt[3] = uip_acc32[3];
/* Do RTT estimation, unless we have done retransmissions. */
if(uip_connr->nrtx == 0) {
signed char m;
@ -1785,20 +1809,22 @@ uip_process(u8_t flag)
}
goto drop;
/* We jump here when we are ready to send the packet, and just want
to set the appropriate TCP sequence numbers in the TCP header. */
tcp_send_ack:
BUF->flags = TCP_ACK;
tcp_send_nodata:
uip_len = UIP_IPTCPH_LEN;
tcp_send_noopts:
BUF->tcpoffset = (UIP_TCPH_LEN / 4) << 4;
tcp_send:
/* We're done with the input processing. We are now ready to send a
reply. Our job is to fill in all the fields of the TCP and IP
headers before calculating the checksum and finally send the
packet. */
tcp_send:
BUF->ackno[0] = uip_connr->rcv_nxt[0];
BUF->ackno[1] = uip_connr->rcv_nxt[1];
BUF->ackno[2] = uip_connr->rcv_nxt[2];
@ -1814,8 +1840,8 @@ uip_process(u8_t flag)
BUF->srcport = uip_connr->lport;
BUF->destport = uip_connr->rport;
uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
uip_ipaddr_copy(BUF->destipaddr, uip_connr->ripaddr);
uip_ipaddr_copy(&BUF->srcipaddr, &uip_hostaddr);
uip_ipaddr_copy(&BUF->destipaddr, &uip_connr->ripaddr);
if(uip_connr->tcpstateflags & UIP_STOPPED) {
/* If the connection has issued uip_stop(), we advertise a zero
@ -1843,9 +1869,8 @@ uip_process(u8_t flag)
/* Calculate TCP checksum. */
BUF->tcpchksum = 0;
BUF->tcpchksum = ~(uip_tcpchksum());
ip_send_nolen:
ip_send_nolen:
#if UIP_CONF_IPV6
BUF->vtc = 0x60;
BUF->tcflow = 0x00;
@ -1861,10 +1886,11 @@ uip_process(u8_t flag)
BUF->ipchksum = 0;
BUF->ipchksum = ~(uip_ipchksum());
DEBUG_PRINTF("uip ip_send_nolen: chkecum 0x%04x\n", uip_ipchksum());
#endif /* UIP_CONF_IPV6 */
#endif /* UIP_CONF_IPV6 */
UIP_STAT(++uip_stat.tcp.sent);
#if UIP_CONF_IPV6
send:
#endif /* UIP_CONF_IPV6 */
DEBUG_PRINTF("Sending packet with length %d (%d)\n", uip_len,
(BUF->len[0] << 8) | BUF->len[1]);
@ -1872,6 +1898,7 @@ uip_process(u8_t flag)
/* Return and let the caller do the actual transmission. */
uip_flags = 0;
return;
drop:
uip_len = 0;
uip_flags = 0;
@ -1883,15 +1910,27 @@ htons(u16_t val)
{
return HTONS(val);
}
u32_t
htonl(u32_t val)
{
return HTONL(val);
}
/*---------------------------------------------------------------------------*/
void
uip_send(const void *data, int len)
{
if(len > 0) {
uip_slen = len;
int copylen;
#define MIN(a,b) ((a) < (b)? (a): (b))
copylen = MIN(len, UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN -
(int)((char *)uip_sappdata - (char *)&uip_buf[UIP_LLH_LEN + UIP_TCPIP_HLEN]));
if(copylen > 0) {
uip_slen = copylen;
if(data != uip_sappdata) {
memcpy(uip_sappdata, (data), uip_slen);
}
}
}
/*---------------------------------------------------------------------------*/
/** @} */
#endif /* UIP_CONF_IPV6 */

@ -7,7 +7,9 @@
/**
* \file
* Header file for the uIP TCP/IP stack.
* \author Adam Dunkels <adam@dunkels.com>
* \author Adam Dunkels <adam@dunkels.com>
* \author Julien Abeille <jabeille@cisco.com> (IPv6 related code)
* \author Mathilde Durvy <mdurvy@cisco.com> (IPv6 related code)
*
* The uIP TCP/IP stack header file contains definitions for a number
* of C macros that are used by uIP programs as well as internal uIP
@ -15,7 +17,6 @@
*
*/
/*
* Copyright (c) 2001-2003, Adam Dunkels.
* All rights reserved.
@ -46,7 +47,7 @@
*
* This file is part of the uIP TCP/IP stack.
*
* $Id: uip.h,v 1.40 2006/06/08 07:12:07 adam Exp $
* $Id: uip.h,v 1.24 2009/04/06 13:18:50 nvt-se Exp $
*
*/
@ -56,23 +57,72 @@
#include "uipopt.h"
/**
* Repressentation of an IP address.
* Representation of an IP address.
*
*/
typedef u16_t uip_ip4addr_t[2];
typedef u16_t uip_ip6addr_t[8];
#if UIP_CONF_IPV6
typedef union uip_ip6addr_t {
u8_t u8[16]; /* Initializer, must come first!!! */
u16_t u16[8];
} uip_ip6addr_t;
typedef uip_ip6addr_t uip_ipaddr_t;
#else /* UIP_CONF_IPV6 */
typedef union uip_ip4addr_t {
u8_t u8[4]; /* Initializer, must come first!!! */
u16_t u16[2];
#if 0
u32_t u32;
#endif
} uip_ip4addr_t;
typedef uip_ip4addr_t uip_ipaddr_t;
#endif /* UIP_CONF_IPV6 */
/*---------------------------------------------------------------------------*/
/** \brief 16 bit 802.15.4 address */
struct uip_802154_shortaddr {
u8_t addr[2];
};
/** \brief 64 bit 802.15.4 address */
struct uip_802154_longaddr {
u8_t addr[8];
};
/** \brief 802.11 address */
struct uip_80211_addr {
u8_t addr[6];
};
/** \brief 802.3 address */
struct uip_eth_addr {
u8_t addr[6];
};
#if UIP_CONF_LL_802154
/** \brief 802.15.4 address */
typedef struct uip_802154_longaddr uip_lladdr_t;
#define UIP_802154_SHORTADDR_LEN 2
#define UIP_802154_LONGADDR_LEN 8
#define UIP_LLADDR_LEN UIP_802154_LONGADDR_LEN
#else /*UIP_CONF_LL_802154*/
#if UIP_CONF_LL_80211
/** \brief 802.11 address */
typedef struct uip_80211_addr uip_lladdr_t;
#define UIP_LLADDR_LEN 6
#else /*UIP_CONF_LL_80211*/
/** \brief Ethernet address */
typedef struct uip_eth_addr uip_lladdr_t;
#define UIP_LLADDR_LEN 6
#endif /*UIP_CONF_LL_80211*/
#endif /*UIP_CONF_LL_802154*/
/*---------------------------------------------------------------------------*/
/* First, the functions that should be called from the
* system. Initialization, the periodic timer and incoming packets are
* system. Initialization, the periodic timer, and incoming packets are
* handled by the following three functions.
*/
/**
* \defgroup uipconffunc uIP configuration functions
* @{
@ -103,7 +153,7 @@ typedef uip_ip4addr_t uip_ipaddr_t;
*
* \hideinitializer
*/
#define uip_sethostaddr(addr) uip_ipaddr_copy(uip_hostaddr, (addr))
#define uip_sethostaddr(addr) uip_ipaddr_copy(&uip_hostaddr, (addr))
/**
* Get the IP address of this host.
@ -123,7 +173,7 @@ typedef uip_ip4addr_t uip_ipaddr_t;
*
* \hideinitializer
*/
#define uip_gethostaddr(addr) uip_ipaddr_copy((addr), uip_hostaddr)
#define uip_gethostaddr(addr) uip_ipaddr_copy((addr), &uip_hostaddr)
/**
* Set the default router's IP address.
@ -135,7 +185,7 @@ typedef uip_ip4addr_t uip_ipaddr_t;
*
* \hideinitializer
*/
#define uip_setdraddr(addr) uip_ipaddr_copy(uip_draddr, (addr))
#define uip_setdraddr(addr) uip_ipaddr_copy(&uip_draddr, (addr))
/**
* Set the netmask.
@ -147,7 +197,7 @@ typedef uip_ip4addr_t uip_ipaddr_t;
*
* \hideinitializer
*/
#define uip_setnetmask(addr) uip_ipaddr_copy(uip_netmask, (addr))
#define uip_setnetmask(addr) uip_ipaddr_copy(&uip_netmask, (addr))
/**
@ -158,7 +208,7 @@ typedef uip_ip4addr_t uip_ipaddr_t;
*
* \hideinitializer
*/
#define uip_getdraddr(addr) uip_ipaddr_copy((addr), uip_draddr)
#define uip_getdraddr(addr) uip_ipaddr_copy((addr), &uip_draddr)
/**
* Get the netmask.
@ -168,7 +218,7 @@ typedef uip_ip4addr_t uip_ipaddr_t;
*
* \hideinitializer
*/
#define uip_getnetmask(addr) uip_ipaddr_copy((addr), uip_netmask)
#define uip_getnetmask(addr) uip_ipaddr_copy((addr), &uip_netmask)
/** @} */
@ -220,13 +270,13 @@ void uip_setipid(u16_t id);
* The usual way of calling the function is presented by the source
* code below.
\code
uip_len = devicedriver_poll();
if(uip_len > 0) {
uip_input();
if(uip_len > 0) {
devicedriver_send();
}
}
uip_len = devicedriver_poll();
if(uip_len > 0) {
uip_input();
if(uip_len > 0) {
devicedriver_send();
}
}
\endcode
*
* \note If you are writing a uIP device driver that needs ARP
@ -234,28 +284,29 @@ void uip_setipid(u16_t id);
* Ethernet, you will need to call the uIP ARP code before calling
* this function:
\code
#define BUF ((struct uip_eth_hdr *)&uip_buf[0])
uip_len = ethernet_devicedrver_poll();
if(uip_len > 0) {
if(BUF->type == HTONS(UIP_ETHTYPE_IP)) {
uip_arp_ipin();
uip_input();
if(uip_len > 0) {
uip_arp_out();
ethernet_devicedriver_send();
}
} else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) {
uip_arp_arpin();
if(uip_len > 0) {
ethernet_devicedriver_send();
}
}
#define BUF ((struct uip_eth_hdr *)&uip_buf[0])
uip_len = ethernet_devicedrver_poll();
if(uip_len > 0) {
if(BUF->type == HTONS(UIP_ETHTYPE_IP)) {
uip_arp_ipin();
uip_input();
if(uip_len > 0) {
uip_arp_out();
ethernet_devicedriver_send();
}
} else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) {
uip_arp_arpin();
if(uip_len > 0) {
ethernet_devicedriver_send();
}
}
\endcode
*
* \hideinitializer
*/
#define uip_input() uip_process(UIP_DATA)
/**
* Periodic processing for a connection identified by its number.
*
@ -269,15 +320,15 @@ void uip_setipid(u16_t id);
* variable is set to a value larger than zero. The device driver
* should be called to send out the packet.
*
* The ususal way of calling the function is through a for() loop like
* The usual way of calling the function is through a for() loop like
* this:
\code
for(i = 0; i < UIP_CONNS; ++i) {
uip_periodic(i);
if(uip_len > 0) {
devicedriver_send();
}
}
for(i = 0; i < UIP_CONNS; ++i) {
uip_periodic(i);
if(uip_len > 0) {
devicedriver_send();
}
}
\endcode
*
* \note If you are writing a uIP device driver that needs ARP
@ -285,21 +336,22 @@ void uip_setipid(u16_t id);
* Ethernet, you will need to call the uip_arp_out() function before
* calling the device driver:
\code
for(i = 0; i < UIP_CONNS; ++i) {
uip_periodic(i);
if(uip_len > 0) {
uip_arp_out();
ethernet_devicedriver_send();
}
}
for(i = 0; i < UIP_CONNS; ++i) {
uip_periodic(i);
if(uip_len > 0) {
uip_arp_out();
ethernet_devicedriver_send();
}
}
\endcode
*
* \param conn The number of the connection which is to be periodically polled.
*
* \hideinitializer
*/
#define uip_periodic(conn) do { uip_conn = &uip_conns[conn]; \
uip_process(UIP_TIMER); } while (0)
#if UIP_TCP
#define uip_periodic(conn) do { uip_conn = &uip_conns[conn]; \
uip_process(UIP_TIMER); } while (0)
/**
*
@ -320,11 +372,11 @@ void uip_setipid(u16_t id);
*
* \hideinitializer
*/
#define uip_periodic_conn(conn) do { uip_conn = conn; \
uip_process(UIP_TIMER); } while (0)
#define uip_periodic_conn(conn) do { uip_conn = conn; \
uip_process(UIP_TIMER); } while (0)
/**
* Reuqest that a particular connection should be polled.
* Request that a particular connection should be polled.
*
* Similar to uip_periodic_conn() but does not perform any timer
* processing. The application is polled for new data.
@ -334,9 +386,10 @@ void uip_setipid(u16_t id);
*
* \hideinitializer
*/
#define uip_poll_conn(conn) do { uip_conn = conn; \
uip_process(UIP_POLL_REQUEST); } while (0)
#define uip_poll_conn(conn) do { uip_conn = conn; \
uip_process(UIP_POLL_REQUEST); } while (0)
#endif /* UIP_TCP */
#if UIP_UDP
/**
@ -346,24 +399,24 @@ void uip_setipid(u16_t id);
* UDP connections. It is called in a similar fashion as the
* uip_periodic() function:
\code
for(i = 0; i < UIP_UDP_CONNS; i++) {
uip_udp_periodic(i);
if(uip_len > 0) {
devicedriver_send();
}
}
for(i = 0; i < UIP_UDP_CONNS; i++) {
uip_udp_periodic(i);
if(uip_len > 0) {
devicedriver_send();
}
}
\endcode
*
* \note As for the uip_periodic() function, special care has to be
* taken when using uIP together with ARP and Ethernet:
\code
for(i = 0; i < UIP_UDP_CONNS; i++) {
uip_udp_periodic(i);
if(uip_len > 0) {
uip_arp_out();
ethernet_devicedriver_send();
}
}
for(i = 0; i < UIP_UDP_CONNS; i++) {
uip_udp_periodic(i);
if(uip_len > 0) {
uip_arp_out();
ethernet_devicedriver_send();
}
}
\endcode
*
* \param conn The number of the UDP connection to be processed.
@ -371,7 +424,7 @@ void uip_setipid(u16_t id);
* \hideinitializer
*/
#define uip_udp_periodic(conn) do { uip_udp_conn = &uip_udp_conns[conn]; \
uip_process(UIP_UDP_TIMER); } while (0)
uip_process(UIP_UDP_TIMER); } while(0)
/**
* Periodic processing for a UDP connection identified by a pointer to
@ -387,12 +440,13 @@ void uip_setipid(u16_t id);
*
* \hideinitializer
*/
#define uip_udp_periodic_conn(conn) do { uip_udp_conn = conn; \
uip_process(UIP_UDP_TIMER); } while (0)
#define uip_udp_periodic_conn(conn) do { uip_udp_conn = conn; \
uip_process(UIP_UDP_TIMER); } while(0)
#endif /* UIP_UDP */
/** \brief Abandon the reassembly of the current packet */
void uip_reass_over(void);
/**
* The uIP packet buffer.
*
@ -409,25 +463,27 @@ void uip_setipid(u16_t id);
void
devicedriver_send(void)
{
hwsend(&uip_buf[0], UIP_LLH_LEN);
if(uip_len <= UIP_LLH_LEN + UIP_TCPIP_HLEN) {
hwsend(&uip_buf[UIP_LLH_LEN], uip_len - UIP_LLH_LEN);
} else {
hwsend(&uip_buf[UIP_LLH_LEN], UIP_TCPIP_HLEN);
hwsend(uip_appdata, uip_len - UIP_TCPIP_HLEN - UIP_LLH_LEN);
}
hwsend(&uip_buf[0], UIP_LLH_LEN);
if(uip_len <= UIP_LLH_LEN + UIP_TCPIP_HLEN) {
hwsend(&uip_buf[UIP_LLH_LEN], uip_len - UIP_LLH_LEN);
} else {
hwsend(&uip_buf[UIP_LLH_LEN], UIP_TCPIP_HLEN);
hwsend(uip_appdata, uip_len - UIP_TCPIP_HLEN - UIP_LLH_LEN);
}
}
\endcode
*/
*/
extern u8_t uip_buf[UIP_BUFSIZE+2];
/** @} */
/*---------------------------------------------------------------------------*/
/* Functions that are used by the uIP application program. Opening and
* closing connections, sending and receiving data, etc. is all
* handled by the functions below.
*/
*/
/**
* \defgroup uipappfunc uIP application functions
* @{
@ -467,14 +523,14 @@ void uip_unlisten(u16_t port);
* Connect to a remote host using TCP.
*
* This function is used to start a new connection to the specified
* port on the specied host. It allocates a new connection identifier,
* port on the specified host. It allocates a new connection identifier,
* sets the connection to the SYN_SENT state and sets the
* retransmission timer to 0. This will cause a TCP SYN segment to be
* sent out the next time this connection is periodically processed,
* which usually is done within 0.5 seconds after the call to
* uip_connect().
*
* \note This function is avaliable only if support for active open
* \note This function is available only if support for active open
* has been configured by defining UIP_ACTIVE_OPEN to 1 in uipopt.h.
*
* \note Since this function requires the port number to be in network
@ -487,7 +543,7 @@ void uip_unlisten(u16_t port);
uip_connect(&ipaddr, HTONS(80));
\endcode
*
* \param ripaddr The IP address of the remote hot.
* \param ripaddr The IP address of the remote host.
*
* \param port A 16-bit port number in network byte order.
*
@ -518,7 +574,7 @@ struct uip_conn *uip_connect(uip_ipaddr_t *ripaddr, u16_t port);
* processing can send data.
*
* The amount of data that actually is sent out after a call to this
* funcion is determined by the maximum amount of data TCP allows. uIP
* function is determined by the maximum amount of data TCP allows. uIP
* will automatically crop the data so that only the appropriate
* amount of data is sent. The function uip_mss() can be used to query
* uIP for the amount of data that actually will be sent.
@ -538,7 +594,7 @@ struct uip_conn *uip_connect(uip_ipaddr_t *ripaddr, u16_t port);
void uip_send(const void *data, int len);
/**
* The length of any incoming data that is currently avaliable (if avaliable)
* The length of any incoming data that is currently available (if available)
* in the uip_appdata buffer.
*
* The test function uip_data() must first be used to check if there
@ -573,7 +629,7 @@ void uip_send(const void *data, int len);
* Abort the current connection.
*
* This function will abort (reset) the current connection, and is
* usually used when an error has occured that prevents using the
* usually used when an error has occurred that prevents using the
* uip_close() function.
*
* \hideinitializer
@ -607,9 +663,9 @@ void uip_send(const void *data, int len);
*
* \hideinitializer
*/
#define uip_restart() do { uip_flags |= UIP_NEWDATA; \
uip_conn->tcpstateflags &= ~UIP_STOPPED; \
} while(0)
#define uip_restart() do { uip_flags |= UIP_NEWDATA; \
uip_conn->tcpstateflags &= ~UIP_STOPPED; \
} while(0)
/* uIP tests that can be made to determine in what state the current
@ -630,7 +686,7 @@ void uip_send(const void *data, int len);
*
* Will reduce to non-zero if there is new data for the application
* present at the uip_appdata pointer. The size of the data is
* avaliable through the uip_len variable.
* available through the uip_len variable.
*
* \hideinitializer
*/
@ -716,7 +772,7 @@ void uip_send(const void *data, int len);
#define uip_poll() (uip_flags & UIP_POLL)
/**
* Get the initial maxium segment size (MSS) of the current
* Get the initial maximum segment size (MSS) of the current
* connection.
*
* \hideinitializer
@ -724,10 +780,10 @@ void uip_send(const void *data, int len);
#define uip_initialmss() (uip_conn->initialmss)
/**
* Get the current maxium segment size that can be sent on the current
* Get the current maximum segment size that can be sent on the current
* connection.
*
* The current maxiumum segment size that can be sent on the
* The current maximum segment size that can be sent on the
* connection is computed from the receiver's window and the MSS of
* the connection (which also is available by calling
* uip_initialmss()).
@ -753,7 +809,7 @@ void uip_send(const void *data, int len);
uip_ipaddr(&addr, 192,168,2,1);
c = uip_udp_new(&addr, HTONS(12345));
if(c != NULL) {
uip_udp_bind(c, HTONS(12344));
uip_udp_bind(c, HTONS(12344));
}
\endcode
* \param ripaddr The IP address of the remote host.
@ -763,7 +819,7 @@ void uip_send(const void *data, int len);
* \return The uip_udp_conn structure for the new connection or NULL
* if no connection could be allocated.
*/
struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport);
struct uip_udp_conn *uip_udp_new(const uip_ipaddr_t *ripaddr, u16_t rport);
/**
* Removed a UDP connection.
@ -811,6 +867,20 @@ struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport);
* formats used by uIP.
*/
/**
* Convert an IP address to four bytes separated by commas.
*
* Example:
\code
uip_ipaddr_t ipaddr;
printf("ipaddr=%d.%d.%d.%d\n", uip_ipaddr_to_quad(&ipaddr));
\endcode
*
* \param a A pointer to a uip_ipaddr_t.
* \hideinitializer
*/
#define uip_ipaddr_to_quad(a) (a)->u8[0],(a)->u8[1],(a)->u8[2],(a)->u8[3]
/**
* Construct an IP address from four bytes.
*
@ -837,10 +907,12 @@ struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport);
*
* \hideinitializer
*/
#define uip_ipaddr(addr, addr0,addr1,addr2,addr3) do { \
((u16_t *)(addr))[0] = HTONS(((addr0) << 8) | (addr1)); \
((u16_t *)(addr))[1] = HTONS(((addr2) << 8) | (addr3)); \
} while(0)
#define uip_ipaddr(addr, addr0,addr1,addr2,addr3) do { \
(addr)->u8[0] = addr0; \
(addr)->u8[1] = addr1; \
(addr)->u8[2] = addr2; \
(addr)->u8[3] = addr3; \
} while(0)
/**
* Construct an IPv6 address from eight 16-bit words.
@ -850,15 +922,42 @@ struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport);
* \hideinitializer
*/
#define uip_ip6addr(addr, addr0,addr1,addr2,addr3,addr4,addr5,addr6,addr7) do { \
((u16_t *)(addr))[0] = HTONS((addr0)); \
((u16_t *)(addr))[1] = HTONS((addr1)); \
((u16_t *)(addr))[2] = HTONS((addr2)); \
((u16_t *)(addr))[3] = HTONS((addr3)); \
((u16_t *)(addr))[4] = HTONS((addr4)); \
((u16_t *)(addr))[5] = HTONS((addr5)); \
((u16_t *)(addr))[6] = HTONS((addr6)); \
((u16_t *)(addr))[7] = HTONS((addr7)); \
} while(0)
(addr)->u16[0] = HTONS(addr0); \
(addr)->u16[1] = HTONS(addr1); \
(addr)->u16[2] = HTONS(addr2); \
(addr)->u16[3] = HTONS(addr3); \
(addr)->u16[4] = HTONS(addr4); \
(addr)->u16[5] = HTONS(addr5); \
(addr)->u16[6] = HTONS(addr6); \
(addr)->u16[7] = HTONS(addr7); \
} while(0)
/**
* Construct an IPv6 address from eight 8-bit words.
*
* This function constructs an IPv6 address.
*
* \hideinitializer
*/
#define uip_ip6addr_u8(addr, addr0,addr1,addr2,addr3,addr4,addr5,addr6,addr7,addr8,addr9,addr10,addr11,addr12,addr13,addr14,addr15) do { \
(addr)->u8[0] = addr0; \
(addr)->u8[1] = addr1; \
(addr)->u8[2] = addr2; \
(addr)->u8[3] = addr3; \
(addr)->u8[4] = addr4; \
(addr)->u8[5] = addr5; \
(addr)->u8[6] = addr6; \
(addr)->u8[7] = addr7; \
(addr)->u8[8] = addr8; \
(addr)->u8[9] = addr9; \
(addr)->u8[10] = addr10; \
(addr)->u8[11] = addr11; \
(addr)->u8[12] = addr12; \
(addr)->u8[13] = addr13; \
(addr)->u8[14] = addr14; \
(addr)->u8[15] = addr15; \
} while(0)
/**
* Copy an IP address to another IP address.
@ -878,14 +977,9 @@ struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport);
*
* \hideinitializer
*/
#if !UIP_CONF_IPV6
#define uip_ipaddr_copy(dest, src) do { \
((u16_t *)dest)[0] = ((u16_t *)src)[0]; \
((u16_t *)dest)[1] = ((u16_t *)src)[1]; \
} while(0)
#else /* !UIP_CONF_IPV6 */
#define uip_ipaddr_copy(dest, src) memcpy(dest, src, sizeof(uip_ip6addr_t))
#endif /* !UIP_CONF_IPV6 */
#ifndef uip_ipaddr_copy
#define uip_ipaddr_copy(dest, src) (*(dest) = *(src))
#endif
/**
* Compare two IP addresses
@ -898,7 +992,7 @@ struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport);
uip_ipaddr(&ipaddr1, 192,16,1,2);
if(uip_ipaddr_cmp(&ipaddr2, &ipaddr1)) {
printf("They are the same");
printf("They are the same");
}
\endcode
*
@ -908,8 +1002,8 @@ struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport);
* \hideinitializer
*/
#if !UIP_CONF_IPV6
#define uip_ipaddr_cmp(addr1, addr2) (((u16_t *)addr1)[0] == ((u16_t *)addr2)[0] && \
((u16_t *)addr1)[1] == ((u16_t *)addr2)[1])
#define uip_ipaddr_cmp(addr1, addr2) ((addr1)->u16[0] == (addr2)->u16[0] && \
(addr1)->u16[1] == (addr2)->u16[1])
#else /* !UIP_CONF_IPV6 */
#define uip_ipaddr_cmp(addr1, addr2) (memcmp(addr1, addr2, sizeof(uip_ip6addr_t)) == 0)
#endif /* !UIP_CONF_IPV6 */
@ -928,7 +1022,7 @@ struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport);
uip_ipaddr(&ipaddr1, 192,16,1,2);
uip_ipaddr(&ipaddr2, 192,16,1,3);
if(uip_ipaddr_maskcmp(&ipaddr1, &ipaddr2, &mask)) {
printf("They are the same");
printf("They are the same");
}
\endcode
*
@ -938,11 +1032,33 @@ struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport);
*
* \hideinitializer
*/
#define uip_ipaddr_maskcmp(addr1, addr2, mask) \
(((((u16_t *)addr1)[0] & ((u16_t *)mask)[0]) == \
(((u16_t *)addr2)[0] & ((u16_t *)mask)[0])) && \
((((u16_t *)addr1)[1] & ((u16_t *)mask)[1]) == \
(((u16_t *)addr2)[1] & ((u16_t *)mask)[1])))
#if !UIP_CONF_IPV6
#define uip_ipaddr_maskcmp(addr1, addr2, mask) \
(((((u16_t *)addr1)[0] & ((u16_t *)mask)[0]) == \
(((u16_t *)addr2)[0] & ((u16_t *)mask)[0])) && \
((((u16_t *)addr1)[1] & ((u16_t *)mask)[1]) == \
(((u16_t *)addr2)[1] & ((u16_t *)mask)[1])))
#else
#define uip_ipaddr_prefixcmp(addr1, addr2, length) (memcmp(addr1, addr2, length>>3) == 0)
#endif
/**
* Check if an address is a broadcast address for a network.
*
* Checks if an address is the broadcast address for a network. The
* network is defined by an IP address that is on the network and the
* network's netmask.
*
* \param addr The IP address.
* \param netaddr The network's IP address.
* \param netmask The network's netmask.
*
* \hideinitializer
*/
/*#define uip_ipaddr_isbroadcast(addr, netaddr, netmask)
((uip_ipaddr_t *)(addr)).u16 & ((uip_ipaddr_t *)(addr)).u16*/
/**
@ -969,10 +1085,10 @@ struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport);
*
* \hideinitializer
*/
#define uip_ipaddr_mask(dest, src, mask) do { \
((u16_t *)dest)[0] = ((u16_t *)src)[0] & ((u16_t *)mask)[0]; \
((u16_t *)dest)[1] = ((u16_t *)src)[1] & ((u16_t *)mask)[1]; \
} while(0)
#define uip_ipaddr_mask(dest, src, mask) do { \
((u16_t *)dest)[0] = ((u16_t *)src)[0] & ((u16_t *)mask)[0]; \
((u16_t *)dest)[1] = ((u16_t *)src)[1] & ((u16_t *)mask)[1]; \
} while(0)
/**
* Pick the first octet of an IP address.
@ -992,7 +1108,7 @@ struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport);
*
* \hideinitializer
*/
#define uip_ipaddr1(addr) (htons(((u16_t *)(addr))[0]) >> 8)
#define uip_ipaddr1(addr) ((addr)->u8[0])
/**
* Pick the second octet of an IP address.
@ -1012,7 +1128,7 @@ struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport);
*
* \hideinitializer
*/
#define uip_ipaddr2(addr) (htons(((u16_t *)(addr))[0]) & 0xff)
#define uip_ipaddr2(addr) ((addr)->u8[1])
/**
* Pick the third octet of an IP address.
@ -1032,7 +1148,7 @@ struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport);
*
* \hideinitializer
*/
#define uip_ipaddr3(addr) (htons(((u16_t *)(addr))[1]) >> 8)
#define uip_ipaddr3(addr) ((addr)->u8[2])
/**
* Pick the fourth octet of an IP address.
@ -1052,7 +1168,7 @@ struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport);
*
* \hideinitializer
*/
#define uip_ipaddr4(addr) (htons(((u16_t *)(addr))[1]) & 0xff)
#define uip_ipaddr4(addr) ((addr)->u8[3])
/**
* Convert 16-bit quantity from host byte order to network byte order.
@ -1066,8 +1182,10 @@ struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport);
#ifndef HTONS
# if UIP_BYTE_ORDER == UIP_BIG_ENDIAN
# define HTONS(n) (n)
# define HTONL(n) (n)
# else /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */
# define HTONS(n) (u16_t)((((u16_t) (n)) << 8) | (((u16_t) (n)) >> 8))
# define HTONL(n) (((u32_t)HTONS(n) << 16) | HTONS((u32_t)(n) >> 16))
# endif /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */
#else
#error "HTONS already defined!"
@ -1087,6 +1205,13 @@ u16_t htons(u16_t val);
#define ntohs htons
#endif
#ifndef htonl
u32_t htonl(u32_t val);
#endif /* htonl */
#ifndef ntohl
#define ntohl htonl
#endif
/** @} */
/**
@ -1133,6 +1258,10 @@ extern void *uip_urgdata;
*/
extern u16_t uip_len;
/**
* The length of the extension headers
*/
extern u8_t uip_ext_len;
/** @} */
#if UIP_URGDATA > 0
@ -1145,7 +1274,7 @@ extern u16_t uip_urglen, uip_surglen;
*
* The uip_conn structure is used for identifying a connection. All
* but one field in the structure are to be considered read-only by an
* application. The only exception is the appstate field whos purpose
* application. The only exception is the appstate field whose purpose
* is to let the application store application-specific state (e.g.,
* file pointers) for the connection. The type of this field is
* configured in the "uipopt.h" header file.
@ -1187,9 +1316,13 @@ struct uip_conn {
* The uip_conn pointer can be used to access the current TCP
* connection.
*/
extern struct uip_conn *uip_conn;
#if UIP_TCP
/* The array containing all uIP connections. */
extern struct uip_conn uip_conns[UIP_CONNS];
#endif
/**
* \addtogroup uiparch
* @{
@ -1199,11 +1332,8 @@ extern struct uip_conn uip_conns[UIP_CONNS];
* 4-byte array used for the 32-bit sequence number calculations.
*/
extern u8_t uip_acc32[4];
/** @} */
#if UIP_UDP
/**
* Representation of a uIP UDP connection.
*/
@ -1222,7 +1352,40 @@ struct uip_udp_conn {
*/
extern struct uip_udp_conn *uip_udp_conn;
extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
#endif /* UIP_UDP */
struct uip_router {
int (*activate)(void);
int (*deactivate)(void);
uip_ipaddr_t *(*lookup)(uip_ipaddr_t *destipaddr, uip_ipaddr_t *nexthop);
};
#if UIP_CONF_ROUTER
extern const struct uip_router *uip_router;
/**
* uIP routing driver registration function.
*/
void uip_router_register(const struct uip_router *router);
#endif /*UIP_CONF_ROUTER*/
#if UIP_CONF_ICMP6
struct uip_icmp6_conn {
uip_icmp6_appstate_t appstate;
};
extern struct uip_icmp6_conn uip_icmp6_conns;
#endif /*UIP_CONF_ICMP6*/
/**
* The uIP TCP/IP statistics.
*
* This is the variable in which the uIP TCP/IP statistics are gathered.
*/
#if UIP_STATISTICS == 1
extern struct uip_stats uip_stat;
#define UIP_STAT(s) s
#else
#define UIP_STAT(s)
#endif /* UIP_STATISTICS == 1 */
/**
* The structure holding the TCP/IP statistics that are gathered if
@ -1231,12 +1394,14 @@ extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
*/
struct uip_stats {
struct {
uip_stats_t drop; /**< Number of dropped packets at the IP
layer. */
uip_stats_t recv; /**< Number of received packets at the IP
layer. */
uip_stats_t sent; /**< Number of sent packets at the IP
layer. */
uip_stats_t forwarded;/**< Number of forwarded packets at the IP
layer. */
uip_stats_t drop; /**< Number of dropped packets at the IP
layer. */
uip_stats_t vhlerr; /**< Number of packets dropped due to wrong
IP version or header length. */
uip_stats_t hblenerr; /**< Number of packets dropped due to wrong
@ -1251,16 +1416,19 @@ struct uip_stats {
were neither ICMP, UDP nor TCP. */
} ip; /**< IP statistics. */
struct {
uip_stats_t drop; /**< Number of dropped ICMP packets. */
uip_stats_t recv; /**< Number of received ICMP packets. */
uip_stats_t sent; /**< Number of sent ICMP packets. */
uip_stats_t drop; /**< Number of dropped ICMP packets. */
uip_stats_t typeerr; /**< Number of ICMP packets with a wrong
type. */
uip_stats_t chkerr; /**< Number of ICMP packets with a bad
checksum. */
} icmp; /**< ICMP statistics. */
#if UIP_TCP
struct {
uip_stats_t drop; /**< Number of dropped TCP segments. */
uip_stats_t recv; /**< Number of recived TCP segments. */
uip_stats_t sent; /**< Number of sent TCP segments. */
uip_stats_t drop; /**< Number of dropped TCP segments. */
uip_stats_t chkerr; /**< Number of TCP segments with a bad
checksum. */
uip_stats_t ackerr; /**< Number of TCP segments with a bad ACK
@ -1272,6 +1440,7 @@ struct uip_stats {
uip_stats_t synrst; /**< Number of SYNs for closed ports,
triggering a RST. */
} tcp; /**< TCP statistics. */
#endif
#if UIP_UDP
struct {
uip_stats_t drop; /**< Number of dropped UDP segments. */
@ -1281,33 +1450,36 @@ struct uip_stats {
checksum. */
} udp; /**< UDP statistics. */
#endif /* UIP_UDP */
#if UIP_CONF_IPV6
struct {
uip_stats_t drop; /**< Number of dropped ND6 packets. */
uip_stats_t recv; /**< Number of recived ND6 packets */
uip_stats_t sent; /**< Number of sent ND6 packets */
} nd6;
#endif /*UIP_CONF_IPV6*/
};
/**
* The uIP TCP/IP statistics.
*
* This is the variable in which the uIP TCP/IP statistics are gathered.
*/
extern struct uip_stats uip_stat;
/*---------------------------------------------------------------------------*/
/* All the stuff below this point is internal to uIP and should not be
* used directly by an application or by a device driver.
*/
/*---------------------------------------------------------------------------*/
/* u8_t uip_flags:
*
* When the application is called, uip_flags will contain the flags
* that are defined in this file. Please read below for more
* infomation.
* information.
*/
extern u8_t uip_flags;
/* The following flags may be set in the global variable uip_flags
before calling the application callback. The UIP_ACKDATA,
UIP_NEWDATA, and UIP_CLOSE flags may both be set at the same time,
whereas the others are mutualy exclusive. Note that these flags
whereas the others are mutually exclusive. Note that these flags
should *NOT* be accessed directly, but only through the uIP
functions/macros. */
@ -1340,18 +1512,28 @@ extern u8_t uip_flags;
#define UIP_TIMEDOUT 128 /* The connection has been aborted due to
too many retransmissions. */
/**
* \brief process the options within a hop by hop or destination option header
* \retval 0: nothing to send,
* \retval 1: drop pkt
* \retval 2: ICMP error message to send
*/
/*static u8_t
uip_ext_hdr_options_process(); */
/* uip_process(flag):
*
* The actual uIP function which does all the work.
*/
void uip_process(u8_t flag);
/* The following flags are passed as an argument to the uip_process()
/* The following flags are passed as an argument to the uip_process()
function. They are used to distinguish between the two cases where
uip_process() is called. It can be called either because we have
incoming data that should be processed, or because the periodic
timer has fired. These values are never used directly, but only in
the macrose defined in this file. */
the macros defined in this file. */
#define UIP_DATA 1 /* Tells uIP that there is incoming
data in the uip_buf buffer. The
@ -1402,8 +1584,7 @@ struct uip_tcpip_hdr {
ttl,
proto;
u16_t ipchksum;
u16_t srcipaddr[2],
destipaddr[2];
uip_ipaddr_t srcipaddr, destipaddr;
#endif /* UIP_CONF_IPV6 */
/* TCP header. */
@ -1439,19 +1620,15 @@ struct uip_icmpip_hdr {
ttl,
proto;
u16_t ipchksum;
u16_t srcipaddr[2],
destipaddr[2];
uip_ipaddr_t srcipaddr, destipaddr;
#endif /* UIP_CONF_IPV6 */
/* ICMP (echo) header. */
/* ICMP header. */
u8_t type, icode;
u16_t icmpchksum;
#if !UIP_CONF_IPV6
u16_t id, seqno;
#else /* !UIP_CONF_IPV6 */
u8_t flags, reserved1, reserved2, reserved3;
u8_t icmp6data[16];
u8_t options[1];
u8_t payload[1];
#endif /* !UIP_CONF_IPV6 */
};
@ -1476,8 +1653,7 @@ struct uip_udpip_hdr {
ttl,
proto;
u16_t ipchksum;
u16_t srcipaddr[2],
destipaddr[2];
uip_ipaddr_t srcipaddr, destipaddr;
#endif /* UIP_CONF_IPV6 */
/* UDP header. */
@ -1487,6 +1663,145 @@ struct uip_udpip_hdr {
u16_t udpchksum;
};
/*
* In IPv6 the length of the L3 headers before the transport header is
* not fixed, due to the possibility to include extension option headers
* after the IP header. hence we split here L3 and L4 headers
*/
/* The IP header */
struct uip_ip_hdr {
#if UIP_CONF_IPV6
/* IPV6 header */
u8_t vtc;
u8_t tcflow;
u16_t flow;
u8_t len[2];
u8_t proto, ttl;
uip_ip6addr_t srcipaddr, destipaddr;
#else /* UIP_CONF_IPV6 */
/* IPV4 header */
u8_t vhl,
tos,
len[2],
ipid[2],
ipoffset[2],
ttl,
proto;
u16_t ipchksum;
uip_ipaddr_t srcipaddr, destipaddr;
#endif /* UIP_CONF_IPV6 */
};
/*
* IPv6 extension option headers: we are able to process
* the 4 extension headers defined in RFC2460 (IPv6):
* - Hop by hop option header, destination option header:
* These two are not used by any core IPv6 protocol, hence
* we just read them and go to the next. They convey options,
* the options defined in RFC2460 are Pad1 and PadN, which do
* some padding, and that we do not need to read (the length
* field in the header is enough)
* - Routing header: this one is most notably used by MIPv6,
* which we do not implement, hence we just read it and go
* to the next
* - Fragmentation header: we read this header and are able to
* reassemble packets
*
* We do not offer any means to send packets with extension headers
*
* We do not implement Authentication and ESP headers, which are
* used in IPSec and defined in RFC4302,4303,4305,4385
*/
/* common header part */
struct uip_ext_hdr {
u8_t next;
u8_t len;
};
/* Hop by Hop option header */
struct uip_hbho_hdr {
u8_t next;
u8_t len;
};
/* destination option header */
struct uip_desto_hdr {
u8_t next;
u8_t len;
};
/* We do not define structures for PAD1 and PADN options */
/*
* routing header
* the routing header as 4 common bytes, then routing header type
* specific data there are several types of routing header. Type 0 was
* deprecated as per RFC5095 most notable other type is 2, used in
* RFC3775 (MIPv6) here we do not implement MIPv6, so we just need to
* parse the 4 first bytes
*/
struct uip_routing_hdr {
u8_t next;
u8_t len;
u8_t routing_type;
u8_t seg_left;
};
/* fragmentation header */
struct uip_frag_hdr {
u8_t next;
u8_t res;
u16_t offsetresmore;
u32_t id;
};
/*
* an option within the destination or hop by hop option headers
* it contains type an length, which is true for all options but PAD1
*/
struct uip_ext_hdr_opt {
u8_t type;
u8_t len;
};
/* PADN option */
struct uip_ext_hdr_opt_padn {
u8_t opt_type;
u8_t opt_len;
};
/* TCP header */
struct uip_tcp_hdr {
u16_t srcport;
u16_t destport;
u8_t seqno[4];
u8_t ackno[4];
u8_t tcpoffset;
u8_t flags;
u8_t wnd[2];
u16_t tcpchksum;
u8_t urgp[2];
u8_t optdata[4];
};
/* The ICMP headers. */
struct uip_icmp_hdr {
u8_t type, icode;
u16_t icmpchksum;
#if !UIP_CONF_IPV6
u16_t id, seqno;
#endif /* !UIP_CONF_IPV6 */
};
/* The UDP headers. */
struct uip_udp_hdr {
u16_t srcport;
u16_t destport;
u16_t udplen;
u16_t udpchksum;
};
/**
@ -1504,28 +1819,88 @@ struct uip_udpip_hdr {
* \hideinitializer
*/
#define UIP_APPDATA_SIZE (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN)
#define UIP_APPDATA_PTR (void *)&uip_buf[UIP_LLH_LEN + UIP_TCPIP_HLEN]
#define UIP_PROTO_ICMP 1
#define UIP_PROTO_TCP 6
#define UIP_PROTO_UDP 17
#define UIP_PROTO_ICMP6 58
#if UIP_CONF_IPV6
/** @{ */
/** \brief extension headers types */
#define UIP_PROTO_HBHO 0
#define UIP_PROTO_DESTO 60
#define UIP_PROTO_ROUTING 43
#define UIP_PROTO_FRAG 44
#define UIP_PROTO_NONE 59
/** @} */
/** @{ */
/** \brief Destination and Hop By Hop extension headers option types */
#define UIP_EXT_HDR_OPT_PAD1 0
#define UIP_EXT_HDR_OPT_PADN 1
/** @} */
/** @{ */
/**
* \brief Bitmaps for extension header processing
*
* When processing extension headers, we should record somehow which one we
* see, because you cannot have twice the same header, except for destination
* We store all this in one u8_t bitmap one bit for each header expected. The
* order in the bitmap is the order recommended in RFC2460
*/
#define UIP_EXT_HDR_BITMAP_HBHO 0x01
#define UIP_EXT_HDR_BITMAP_DESTO1 0x02
#define UIP_EXT_HDR_BITMAP_ROUTING 0x04
#define UIP_EXT_HDR_BITMAP_FRAG 0x08
#define UIP_EXT_HDR_BITMAP_AH 0x10
#define UIP_EXT_HDR_BITMAP_ESP 0x20
#define UIP_EXT_HDR_BITMAP_DESTO2 0x40
/** @} */
#endif /* UIP_CONF_IPV6 */
/* Header sizes. */
#if UIP_CONF_IPV6
#define UIP_IPH_LEN 40
#define UIP_FRAGH_LEN 8
#else /* UIP_CONF_IPV6 */
#define UIP_IPH_LEN 20 /* Size of IP header */
#endif /* UIP_CONF_IPV6 */
#define UIP_UDPH_LEN 8 /* Size of UDP header */
#define UIP_TCPH_LEN 20 /* Size of TCP header */
#ifdef UIP_IPH_LEN
#define UIP_ICMPH_LEN 4 /* Size of ICMP header */
#endif
#define UIP_IPUDPH_LEN (UIP_UDPH_LEN + UIP_IPH_LEN) /* Size of IP +
UDP
header */
* UDP
* header */
#define UIP_IPTCPH_LEN (UIP_TCPH_LEN + UIP_IPH_LEN) /* Size of IP +
TCP
header */
* TCP
* header */
#define UIP_TCPIP_HLEN UIP_IPTCPH_LEN
#define UIP_IPICMPH_LEN (UIP_IPH_LEN + UIP_ICMPH_LEN) /* size of ICMP
+ IP header */
#define UIP_LLIPH_LEN (UIP_LLH_LEN + UIP_IPH_LEN) /* size of L2
+ IP header */
#if UIP_CONF_IPV6
/**
* The sums below are quite used in ND. When used for uip_buf, we
* include link layer length when used for uip_len, we do not, hence
* we need values with and without LLH_LEN we do not use capital
* letters as these values are variable
*/
#define uip_l2_l3_hdr_len (UIP_LLH_LEN + UIP_IPH_LEN + uip_ext_len)
#define uip_l2_l3_icmp_hdr_len (UIP_LLH_LEN + UIP_IPH_LEN + uip_ext_len + UIP_ICMPH_LEN)
#define uip_l3_hdr_len (UIP_IPH_LEN + uip_ext_len)
#define uip_l3_icmp_hdr_len (UIP_IPH_LEN + uip_ext_len + UIP_ICMPH_LEN)
#endif /*UIP_CONF_IPV6*/
#if UIP_FIXEDADDR
@ -1533,15 +1908,161 @@ extern const uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr;
#else /* UIP_FIXEDADDR */
extern uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr;
#endif /* UIP_FIXEDADDR */
extern const uip_ipaddr_t uip_broadcast_addr;
extern const uip_ipaddr_t uip_all_zeroes_addr;
#if UIP_FIXEDETHADDR
extern const uip_lladdr_t uip_lladdr;
#else
extern uip_lladdr_t uip_lladdr;
#endif
#ifdef UIP_CONF_IPV6
/**
* \brief Is IPv6 address a the unspecified address
* a is of type uip_ipaddr_t
*/
#define uip_is_addr_unspecified(a) \
((((a)->u16[0]) == 0) && \
(((a)->u16[1]) == 0) && \
(((a)->u16[2]) == 0) && \
(((a)->u16[3]) == 0) && \
(((a)->u16[4]) == 0) && \
(((a)->u16[5]) == 0) && \
(((a)->u16[6]) == 0) && \
(((a)->u16[7]) == 0))
/** \brief Is IPv6 address a the link local all-nodes multicast address */
#define uip_is_addr_linklocal_allnodes_mcast(a) \
((((a)->u8[0]) == 0xff) && \
(((a)->u8[1]) == 0x02) && \
(((a)->u16[1]) == 0) && \
(((a)->u16[2]) == 0) && \
(((a)->u16[3]) == 0) && \
(((a)->u16[4]) == 0) && \
(((a)->u16[5]) == 0) && \
(((a)->u16[6]) == 0) && \
(((a)->u8[14]) == 0) && \
(((a)->u8[15]) == 0x01))
/** \brief set IP address a to unspecified */
#define uip_create_unspecified(a) uip_ip6addr(a, 0, 0, 0, 0, 0, 0, 0, 0)
/** \brief set IP address a to the link local all-nodes multicast address */
#define uip_create_linklocal_allnodes_mcast(a) uip_ip6addr(a, 0xff02, 0, 0, 0, 0, 0, 0, 0x0001)
/** \brief set IP address a to the link local all-routers multicast address */
#define uip_create_linklocal_allrouters_mcast(a) uip_ip6addr(a, 0xff02, 0, 0, 0, 0, 0, 0, 0x0002)
/**
* \brief is addr (a) a solicited node multicast address, see RFC3513
* a is of type uip_ipaddr_t*
*/
#define uip_is_addr_solicited_node(a) \
((((a)->u8[0]) == 0xFF) && \
(((a)->u8[1]) == 0x02) && \
(((a)->u16[1]) == 0) && \
(((a)->u16[2]) == 0) && \
(((a)->u16[3]) == 0) && \
(((a)->u16[4]) == 0) && \
(((a)->u16[5]) == 1) && \
(((a)->u8[12]) == 0xFF))
/**
* \briefput in b the solicited node address corresponding to address a
* both a and b are of type uip_ipaddr_t*
* */
#define uip_create_solicited_node(a, b) \
(((b)->u8[0]) = 0xFF); \
(((b)->u8[1]) = 0x02); \
(((b)->u16[1]) = 0); \
(((b)->u16[2]) = 0); \
(((b)->u16[3]) = 0); \
(((b)->u16[4]) = 0); \
(((b)->u8[10]) = 0); \
(((b)->u8[11]) = 0x01); \
(((b)->u8[12]) = 0xFF); \
(((b)->u8[13]) = ((a)->u8[13])); \
(((b)->u16[7]) = ((a)->u16[7]))
/**
* \brief is addr (a) a link local unicast address, see RFC3513
* i.e. is (a) on prefix FE80::/10
* a is of type uip_ipaddr_t*
*/
#define uip_is_addr_link_local(a) \
((((a)->u8[0]) == 0xFE) && \
(((a)->u8[1]) == 0x80))
/**
* \brief was addr (a) forged based on the mac address m
* a type is uip_ipaddr_t
* m type is uiplladdr_t
*/
#if UIP_CONF_LL_802154
#define uip_is_addr_mac_addr_based(a, m) \
((((a)->u8[8]) == (((m)->addr[0]) ^ 0x02)) && \
(((a)->u8[9]) == (m)->addr[1]) && \
(((a)->u8[10]) == (m)->addr[2]) && \
(((a)->u8[11]) == (m)->addr[3]) && \
(((a)->u8[12]) == (m)->addr[4]) && \
(((a)->u8[13]) == (m)->addr[5]) && \
(((a)->u8[14]) == (m)->addr[6]) && \
(((a)->u8[15]) == (m)->addr[7]))
#else
#define uip_is_addr_mac_addr_based(a, m) \
((((a)->u8[8]) == (((m)->addr[0]) | 0x02)) && \
(((a)->u8[9]) == (m)->addr[1]) && \
(((a)->u8[10]) == (m)->addr[2]) && \
(((a)->u8[11]) == 0xff) && \
(((a)->u8[12]) == 0xfe) && \
(((a)->u8[13]) == (m)->addr[3]) && \
(((a)->u8[14]) == (m)->addr[4]) && \
(((a)->u8[15]) == (m)->addr[5]))
#endif /*UIP_CONF_LL_802154*/
/**
* \brief is address a multicast address, see RFC 3513
* a is of type uip_ipaddr_t*
* */
#define uip_is_addr_mcast(a) \
(((a)->u8[0]) == 0xFF)
/**
* Representation of a 48-bit Ethernet address.
* \brief is group-id of multicast address a
* the all nodes group-id
*/
struct uip_eth_addr {
u8_t addr[6];
};
#define uip_is_mcast_group_id_all_nodes(a) \
((((a)->u16[1]) == 0) && \
(((a)->u16[2]) == 0) && \
(((a)->u16[3]) == 0) && \
(((a)->u16[4]) == 0) && \
(((a)->u16[5]) == 0) && \
(((a)->u16[6]) == 0) && \
(((a)->u8[14]) == 0) && \
(((a)->u8[15]) == 1))
/**
* \brief is group-id of multicast address a
* the all routers group-id
*/
#define uip_is_mcast_group_id_all_routers(a) \
((((a)->u16[1]) == 0) && \
(((a)->u16[2]) == 0) && \
(((a)->u16[3]) == 0) && \
(((a)->u16[4]) == 0) && \
(((a)->u16[5]) == 0) && \
(((a)->u16[6]) == 0) && \
(((a)->u8[14]) == 0) && \
(((a)->u8[15]) == 2))
#endif /*UIP_CONF_IPV6*/
/**
* Calculate the Internet checksum over a buffer.
@ -1594,6 +2115,13 @@ u16_t uip_tcpchksum(void);
*/
u16_t uip_udpchksum(void);
/**
* Calculate the ICMP checksum of the packet in uip_buf.
*
* \return The ICMP checksum of the ICMP packet in uip_buf
*/
u16_t uip_icmp6chksum(void);
#endif /* __UIP_H__ */

@ -1,138 +0,0 @@
/**
* \addtogroup uip
* {@
*/
/**
* \defgroup uiparch Architecture specific uIP functions
* @{
*
* The functions in the architecture specific module implement the IP
* check sum and 32-bit additions.
*
* The IP checksum calculation is the most computationally expensive
* operation in the TCP/IP stack and it therefore pays off to
* implement this in efficient assembler. The purpose of the uip-arch
* module is to let the checksum functions to be implemented in
* architecture specific assembler.
*
*/
/**
* \file
* Declarations of architecture specific functions.
* \author Adam Dunkels <adam@dunkels.com>
*/
/*
* Copyright (c) 2001, 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.
*
* This file is part of the uIP TCP/IP stack.
*
* $Id: uip_arch.h,v 1.2 2006/06/07 09:15:19 adam Exp $
*
*/
#ifndef __UIP_ARCH_H__
#define __UIP_ARCH_H__
#include "uip.h"
/**
* Carry out a 32-bit addition.
*
* Because not all architectures for which uIP is intended has native
* 32-bit arithmetic, uIP uses an external C function for doing the
* required 32-bit additions in the TCP protocol processing. This
* function should add the two arguments and place the result in the
* global variable uip_acc32.
*
* \note The 32-bit integer pointed to by the op32 parameter and the
* result in the uip_acc32 variable are in network byte order (big
* endian).
*
* \param op32 A pointer to a 4-byte array representing a 32-bit
* integer in network byte order (big endian).
*
* \param op16 A 16-bit integer in host byte order.
*/
void uip_add32(u8_t *op32, u16_t op16);
/**
* Calculate the Internet checksum over a buffer.
*
* The Internet checksum is the one's complement of the one's
* complement sum of all 16-bit words in the buffer.
*
* See RFC1071.
*
* \note This function is not called in the current version of uIP,
* but future versions might make use of it.
*
* \param buf A pointer to the buffer over which the checksum is to be
* computed.
*
* \param len The length of the buffer over which the checksum is to
* be computed.
*
* \return The Internet checksum of the buffer.
*/
u16_t uip_chksum(u16_t *buf, u16_t len);
/**
* Calculate the IP header checksum of the packet header in uip_buf.
*
* The IP header checksum is the Internet checksum of the 20 bytes of
* the IP header.
*
* \return The IP header checksum of the IP header in the uip_buf
* buffer.
*/
u16_t uip_ipchksum(void);
/**
* Calculate the TCP checksum of the packet in uip_buf and uip_appdata.
*
* The TCP checksum is the Internet checksum of data contents of the
* TCP segment, and a pseudo-header as defined in RFC793.
*
* \note The uip_appdata pointer that points to the packet data may
* point anywhere in memory, so it is not possible to simply calculate
* the Internet checksum of the contents of the uip_buf buffer.
*
* \return The TCP checksum of the TCP segment in uip_buf and pointed
* to by uip_appdata.
*/
u16_t uip_tcpchksum(void);
u16_t uip_udpchksum(void);
/** @} */
/** @} */
#endif /* __UIP_ARCH_H__ */

@ -54,7 +54,7 @@
*
* This file is part of the uIP TCP/IP stack.
*
* $Id: uip_arp.c,v 1.8 2006/06/02 23:36:21 adam Exp $
* $Id: uip_arp.c,v 1.5 2008/02/07 01:35:00 adamdunkels Exp $
*
*/
@ -71,9 +71,9 @@ struct arp_hdr {
u8_t protolen;
u16_t opcode;
struct uip_eth_addr shwaddr;
u16_t sipaddr[2];
uip_ipaddr_t sipaddr;
struct uip_eth_addr dhwaddr;
u16_t dipaddr[2];
uip_ipaddr_t dipaddr;
};
struct ethip_hdr {
@ -87,8 +87,7 @@ struct ethip_hdr {
ttl,
proto;
u16_t ipchksum;
u16_t srcipaddr[2],
destipaddr[2];
uip_ipaddr_t srcipaddr, destipaddr;
};
#define ARP_REQUEST 1
@ -97,7 +96,7 @@ struct ethip_hdr {
#define ARP_HWTYPE_ETH 1
struct arp_entry {
u16_t ipaddr[2];
uip_ipaddr_t ipaddr;
struct uip_eth_addr ethaddr;
u8_t time;
};
@ -107,7 +106,7 @@ static const struct uip_eth_addr broadcast_ethaddr =
static const u16_t broadcast_ipaddr[2] = {0xffff,0xffff};
static struct arp_entry arp_table[UIP_ARPTAB_SIZE];
static u16_t ipaddr[2];
static uip_ipaddr_t ipaddr;
static u8_t i, c;
static u8_t arptime;
@ -115,6 +114,15 @@ static u8_t tmpage;
#define BUF ((struct arp_hdr *)&uip_buf[0])
#define IPBUF ((struct ethip_hdr *)&uip_buf[0])
#define DEBUG 0
#if DEBUG
#include <stdio.h>
#define PRINTF(...) printf(__VA_ARGS__)
#else
#define PRINTF(...)
#endif
/*-----------------------------------------------------------------------------------*/
/**
* Initialize the ARP module.
@ -125,7 +133,7 @@ void
uip_arp_init(void)
{
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
memset(arp_table[i].ipaddr, 0, 4);
memset(&arp_table[i].ipaddr, 0, 4);
}
}
/*-----------------------------------------------------------------------------------*/
@ -146,16 +154,16 @@ uip_arp_timer(void)
++arptime;
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
tabptr = &arp_table[i];
if((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 &&
if(uip_ipaddr_cmp(&tabptr->ipaddr, &uip_all_zeroes_addr) &&
arptime - tabptr->time >= UIP_ARP_MAXAGE) {
memset(tabptr->ipaddr, 0, 4);
memset(&tabptr->ipaddr, 0, 4);
}
}
}
/*-----------------------------------------------------------------------------------*/
static void
uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr)
uip_arp_update(uip_ipaddr_t *ipaddr, struct uip_eth_addr *ethaddr)
{
register struct arp_entry *tabptr;
/* Walk through the ARP mapping table and try to find an entry to
@ -165,13 +173,11 @@ uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr)
tabptr = &arp_table[i];
/* Only check those entries that are actually in use. */
if(tabptr->ipaddr[0] != 0 &&
tabptr->ipaddr[1] != 0) {
if(!uip_ipaddr_cmp(&tabptr->ipaddr, &uip_all_zeroes_addr)) {
/* Check if the source IP address of the incoming packet matches
the IP address in this ARP table entry. */
if(ipaddr[0] == tabptr->ipaddr[0] &&
ipaddr[1] == tabptr->ipaddr[1]) {
if(uip_ipaddr_cmp(ipaddr, &tabptr->ipaddr)) {
/* An old entry found, update this and return. */
memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
@ -188,8 +194,7 @@ uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr)
/* First, we try to find an unused entry in the ARP table. */
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
tabptr = &arp_table[i];
if(tabptr->ipaddr[0] == 0 &&
tabptr->ipaddr[1] == 0) {
if(uip_ipaddr_cmp(&tabptr->ipaddr, &uip_all_zeroes_addr)) {
break;
}
}
@ -212,7 +217,7 @@ uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr)
/* Now, i is the ARP table entry which we will fill with the new
information. */
memcpy(tabptr->ipaddr, ipaddr, 4);
uip_ipaddr_copy(&tabptr->ipaddr, ipaddr);
memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
tabptr->time = arptime;
}
@ -288,24 +293,28 @@ uip_arp_arpin(void)
case HTONS(ARP_REQUEST):
/* ARP request. If it asked for our address, we send out a
reply. */
if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) {
/* if(BUF->dipaddr[0] == uip_hostaddr[0] &&
BUF->dipaddr[1] == uip_hostaddr[1]) {*/
PRINTF("uip_arp_arpin: request for %d.%d.%d.%d (we are %d.%d.%d.%d)\n",
BUF->dipaddr.u8[0], BUF->dipaddr.u8[1],
BUF->dipaddr.u8[2], BUF->dipaddr.u8[3],
uip_hostaddr.u8[0], uip_hostaddr.u8[1],
uip_hostaddr.u8[2], uip_hostaddr.u8[3]);
if(uip_ipaddr_cmp(&BUF->dipaddr, &uip_hostaddr)) {
/* First, we register the one who made the request in our ARP
table, since it is likely that we will do more communication
with this host in the future. */
uip_arp_update(BUF->sipaddr, &BUF->shwaddr);
uip_arp_update(&BUF->sipaddr, &BUF->shwaddr);
/* The reply opcode is 2. */
BUF->opcode = HTONS(2);
BUF->opcode = HTONS(ARP_REPLY);
memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6);
memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);
memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6);
BUF->dipaddr[0] = BUF->sipaddr[0];
BUF->dipaddr[1] = BUF->sipaddr[1];
BUF->sipaddr[0] = uip_hostaddr[0];
BUF->sipaddr[1] = uip_hostaddr[1];
uip_ipaddr_copy(&BUF->dipaddr, &BUF->sipaddr);
uip_ipaddr_copy(&BUF->sipaddr, &uip_hostaddr);
BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
uip_len = sizeof(struct arp_hdr);
@ -314,8 +323,8 @@ uip_arp_arpin(void)
case HTONS(ARP_REPLY):
/* ARP reply. We insert or update the ARP table if it was meant
for us. */
if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) {
uip_arp_update(BUF->sipaddr, &BUF->shwaddr);
if(uip_ipaddr_cmp(&BUF->dipaddr, &uip_hostaddr)) {
uip_arp_update(&BUF->sipaddr, &BUF->shwaddr);
}
break;
}
@ -363,23 +372,23 @@ uip_arp_out(void)
packet with an ARP request for the IP address. */
/* First check if destination is a local broadcast. */
if(uip_ipaddr_cmp(IPBUF->destipaddr, broadcast_ipaddr)) {
if(uip_ipaddr_cmp(&IPBUF->destipaddr, &uip_broadcast_addr)) {
memcpy(IPBUF->ethhdr.dest.addr, broadcast_ethaddr.addr, 6);
} else {
/* Check if the destination address is on the local network. */
if(!uip_ipaddr_maskcmp(IPBUF->destipaddr, uip_hostaddr, uip_netmask)) {
if(!uip_ipaddr_maskcmp(&IPBUF->destipaddr, &uip_hostaddr, &uip_netmask)) {
/* Destination address was not on the local network, so we need to
use the default router's IP address instead of the destination
address when determining the MAC address. */
uip_ipaddr_copy(ipaddr, uip_draddr);
uip_ipaddr_copy(&ipaddr, &uip_draddr);
} else {
/* Else, we use the destination IP address. */
uip_ipaddr_copy(ipaddr, IPBUF->destipaddr);
uip_ipaddr_copy(&ipaddr, &IPBUF->destipaddr);
}
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
tabptr = &arp_table[i];
if(uip_ipaddr_cmp(ipaddr, tabptr->ipaddr)) {
if(uip_ipaddr_cmp(&ipaddr, &tabptr->ipaddr)) {
break;
}
}
@ -393,8 +402,8 @@ uip_arp_out(void)
memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);
uip_ipaddr_copy(BUF->dipaddr, ipaddr);
uip_ipaddr_copy(BUF->sipaddr, uip_hostaddr);
uip_ipaddr_copy(&BUF->dipaddr, &ipaddr);
uip_ipaddr_copy(&BUF->sipaddr, &uip_hostaddr);
BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */
BUF->hwtype = HTONS(ARP_HWTYPE_ETH);
BUF->protocol = HTONS(UIP_ETHTYPE_IP);

@ -45,7 +45,7 @@
*
* This file is part of the uIP TCP/IP stack.
*
* $Id: uip_arp.h,v 1.5 2006/06/11 21:46:39 adam Exp $
* $Id: uip_arp.h,v 1.2 2006/08/26 23:58:45 oliverschmidt Exp $
*
*/
@ -66,9 +66,9 @@ struct uip_eth_hdr {
u16_t type;
};
#define UIP_ETHTYPE_ARP 0x0806
#define UIP_ETHTYPE_IP 0x0800
#define UIP_ETHTYPE_IP6 0x86dd
#define UIP_ETHTYPE_ARP 0x0806
#define UIP_ETHTYPE_IP 0x0800
#define UIP_ETHTYPE_IPV6 0x86dd
/* The uip_arp_init() function must be called before any of the other
@ -139,6 +139,7 @@ void uip_arp_timer(void);
uip_ethaddr.addr[5] = eaddr.addr[5];} while(0)
/** @} */
/** @} */
#endif /* __UIP_ARP_H__ */
/** @} */

@ -1,74 +0,0 @@
/*
* Copyright (c) 2004, Adam Dunkels and the 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 uIP TCP/IP stack
*
* $Id: uiplib.c,v 1.2 2006/06/12 08:00:31 adam Exp $
*
*/
#include "uip.h"
#include "uiplib.h"
/*-----------------------------------------------------------------------------------*/
unsigned char
uiplib_ipaddrconv(char *addrstr, unsigned char *ipaddr)
{
unsigned char tmp;
char c;
unsigned char i, j;
tmp = 0;
for(i = 0; i < 4; ++i) {
j = 0;
do {
c = *addrstr;
++j;
if(j > 4) {
return 0;
}
if(c == '.' || c == 0) {
*ipaddr = tmp;
++ipaddr;
tmp = 0;
} else if(c >= '0' && c <= '9') {
tmp = (tmp * 10) + (c - '0');
} else {
return 0;
}
++addrstr;
} while(c != '.' && c != 0);
}
return 1;
}
/*-----------------------------------------------------------------------------------*/

@ -1,71 +0,0 @@
/**
* \file
* Various uIP library functions.
* \author
* Adam Dunkels <adam@sics.se>
*
*/
/*
* Copyright (c) 2002, 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.
*
* This file is part of the uIP TCP/IP stack
*
* $Id: uiplib.h,v 1.1 2006/06/07 09:15:19 adam Exp $
*
*/
#ifndef __UIPLIB_H__
#define __UIPLIB_H__
/**
* \addtogroup uipconvfunc
* @{
*/
/**
* Convert a textual representation of an IP address to a numerical representation.
*
* This function takes a textual representation of an IP address in
* the form a.b.c.d and converts it into a 4-byte array that can be
* used by other uIP functions.
*
* \param addrstr A pointer to a string containing the IP address in
* textual form.
*
* \param addr A pointer to a 4-byte array that will be filled in with
* the numerical representation of the address.
*
* \retval 0 If the IP address could not be parsed.
* \retval Non-zero If the IP address was parsed.
*/
unsigned char uiplib_ipaddrconv(char *addrstr, unsigned char *addr);
/** @} */
#endif /* __UIPLIB_H__ */

@ -1,15 +1,20 @@
/**
* \addtogroup uip
* @{
*/
/**
* \defgroup uipopt Configuration options for uIP
* @{
*
* uIP is configured using the per-project configuration file
* uipopt.h. This file contains all compile-time options for uIP and
* "uipopt.h". This file contains all compile-time options for uIP and
* should be tweaked to match each specific project. The uIP
* distribution contains a documented example "uipopt.h" that can be
* copied and modified for each project.
*
* \note Most of the configuration options in the uipopt.h should not
* be changed, but rather the per-project uip-conf.h file.
* \note Contiki does not use the uipopt.h file to configure uIP, but
* uses a per-port uip-conf.h file that should be edited instead.
*/
/**
@ -53,7 +58,7 @@
*
* This file is part of the uIP TCP/IP stack.
*
* $Id: uipopt.h,v 1.4 2006/06/12 08:00:31 adam Exp $
* $Id: uipopt.h,v 1.11 2009/04/10 00:37:48 adamdunkels Exp $
*
*/
@ -67,23 +72,23 @@
#define UIP_BIG_ENDIAN 1234
#endif /* UIP_BIG_ENDIAN */
#include "uip-conf.h"
/*------------------------------------------------------------------------------*/
/**
* \name Static configuration options
* \defgroup uipoptstaticconf Static configuration options
* @{
*
* These configuration options can be used for setting the IP address
* settings statically, but only if UIP_FIXEDADDR is set to 1. The
* configuration options for a specific node includes IP address,
* netmask and default router as well as the Ethernet address. The
* netmask, default router and Ethernet address are appliciable only
* netmask, default router and Ethernet address are applicable only
* if uIP should be run over Ethernet.
*
* This options are meaningful only for the IPv4 code.
*
* All of these should be changed to suit your project.
*/
*/
/**
* Determines if uIP should use a fixed IP address or not.
@ -97,7 +102,7 @@
#define UIP_FIXEDADDR 0
/**
* Ping IP address asignment.
* Ping IP address assignment.
*
* uIP uses a "ping" packets for setting its own IP address if this
* option is set. If so, uIP will start with an empty IP address and
@ -129,7 +134,7 @@
/** @} */
/*------------------------------------------------------------------------------*/
/**
* \name IP configuration options
* \defgroup uipoptip IP configuration options
* @{
*
*/
@ -140,11 +145,18 @@
*/
#define UIP_TTL 64
/**
* The maximum time an IP fragment should wait in the reassembly
* buffer before it is dropped.
*
*/
#define UIP_REASS_MAXAGE 60 /*60s*/
/**
* Turn on support for IP packet reassembly.
*
* uIP supports reassembly of fragmented IP packets. This features
* requires an additonal amount of RAM to hold the reassembly buffer
* requires an additional amount of RAM to hold the reassembly buffer
* and the reassembly code size is approximately 700 bytes. The
* reassembly buffer is of the same size as the uip_buf buffer
* (configured by UIP_BUFSIZE).
@ -153,32 +165,84 @@
*
* \hideinitializer
*/
#ifdef UIP_CONF_REASSEMBLY
#define UIP_REASSEMBLY UIP_CONF_REASSEMBLY
#else /* UIP_CONF_REASSEMBLY */
#define UIP_REASSEMBLY 0
#endif /* UIP_CONF_REASSEMBLY */
/** @} */
/*------------------------------------------------------------------------------*/
/**
* The maximum time an IP fragment should wait in the reassembly
* buffer before it is dropped.
* \defgroup uipoptipv6 IPv6 configuration options
* @{
*
*/
#define UIP_REASS_MAXAGE 40
/** The maximum transmission unit at the IP Layer*/
#define UIP_LINK_MTU 1280
#ifndef UIP_CONF_IPV6
/** Do we use IPv6 or not (default: no) */
#define UIP_CONF_IPV6 0
#endif
#ifndef UIP_CONF_IPV6_QUEUE_PKT
/** Do we do per %neighbor queuing during address resolution (default: no) */
#define UIP_CONF_IPV6_QUEUE_PKT 0
#endif
#ifndef UIP_CONF_IPV6_CHECKS
/** Do we do IPv6 consistency checks (highly recommended, default: yes) */
#define UIP_CONF_IPV6_CHECKS 1
#endif
#ifndef UIP_CONF_IPV6_REASSEMBLY
/** Do we do IPv6 fragmentation (default: no) */
#define UIP_CONF_IPV6_REASSEMBLY 0
#endif
#ifndef UIP_CONF_NETIF_MAX_ADDRESSES
/** Default number of IPv6 addresses associated to the node's interface */
#define UIP_CONF_NETIF_MAX_ADDRESSES 3
#endif
#ifndef UIP_CONF_ND6_MAX_PREFIXES
/** Default number of IPv6 prefixes associated to the node's interface */
#define UIP_CONF_ND6_MAX_PREFIXES 3
#endif
#ifndef UIP_CONF_ND6_MAX_NEIGHBORS
/** Default number of neighbors that can be stored in the %neighbor cache */
#define UIP_CONF_ND6_MAX_NEIGHBORS 4
#endif
#ifndef UIP_CONF_ND6_MAX_DEFROUTERS
/** Minimum number of default routers */
#define UIP_CONF_ND6_MAX_DEFROUTERS 2
#endif
/** @} */
/*------------------------------------------------------------------------------*/
/**
* \name UDP configuration options
* \defgroup uipoptudp UDP configuration options
* @{
*
* \note The UDP support in uIP is still not entirely complete; there
* is no support for sending or receiving broadcast or multicast
* packets, but it works well enough to support a number of vital
* applications such as DNS queries, though
*/
/**
* Toggles wether UDP support should be compiled in or not.
* Toggles whether UDP support should be compiled in or not.
*
* \hideinitializer
*/
#ifdef UIP_CONF_UDP
#define UIP_UDP UIP_CONF_UDP
#else /* UIP_CONF_UDP */
#define UIP_UDP 0
#define UIP_UDP 1
#endif /* UIP_CONF_UDP */
/**
@ -216,28 +280,43 @@
/** @} */
/*------------------------------------------------------------------------------*/
/**
* \name TCP configuration options
* \defgroup uipopttcp TCP configuration options
* @{
*/
/**
* Toggles whether UDP support should be compiled in or not.
*
* \hideinitializer
*/
#ifdef UIP_CONF_TCP
#define UIP_TCP UIP_CONF_TCP
#else /* UIP_CONF_UDP */
#define UIP_TCP 1
#endif /* UIP_CONF_UDP */
/**
* Determines if support for opening connections from uIP should be
* compiled in.
*
* If the applications that are running on top of uIP for this project
* do not need to open outgoing TCP connections, this configration
* do not need to open outgoing TCP connections, this configuration
* option can be turned off to reduce the code size of uIP.
*
* \hideinitializer
*/
#ifndef UIP_CONF_ACTIVE_OPEN
#define UIP_ACTIVE_OPEN 1
#else /* UIP_CONF_ACTIVE_OPEN */
#define UIP_ACTIVE_OPEN UIP_CONF_ACTIVE_OPEN
#endif /* UIP_CONF_ACTIVE_OPEN */
/**
* The maximum number of simultaneously open TCP connections.
*
* Since the TCP connections are statically allocated, turning this
* configuration knob down results in less RAM used. Each TCP
* connection requires approximatly 30 bytes of memory.
* connection requires approximately 30 bytes of memory.
*
* \hideinitializer
*/
@ -302,12 +381,16 @@
* This is should not be to set to more than
* UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN.
*/
#ifdef UIP_CONF_TCP_MSS
#define UIP_TCP_MSS UIP_CONF_TCP_MSS
#else
#define UIP_TCP_MSS (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN)
#endif
/**
* The size of the advertised receiver's window.
*
* Should be set low (i.e., to the size of the uip_buf buffer) is the
* Should be set low (i.e., to the size of the uip_buf buffer) if the
* application is slow to process incoming data, or high (32768 bytes)
* if the application processes data quickly.
*
@ -322,7 +405,7 @@
/**
* How long a connection should stay in the TIME_WAIT state.
*
* This configiration option has no real implication, and it should be
* This configuration option has no real implication, and it should be
* left untouched.
*/
#define UIP_TIME_WAIT_TIMEOUT 120
@ -331,7 +414,7 @@
/** @} */
/*------------------------------------------------------------------------------*/
/**
* \name ARP configuration options
* \defgroup uipoptarp ARP configuration options
* @{
*/
@ -350,19 +433,70 @@
#endif
/**
* The maxium age of ARP table entries measured in 10ths of seconds.
* The maximum age of ARP table entries measured in 10ths of seconds.
*
* An UIP_ARP_MAXAGE of 120 corresponds to 20 minutes (BSD
* default).
*/
#define UIP_ARP_MAXAGE 120
/** @} */
/*------------------------------------------------------------------------------*/
/**
* \defgroup uipoptmac layer 2 options (for ipv6)
* @{
*/
#define UIP_DEFAULT_PREFIX_LEN 64
/** @} */
/*------------------------------------------------------------------------------*/
/**
* \name General configuration options
* \defgroup uipoptsics 6lowpan options (for ipv6)
* @{
*/
/**
* Timeout for packet reassembly at the 6lowpan layer
* (should be < 60s)
*/
#ifdef SICSLOWPAN_CONF_MAXAGE
#define SICSLOWPAN_REASS_MAXAGE SICSLOWPAN_CONF_MAXAGE
#else
#define SICSLOWPAN_REASS_MAXAGE 20
#endif
/**
* Do we compress the IP header or not (default: no)
*/
#ifndef SICSLOWPAN_CONF_COMPRESSION
#define SICSLOWPAN_CONF_COMPRESSION 0
#endif
/**
* If we use IPHC compression, how many address contexts do we support
*/
#ifndef SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS
#define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 1
#endif
/**
* Do we support 6lowpan fragmentation
*/
#ifndef SICSLOWPAN_CONF_FRAG
#define SICSLOWPAN_CONF_FRAG 0
#endif
/** @} */
/*------------------------------------------------------------------------------*/
/**
* \defgroup uipoptgeneral General configuration options
* @{
*/
@ -370,13 +504,13 @@
* The size of the uIP packet buffer.
*
* The uIP packet buffer should not be smaller than 60 bytes, and does
* not need to be larger than 1500 bytes. Lower size results in lower
* not need to be larger than 1514 bytes. Lower size results in lower
* TCP throughput, larger size results in higher TCP throughput.
*
* \hideinitializer
*/
#ifndef UIP_CONF_BUFFER_SIZE
#define UIP_BUFSIZE 400
#define UIP_BUFSIZE UIP_LINK_MTU + UIP_LLH_LEN
#else /* UIP_CONF_BUFFER_SIZE */
#define UIP_BUFSIZE UIP_CONF_BUFFER_SIZE
#endif /* UIP_CONF_BUFFER_SIZE */
@ -440,18 +574,23 @@ void uip_log(char *msg);
* found. For Ethernet, this should be set to 14. For SLIP, this
* should be set to 0.
*
* \note we probably won't use this constant for other link layers than
* ethernet as they have variable header length (this is due to variable
* number and type of address fields and to optional security features)
* E.g.: 802.15.4 -> 2 + (1/2*4/8) + 0/5/6/10/14
* 802.11 -> 4 + (6*3/4) + 2
* \hideinitializer
*/
#ifdef UIP_CONF_LLH_LEN
#define UIP_LLH_LEN UIP_CONF_LLH_LEN
#else /* UIP_CONF_LLH_LEN */
#else /* UIP_LLH_LEN */
#define UIP_LLH_LEN 14
#endif /* UIP_CONF_LLH_LEN */
/** @} */
/*------------------------------------------------------------------------------*/
/**
* \name CPU architecture configuration
* \defgroup uipoptcpu CPU architecture configuration
* @{
*
* The CPU architecture configuration is where the endianess of the
@ -464,8 +603,8 @@ void uip_log(char *msg);
/**
* The byte order of the CPU architecture on which uIP is to be run.
*
* This option can be either BIG_ENDIAN (Motorola byte order) or
* LITTLE_ENDIAN (Intel byte order).
* This option can be either UIP_BIG_ENDIAN (Motorola byte order) or
* UIP_LITTLE_ENDIAN (Intel byte order).
*
* \hideinitializer
*/
@ -478,8 +617,17 @@ void uip_log(char *msg);
/** @} */
/*------------------------------------------------------------------------------*/
#include <ff.h>
#include <stdbool.h>
#include <stdint.h>
typedef uint8_t u8_t;
typedef uint16_t u16_t;
typedef uint32_t u32_t;
typedef uint32_t uip_stats_t;
/**
* \name Appication specific configurations
* \defgroup uipoptapp Application specific configurations
* @{
*
* An uIP application is implemented using a single application
@ -497,18 +645,20 @@ void uip_log(char *msg);
* The following example illustrates how this can look.
\code
void httpd_appcall(void);
#define UIP_APPCALL httpd_appcall
void httpd_appcall(void);
#define UIP_APPCALL httpd_appcall
struct httpd_state {
u8_t state;
u16_t count;
char *dataptr;
char *script;
};
typedef struct httpd_state uip_tcp_appstate_t
struct httpd_state {
u8_t state;
u16_t count;
char *dataptr;
char *script;
};
typedef struct httpd_state uip_tcp_appstate_t
\endcode
*/
*/
#define UIP_UDP_APPCALL DHCPApp_Callback
void UIP_UDP_APPCALL(void);
/**
* \var #define UIP_APPCALL
@ -517,6 +667,8 @@ typedef struct httpd_state uip_tcp_appstate_t
* response to TCP/IP events.
*
*/
#define UIP_APPCALL WebserverApp_Callback
void UIP_APPCALL(void);
/**
* \var typedef uip_tcp_appstate_t
@ -525,6 +677,17 @@ typedef struct httpd_state uip_tcp_appstate_t
* uip_conn structure. This usually is typedef:ed to a struct holding
* application state information.
*/
typedef struct
{
uint8_t CurrentState;
uint8_t NextState;
char FileName[30];
FIL FileHandle;
bool FileOpen;
uint32_t ACKedFilePos;
uint16_t SentChunkSize;
} uip_tcp_appstate_t;
/**
* \var typedef uip_udp_appstate_t
@ -533,7 +696,21 @@ typedef struct httpd_state uip_tcp_appstate_t
* uip_conn structure. This usually is typedef:ed to a struct holding
* application state information.
*/
/** @} */
typedef struct
{
uint8_t CurrentState;
struct uip_udp_conn* Connection;
struct
{
uint8_t AllocatedIP[4];
uint8_t Netmask[4];
uint8_t GatewayIP[4];
uint8_t ServerIP[4];
} DHCPOffer_Data;
} uip_udp_appstate_t;
/** @} */
#endif /* __UIPOPT_H__ */
/** @} */
/** @} */

@ -76,9 +76,10 @@
* <td><b>Description:</b></td>
* </tr>
* <tr>
* <td>ENABLE_DHCP</td>
* <td>ENABLE_DHCP=<i>x</i></td>
* <td>Makefile CDEFS</td>
* <td>When defined, enables the DHCP client for dynamic IP allocation of the network settings from a DHCP server.</td>
* <td>When set to 1, this enables the DHCP client for dynamic IP allocation of the network settings from a DHCP server.
* To disable DHCP and use the fixed address settings set elsewhere, set this to zero (do not undefine it).</td>
* </tr>
* <tr>
* <td>DEVICE_IP_ADDRESS</td>

@ -135,8 +135,7 @@ SRC = $(TARGET).c \
Lib/uip/uip.c \
Lib/uip/uip_arp.c \
Lib/uip/timer.c \
Lib/uip/uip-neighbor.c \
Lib/uip/conf/clock-arch.c \
Lib/uip/clock.c \
Lib/FATFs/diskio.c \
Lib/FATFs/ff.c \
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/DevChapter9.c \
@ -198,7 +197,13 @@ CSTANDARD = -std=gnu99
# Place -D or -U options here for C sources
CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD) $(LUFA_OPTS)
CDEFS += -DENABLE_DHCP
CDEFS += -DENABLE_DHCP=1
CDEFS += -DUIP_CONF_UDP_CONNS=1 -DUIP_CONF_TCP=1 -DUIP_CONF_MAX_CONNECTIONS=5
CDEFS += -DUIP_CONF_MAX_LISTENPORTS=1 -DUIP_CONF_BUFFER_SIZE=1514
CDEFS += -DUIP_CONF_LL_802154=0 -DUIP_CONF_LL_80211=0 -DUIP_CONF_ROUTER=0 -DUIP_CONF_ICMP6=0 -DUIP_CONF_LL_802154=0
CDEFS += -DUIP_ARCH_ADD32=0 -DUIP_ARCH_CHKSUM=0 -DUIP_CONF_ICMP_DEST_UNREACH=1 -DUIP_NEIGHBOR_CONF_ADDRTYPE=0
CDEFS += -DUIP_CONF_UDP=ENABLE_DHCP
# Place -D or -U options here for ASM sources

Loading…
Cancel
Save