summaryrefslogtreecommitdiff
path: root/nuttx
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-08-26 23:12:17 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-08-26 23:12:17 +0000
commit93f9271b27b33e322ffa45ec71c43884674458af (patch)
tree36f9bb5f22dc98aee189714b2733c7cbcb6c08d1 /nuttx
parentc010014195f732bf60d018d9432354fba0950a11 (diff)
downloadpx4-nuttx-93f9271b27b33e322ffa45ec71c43884674458af.tar.gz
px4-nuttx-93f9271b27b33e322ffa45ec71c43884674458af.tar.bz2
px4-nuttx-93f9271b27b33e322ffa45ec71c43884674458af.zip
Import of uIP 1.0
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@308 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx')
-rw-r--r--nuttx/examples/uip/Makefile77
-rw-r--r--nuttx/examples/uip/main.c165
-rw-r--r--nuttx/include/net/uip/httpd.h78
-rw-r--r--nuttx/include/net/uip/psock.h237
-rw-r--r--nuttx/include/net/uip/resolv.h60
-rw-r--r--nuttx/include/net/uip/smtp.h75
-rw-r--r--nuttx/include/net/uip/uip-arch.h343
-rw-r--r--nuttx/include/net/uip/uip-arp.h122
-rw-r--r--nuttx/include/net/uip/uip.h1172
-rw-r--r--nuttx/include/net/uip/uipopt.h423
-rw-r--r--nuttx/net/Makefile86
-rw-r--r--nuttx/net/uip/.psock.h.swobin0 -> 16398 bytes
-rw-r--r--nuttx/net/uip/Make.defs38
-rw-r--r--nuttx/net/uip/psock.c377
-rw-r--r--nuttx/net/uip/uip-arp.c405
-rw-r--r--nuttx/net/uip/uip-fw.c513
-rw-r--r--nuttx/net/uip/uip-fw.h176
-rw-r--r--nuttx/net/uip/uip-neighbor.c158
-rw-r--r--nuttx/net/uip/uip-neighbor.h54
-rw-r--r--nuttx/net/uip/uip-split.c132
-rw-r--r--nuttx/net/uip/uip-split.h96
-rw-r--r--nuttx/net/uip/uip-wait.c180
-rw-r--r--nuttx/net/uip/uip.c2091
-rw-r--r--nuttx/netutils/Makefile97
-rw-r--r--nuttx/netutils/README5
-rw-r--r--nuttx/netutils/dhcpc/Make.defs39
-rw-r--r--nuttx/netutils/dhcpc/dhcpc.c390
-rw-r--r--nuttx/netutils/dhcpc/dhcpc.h58
-rw-r--r--nuttx/netutils/resolv/Make.defs39
-rw-r--r--nuttx/netutils/resolv/resolv.c450
-rw-r--r--nuttx/netutils/smtp/Make.defs38
-rwxr-xr-xnuttx/netutils/smtp/makestrings40
-rw-r--r--nuttx/netutils/smtp/smtp-strings11
-rw-r--r--nuttx/netutils/smtp/smtp-strings.c33
-rw-r--r--nuttx/netutils/smtp/smtp-strings.h11
-rw-r--r--nuttx/netutils/smtp/smtp.c252
-rw-r--r--nuttx/netutils/telnetd/Make.defs37
-rw-r--r--nuttx/netutils/telnetd/shell.c123
-rw-r--r--nuttx/netutils/telnetd/shell.h104
-rw-r--r--nuttx/netutils/telnetd/telnetd.c336
-rw-r--r--nuttx/netutils/telnetd/telnetd.h53
-rw-r--r--nuttx/netutils/uiplib/Make.defs37
-rw-r--r--nuttx/netutils/uiplib/uiplib.c73
-rw-r--r--nuttx/netutils/uiplib/uiplib.h71
-rw-r--r--nuttx/netutils/webclient/Make.defs37
-rwxr-xr-xnuttx/netutils/webclient/makestrings40
-rw-r--r--nuttx/netutils/webclient/webclient-strings31
-rw-r--r--nuttx/netutils/webclient/webclient-strings.c93
-rw-r--r--nuttx/netutils/webclient/webclient-strings.h31
-rw-r--r--nuttx/netutils/webclient/webclient.c450
-rw-r--r--nuttx/netutils/webclient/webclient.h214
-rw-r--r--nuttx/netutils/webserver/Make.defs37
-rw-r--r--nuttx/netutils/webserver/http-strings35
-rw-r--r--nuttx/netutils/webserver/http-strings.c102
-rw-r--r--nuttx/netutils/webserver/http-strings.h34
-rw-r--r--nuttx/netutils/webserver/httpd-cgi.c178
-rw-r--r--nuttx/netutils/webserver/httpd-cgi.h67
-rw-r--r--nuttx/netutils/webserver/httpd-fs.c134
-rw-r--r--nuttx/netutils/webserver/httpd-fsdata.c617
-rw-r--r--nuttx/netutils/webserver/httpd-fsdata.h66
-rw-r--r--nuttx/netutils/webserver/httpd.c305
-rwxr-xr-xnuttx/netutils/webserver/makefsdata78
-rwxr-xr-xnuttx/netutils/webserver/makestrings40
63 files changed, 11944 insertions, 0 deletions
diff --git a/nuttx/examples/uip/Makefile b/nuttx/examples/uip/Makefile
new file mode 100644
index 000000000..6d10d8e9b
--- /dev/null
+++ b/nuttx/examples/uip/Makefile
@@ -0,0 +1,77 @@
+############################################################
+# Makefile
+#
+# Copyright (C) 2007 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name Gregory Nutt nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################
+
+-include $(TOPDIR)/.config
+-include $(TOPDIR)/Make.defs
+
+MKDEP = $(TOPDIR)/tools/mkdeps.sh
+
+ASRCS =
+AOBJS = $(ASRCS:.S=$(OBJEXT))
+CSRCS = main.c
+COBJS = $(CSRCS:.c=$(OBJEXT))
+
+SRCS = $(ASRCS) $(CSRCS)
+OBJS = $(AOBJS) $(COBJS)
+
+BIN = lib$(CONFIG_EXAMPLE)$(LIBEXT)
+
+all: $(BIN)
+
+$(AOBJS): %$(OBJEXT): %.S
+ $(CC) -c $(CFLAGS) $< -o $@
+
+$(COBJS): %$(OBJEXT): %.c
+ $(CC) -c $(CFLAGS) $< -o $@
+
+$(BIN): $(OBJS)
+ ( for obj in $(OBJS) ; do \
+ $(AR) $@ $${obj} || \
+ { echo "$(AR) $@ $obj FAILED!" ; exit 1 ; } ; \
+ done ; )
+
+.depend: Makefile $(SRCS)
+ $(MKDEP) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep
+ touch $@
+
+depend: .depend
+
+clean:
+ rm -f $(BIN) *.o *.rel *.asm *.lst *.sym *.adb *~
+
+distclean: clean
+ rm -f Make.dep .depend
+
+-include Make.dep
diff --git a/nuttx/examples/uip/main.c b/nuttx/examples/uip/main.c
new file mode 100644
index 000000000..1c3fff340
--- /dev/null
+++ b/nuttx/examples/uip/main.c
@@ -0,0 +1,165 @@
+/* main.c
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Adam Dunkels.
+ * 4. 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: main.c,v 1.1.1.1 2007-08-26 23:10:37 patacongo Exp $
+ *
+ */
+
+#include <stdio.h>
+#include <time.h>
+
+#include <net/uip/uip.h>
+#include <net/uip/uip-arp.h>
+
+/* Here we include the header file for the application(s) we use in
+ * our project as defined in the config/<board-name>/defconfig file
+ */
+
+#define CONFIG_EXAMPLE_UIP_WEBSERVER 1 /* For now */
+
+#if defined(CONFIG_EXAMPLE_UIP_SMTP)
+# include <net/uip/smtp.h>
+#elif defined(CONFIG_EXAMPLE_UIP_TELNETD)
+# include <net/uip/telnetd.h>
+#elif defined(CONFIG_EXAMPLE_UIP_WEBSERVER)
+# include <net/uip/httpd.h>
+#elif defined(CONFIG_EXAMPLE_UIP_DHCPC)
+# include <net/uip/dhcpc.h>
+#elif defined(CONFIG_EXAMPLE_UIP_RESOLV)
+# include <net/uip/resolv.h>
+#elif defined(CONFIG_EXAMPLE_UIP_WEBCLIENT)
+# include <net/uip/webclient.h>
+#endif
+
+int user_start(int argc, char *argv[])
+{
+ int i;
+ uip_ipaddr_t ipaddr;
+#if defined(CONFIG_EXAMPLE_UIP_DHCPC)
+ uint16 mac[6] = {1,2,3,4,5,6};
+#endif
+
+ uip_ipaddr(ipaddr, 192,168,0,2);
+ uip_sethostaddr(ipaddr);
+ uip_ipaddr(ipaddr, 192,168,0,1);
+ uip_setdraddr(ipaddr);
+ uip_ipaddr(ipaddr, 255,255,255,0);
+ uip_setnetmask(ipaddr);
+
+#if defined(CONFIG_EXAMPLE_UIP_WEBSERVER)
+ httpd_init();
+#elif defined(CONFIG_EXAMPLE_UIP_TELNETD)
+ telnetd_init();
+#elif defined(CONFIG_EXAMPLE_UIP_DHCPC)
+ dhcpc_init(&mac, 6);
+#elif defined(CONFIG_EXAMPLE_UIP_SMTP)
+ uip_ipaddr(ipaddr, 127,0,0,1);
+ smtp_configure("localhost", ipaddr);
+ SMTP_SEND("adam@sics.se", NULL, "uip-testing@example.com",
+ "Testing SMTP from uIP",
+ "Test message sent by uIP\r\n");
+#elif defined(CONFIG_EXAMPLE_UIP_WEBCLIENT)
+ webclient_init();
+ resolv_init();
+ uip_ipaddr(ipaddr, 195,54,122,204);
+ resolv_conf(ipaddr);
+ resolv_query("www.sics.se");
+#endif
+
+ while(1)
+ {
+ sleep(3);
+ printf("main: Still running\n");
+ }
+ return 0;
+}
+
+void uip_log(char *m)
+{
+ printf("uIP log message: %s\n", m);
+}
+
+void resolv_found(char *name, uint16 *ipaddr)
+{
+ if (ipaddr == NULL)
+ {
+ printf("Host '%s' not found.\n", name);
+ }
+ else
+ {
+ printf("Found name '%s' = %d.%d.%d.%d\n", name,
+ htons(ipaddr[0]) >> 8, htons(ipaddr[0]) & 0xff,
+ htons(ipaddr[1]) >> 8, htons(ipaddr[1]) & 0xff);
+ /* webclient_get("www.sics.se", 80, "/~adam/uip");*/
+ }
+}
+
+#ifdef __DHCPC_H__
+void dhcpc_configured(const struct dhcpc_state *s)
+{
+ uip_sethostaddr(s->ipaddr);
+ uip_setnetmask(s->netmask);
+ uip_setdraddr(s->default_router);
+ resolv_conf(s->dnsaddr);
+}
+#endif /* __DHCPC_H__ */
+
+void smtp_done(unsigned char code)
+{
+ printf("SMTP done with code %d\n", code);
+}
+
+void webclient_closed(void)
+{
+ printf("Webclient: connection closed\n");
+}
+
+void webclient_aborted(void)
+{
+ printf("Webclient: connection aborted\n");
+}
+
+void webclient_timedout(void)
+{
+ printf("Webclient: connection timed out\n");
+}
+
+void webclient_connected(void)
+{
+ printf("Webclient: connected, waiting for data...\n");
+}
+
+void webclient_datahandler(char *data, uint16 len)
+{
+ printf("Webclient: got %d bytes of data.\n", len);
+}
diff --git a/nuttx/include/net/uip/httpd.h b/nuttx/include/net/uip/httpd.h
new file mode 100644
index 000000000..1c9420448
--- /dev/null
+++ b/nuttx/include/net/uip/httpd.h
@@ -0,0 +1,78 @@
+/* httpd.h
+ *
+ * Copyright (c) 2001-2005, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HTTPD_H__
+#define __HTTPD_H__
+
+#include <sys/types.h>
+#include <net/uip/psock.h>
+
+#define HTTPD_FS_STATISTICS 1
+
+struct httpd_fs_file
+{
+ char *data;
+ int len;
+};
+
+struct httpd_state
+{
+ unsigned char timer;
+ struct psock sin, sout;
+ char inputbuf[50];
+ char filename[20];
+ char state;
+ struct httpd_fs_file file;
+ int len;
+ char *scriptptr;
+ int scriptlen;
+
+ unsigned short count;
+};
+
+#ifdef HTTPD_FS_STATISTICS
+#if HTTPD_FS_STATISTICS == 1
+extern uint16 httpd_fs_count(char *name);
+#endif /* HTTPD_FS_STATISTICS */
+#endif /* HTTPD_FS_STATISTICS */
+
+void httpd_init(void);
+void httpd_log(char *msg);
+void httpd_log_file(uint16 *requester, char *file);
+
+/* file must be allocated by caller and will be filled in
+ * by the function.
+ */
+
+int httpd_fs_open(const char *name, struct httpd_fs_file *file);
+void httpd_fs_init(void);
+
+
+#endif /* __HTTPD_H__ */
diff --git a/nuttx/include/net/uip/psock.h b/nuttx/include/net/uip/psock.h
new file mode 100644
index 000000000..9e505c970
--- /dev/null
+++ b/nuttx/include/net/uip/psock.h
@@ -0,0 +1,237 @@
+/* psock.h
+ * Protosocket library 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.
+ */
+
+/* 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().
+ *
+ */
+
+#ifndef __PSOCK_H__
+#define __PSOCK_H__
+
+#include <sys/types.h>
+#include <net/uip/uipopt.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
+{
+ uint8 *ptr;
+ unsigned short left;
+};
+
+/* The representation of a protosocket.
+ *
+ * The protosocket structrure is an opaque structure with no user-visible
+ * elements.
+ */
+
+struct psock
+{
+ const uint8 *sendptr; /* Pointer to the next data to be sent. */
+ uint8 *readptr; /* Pointer to the next data to be read. */
+ uint8 *bufptr; /* Pointer to the buffer used for buffering incoming data. */
+ uint16 sendlen; /* The number of bytes left to be sent. */
+ uint16 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. */
+};
+
+/* Initialize a protosocket.
+ *
+ * Initializes a protosocket and must be called before the
+ * protosocket is used. The initialization also specifies the input buffer
+ * for the protosocket.
+ *
+ * psock (struct psock *) A pointer to the protosocket to be
+ * initialized
+ *
+ * buffer (char *) A pointer to the input buffer for the
+ * protosocket.
+ *
+ * buffersize (unsigned int) The size of the input buffer.
+ */
+
+extern void psock_init(struct psock *psock, char *buffer, unsigned int buffersize);
+
+/* 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.
+ *
+ * psock (struct psock *) A pointer to the protosocket over which
+ * data is to be sent.
+ *
+ * data (char *) A pointer to the data that is to be sent.
+ *
+ * datalen (unsigned int) The length of the data that is to be
+ * sent.
+ */
+
+extern void psock_send(struct psock *psock, const char *buf, unsigned int len);
+
+/*Send a null-terminated string.
+ *
+ * psock Pointer to the protosocket.
+ * str The string to be sent.
+ *
+ * This function sends a null-terminated string over the
+ * protosocket.
+ */
+
+#define PSOCK_SEND_STR(psock, str) psock_send(psock, str, strlen(str))
+
+/* Generate data with a function and send it
+ *
+ * psock Pointer to the protosocket.
+ * generator Pointer to the generator function
+ * 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.
+ */
+
+extern void psock_generator_send(struct psock *psock, unsigned short (*f)(void *), void *arg);
+
+/* Close a protosocket.
+ *
+ * This macro closes a protosocket and can only be called from within the
+ * protothread in which the protosocket lives.
+ *
+ * psock (struct psock *) A pointer to the protosocket that is to
+ * be closed.
+ */
+
+#define PSOCK_CLOSE(psock) uip_close()
+
+/* 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..
+ *
+ * psock (struct psock *) A pointer to the protosocket from which
+ * data should be read.
+ */
+
+extern void psock_readbuf(struct psock *psock);
+
+/* 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.
+ *
+ * psock (struct psock *) A pointer to the protosocket from which
+ * data should be read.
+ *
+ * c (char) The character at which to stop reading.
+ */
+
+extern void psock_readto(struct psock *psock, unsigned char c);
+
+/* The length of the data that was previously read.
+ *
+ * Returns the length of the data that was previously read
+ * using PSOCK_READTO() or PSOCK_READ().
+ *
+ * psock (struct psock *) A pointer to the protosocket holding the data.
+ */
+
+extern uint16 psock_datalen(struct psock *psock);
+
+/* Check if there is new data has arrived on a protosocket without blocking
+ *
+ * psock (struct psock *) A pointer to the protosocket.
+ */
+
+extern boolean psock_checknewdata(struct psock *s);
+
+/* Block until new data has arrived on a protosocket.
+ *
+ * psock (struct psock *) A pointer to the protosocket.
+ */
+
+extern void psock_waitnewdata(struct psock *s);
+
+#endif /* __PSOCK_H__ */
+
+/** @} */
diff --git a/nuttx/include/net/uip/resolv.h b/nuttx/include/net/uip/resolv.h
new file mode 100644
index 000000000..3411966ea
--- /dev/null
+++ b/nuttx/include/net/uip/resolv.h
@@ -0,0 +1,60 @@
+/* resolv.h
+ * DNS resolver code header file.
+ * Authtor Adam Dunkels <adam@dunkels.com>
+ *
+ * Copyright (c) 2002-2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __UIP_RESOLV_H__
+#define __UIP_RESOLV_H__
+
+#include <sys/types.h>
+#include <net/uip/uipopt.h>
+
+/* Callback function which is called when a hostname is found.
+ *
+ * This function must be implemented by the module that uses the DNS
+ * resolver. It is called when a hostname is found, or when a hostname
+ * was not found.
+ *
+ * name A pointer to the name that was looked up. \param
+ * ipaddr A pointer to a 4-byte array containing the IP address of the
+ * hostname, or NULL if the hostname could not be found.
+ */
+
+extern void resolv_found(char *name, uint16 *ipaddr);
+
+/* Functions. */
+
+extern void resolv_conf(uint16 *dnsserver);
+extern uint16 *resolv_getserver(void);
+extern void resolv_init(void);
+extern uint16 *resolv_lookup(char *name);
+extern void resolv_query(char *name);
+
+#endif /* __UIP_RESOLV_H__ */
diff --git a/nuttx/include/net/uip/smtp.h b/nuttx/include/net/uip/smtp.h
new file mode 100644
index 000000000..da2683f65
--- /dev/null
+++ b/nuttx/include/net/uip/smtp.h
@@ -0,0 +1,75 @@
+/* smtp.h
+ * SMTP header file
+ * Author: Adam Dunkels <adam@dunkels.com>
+ *
+ * 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.
+ */
+
+#ifndef __SMTP_H__
+#define __SMTP_H__
+
+#include <sys/types.h>
+
+#include <net/uip/uipopt.h>
+
+/* Error number that signifies a non-error condition. */
+
+#define SMTP_ERR_OK 0
+
+/* Callback function that is called when an e-mail transmission is
+ * done.
+ *
+ * This function must be implemented by the module that uses the SMTP
+ * module.
+ *
+ * error The number of the error if an error occured, or
+ * SMTP_ERR_OK.
+ */
+
+void smtp_done(unsigned char error);
+
+void smtp_init(void);
+void smtp_configure(char *localhostname, uint16 *smtpserver);
+unsigned char smtp_send(char *to, char *from,
+ char *subject, char *msg,
+ uint16 msglen);
+
+struct smtp_state
+{
+ uint8 state;
+ char *to;
+ char *from;
+ char *subject;
+ char *msg;
+ uint16 msglen;
+
+ uint16 sentlen, textlen;
+ uint16 sendptr;
+};
+
+#endif /* __SMTP_H__ */
diff --git a/nuttx/include/net/uip/uip-arch.h b/nuttx/include/net/uip/uip-arch.h
new file mode 100644
index 000000000..f49448da2
--- /dev/null
+++ b/nuttx/include/net/uip/uip-arch.h
@@ -0,0 +1,343 @@
+/****************************************************************************
+ * uip-arch.h
+ * Defines architecture-specific device driver interfaces to uIP
+ *
+ * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Derived largely from portions of uIP with has a similar BSD-styple license:
+ *
+ * Copyright (c) 2001-2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __UIP_ARCH_H
+#define __UIP_ARCH_H
+
+#include <sys/types.h>
+#include <net/uip/uip.h>
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <net/uip/uipopt.h>
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/* The following flags are passed as an argument to the uip_interrupt()
+ * function. They are used to distinguish between the two cases where
+ * uip_interrupt() 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.
+ */
+
+#define UIP_DATA 1 /* Tells uIP that there is incoming data in the uip_buf buffer. The
+ * length of the data is stored in the global variable uip_len. */
+#define UIP_TIMER 2 /* Tells uIP that the periodic timer has fired. */
+#define UIP_POLL_REQUEST 3 /* Tells uIP that a connection should be polled. */
+#define UIP_UDP_SEND_CONN 4 /* Tells uIP that a UDP datagram should be constructed in the
+ * uip_buf buffer. */
+#if UIP_UDP
+# define UIP_UDP_TIMER 5
+#endif /* UIP_UDP */
+
+/* uIP device driver functions
+ *
+ * These functions are used by a network device driver for interacting
+ * with uIP.
+ *
+ * Process an incoming packet.
+ *
+ * This function should be called when the device driver has received
+ * a packet from the network. The packet from the device driver must
+ * be present in the uip_buf buffer, and the length of the packet
+ * should be placed in the uip_len variable.
+ *
+ * When the function returns, there may be an outbound packet placed
+ * in the uip_buf packet buffer. If so, the uip_len variable is set to
+ * the length of the packet. If no packet is to be sent out, the
+ * uip_len variable is set to 0.
+ *
+ * The usual way of calling the function is presented by the source
+ * code below.
+ *
+ * uip_len = devicedriver_poll();
+ * if(uip_len > 0) {
+ * uip_input();
+ * if(uip_len > 0) {
+ * devicedriver_send();
+ * }
+ * }
+ *
+ * Note: If you are writing a uIP device driver that needs ARP
+ * (Address Resolution Protocol), e.g., when running uIP over
+ * Ethernet, you will need to call the uIP ARP code before calling
+ * this function:
+ *
+ * #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 uip_input() uip_interrupt(UIP_DATA)
+
+/* Periodic processing for a connection identified by its number.
+ *
+ * This function does the necessary periodic processing (timers,
+ * polling) for a uIP TCP conneciton, and should be called when the
+ * periodic uIP timer goes off. It should be called for every
+ * connection, regardless of whether they are open of closed.
+ *
+ * When the function returns, it may have an outbound packet waiting
+ * for service in the uIP packet buffer, and if so the uip_len
+ * 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
+ * this:
+ *
+ * for(i = 0; i < UIP_CONNS; ++i) {
+ * uip_periodic(i);
+ * if(uip_len > 0) {
+ * devicedriver_send();
+ * }
+ * }
+ *
+ * Note: If you are writing a uIP device driver that needs ARP
+ * (Address Resolution Protocol), e.g., when running uIP over
+ * Ethernet, you will need to call the uip_arp_out() function before
+ * calling the device driver:
+ *
+ * for(i = 0; i < UIP_CONNS; ++i) {
+ * uip_periodic(i);
+ * if(uip_len > 0) {
+ * uip_arp_out();
+ * ethernet_devicedriver_send();
+ * }
+ * }
+ *
+ * conn The number of the connection which is to be periodically polled.
+ */
+
+#define uip_periodic(conn) do { uip_conn = &uip_conns[conn]; \
+ uip_interrupt(UIP_TIMER); } while (0)
+
+#define uip_conn_active(conn) (uip_conns[conn].tcpstateflags != UIP_CLOSED)
+
+/* Perform periodic processing for a connection identified by a pointer
+ * to its structure.
+ *
+ * Same as uip_periodic() but takes a pointer to the actual uip_conn
+ * struct instead of an integer as its argument. This function can be
+ * used to force periodic processing of a specific connection.
+ *
+ * conn A pointer to the uip_conn struct for the connection to
+ * be processed.
+ */
+
+#define uip_periodic_conn(conn) do { uip_conn = conn; uip_interrupt(UIP_TIMER); } while (0)
+
+/* 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.
+ *
+ * conn A pointer to the uip_conn struct for the connection to
+ * be processed.
+ */
+
+#define uip_poll_conn(conn) do { uip_conn = conn; uip_interrupt(UIP_POLL_REQUEST); } while (0)
+
+
+#if UIP_UDP
+/* Periodic processing for a UDP connection identified by its number.
+ *
+ * This function is essentially the same as uip_periodic(), but for
+ * UDP connections. It is called in a similar fashion as the
+ * uip_periodic() function:
+ *
+ * for(i = 0; i < UIP_UDP_CONNS; i++) {
+ * uip_udp_periodic(i);
+ * if(uip_len > 0) {
+ * devicedriver_send();
+ * }
+ * }
+ *
+ * Note: As for the uip_periodic() function, special care has to be
+ * taken when using uIP together with ARP and Ethernet:
+ *
+ * for(i = 0; i < UIP_UDP_CONNS; i++) {
+ * uip_udp_periodic(i);
+ * if(uip_len > 0) {
+ * uip_arp_out();
+ * ethernet_devicedriver_send();
+ * }
+ * }
+ *
+ * conn The number of the UDP connection to be processed.
+ */
+
+#define uip_udp_periodic(conn) do { uip_udp_conn = &uip_udp_conns[conn]; \
+ uip_interrupt(UIP_UDP_TIMER); } while (0)
+
+/* Periodic processing for a UDP connection identified by a pointer to
+ * its structure.
+ *
+ * Same as uip_udp_periodic() but takes a pointer to the actual
+ * uip_conn struct instead of an integer as its argument. This
+ * function can be used to force periodic processing of a specific
+ * connection.
+ *
+ * conn A pointer to the uip_udp_conn struct for the connection
+ * to be processed.
+ */
+
+#define uip_udp_periodic_conn(conn) do { uip_udp_conn = conn; \
+ uip_interrupt(UIP_UDP_TIMER); } while (0)
+
+
+#endif /* UIP_UDP */
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Pulblic Function Prototypes
+ ****************************************************************************/
+
+/* Architecure support
+ *
+ * uip_interrupt(flag):
+ *
+ * The actual uIP function which does all the work. Called from the
+ * interrupt level by a device driver.
+ */
+
+extern void uip_interrupt(uint8 flag);
+
+/* By defining UIP_ARCH_CHKSUM, the architecture can replace the following
+ * functions with hardware assisted solutions.
+ */
+
+/* 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).
+ *
+ * op32 A pointer to a 4-byte array representing a 32-bit
+ * integer in network byte order (big endian).
+ *
+ * op16 A 16-bit integer in host byte order.
+ */
+
+#if UIP_ARCH_ADD32
+extern void uip_add32(uint8 *op32, uint16 op16);
+#endif
+
+/* 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.
+ *
+ * buf A pointer to the buffer over which the checksum is to be
+ * computed.
+ *
+ * len The length of the buffer over which the checksum is to
+ * be computed.
+ *
+ * Return: The Internet checksum of the buffer.
+ */
+
+extern uint16 uip_chksum(uint16 *buf, uint16 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.
+ */
+
+extern uint16 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.
+ */
+
+extern uint16 uip_tcpchksum(void);
+
+extern uint16 uip_udpchksum(void);
+
+#endif /* __UIP_ARCH_H */
diff --git a/nuttx/include/net/uip/uip-arp.h b/nuttx/include/net/uip/uip-arp.h
new file mode 100644
index 000000000..2f5148e1a
--- /dev/null
+++ b/nuttx/include/net/uip/uip-arp.h
@@ -0,0 +1,122 @@
+/* uip-arp.h
+ * Macros and definitions for the ARP module.
+ * Author: Adam Dunkels <adam@dunkels.com>
+ *
+ * Copyright (c) 2001-2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __UIP_ARP_H__
+#define __UIP_ARP_H__
+
+#include <sys/types.h>
+#include <net/uip/uip.h>
+
+extern struct uip_eth_addr uip_ethaddr;
+
+/* The Ethernet header */
+
+struct uip_eth_hdr
+{
+ struct uip_eth_addr dest;
+ struct uip_eth_addr src;
+ uint16 type;
+};
+
+#define UIP_ETHTYPE_ARP 0x0806
+#define UIP_ETHTYPE_IP 0x0800
+#define UIP_ETHTYPE_IP6 0x86dd
+
+/* The uip_arp_init() function must be called before any of the other
+ * ARP functions.
+ */
+
+void uip_arp_init(void);
+
+/* The uip_arp_ipin() function should be called whenever an IP packet
+ * arrives from the Ethernet. This function refreshes the ARP table or
+ * inserts a new mapping if none exists. The function assumes that an
+ * IP packet with an Ethernet header is present in the uip_buf buffer
+ * and that the length of the packet is in the uip_len variable.
+ */
+
+/*void uip_arp_ipin(void);*/
+#define uip_arp_ipin()
+
+/* The uip_arp_arpin() should be called when an ARP packet is received
+ * by the Ethernet driver. This function also assumes that the
+ * Ethernet frame is present in the uip_buf buffer. When the
+ * uip_arp_arpin() function returns, the contents of the uip_buf
+ * buffer should be sent out on the Ethernet if the uip_len variable
+ * is > 0.
+ */
+
+void uip_arp_arpin(void);
+
+/* The uip_arp_out() function should be called when an IP packet
+ * should be sent out on the Ethernet. This function creates an
+ * Ethernet header before the IP header in the uip_buf buffer. The
+ * Ethernet header will have the correct Ethernet MAC destination
+ * address filled in if an ARP table entry for the destination IP
+ * address (or the IP address of the default router) is present. If no
+ * such table entry is found, the IP packet is overwritten with an ARP
+ * request and we rely on TCP to retransmit the packet that was
+ * overwritten. In any case, the uip_len variable holds the length of
+ * the Ethernet frame that should be transmitted.
+ */
+
+void uip_arp_out(void);
+
+/* The uip_arp_timer() function should be called every ten seconds. It
+ * is responsible for flushing old entries in the ARP table.
+ */
+
+void uip_arp_timer(void);
+
+/* Specifiy the Ethernet MAC address.
+ *
+ * The ARP code needs to know the MAC address of the Ethernet card in
+ * order to be able to respond to ARP queries and to generate working
+ * Ethernet headers.
+ *
+ * Note: This macro only specifies the Ethernet MAC address to the ARP
+ * code. It cannot be used to change the MAC address of the Ethernet
+ * card.
+ *
+ * eaddr A pointer to a struct uip_eth_addr containing the
+ * Ethernet MAC address of the Ethernet card.
+ */
+
+#define uip_setethaddr(eaddr) do {uip_ethaddr.addr[0] = eaddr.addr[0]; \
+ uip_ethaddr.addr[1] = eaddr.addr[1];\
+ uip_ethaddr.addr[2] = eaddr.addr[2];\
+ uip_ethaddr.addr[3] = eaddr.addr[3];\
+ uip_ethaddr.addr[4] = eaddr.addr[4];\
+ uip_ethaddr.addr[5] = eaddr.addr[5];} while(0)
+
+#endif /* __UIP_ARP_H__ */
diff --git a/nuttx/include/net/uip/uip.h b/nuttx/include/net/uip/uip.h
new file mode 100644
index 000000000..0185a8da0
--- /dev/null
+++ b/nuttx/include/net/uip/uip.h
@@ -0,0 +1,1172 @@
+/**
+ * uip.h
+ * Header file for the uIP TCP/IP stack.
+ * author Adam Dunkels <adam@dunkels.com>
+ *
+ * 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
+ * structures, TCP/IP header structures and function declarations.
+ *
+ * Copyright (c) 2001-2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: uip.h,v 1.1.1.1 2007-08-26 23:12:16 patacongo Exp $
+ *
+ ****************************************************************************/
+
+#ifndef __UIP_H__
+#define __UIP_H__
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <sys/types.h>
+#include <nuttx/config.h>
+#include <net/uip/uipopt.h>
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/* 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 should *NOT* be accessed directly,
+ * but only through the uIP functions/macros.
+ */
+
+#define UIP_ACKDATA (1 << 0) /* Signifies that the outstanding data was acked and the
+ * application should send out new data instead of retransmitting
+ * the last data. */
+#define UIP_NEWDATA (1 << 1) /* Flags the fact that the peer has sent us new data. */
+#define UIP_REXMIT (1 << 2) /* Tells the application to retransmit the data that was last
+ * sent. */
+#define UIP_POLL (1 << 3) /* Used for polling the application, to check if the application
+ * has data that it wants to send. */
+#define UIP_CLOSE (1 << 4) /* The remote host has closed the connection, thus the connection
+ * has gone away. Or the application signals that it wants to
+ * close the connection. */
+#define UIP_ABORT (1 << 5) /* The remote host has aborted the connection, thus the connection
+ * has gone away. Or the application signals that it wants to
+ * abort the connection. */
+#define UIP_CONNECTED (1 << 6) /* We have got a connection from a remote host and have set up a
+ * new connection for it, or an active connection has been
+ * successfully established. */
+#define UIP_TIMEDOUT (1 << 7) /* The connection has been aborted due to too many retransmissions. */
+#define UIP_APPTIMEOUT (1 << 8) /* Application time limit has elapsed */
+
+/* The TCP states used in the uip_conn->tcpstateflags. */
+
+#define UIP_CLOSED 0
+#define UIP_SYN_RCVD 1
+#define UIP_SYN_SENT 2
+#define UIP_ESTABLISHED 3
+#define UIP_FIN_WAIT_1 4
+#define UIP_FIN_WAIT_2 5
+#define UIP_CLOSING 6
+#define UIP_TIME_WAIT 7
+#define UIP_LAST_ACK 8
+#define UIP_TS_MASK 15
+
+#define UIP_STOPPED 16
+
+/* The buffer size available for user data in the \ref uip_buf buffer.
+ *
+ * This macro holds the available size for user data in the \ref
+ * uip_buf buffer. The macro is intended to be used for checking
+ * bounds of available user data.
+ *
+ * Example:
+ *
+ * snprintf(uip_appdata, UIP_APPDATA_SIZE, "%u\n", i);
+ */
+
+#define UIP_APPDATA_SIZE (UIP_BUFSIZE - 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
+
+/* Header sizes. */
+#ifdef CONFIG_NET_UIP_IPv6
+# define UIP_IPH_LEN 40
+#else /* CONFIG_NET_UIP_IPv6 */
+# define UIP_IPH_LEN 20 /* Size of IP header */
+#endif /* CONFIG_NET_UIP_IPv6 */
+#define UIP_UDPH_LEN 8 /* Size of UDP header */
+#define UIP_TCPH_LEN 20 /* Size of TCP header */
+#define UIP_IPUDPH_LEN (UIP_UDPH_LEN + UIP_IPH_LEN) /* Size of IP + UDP header */
+#define UIP_IPTCPH_LEN (UIP_TCPH_LEN + UIP_IPH_LEN) /* Size of IP + TCP header */
+#define UIP_TCPIP_HLEN UIP_IPTCPH_LEN
+
+/****************************************************************************
+ * Public Type Definitions
+ ****************************************************************************/
+
+/* Repressentation of an IP address. */
+
+typedef uint16 uip_ip4addr_t[2];
+typedef uint16 uip_ip6addr_t[8];
+
+#ifdef CONFIG_NET_UIP_IPv6
+typedef uip_ip6addr_t uip_ipaddr_t;
+#else /* CONFIG_NET_UIP_IPv6 */
+typedef uip_ip4addr_t uip_ipaddr_t;
+#endif /* CONFIG_NET_UIP_IPv6 */
+
+/* Representation of a uIP TCP connection.
+ *
+ * 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 "private: field whos purpose
+ * is to let the application store application-specific state (e.g.,
+ * file pointers) for the connection.
+ */
+
+struct uip_conn
+{
+ uip_ipaddr_t ripaddr; /* The IP address of the remote host. */
+
+ uint16 lport; /* The local TCP port, in network byte order. */
+ uint16 rport; /* The local remote TCP port, in network byte
+ order. */
+
+ uint8 rcv_nxt[4]; /* The sequence number that we expect to
+ receive next. */
+ uint8 snd_nxt[4]; /* The sequence number that was last sent by
+ us. */
+ uint16 len; /* Length of the data that was previously sent. */
+ uint16 mss; /* Current maximum segment size for the
+ connection. */
+ uint16 initialmss; /* Initial maximum segment size for the
+ connection. */
+ uint8 sa; /* Retransmission time-out calculation state
+ variable. */
+ uint8 sv; /* Retransmission time-out calculation state
+ variable. */
+ uint8 rto; /* Retransmission time-out. */
+ uint8 tcpstateflags; /* TCP state and flags. */
+ uint8 timer; /* The retransmission timer. */
+ uint8 nrtx; /* The number of retransmissions for the last
+ segment sent. */
+
+ /* Higher level logic can retain application specific information
+ * in the following:
+ */
+
+ void *private;
+};
+
+#if UIP_UDP
+/* Representation of a uIP UDP connection. */
+
+struct uip_udp_conn
+{
+ uip_ipaddr_t ripaddr; /* The IP address of the remote peer. */
+ uint16 lport; /* The local port number in network byte order. */
+ uint16 rport; /* The remote port number in network byte order. */
+ uint8 ttl; /* Default time-to-live. */
+
+ /* Higher level logic can retain application specific information
+ * in the following:
+ */
+
+ void *private;
+};
+#endif /* UIP_UDP */
+
+/**
+ * The structure holding the TCP/IP statistics that are gathered if
+ * UIP_STATISTICS is set to 1.
+ *
+ */
+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 vhlerr; /* Number of packets dropped due to wrong
+ IP version or header length. */
+ uip_stats_t hblenerr; /* Number of packets dropped due to wrong
+ IP length, high byte. */
+ uip_stats_t lblenerr; /* Number of packets dropped due to wrong
+ IP length, low byte. */
+ uip_stats_t fragerr; /* Number of packets dropped since they
+ were IP fragments. */
+ uip_stats_t chkerr; /* Number of packets dropped due to IP
+ checksum errors. */
+ uip_stats_t protoerr; /* Number of packets dropped since they
+ 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 typeerr; /* Number of ICMP packets with a wrong type. */
+ } icmp; /* ICMP statistics. */
+ 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 chkerr; /* Number of TCP segments with a bad checksum. */
+ uip_stats_t ackerr; /* Number of TCP segments with a bad ACK number. */
+ uip_stats_t rst; /* Number of recevied TCP RST (reset) segments. */
+ uip_stats_t rexmit; /* Number of retransmitted TCP segments. */
+ uip_stats_t syndrop; /* Number of dropped SYNs due to too few
+ connections was avaliable. */
+ uip_stats_t synrst; /* Number of SYNs for closed ports,
+ triggering a RST. */
+ } tcp; /* TCP statistics. */
+#if UIP_UDP
+ struct {
+ uip_stats_t drop; /* Number of dropped UDP segments. */
+ uip_stats_t recv; /* Number of recived UDP segments. */
+ uip_stats_t sent; /* Number of sent UDP segments. */
+ uip_stats_t chkerr; /* Number of UDP segments with a bad checksum. */
+ } udp; /* UDP statistics. */
+#endif /* UIP_UDP */
+};
+
+/* The TCP and IP headers. */
+
+struct uip_tcpip_hdr {
+#ifdef CONFIG_NET_UIP_IPv6
+ /* IPv6 header. */
+
+ uint8 vtc,
+ tcflow;
+ uint16 flow;
+ uint8 len[2];
+ uint8 proto, ttl;
+ uip_ip6addr_t srcipaddr, destipaddr;
+#else /* CONFIG_NET_UIP_IPv6 */
+ /* IPv4 header. */
+
+ uint8 vhl,
+ tos,
+ len[2],
+ ipid[2],
+ ipoffset[2],
+ ttl,
+ proto;
+ uint16 ipchksum;
+ uint16 srcipaddr[2],
+ destipaddr[2];
+#endif /* CONFIG_NET_UIP_IPv6 */
+
+ /* TCP header. */
+
+ uint16 srcport,
+ destport;
+ uint8 seqno[4],
+ ackno[4],
+ tcpoffset,
+ flags,
+ wnd[2];
+ uint16 tcpchksum;
+ uint8 urgp[2];
+ uint8 optdata[4];
+};
+
+/* The ICMP and IP headers. */
+
+struct uip_icmpip_hdr {
+#ifdef CONFIG_NET_UIP_IPv6
+ /* IPv6 header. */
+
+ uint8 vtc,
+ tcf;
+ uint16 flow;
+ uint8 len[2];
+ uint8 proto, ttl;
+ uip_ip6addr_t srcipaddr, destipaddr;
+#else /* CONFIG_NET_UIP_IPv6 */
+ /* IPv4 header. */
+
+ uint8 vhl,
+ tos,
+ len[2],
+ ipid[2],
+ ipoffset[2],
+ ttl,
+ proto;
+ uint16 ipchksum;
+ uint16 srcipaddr[2],
+ destipaddr[2];
+#endif /* CONFIG_NET_UIP_IPv6 */
+
+ /* ICMP (echo) header. */
+ uint8 type, icode;
+ uint16 icmpchksum;
+#ifndef CONFIG_NET_UIP_IPv6
+ uint16 id, seqno;
+#else /* !CONFIG_NET_UIP_IPv6 */
+ uint8 flags, reserved1, reserved2, reserved3;
+ uint8 icmp6data[16];
+ uint8 options[1];
+#endif /* !CONFIG_NET_UIP_IPv6 */
+};
+
+/* The UDP and IP headers. */
+
+struct uip_udpip_hdr {
+#ifdef CONFIG_NET_UIP_IPv6
+ /* IPv6 header. */
+
+ uint8 vtc,
+ tcf;
+ uint16 flow;
+ uint8 len[2];
+ uint8 proto, ttl;
+ uip_ip6addr_t srcipaddr, destipaddr;
+#else /* CONFIG_NET_UIP_IPv6 */
+ /* IP header. */
+
+ uint8 vhl,
+ tos,
+ len[2],
+ ipid[2],
+ ipoffset[2],
+ ttl,
+ proto;
+ uint16 ipchksum;
+ uint16 srcipaddr[2],
+ destipaddr[2];
+#endif /* CONFIG_NET_UIP_IPv6 */
+
+ /* UDP header. */
+
+ uint16 srcport,
+ destport;
+ uint16 udplen;
+ uint16 udpchksum;
+};
+
+/* Representation of a 48-bit Ethernet address. */
+
+struct uip_eth_addr {
+ uint8 addr[6];
+};
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* The uIP packet buffer.
+ *
+ * The uip_buf array is used to hold incoming and outgoing
+ * packets. The device driver should place incoming data into this
+ * buffer. When sending data, the device driver should read the link
+ * level headers and the TCP/IP headers from this buffer. The size of
+ * the link level headers is configured by the UIP_LLH_LEN define.
+ *
+ * Note: The application data need not be placed in this buffer, so
+ * the device driver must read it from the place pointed to by the
+ * uip_appdata pointer as illustrated by the following example:
+ *
+ * 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);
+ * }
+ * }
+ */
+
+extern uint8 uip_buf[UIP_BUFSIZE+2];
+
+/* Pointer to the application data in the packet buffer.
+ *
+ * This pointer points to the application data when the application is
+ * called. If the application wishes to send data, the application may
+ * use this space to write the data into before calling uip_send().
+ */
+
+extern void *uip_appdata;
+
+#if UIP_URGDATA > 0
+/* uint8 *uip_urgdata:
+ *
+ * This pointer points to any urgent data that has been received. Only
+ * present if compiled with support for urgent data (UIP_URGDATA).
+ */
+extern void *uip_urgdata;
+#endif /* UIP_URGDATA > 0 */
+
+
+/* Variables used in uIP device drivers
+ *
+ * uIP has a few global variables that are used in device drivers for
+ * uIP.
+ *
+ * The length of the packet in the uip_buf buffer.
+ *
+ * The global variable uip_len holds the length of the packet in the
+ * uip_buf buffer.
+ *
+ * When the network device driver calls the uIP input function,
+ * uip_len should be set to the length of the packet in the uip_buf
+ * buffer.
+ *
+ * When sending packets, the device driver should use the contents of
+ * the uip_len variable to determine the length of the outgoing
+ * packet.
+ *
+ */
+
+extern uint16 uip_len;
+
+#if UIP_URGDATA > 0
+extern uint16 uip_urglen, uip_surglen;
+#endif /* UIP_URGDATA > 0 */
+
+/* Pointer to the current TCP connection.
+ *
+ * The uip_conn pointer can be used to access the current TCP
+ * connection.
+ */
+
+extern struct uip_conn *uip_conn;
+
+/* The array containing all uIP connections. */
+extern struct uip_conn uip_conns[UIP_CONNS];
+
+/* 4-byte array used for the 32-bit sequence number calculations.*/
+
+extern uint8 uip_acc32[4];
+
+/* The current UDP connection. */
+
+#if UIP_UDP
+extern struct uip_udp_conn *uip_udp_conn;
+extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
+#endif /* UIP_UDP */
+
+/* The uIP TCP/IP statistics.
+ *
+ * This is the variable in which the uIP TCP/IP statistics are gathered.
+ */
+
+extern struct uip_stats uip_stat;
+
+/* uint16 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.
+ */
+
+extern uint16 uip_flags;
+
+#if UIP_FIXEDADDR
+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 */
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/* uIP configuration functions
+ *
+ * The uIP configuration functions are used for setting run-time
+ * parameters in uIP such as IP addresses.
+ *
+ * Set the IP address of this host.
+ *
+ * The IP address is represented as a 4-byte array where the first
+ * octet of the IP address is put in the first member of the 4-byte
+ * array.
+ *
+ * Example:
+ *
+ * uip_ipaddr_t addr;
+ *
+ * uip_ipaddr(&addr, 192,168,1,2);
+ * uip_sethostaddr(&addr);
+ *
+ * addr A pointer to an IP address of type uip_ipaddr_t;
+ */
+
+#define uip_sethostaddr(addr) uip_ipaddr_copy(uip_hostaddr, (addr))
+
+/* Get the IP address of this host.
+ *
+ * The IP address is represented as a 4-byte array where the first
+ * octet of the IP address is put in the first member of the 4-byte
+ * array.
+ *
+ * Example:
+ *
+ * uip_ipaddr_t hostaddr;
+ *
+ * uip_gethostaddr(&hostaddr);
+ *
+ * addr A pointer to a uip_ipaddr_t variable that will be
+ * filled in with the currently configured IP address.
+ */
+
+#define uip_gethostaddr(addr) uip_ipaddr_copy((addr), uip_hostaddr)
+
+/* Set the default router's IP address.
+ *
+ * addr A pointer to a uip_ipaddr_t variable containing the IP
+ * address of the default router.
+ */
+
+#define uip_setdraddr(addr) uip_ipaddr_copy(uip_draddr, (addr))
+
+/* Set the netmask.
+ *
+ * addr A pointer to a uip_ipaddr_t variable containing the IP
+ * address of the netmask.
+ */
+
+#define uip_setnetmask(addr) uip_ipaddr_copy(uip_netmask, (addr))
+
+/* Get the default router's IP address.
+ *
+ * addr A pointer to a uip_ipaddr_t variable that will be
+ * filled in with the IP address of the default router.
+ */
+
+#define uip_getdraddr(addr) uip_ipaddr_copy((addr), uip_draddr)
+
+/* Get the netmask.
+ *
+ * addr A pointer to a uip_ipaddr_t variable that will be
+ * filled in with the value of the netmask.
+ */
+
+#define uip_getnetmask(addr) uip_ipaddr_copy((addr), uip_netmask)
+
+/* uIP initialization functions
+ *
+ * The uIP initialization functions are used for booting uIP.
+ *
+ * This function should be called at boot up to initilize the uIP
+ * TCP/IP stack.
+ */
+
+void uip_init(void);
+
+/* This function may be used at boot time to set the initial ip_id.*/
+
+void uip_setipid(uint16 id);
+
+/* uIP application functions
+ *
+ * Functions used by an application running of top of uIP. This includes
+ * functions for opening and closing connections, sending and receiving
+ * data, etc.
+ *
+ * The following function must be provided by the application logic. It
+ * is called from the UIP interrupt handler when interesting events are
+ * detected that may be of interest to the application.
+ */
+
+void uip_interrupt_event(void);
+#if UIP_UDP
+void uip_interrupt_udp_event(void);
+#endif
+
+/* Start listening to the specified port.
+ *
+ * Note: Since this function expects the port number in network byte
+ * order, a conversion using HTONS() or htons() is necessary.
+ *
+ * port A 16-bit port number in network byte order.
+ */
+
+void uip_listen(uint16 port);
+
+/* Stop listening to the specified port.
+ *
+ * Note: Since this function expects the port number in network byte
+ * order, a conversion using HTONS() or htons() is necessary.
+ *
+ * port A 16-bit port number in network byte order.
+ */
+
+void uip_unlisten(uint16 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,
+ * 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
+ * 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
+ * byte order, a conversion using HTONS() or htons() is necessary.
+ *
+ * Example:
+ *
+ * uip_ipaddr_t ipaddr;
+ *
+ * uip_ipaddr(&ipaddr, 192,168,1,2);
+ * uip_connect(&ipaddr, HTONS(80));
+ *
+ * ripaddr The IP address of the remote hot.
+ *
+ * port A 16-bit port number in network byte order.
+ *
+ * Return: A pointer to the uIP connection identifier for the new connection,
+ * or NULL if no connection could be allocated.
+ */
+
+struct uip_conn *uip_connect(uip_ipaddr_t *ripaddr, uint16 port);
+
+
+/* Check if a connection has outstanding (i.e., unacknowledged) data.
+ *
+ * conn A pointer to the uip_conn structure for the connection.
+ */
+
+#define uip_outstanding(conn) ((conn)->len)
+
+/* Send data on the current connection.
+ *
+ * This function is used to send out a single segment of TCP
+ * data. Only applications that have been invoked by uIP for event
+ * 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
+ * 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.
+ *
+ * Note: This function does not guarantee that the sent data will
+ * arrive at the destination. If the data is lost in the network, the
+ * application will be invoked with the uip_rexmit() event being
+ * set. The application will then have to resend the data using this
+ * function.
+ *
+ * data A pointer to the data which is to be sent.
+ *
+ * len The maximum amount of data bytes to be sent.
+ */
+
+void uip_send(const void *data, int len);
+
+/* The length of any incoming data that is currently avaliable (if avaliable)
+ * in the uip_appdata buffer.
+ *
+ * The test function uip_data() must first be used to check if there
+ * is any data available at all.
+ */
+
+#define uip_datalen() uip_len
+
+/* The length of any out-of-band data (urgent data) that has arrived
+ * on the connection.
+ *
+ * Note: The configuration parameter UIP_URGDATA must be set for this
+ * function to be enabled.
+ */
+
+#define uip_urgdatalen() uip_urglen
+
+/* Close the current connection.
+ *
+ * This function will close the current connection in a nice way.
+ */
+
+#define uip_close() (uip_flags = UIP_CLOSE)
+
+/* 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
+ * uip_close() function.
+ */
+
+#define uip_abort() (uip_flags = UIP_ABORT)
+
+/* Tell the sending host to stop sending data.
+ *
+ * This function will close our receiver's window so that we stop
+ * receiving data for the current connection.
+ */
+
+#define uip_stop() (uip_conn->tcpstateflags |= UIP_STOPPED)
+
+/* Find out if the current connection has been previously stopped with
+ * uip_stop().
+ */
+
+#define uip_stopped(conn) ((conn)->tcpstateflags & UIP_STOPPED)
+
+/* Restart the current connection, if is has previously been stopped
+ * with uip_stop().
+ *
+ * This function will open the receiver's window again so that we
+ * start receiving data for the current connection.
+ */
+
+#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
+ * connection is, and what the application function should do.
+ *
+ * Is the current connection a UDP connection?
+ *
+ * This function checks whether the current connection is a UDP connection.
+ */
+
+#define uip_udpconnection() (uip_conn == NULL)
+
+/* Is new incoming data available?
+ *
+ * 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.
+ */
+
+#define uip_newdata() (uip_flags & UIP_NEWDATA)
+
+/* Has previously sent data been acknowledged?
+ *
+ * Will reduce to non-zero if the previously sent data has been
+ * acknowledged by the remote host. This means that the application
+ * can send new data.
+ */
+
+#define uip_acked() (uip_flags & UIP_ACKDATA)
+
+/* Has the connection just been connected?
+ *
+ * Reduces to non-zero if the current connection has been connected to
+ * a remote host. This will happen both if the connection has been
+ * actively opened (with uip_connect()) or passively opened (with
+ * uip_listen()).
+ */
+
+#define uip_connected() (uip_flags & UIP_CONNECTED)
+
+/* Has the connection been closed by the other end?
+ *
+ * Is non-zero if the connection has been closed by the remote
+ * host. The application may then do the necessary clean-ups.
+ */
+
+#define uip_closed() (uip_flags & UIP_CLOSE)
+
+/* Has the connection been aborted by the other end?
+ *
+ * Non-zero if the current connection has been aborted (reset) by the
+ * remote host.
+ */
+
+#define uip_aborted() (uip_flags & UIP_ABORT)
+
+/* Has the connection timed out?
+ *
+ * Non-zero if the current connection has been aborted due to too many
+ * retransmissions.
+ */
+
+#define uip_timedout() (uip_flags & UIP_TIMEDOUT)
+
+/* Do we need to retransmit previously data?
+ *
+ * Reduces to non-zero if the previously sent data has been lost in
+ * the network, and the application should retransmit it. The
+ * application should send the exact same data as it did the last
+ * time, using the uip_send() function.
+ */
+
+#define uip_rexmit() (uip_flags & UIP_REXMIT)
+
+/* Is the connection being polled by uIP?
+ *
+ * Is non-zero if the reason the application is invoked is that the
+ * current connection has been idle for a while and should be
+ * polled.
+ *
+ * The polling event can be used for sending data without having to
+ * wait for the remote host to send data.
+ */
+
+#define uip_poll() (uip_flags & UIP_POLL)
+
+/* Get the initial maxium segment size (MSS) of the current
+ * connection.
+ */
+
+#define uip_initialmss() (uip_conn->initialmss)
+
+/* Get the current maxium segment size that can be sent on the current
+ * connection.
+ *
+ * The current maxiumum 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()).
+ */
+
+#define uip_mss() (uip_conn->mss)
+
+/* Set up a new UDP connection.
+ *
+ * This function sets up a new UDP connection. The function will
+ * automatically allocate an unused local port for the new
+ * connection. However, another port can be chosen by using the
+ * uip_udp_bind() call, after the uip_udp_new() function has been
+ * called.
+ *
+ * Example:
+ *
+ * uip_ipaddr_t addr;
+ * struct uip_udp_conn *c;
+ *
+ * uip_ipaddr(&addr, 192,168,2,1);
+ * c = uip_udp_new(&addr, HTONS(12345));
+ * if(c != NULL) {
+ * uip_udp_bind(c, HTONS(12344));
+ * }
+ *
+ * ripaddr The IP address of the remote host.
+ *
+ * rport The remote port number in network byte order.
+ *
+ * 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, uint16 rport);
+
+/* Removed a UDP connection.
+ *
+ * conn A pointer to the uip_udp_conn structure for the connection.
+ */
+
+#define uip_udp_remove(conn) (conn)->lport = 0
+
+/* Bind a UDP connection to a local port.
+ *
+ * conn A pointer to the uip_udp_conn structure for the
+ * connection.
+ *
+ * port The local port number, in network byte order.
+ */
+
+#define uip_udp_bind(conn, port) (conn)->lport = port
+
+/* Send a UDP datagram of length len on the current connection.
+ *
+ * This function can only be called in response to a UDP event (poll
+ * or newdata). The data must be present in the uip_buf buffer, at the
+ * place pointed to by the uip_appdata pointer.
+ *
+ * len The length of the data in the uip_buf buffer.
+ */
+
+#define uip_udp_send(len) uip_send((char *)uip_appdata, len)
+
+/* uIP convenience and converting functions.
+ *
+ * These functions can be used for converting between different data
+ * formats used by uIP.
+ *
+ * Construct an IP address from four bytes.
+ *
+ * This function constructs an IP address of the type that uIP handles
+ * internally from four bytes. The function is handy for specifying IP
+ * addresses to use with e.g. the uip_connect() function.
+ *
+ * Example:
+ *
+ * uip_ipaddr_t ipaddr;
+ * struct uip_conn *c;
+ *
+ * uip_ipaddr(&ipaddr, 192,168,1,2);
+ * c = uip_connect(&ipaddr, HTONS(80));
+ *
+ * addr A pointer to a uip_ipaddr_t variable that will be
+ * filled in with the IP address.
+ *
+ * addr0 The first octet of the IP address.
+ * addr1 The second octet of the IP address.
+ * addr2 The third octet of the IP address.
+ * addr3 The forth octet of the IP address.
+ */
+
+#define uip_ipaddr(addr, addr0,addr1,addr2,addr3) do { \
+ ((uint16 *)(addr))[0] = HTONS(((addr0) << 8) | (addr1)); \
+ ((uint16 *)(addr))[1] = HTONS(((addr2) << 8) | (addr3)); \
+ } while(0)
+
+/* Construct an IPv6 address from eight 16-bit words.
+ *
+ * This function constructs an IPv6 address.
+ */
+
+#define uip_ip6addr(addr, addr0,addr1,addr2,addr3,addr4,addr5,addr6,addr7) do { \
+ ((uint16 *)(addr))[0] = HTONS((addr0)); \
+ ((uint16 *)(addr))[1] = HTONS((addr1)); \
+ ((uint16 *)(addr))[2] = HTONS((addr2)); \
+ ((uint16 *)(addr))[3] = HTONS((addr3)); \
+ ((uint16 *)(addr))[4] = HTONS((addr4)); \
+ ((uint16 *)(addr))[5] = HTONS((addr5)); \
+ ((uint16 *)(addr))[6] = HTONS((addr6)); \
+ ((uint16 *)(addr))[7] = HTONS((addr7)); \
+ } while(0)
+
+/* Copy an IP address to another IP address.
+ *
+ * Copies an IP address from one place to another.
+ *
+ * Example:
+ *
+ * uip_ipaddr_t ipaddr1, ipaddr2;
+ *
+ * uip_ipaddr(&ipaddr1, 192,16,1,2);
+ * uip_ipaddr_copy(&ipaddr2, &ipaddr1);
+ *
+ * dest The destination for the copy.
+ * src The source from where to copy.
+ */
+
+#ifndef CONFIG_NET_UIP_IPv6
+#define uip_ipaddr_copy(dest, src) do { \
+ ((uint16 *)dest)[0] = ((uint16 *)src)[0]; \
+ ((uint16 *)dest)[1] = ((uint16 *)src)[1]; \
+ } while(0)
+#else /* !CONFIG_NET_UIP_IPv6 */
+#define uip_ipaddr_copy(dest, src) memcpy(dest, src, sizeof(uip_ip6addr_t))
+#endif /* !CONFIG_NET_UIP_IPv6 */
+
+/* Compare two IP addresses
+ *
+ * Example:
+ *
+ * uip_ipaddr_t ipaddr1, ipaddr2;
+ *
+ * uip_ipaddr(&ipaddr1, 192,16,1,2);
+ * if(uip_ipaddr_cmp(&ipaddr2, &ipaddr1)) {
+ * printf("They are the same");
+ * }
+ *
+ * addr1 The first IP address.
+ * addr2 The second IP address.
+ */
+
+#ifndef CONFIG_NET_UIP_IPv6
+#define uip_ipaddr_cmp(addr1, addr2) (((uint16 *)addr1)[0] == ((uint16 *)addr2)[0] && \
+ ((uint16 *)addr1)[1] == ((uint16 *)addr2)[1])
+#else /* !CONFIG_NET_UIP_IPv6 */
+#define uip_ipaddr_cmp(addr1, addr2) (memcmp(addr1, addr2, sizeof(uip_ip6addr_t)) == 0)
+#endif /* !CONFIG_NET_UIP_IPv6 */
+
+/**
+ * Compare two IP addresses with netmasks
+ *
+ * Compares two IP addresses with netmasks. The masks are used to mask
+ * out the bits that are to be compared.
+ *
+ * Example:
+ *
+ * uip_ipaddr_t ipaddr1, ipaddr2, mask;
+ *
+ * uip_ipaddr(&mask, 255,255,255,0);
+ * 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");
+ * }
+ *
+ * addr1 The first IP address.
+ * addr2 The second IP address.
+ * mask The netmask.
+ */
+
+#define uip_ipaddr_maskcmp(addr1, addr2, mask) \
+ (((((uint16 *)addr1)[0] & ((uint16 *)mask)[0]) == \
+ (((uint16 *)addr2)[0] & ((uint16 *)mask)[0])) && \
+ ((((uint16 *)addr1)[1] & ((uint16 *)mask)[1]) == \
+ (((uint16 *)addr2)[1] & ((uint16 *)mask)[1])))
+
+
+/**
+ * Mask out the network part of an IP address.
+ *
+ * Masks out the network part of an IP address, given the address and
+ * the netmask.
+ *
+ * Example:
+ *
+ * uip_ipaddr_t ipaddr1, ipaddr2, netmask;
+ *
+ * uip_ipaddr(&ipaddr1, 192,16,1,2);
+ * uip_ipaddr(&netmask, 255,255,255,0);
+ * uip_ipaddr_mask(&ipaddr2, &ipaddr1, &netmask);
+ *
+ * In the example above, the variable "ipaddr2" will contain the IP
+ * address 192.168.1.0.
+ *
+ * dest Where the result is to be placed.
+ * src The IP address.
+ * mask The netmask.
+ */
+
+#define uip_ipaddr_mask(dest, src, mask) do { \
+ ((uint16 *)dest)[0] = ((uint16 *)src)[0] & ((uint16 *)mask)[0]; \
+ ((uint16 *)dest)[1] = ((uint16 *)src)[1] & ((uint16 *)mask)[1]; \
+ } while(0)
+
+/* Pick the first octet of an IP address.
+ *
+ * Picks out the first octet of an IP address.
+ *
+ * Example:
+ *
+ * uip_ipaddr_t ipaddr;
+ * uint8 octet;
+ *
+ * uip_ipaddr(&ipaddr, 1,2,3,4);
+ * octet = uip_ipaddr1(&ipaddr);
+ *
+ * In the example above, the variable "octet" will contain the value 1.
+ */
+
+#define uip_ipaddr1(addr) (htons(((uint16 *)(addr))[0]) >> 8)
+
+/* Pick the second octet of an IP address.
+ *
+ * Picks out the second octet of an IP address.
+ *
+ * Example:
+ *
+ * uip_ipaddr_t ipaddr;
+ * uint8 octet;
+ *
+ * uip_ipaddr(&ipaddr, 1,2,3,4);
+ * octet = uip_ipaddr2(&ipaddr);
+ *
+ * In the example above, the variable "octet" will contain the value 2.
+ */
+
+#define uip_ipaddr2(addr) (htons(((uint16 *)(addr))[0]) & 0xff)
+
+/* Pick the third octet of an IP address.
+ *
+ * Picks out the third octet of an IP address.
+ *
+ * Example:
+ *
+ * uip_ipaddr_t ipaddr;
+ * uint8 octet;
+ *
+ * uip_ipaddr(&ipaddr, 1,2,3,4);
+ * octet = uip_ipaddr3(&ipaddr);
+ *
+ * In the example above, the variable "octet" will contain the value 3.
+ */
+
+#define uip_ipaddr3(addr) (htons(((uint16 *)(addr))[1]) >> 8)
+
+/* Pick the fourth octet of an IP address.
+ *
+ * Picks out the fourth octet of an IP address.
+ *
+ * Example:
+ *
+ * uip_ipaddr_t ipaddr;
+ * uint8 octet;
+ *
+ * uip_ipaddr(&ipaddr, 1,2,3,4);
+ * octet = uip_ipaddr4(&ipaddr);
+ *
+ * In the example above, the variable "octet" will contain the value 4.
+ */
+
+#define uip_ipaddr4(addr) (htons(((uint16 *)(addr))[1]) & 0xff)
+
+/* Convert 16-bit quantity from host byte order to network byte order.
+ *
+ * This macro is primarily used for converting constants from host
+ * byte order to network byte order. For converting variables to
+ * network byte order, use the htons() function instead.
+ */
+
+#ifndef HTONS
+# if UIP_BYTE_ORDER == UIP_BIG_ENDIAN
+# define HTONS(n) (n)
+# else /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */
+# define HTONS(n) (uint16)((((uint16) (n)) << 8) | (((uint16) (n)) >> 8))
+# endif /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */
+#else
+#error "HTONS already defined!"
+#endif /* HTONS */
+
+/* Convert 16-bit quantity from host byte order to network byte order.
+ *
+ * This function is primarily used for converting variables from host
+ * byte order to network byte order. For converting constants to
+ * network byte order, use the HTONS() macro instead.
+ */
+
+#ifndef htons
+uint16 htons(uint16 val);
+#endif /* htons */
+#ifndef ntohs
+#define ntohs htons
+#endif
+
+/* This function is called user code to set up the wait */
+
+#define uip_event_wait(waitflags) uip_event_timedwait(waitflags,0)
+extern int uip_event_timedwait(uint16 waitflags, int timeout);
+
+/* This function is called from uip_interrupt() to wake up any
+ * waiting threads/tasks.
+ */
+
+extern void uip_event_signal(void);
+
+#endif /* __UIP_H__ */
diff --git a/nuttx/include/net/uip/uipopt.h b/nuttx/include/net/uip/uipopt.h
new file mode 100644
index 000000000..1e468f6d8
--- /dev/null
+++ b/nuttx/include/net/uip/uipopt.h
@@ -0,0 +1,423 @@
+/****************************************************************************
+ * uipopt.h
+ * Configuration options for uIP.
+ * author Adam Dunkels <adam@dunkels.com>
+ *
+ * This file is used for tweaking various configuration options for
+ * uIP. You should make a copy of this file into one of your project's
+ * directories instead of editing this example "uipopt.h" file that
+ * comes with the uIP distribution.
+ *
+ * uIP is configured using the per-project configuration file
+ * 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 defconfig file.
+ *
+ * Copyright (c) 2001-2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: uipopt.h,v 1.1.1.1 2007-08-26 23:12:17 patacongo Exp $
+ *
+ */
+
+#ifndef __UIPOPT_H__
+#define __UIPOPT_H__
+
+#include <sys/types.h>
+#include <nuttx/config.h>
+
+/*------------------------------------------------------------------------------*/
+
+/**
+ * \name 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
+ * if uIP should be run over Ethernet.
+ *
+ * All of these should be changed to suit your project.
+*/
+
+/**
+ * Statistics datatype
+ *
+ * This typedef defines the dataype used for keeping statistics in
+ * uIP.
+ */
+typedef uint16 uip_stats_t;
+
+/**
+ * Determines if uIP should use a fixed IP address or not.
+ *
+ * If uIP should use a fixed IP address, the settings are set in the
+ * uipopt.h file. If not, the macros uip_sethostaddr(),
+ * uip_setdraddr() and uip_setnetmask() should be used instead.
+ */
+#define UIP_FIXEDADDR 0
+
+/**
+ * Ping IP address asignment.
+ *
+ * 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
+ * the destination IP address of the first incoming "ping" (ICMP echo)
+ * packet will be used for setting the hosts IP address.
+ *
+ * \note This works only if UIP_FIXEDADDR is 0.
+ */
+
+#ifdef CONFIG_UIP_PINGADDRCONF
+#define UIP_PINGADDRCONF CONFIG_UIP_PINGADDRCONF
+#else /* CONFIG_UIP_PINGADDRCONF */
+#define UIP_PINGADDRCONF 0
+#endif /* CONFIG_UIP_PINGADDRCONF */
+
+/**
+ * Specifies if the uIP ARP module should be compiled with a fixed
+ * Ethernet MAC address or not.
+ *
+ * If this configuration option is 0, the macro uip_setethaddr() can
+ * be used to specify the Ethernet address at run-time.
+ */
+#define UIP_FIXEDETHADDR 0
+
+/*------------------------------------------------------------------------------*/
+/**
+ * \name IP configuration options
+ */
+/**
+ * The IP TTL (time to live) of IP packets sent by uIP.
+ *
+ * This should normally not be changed.
+ */
+#define UIP_TTL 64
+
+/**
+ * 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
+ * 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).
+ *
+ * \note IP packet reassembly is not heavily tested.
+ */
+#define UIP_REASSEMBLY 0
+
+/**
+ * The maximum time an IP fragment should wait in the reassembly
+ * buffer before it is dropped.
+ *
+ */
+#define UIP_REASS_MAXAGE 40
+
+/*------------------------------------------------------------------------------*/
+/**
+ * \name UDP configuration options
+ */
+
+/**
+ * Toggles wether UDP support should be compiled in or not.
+ */
+#ifdef CONFIG_UIP_UDP
+# define UIP_UDP CONFIG_UIP_UDP
+#else /* CONFIG_UIP_UDP */
+# define UIP_UDP 0
+#endif /* CONFIG_UIP_UDP */
+
+/**
+ * Toggles if UDP checksums should be used or not.
+ *
+ * \note Support for UDP checksums is currently not included in uIP,
+ * so this option has no function.
+ */
+#ifdef CONFIG_UIP_UDP_CHECKSUMS
+# define UIP_UDP_CHECKSUMS CONFIG_UIP_UDP_CHECKSUMS
+#else
+# define UIP_UDP_CHECKSUMS 0
+#endif
+
+/**
+ * The maximum amount of concurrent UDP connections.
+ */
+#ifdef CONFIG_UIP_UDP_CONNS
+# define UIP_UDP_CONNS CONFIG_UIP_UDP_CONNS
+#else /* CONFIG_UIP_UDP_CONNS */
+# define UIP_UDP_CONNS 10
+#endif /* CONFIG_UIP_UDP_CONNS */
+
+/**
+ * The name of the function that should be called when UDP datagrams arrive.
+ */
+
+
+/*------------------------------------------------------------------------------*/
+/**
+ * \name TCP configuration options
+ */
+
+/**
+ * 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
+ * option can be turned off to reduce the code size of uIP.
+ */
+#define UIP_ACTIVE_OPEN 1
+
+/**
+ * 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.
+ */
+#ifndef CONFIG_UIP_MAX_CONNECTIONS
+# define UIP_CONNS 10
+#else /* CONFIG_UIP_MAX_CONNECTIONS */
+# define UIP_CONNS CONFIG_UIP_MAX_CONNECTIONS
+#endif /* CONFIG_UIP_MAX_CONNECTIONS */
+
+/**
+ * The maximum number of simultaneously listening TCP ports.
+ *
+ * Each listening TCP port requires 2 bytes of memory.
+ */
+#ifndef CONFIG_UIP_MAX_LISTENPORTS
+# define UIP_LISTENPORTS 20
+#else /* CONFIG_UIP_MAX_LISTENPORTS */
+# define UIP_LISTENPORTS CONFIG_UIP_MAX_LISTENPORTS
+#endif /* CONFIG_UIP_MAX_LISTENPORTS */
+
+/**
+ * Determines if support for TCP urgent data notification should be
+ * compiled in.
+ *
+ * Urgent data (out-of-band data) is a rarely used TCP feature that
+ * very seldom would be required.
+ */
+#define UIP_URGDATA 0
+
+/**
+ * The initial retransmission timeout counted in timer pulses.
+ *
+ * This should not be changed.
+ */
+#define UIP_RTO 3
+
+/**
+ * The maximum number of times a segment should be retransmitted
+ * before the connection should be aborted.
+ *
+ * This should not be changed.
+ */
+#define UIP_MAXRTX 8
+
+/**
+ * The maximum number of times a SYN segment should be retransmitted
+ * before a connection request should be deemed to have been
+ * unsuccessful.
+ *
+ * This should not need to be changed.
+ */
+#define UIP_MAXSYNRTX 5
+
+/**
+ * The TCP maximum segment size.
+ *
+ * This is should not be to set to more than
+ * UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN.
+ */
+#define UIP_TCP_MSS (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN)
+
+/**
+ * The size of the advertised receiver's window.
+ *
+ * Should be set low (i.e., to the size of the uip_buf buffer) is the
+ * application is slow to process incoming data, or high (32768 bytes)
+ * if the application processes data quickly.
+ */
+#ifndef CONFIG_UIP_RECEIVE_WINDOW
+# define UIP_RECEIVE_WINDOW UIP_TCP_MSS
+#else
+# define UIP_RECEIVE_WINDOW CONFIG_UIP_RECEIVE_WINDOW
+#endif
+
+/**
+ * How long a connection should stay in the TIME_WAIT state.
+ *
+ * This configiration option has no real implication, and it should be
+ * left untouched.
+ */
+#define UIP_TIME_WAIT_TIMEOUT 120
+
+
+/*------------------------------------------------------------------------------*/
+/**
+ * \name ARP configuration options
+ */
+
+/**
+ * The size of the ARP table.
+ *
+ * This option should be set to a larger value if this uIP node will
+ * have many connections from the local network.
+ */
+#ifdef CONFIG_UIP_ARPTAB_SIZE
+# define UIP_ARPTAB_SIZE CONFIG_UIP_ARPTAB_SIZE
+#else
+# define UIP_ARPTAB_SIZE 8
+#endif
+
+/**
+ * The maxium 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
+
+/*------------------------------------------------------------------------------*/
+
+/**
+ * \name General configuration options
+ */
+
+/**
+ * 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
+ * TCP throughput, larger size results in higher TCP throughput.
+ */
+#ifndef CONFIG_UIP_BUFFER_SIZE
+# define UIP_BUFSIZE 400
+#else /* CONFIG_UIP_BUFFER_SIZE */
+# define UIP_BUFSIZE CONFIG_UIP_BUFFER_SIZE
+#endif /* CONFIG_UIP_BUFFER_SIZE */
+
+
+/**
+ * Determines if statistics support should be compiled in.
+ *
+ * The statistics is useful for debugging and to show the user.
+ */
+
+#ifndef CONFIG_UIP_STATISTICS
+# define UIP_STATISTICS 0
+#else /* CONFIG_UIP_STATISTICS */
+# define UIP_STATISTICS CONFIG_UIP_STATISTICS
+#endif /* CONFIG_UIP_STATISTICS */
+
+/**
+ * Determines if logging of certain events should be compiled in.
+ *
+ * This is useful mostly for debugging. The function uip_log()
+ * must be implemented to suit the architecture of the project, if
+ * logging is turned on.
+ */
+
+#ifndef CONFIG_UIP_LOGGING
+# define UIP_LOGGING 0
+#else /* CONFIG_UIP_LOGGING */
+# define UIP_LOGGING CONFIG_UIP_LOGGING
+#endif /* CONFIG_UIP_LOGGING */
+
+/**
+ * Broadcast support.
+ *
+ * This flag configures IP broadcast support. This is useful only
+ * together with UDP.
+ */
+
+#ifndef CONFIG_UIP_BROADCAST
+# define UIP_BROADCAST 0
+#else /* CONFIG_UIP_BROADCAST */
+# define UIP_BROADCAST CONFIG_UIP_BROADCAST
+#endif /* CONFIG_UIP_BROADCAST */
+
+/**
+ * Print out a uIP log message.
+ *
+ * This function must be implemented by the module that uses uIP, and
+ * is called by uIP whenever a log message is generated.
+ */
+void uip_log(char *msg);
+
+/**
+ * The link level header length.
+ *
+ * This is the offset into the uip_buf where the IP header can be
+ * found. For Ethernet, this should be set to 14. For SLIP, this
+ * should be set to 0.
+ */
+
+#ifdef CONFIG_UIP_LLH_LEN
+# define UIP_LLH_LEN CONFIG_UIP_LLH_LEN
+#else /* CONFIG_UIP_LLH_LEN */
+# define UIP_LLH_LEN 14
+#endif /* CONFIG_UIP_LLH_LEN */
+
+/*------------------------------------------------------------------------------*/
+/**
+ * \name CPU architecture configuration
+ *
+ * The CPU architecture configuration is where the endianess of the
+ * CPU on which uIP is to be run is specified. Most CPUs today are
+ * little endian, and the most notable exception are the Motorolas
+ * which are big endian. The CONFIG_ENDIAN_BIG macro should be changed
+ * if uIP is to be run on a big endian architecture.
+ */
+
+/**
+ * The byte order of the CPU architecture on which uIP is to be run.
+ *
+ * This option can be either CONFIG_ENDIAN_BIG (Motorola byte order) or
+ * default little endian byte order (Intel byte order).
+ */
+
+#define UIP_BIG_ENDIAN 1234
+#define UIP_LITTLE_ENDIAN 3412
+
+#ifdef CONFIG_ENDIAN_BIG
+# define UIP_BYTE_ORDER UIP_BIG_ENDIAN
+#else
+# define UIP_BYTE_ORDER UIP_LITTLE_ENDIAN
+#endif
+
+#endif /* __UIPOPT_H__ */
diff --git a/nuttx/net/Makefile b/nuttx/net/Makefile
new file mode 100644
index 000000000..5aeacc213
--- /dev/null
+++ b/nuttx/net/Makefile
@@ -0,0 +1,86 @@
+############################################################
+# Makefile
+#
+# Copyright (C) 2007 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name Gregory Nutt nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################
+
+-include $(TOPDIR)/Make.defs
+
+MKDEP = $(TOPDIR)/tools/mkdeps.sh
+
+ifeq ($(CONFIG_NET_UIP),y)
+include uip/Make.defs
+endif
+
+ASRCS = $(UIP_ASRCS)
+AOBJS = $(ASRCS:.S=$(OBJEXT))
+
+CSRCS = $(UIP_CSRCS)
+COBJS = $(CSRCS:.c=$(OBJEXT))
+
+SRCS = $(ASRCS) $(CSRCS)
+OBJS = $(AOBJS) $(COBJS)
+
+BIN = libnet$(LIBEXT)
+
+VPATH = uip
+
+all: $(BIN)
+
+$(AOBJS): %$(OBJEXT): %.S
+ $(CC) -c $(CFLAGS) -D__ASSEMBLY__ $< -o $@
+
+$(COBJS): %$(OBJEXT): %.c
+ $(CC) -c $(CFLAGS) $< -o $@
+
+$(BIN): $(OBJS)
+ ( for obj in $(OBJS) ; do \
+ $(AR) $@ $${obj} || \
+ { echo "$(AR) $@ $obj FAILED!" ; exit 1 ; } ; \
+ done ; )
+
+.depend: Makefile $(SRCS)
+ifeq ($(CONFIG_NET_UIP),y)
+ $(MKDEP) --dep-path uip $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep
+endif
+ touch $@
+
+depend: .depend
+
+clean:
+ rm -f $(BIN) *.o *.rel *.asm *.lst *.sym *.adb *~
+ if [ ! -z "$(OBJEXT)" ]; then rm -f *$(OBJEXT); fi
+
+distclean: clean
+ rm -f Make.dep .depend
+
+-include Make.dep
diff --git a/nuttx/net/uip/.psock.h.swo b/nuttx/net/uip/.psock.h.swo
new file mode 100644
index 000000000..9daa59748
--- /dev/null
+++ b/nuttx/net/uip/.psock.h.swo
Binary files differ
diff --git a/nuttx/net/uip/Make.defs b/nuttx/net/uip/Make.defs
new file mode 100644
index 000000000..85d61d0d9
--- /dev/null
+++ b/nuttx/net/uip/Make.defs
@@ -0,0 +1,38 @@
+############################################################################
+# Make.defs
+#
+# Copyright (C) 2007 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name Gregory Nutt nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+UIP_ASRCS =
+UIP_CSRCS = psock.c uip-arp.c uip.c uip-fw.c uip-neighbor.c uip-split.c uip-wait.c
+
diff --git a/nuttx/net/uip/psock.c b/nuttx/net/uip/psock.c
new file mode 100644
index 000000000..892c97602
--- /dev/null
+++ b/nuttx/net/uip/psock.c
@@ -0,0 +1,377 @@
+/*
+ * 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.1.1.1 2007-08-26 23:04:11 patacongo Exp $
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+#include <debug.h>
+
+#include <net/uip/uip.h>
+#include <net/uip/uipopt.h>
+#include <net/uip/psock.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, uint8 *bufptr, uint16 bufsize)
+{
+ buf->ptr = bufptr;
+ buf->left = bufsize;
+}
+
+static uint8 buf_bufdata(struct psock_buf *buf, uint16 len, uint8 **dataptr, uint16 *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 uint8 buf_bufto(struct psock_buf *buf, uint8 endmarker, uint8 **dataptr, uint16 *datalen)
+{
+ uint8 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 boolean send_data(register struct psock *s)
+{
+ /* Inidicate that we are blocked waiting for the send to complete */
+
+ s->state = STATE_BLOCKED_SEND;
+
+ /* Loop until we successfully send the data */
+
+ for (;;)
+ {
+ /* If the data has not been sent OR if it needs to be retransmitted,
+ * then send it now.
+ */
+
+ 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;
+ }
+
+ /* Check if all data has been sent and acknowledged */
+
+ if (s->state == STATE_DATA_SENT && uip_acked())
+ {
+ /* Yes.. the data has been sent AND acknowledge */
+
+ 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 TRUE;
+ }
+
+ /* No.. then wait on the retransmit or acked events */
+
+ (void)uip_event_wait(UIP_ACKDATA|UIP_REXMIT);
+ }
+
+ return FALSE; /* We never get here */
+}
+
+void psock_send(struct psock *s, const char *buf, unsigned int len)
+{
+ /* If there is no data to send, we exit immediately. */
+
+ if (len > 0)
+ {
+ /* Save the length of and a pointer to the data that is to be sent. */
+
+ s->sendptr = (const uint8*)buf;
+ s->sendlen = len;
+ s->state = STATE_NONE;
+
+ /* Loop here until all data is sent. The s->sendlen variable is updated
+ * by the data_sent() function.
+ */
+
+ while(s->sendlen > 0) {
+
+ /* Wait until the data has been sent and acknowledged */
+
+ send_data(s);
+ }
+
+ /* Done */
+
+ s->state = STATE_NONE;
+ }
+}
+
+void psock_generator_send(register struct psock *s, unsigned short (*generate)(void *), void *arg)
+{
+ /* Ensure that there is a generator function to call. */
+
+ if (generate != NULL)
+ {
+ /* 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. */
+
+ send_data(s);
+ }
+ while(s->sendlen > 0);
+
+ /* Done */
+
+ s->state = STATE_NONE;
+ }
+}
+
+uint16 psock_datalen(struct psock *psock)
+{
+ return psock->bufsize - psock->buf.left;
+}
+
+boolean psock_checknewdata(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 TRUE;
+ }
+ else if (s->state == STATE_READ)
+ {
+ /* All data in uip_appdata buffer already consumed. */
+
+ s->state = STATE_BLOCKED_NEWDATA;
+ return FALSE;
+ }
+ else if (uip_newdata())
+ {
+ /* There is new data that has not been consumed. */
+
+ return TRUE;
+ }
+ else
+ {
+ /* There is no new data. */
+
+ return FALSE;
+ }
+}
+
+void psock_waitnewdata(struct psock *s)
+{
+ while (!psock_checknewdata(s))
+ {
+ uip_event_wait(UIP_NEWDATA);
+ }
+}
+
+void psock_readto(register struct psock *psock, unsigned char c)
+{
+restart:
+ 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)
+ {
+ psock_waitnewdata(psock);
+ psock->state = STATE_READ;
+ psock->readptr = (uint8 *)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;
+ goto restart;
+ }
+}
+
+void psock_readbuf(register struct psock *psock)
+{
+restart:
+ 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)
+ {
+ psock_waitnewdata(psock);
+ dbg("Waited for newdata\n");
+ psock->state = STATE_READ;
+ psock->readptr = (uint8 *)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;
+ goto restart;
+ }
+}
+
+void psock_init(register struct psock *psock, char *buffer, unsigned int buffersize)
+{
+ psock->state = STATE_NONE;
+ psock->readlen = 0;
+ psock->bufptr = (uint8*)buffer;
+ psock->bufsize = buffersize;
+ buf_setup(&psock->buf, (uint8*)buffer, buffersize);
+}
diff --git a/nuttx/net/uip/uip-arp.c b/nuttx/net/uip/uip-arp.c
new file mode 100644
index 000000000..f27f5bb2e
--- /dev/null
+++ b/nuttx/net/uip/uip-arp.c
@@ -0,0 +1,405 @@
+/* uip-arp.c
+ * Implementation of the ARP Address Resolution Protocol.
+ * Author: Adam Dunkels <adam@dunkels.com>
+ *
+ * The Address Resolution Protocol ARP is used for mapping between IP
+ * addresses and link level addresses such as the Ethernet MAC
+ * addresses. ARP uses broadcast queries to ask for the link level
+ * address of a known IP address and the host which is configured with
+ * the IP address for which the query was meant, will respond with its
+ * link level address.
+ *
+ * Note: This ARP implementation only supports Ethernet.
+ *
+ * Copyright (c) 2001-2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <string.h>
+#include <net/uip/uip-arp.h>
+
+struct arp_hdr
+{
+ struct uip_eth_hdr ethhdr;
+ uint16 hwtype;
+ uint16 protocol;
+ uint8 hwlen;
+ uint8 protolen;
+ uint16 opcode;
+ struct uip_eth_addr shwaddr;
+ uint16 sipaddr[2];
+ struct uip_eth_addr dhwaddr;
+ uint16 dipaddr[2];
+};
+
+struct ethip_hdr {
+ struct uip_eth_hdr ethhdr;
+ /* IP header. */
+ uint8 vhl,
+ tos,
+ len[2],
+ ipid[2],
+ ipoffset[2],
+ ttl,
+ proto;
+ uint16 ipchksum;
+ uint16 srcipaddr[2],
+ destipaddr[2];
+};
+
+#define ARP_REQUEST 1
+#define ARP_REPLY 2
+
+#define ARP_HWTYPE_ETH 1
+
+struct arp_entry {
+ uint16 ipaddr[2];
+ struct uip_eth_addr ethaddr;
+ uint8 time;
+};
+
+static const struct uip_eth_addr broadcast_ethaddr =
+ {{0xff,0xff,0xff,0xff,0xff,0xff}};
+static const uint16 broadcast_ipaddr[2] = {0xffff,0xffff};
+
+static struct arp_entry arp_table[UIP_ARPTAB_SIZE];
+static uint16 ipaddr[2];
+static uint8 i, c;
+
+static uint8 arptime;
+static uint8 tmpage;
+
+#define BUF ((struct arp_hdr *)&uip_buf[0])
+#define IPBUF ((struct ethip_hdr *)&uip_buf[0])
+/*-----------------------------------------------------------------------------------*/
+/**
+ * Initialize the ARP module.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+uip_arp_init(void)
+{
+ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
+ memset(arp_table[i].ipaddr, 0, 4);
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+/**
+ * Periodic ARP processing function.
+ *
+ * This function performs periodic timer processing in the ARP module
+ * and should be called at regular intervals. The recommended interval
+ * is 10 seconds between the calls.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+uip_arp_timer(void)
+{
+ struct arp_entry *tabptr;
+
+ ++arptime;
+ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
+ tabptr = &arp_table[i];
+ if((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 &&
+ arptime - tabptr->time >= UIP_ARP_MAXAGE) {
+ memset(tabptr->ipaddr, 0, 4);
+ }
+ }
+
+}
+
+/*-----------------------------------------------------------------------------------*/
+static void
+uip_arp_update(uint16 *pipaddr, struct uip_eth_addr *ethaddr)
+{
+ register struct arp_entry *tabptr;
+ /* Walk through the ARP mapping table and try to find an entry to
+ update. If none is found, the IP -> MAC address mapping is
+ inserted in the ARP table. */
+ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
+
+ tabptr = &arp_table[i];
+ /* Only check those entries that are actually in use. */
+ if(tabptr->ipaddr[0] != 0 &&
+ tabptr->ipaddr[1] != 0) {
+
+ /* Check if the source IP address of the incoming packet matches
+ the IP address in this ARP table entry. */
+ if(pipaddr[0] == tabptr->ipaddr[0] &&
+ pipaddr[1] == tabptr->ipaddr[1]) {
+
+ /* An old entry found, update this and return. */
+ memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
+ tabptr->time = arptime;
+
+ return;
+ }
+ }
+ }
+
+ /* If we get here, no existing ARP table entry was found, so we
+ create one. */
+
+ /* 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) {
+ break;
+ }
+ }
+
+ /* If no unused entry is found, we try to find the oldest entry and
+ throw it away. */
+ if(i == UIP_ARPTAB_SIZE) {
+ tmpage = 0;
+ c = 0;
+ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
+ tabptr = &arp_table[i];
+ if(arptime - tabptr->time > tmpage) {
+ tmpage = arptime - tabptr->time;
+ c = i;
+ }
+ }
+ i = c;
+ tabptr = &arp_table[i];
+ }
+
+ /* Now, i is the ARP table entry which we will fill with the new
+ information. */
+ memcpy(tabptr->ipaddr, pipaddr, 4);
+ memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
+ tabptr->time = arptime;
+}
+/*-----------------------------------------------------------------------------------*/
+/**
+ * ARP processing for incoming IP packets
+ *
+ * This function should be called by the device driver when an IP
+ * packet has been received. The function will check if the address is
+ * in the ARP cache, and if so the ARP cache entry will be
+ * refreshed. If no ARP cache entry was found, a new one is created.
+ *
+ * This function expects an IP packet with a prepended Ethernet header
+ * in the uip_buf[] buffer, and the length of the packet in the global
+ * variable uip_len.
+ */
+/*-----------------------------------------------------------------------------------*/
+#if 0
+void
+uip_arp_ipin(void)
+{
+ uip_len -= sizeof(struct uip_eth_hdr);
+
+ /* Only insert/update an entry if the source IP address of the
+ incoming IP packet comes from a host on the local network. */
+ if((IPBUF->srcipaddr[0] & uip_netmask[0]) !=
+ (uip_hostaddr[0] & uip_netmask[0])) {
+ return;
+ }
+ if((IPBUF->srcipaddr[1] & uip_netmask[1]) !=
+ (uip_hostaddr[1] & uip_netmask[1])) {
+ return;
+ }
+ uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src));
+
+ return;
+}
+#endif /* 0 */
+/*-----------------------------------------------------------------------------------*/
+/**
+ * ARP processing for incoming ARP packets.
+ *
+ * This function should be called by the device driver when an ARP
+ * packet has been received. The function will act differently
+ * depending on the ARP packet type: if it is a reply for a request
+ * that we previously sent out, the ARP cache will be filled in with
+ * the values from the ARP reply. If the incoming ARP packet is an ARP
+ * request for our IP address, an ARP reply packet is created and put
+ * into the uip_buf[] buffer.
+ *
+ * When the function returns, the value of the global variable uip_len
+ * indicates whether the device driver should send out a packet or
+ * not. If uip_len is zero, no packet should be sent. If uip_len is
+ * non-zero, it contains the length of the outbound packet that is
+ * present in the uip_buf[] buffer.
+ *
+ * This function expects an ARP packet with a prepended Ethernet
+ * header in the uip_buf[] buffer, and the length of the packet in the
+ * global variable uip_len.
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+uip_arp_arpin(void)
+{
+
+ if(uip_len < sizeof(struct arp_hdr)) {
+ uip_len = 0;
+ return;
+ }
+ uip_len = 0;
+
+ switch(BUF->opcode) {
+ 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)) {
+ /* 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);
+
+ /* The reply opcode is 2. */
+ BUF->opcode = HTONS(2);
+
+ 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];
+
+ BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
+ uip_len = sizeof(struct arp_hdr);
+ }
+ break;
+ 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);
+ }
+ break;
+ }
+
+ return;
+}
+/*-----------------------------------------------------------------------------------*/
+/**
+ * Prepend Ethernet header to an outbound IP packet and see if we need
+ * to send out an ARP request.
+ *
+ * This function should be called before sending out an IP packet. The
+ * function checks the destination IP address of the IP packet to see
+ * what Ethernet MAC address that should be used as a destination MAC
+ * address on the Ethernet.
+ *
+ * If the destination IP address is in the local network (determined
+ * by logical ANDing of netmask and our IP address), the function
+ * checks the ARP cache to see if an entry for the destination IP
+ * address is found. If so, an Ethernet header is prepended and the
+ * function returns. If no ARP cache entry is found for the
+ * destination IP address, the packet in the uip_buf[] is replaced by
+ * an ARP request packet for the IP address. The IP packet is dropped
+ * and it is assumed that they higher level protocols (e.g., TCP)
+ * eventually will retransmit the dropped packet.
+ *
+ * If the destination IP address is not on the local network, the IP
+ * address of the default router is used instead.
+ *
+ * When the function returns, a packet is present in the uip_buf[]
+ * buffer, and the length of the packet is in the global variable
+ * uip_len.
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+uip_arp_out(void)
+{
+ struct arp_entry *tabptr;
+
+ /* Find the destination IP address in the ARP table and construct
+ the Ethernet header. If the destination IP addres isn't on the
+ local network, we use the default router's IP address instead.
+
+ If not ARP table entry is found, we overwrite the original IP
+ 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)) {
+ 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)) {
+ /* 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);
+ } else {
+ /* Else, we use the destination IP address. */
+ 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)) {
+ break;
+ }
+ }
+
+ if(i == UIP_ARPTAB_SIZE) {
+ /* The destination address was not in our ARP table, so we
+ overwrite the IP packet with an ARP request. */
+
+ memset(BUF->ethhdr.dest.addr, 0xff, 6);
+ memset(BUF->dhwaddr.addr, 0x00, 6);
+ 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);
+ BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */
+ BUF->hwtype = HTONS(ARP_HWTYPE_ETH);
+ BUF->protocol = HTONS(UIP_ETHTYPE_IP);
+ BUF->hwlen = 6;
+ BUF->protolen = 4;
+ BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
+
+ uip_appdata = &uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN];
+
+ uip_len = sizeof(struct arp_hdr);
+ return;
+ }
+
+ /* Build an ethernet header. */
+ memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6);
+ }
+ memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
+
+ IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP);
+
+ uip_len += sizeof(struct uip_eth_hdr);
+}
+/*-----------------------------------------------------------------------------------*/
+
+/** @} */
+/** @} */
diff --git a/nuttx/net/uip/uip-fw.c b/nuttx/net/uip/uip-fw.c
new file mode 100644
index 000000000..7e5356f56
--- /dev/null
+++ b/nuttx/net/uip/uip-fw.c
@@ -0,0 +1,513 @@
+/* uip-fw.c
+ * 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.
+ *
+ * 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.
+ */
+
+#include <net/uip/uip.h>
+#include <net/uip/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. */
+ uint8 vhl,
+ tos;
+ uint16 len,
+ ipid,
+ ipoffset;
+ uint8 ttl,
+ proto;
+ uint16 ipchksum;
+ uint16 srcipaddr[2],
+ destipaddr[2];
+
+ /* TCP header. */
+ uint16 srcport,
+ destport;
+ uint8 seqno[4],
+ ackno[4],
+ tcpoffset,
+ flags,
+ wnd[2];
+ uint16 tcpchksum;
+ uint8 urgp[2];
+ uint8 optdata[4];
+};
+
+struct icmpip_hdr {
+ /* IP header. */
+ uint8 vhl,
+ tos,
+ len[2],
+ ipid[2],
+ ipoffset[2],
+ ttl,
+ proto;
+ uint16 ipchksum;
+ uint16 srcipaddr[2],
+ destipaddr[2];
+ /* ICMP (echo) header. */
+ uint8 type, icode;
+ uint16 icmpchksum;
+ uint16 id, seqno;
+ uint8 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 {
+ uint16 timer;
+
+ uint16 srcipaddr[2];
+ uint16 destipaddr[2];
+ uint16 ipid;
+ uint8 proto;
+ uint8 unused;
+
+#if notdef
+ uint16 payload[2];
+#endif
+
+#if UIP_REASSEMBLY > 0
+ uint16 len, offset;
+#endif
+};
+
+/*
+ * The number of packets to remember when looking for duplicates.
+ */
+#ifdef CONFIG_UIP_FWCACHE_SIZE
+# define FWCACHE_SIZE CONFIG_UIP_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(uint16 *ipaddr, uint16 *netipaddr, uint16 *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)
+{
+ uint16 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((uint16 *)&(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.
+ */
+/*------------------------------------------------------------------------------*/
+uint8
+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.
+ */
+/*------------------------------------------------------------------------------*/
+uint8
+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;
+ }
+ }
+}
+/*------------------------------------------------------------------------------*/
diff --git a/nuttx/net/uip/uip-fw.h b/nuttx/net/uip/uip-fw.h
new file mode 100644
index 000000000..cba0bea13
--- /dev/null
+++ b/nuttx/net/uip/uip-fw.h
@@ -0,0 +1,176 @@
+/**
+ * \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.1.1.1 2007-08-26 23:04:07 patacongo Exp $
+ */
+#ifndef __UIP_FW_H__
+#define __UIP_FW_H__
+
+#include <net/uip/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. */
+ uint16 ipaddr[2]; /**< The IP address of this interface. */
+ uint16 netmask[2]; /**< The netmask of the interface. */
+ uint8 (* 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] = ((uint16 *)(addr))[0]; \
+ (netif)->ipaddr[1] = ((uint16 *)(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] = ((uint16 *)(addr))[0]; \
+ (netif)->netmask[1] = ((uint16 *)(addr))[1]; } while(0)
+
+void uip_fw_init(void);
+uint8 uip_fw_forward(void);
+uint8 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__ */
+
+/** @} */
diff --git a/nuttx/net/uip/uip-neighbor.c b/nuttx/net/uip/uip-neighbor.c
new file mode 100644
index 000000000..6da1a891d
--- /dev/null
+++ b/nuttx/net/uip/uip-neighbor.c
@@ -0,0 +1,158 @@
+/*
+ * 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.1.1.1 2007-08-26 23:04:08 patacongo 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;
+ uint8 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;
+ uint8 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;
+}
+/*---------------------------------------------------------------------------*/
diff --git a/nuttx/net/uip/uip-neighbor.h b/nuttx/net/uip/uip-neighbor.h
new file mode 100644
index 000000000..277b5f848
--- /dev/null
+++ b/nuttx/net/uip/uip-neighbor.h
@@ -0,0 +1,54 @@
+/* uip-neighbor.h
+ * 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>
+ *
+ * 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.
+ */
+
+#ifndef __UIP_NEIGHBOR_H__
+#define __UIP_NEIGHBOR_H__
+
+#include <net/uip/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__ */
diff --git a/nuttx/net/uip/uip-split.c b/nuttx/net/uip/uip-split.c
new file mode 100644
index 000000000..155418a9c
--- /dev/null
+++ b/nuttx/net/uip/uip-split.c
@@ -0,0 +1,132 @@
+/* uip-split.c
+ * 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.
+ */
+
+#include <nuttx/config.h>
+#include <string.h>
+
+#include <net/uip/uip.h>
+#include <net/uip/uip-arch.h>
+
+#include "uip-split.h"
+#include "uip-fw.h"
+
+#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
+
+/*-----------------------------------------------------------------------------*/
+void
+uip_split_output(void)
+{
+ uint16 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;
+#ifdef CONFIG_NET_UIP_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 /* CONFIG_NET_UIP_IPv6 */
+ BUF->len[0] = uip_len >> 8;
+ BUF->len[1] = uip_len & 0xff;
+#endif /* CONFIG_NET_UIP_IPv6 */
+
+ /* Recalculate the TCP checksum. */
+ BUF->tcpchksum = 0;
+ BUF->tcpchksum = ~(uip_tcpchksum());
+
+#ifndef CONFIG_NET_UIP_IPv6
+ /* Recalculate the IP checksum. */
+ BUF->ipchksum = 0;
+ BUF->ipchksum = ~(uip_ipchksum());
+#endif /* CONFIG_NET_UIP_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;
+#ifdef CONFIG_NET_UIP_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 /* CONFIG_NET_UIP_IPv6 */
+ BUF->len[0] = uip_len >> 8;
+ BUF->len[1] = uip_len & 0xff;
+#endif /* CONFIG_NET_UIP_IPv6 */
+
+ /* uip_appdata += len1;*/
+ memcpy(uip_appdata, (uint8 *)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());
+
+#ifndef CONFIG_NET_UIP_IPv6
+ /* Recalculate the IP checksum. */
+ BUF->ipchksum = 0;
+ BUF->ipchksum = ~(uip_ipchksum());
+#endif /* CONFIG_NET_UIP_IPv6 */
+
+ /* Transmit the second packet. */
+ /* uip_fw_output();*/
+ tcpip_output();
+ } else {
+ /* uip_fw_output();*/
+ tcpip_output();
+ }
+
+}
+/*-----------------------------------------------------------------------------*/
diff --git a/nuttx/net/uip/uip-split.h b/nuttx/net/uip/uip-split.h
new file mode 100644
index 000000000..99f36ccdb
--- /dev/null
+++ b/nuttx/net/uip/uip-split.h
@@ -0,0 +1,96 @@
+/*
+ * 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.1.1.1 2007-08-26 23:04:08 patacongo 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__ */
+
+/** @} */
+/** @} */
diff --git a/nuttx/net/uip/uip-wait.c b/nuttx/net/uip/uip-wait.c
new file mode 100644
index 000000000..c7bf0a1bb
--- /dev/null
+++ b/nuttx/net/uip/uip-wait.c
@@ -0,0 +1,180 @@
+/************************************************************
+ * uip-wait.c
+ *
+ * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************/
+
+/************************************************************
+ * Included Files
+ ************************************************************/
+
+#include <nuttx/config.h>
+#include <semaphore.h>
+#include <wdog.h>
+#include <arch/irq.h>
+#include <net/uip/uip.h>
+
+/************************************************************
+ * Definitions
+ ************************************************************/
+
+/************************************************************
+ * Private Data
+ ************************************************************/
+
+/* Threads and tasks can both wait a semaphore. This
+ * initializer uses internal, non-portable knowledge of the\
+ * structure of sem_t to initialize it to the value 0.
+ */
+
+static sem_t uip_waitsem = { 0 }; /* Semaphore to wait on */
+static uint16 uip_waitflags = 0; /* UIP flags to wait for */
+
+/************************************************************
+ * Private Functions
+ ************************************************************/
+
+/* Called from the timer interrupt handler when a event wait
+ * watchdog expires.
+ */
+
+static void uip_event_timeout(int argc, uint32 itcb, ...)
+{
+ irqstate_t save = irqsave(); /* Should not be necessary */
+ uip_flags |= UIP_APPTIMEOUT; /* Set software timeout event */
+ uip_event_signal(); /* Signal the waiting thread/task */
+ irqrestore(save); /* Restore interrupts */
+}
+
+/************************************************************
+ * Global Functions
+ ************************************************************/
+
+/* This function is called user code to set up the wait */
+
+int uip_event_timedwait(uint16 waitflags, int timeout)
+{
+ /* Prevent conflicts with the interrupt level operation of
+ * uip_event_signal().
+ */
+ irqstate_t save = irqsave();
+ WDOG_ID wdog;
+
+ /* At present, we support only a single waiter. If uip_waitflags
+ * is non-zero on entry, then there is a problem.
+ */
+
+ if ( uip_waitflags == 0)
+ {
+ /* If the requested event bits are not set in the uip_flags,
+ * then wait. We will be awakened as soon as an interrupt is
+ * received that sets these bits.
+ */
+
+ goto errout_with_irqdisabled;
+ }
+
+ /* Loop until the requested bits are set in the flags */
+
+ while ((waitflags & uip_flags) != 0)
+ {
+ /* Set the event flags that the caller is waiting on */
+
+ uip_waitflags = waitflags;
+
+ /* Was a timeut requested as well? */
+
+ if (timeout)
+ {
+ /* Yes, then set the application timeout event as well */
+
+ uip_waitflags |= UIP_APPTIMEOUT;
+
+ /* Create a watchdog */
+
+ wdog = wd_create();
+ if (!wdog)
+ {
+ goto errout_with_irqdisabled;
+ }
+
+ /* Start the watchdog */
+
+ wd_start(wdog, timeout, (wdentry_t)uip_event_timeout, 0);
+ }
+
+ /* Wait for the event (or timeout) to occur */
+
+ if (sem_wait(&uip_waitsem) != 0)
+ {
+ goto errout_with_watchdog;
+ }
+
+ /* We no longer need the watchdog */
+
+ if (wdog)
+ {
+ wd_delete(wdog);
+ wdog = NULL;
+ }
+ }
+
+ irqrestore(save);
+ return OK;
+
+errout_with_watchdog:
+ if (wdog)
+ {
+ wd_delete(wdog);
+ }
+
+errout_with_irqdisabled:
+ irqrestore(save);
+ return ERROR;
+}
+
+/* This function is called from uip_interrupt() to wake up any
+ * waiting threads/tasks.
+ */
+
+void uip_event_signal(void)
+{
+ /* If any bits in uip_waitflags match bits set in uip_flags, then
+ * there must be a thread/task waiting for this event to occur.
+ */
+
+ if ((uip_waitflags & uip_flags) != 0)
+ {
+ sem_post(&uip_waitsem); /* Post the event */
+ uip_waitflags = 0; /* Prohibit posting the event multiple times */
+ }
+}
diff --git a/nuttx/net/uip/uip.c b/nuttx/net/uip/uip.c
new file mode 100644
index 000000000..b81c85cd9
--- /dev/null
+++ b/nuttx/net/uip/uip.c
@@ -0,0 +1,2091 @@
+/****************************************************************************
+ * uip.c
+ * The uIP TCP/IP stack code.
+ * author Adam Dunkels <adam@dunkels.com>
+ *
+ * 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.
+ *
+ * Copyright (c) 2001-2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * uIP is a small implementation of the IP, UDP and TCP protocols (as
+ * well as some basic ICMP stuff). The implementation couples the IP,
+ * UDP, TCP and the application layers very tightly. To keep the size
+ * of the compiled code down, this code frequently uses the goto
+ * statement. While it would be possible to break the uip_interrupt()
+ * function into many smaller functions, this would increase the code
+ * size because of the overhead of parameter passing and the fact that
+ * the optimier would not be as efficient.
+ *
+ * The principle is that we have a small buffer, called the uip_buf,
+ * in which the device driver puts an incoming packet. The TCP/IP
+ * stack parses the headers in the packet, and calls the
+ * application. If the remote host has sent data to the application,
+ * this data is present in the uip_buf and the application read the
+ * data from there. It is up to the application to put this data into
+ * a byte stream if needed. The application will not be fed with data
+ * that is out of sequence.
+ *
+ * If the application whishes to send data to the peer, it should put
+ * its data into the uip_buf. The uip_appdata pointer points to the
+ * first available byte. The TCP/IP stack will calculate the
+ * checksums, and fill in the necessary header fields and finally send
+ * the packet back to the peer.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+#include <debug.h>
+
+#include <net/uip/uipopt.h>
+#include <net/uip/uip.h>
+#include <net/uip/uip-arch.h>
+
+#ifdef CONFIG_NET_UIP_IPv6
+# include "uip-neighbor.h"
+#endif /* CONFIG_NET_UIP_IPv6 */
+
+#include <string.h>
+
+#if UIP_LOGGING == 1
+#include <stdio.h>
+extern void uip_log(char *msg);
+# define UIP_LOG(m) uip_log(m)
+#else
+# define UIP_LOG(m)
+#endif /* UIP_LOGGING == 1 */
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+#define TCP_FIN 0x01
+#define TCP_SYN 0x02
+#define TCP_RST 0x04
+#define TCP_PSH 0x08
+#define TCP_ACK 0x10
+#define TCP_URG 0x20
+#define TCP_CTL 0x3f
+
+#define TCP_OPT_END 0 /* End of TCP options list */
+#define TCP_OPT_NOOP 1 /* "No-operation" TCP option */
+#define TCP_OPT_MSS 2 /* Maximum segment size TCP option */
+
+#define TCP_OPT_MSS_LEN 4 /* Length of TCP MSS option. */
+
+#define ICMP_ECHO_REPLY 0
+#define ICMP_ECHO 8
+
+#define ICMP6_ECHO_REPLY 129
+#define ICMP6_ECHO 128
+#define ICMP6_NEIGHBOR_SOLICITATION 135
+#define ICMP6_NEIGHBOR_ADVERTISEMENT 136
+
+#define ICMP6_FLAG_S (1 << 6)
+
+#define ICMP6_OPTION_SOURCE_LINK_ADDRESS 1
+#define ICMP6_OPTION_TARGET_LINK_ADDRESS 2
+
+/* Macros. */
+#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
+#define FBUF ((struct uip_tcpip_hdr *)&uip_reassbuf[0])
+#define ICMPBUF ((struct uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN])
+#define UDPBUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])
+
+/****************************************************************************
+ * Public Variables
+ ****************************************************************************/
+
+/* The IP address of this host. If it is defined to be fixed (by
+ setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set
+ 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)};
+
+const uip_ipaddr_t uip_draddr =
+ {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1),
+ HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)};
+
+const uip_ipaddr_t uip_netmask =
+ {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1),
+ HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)};
+#else
+uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask;
+#endif /* UIP_FIXEDADDR */
+
+#ifndef CONFIG_UIP_EXTERNAL_BUFFER
+uint8 uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains incoming packets. */
+#endif /* CONFIG_UIP_EXTERNAL_BUFFER */
+
+void *uip_appdata; /* The uip_appdata pointer points to application data. */
+void *uip_sappdata; /* The uip_appdata pointer points to the application
+ * data which is to be sent. */
+#if UIP_URGDATA > 0
+void *uip_urgdata; /* The uip_urgdata pointer points to urgent data
+ * (out-of-band data), if present. */
+uint16 uip_urglen, uip_surglen;
+#endif /* UIP_URGDATA > 0 */
+
+uint16 uip_len, uip_slen; /* The uip_len is either 8 or 16 bits, depending
+ * on the maximum packet size. */
+
+uint16 uip_flags; /* The uip_flags variable is used for communication
+ * between the TCP/IP stack and the application
+ * program. */
+struct uip_conn *uip_conn; /* uip_conn always points to the current connection. */
+
+struct uip_conn uip_conns[UIP_CONNS];
+ /* The uip_conns array holds all TCP connections. */
+uint16 uip_listenports[UIP_LISTENPORTS];
+ /* The uip_listenports list all currently listning ports. */
+#if UIP_UDP
+struct uip_udp_conn *uip_udp_conn;
+struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
+#endif /* UIP_UDP */
+
+/* Temporary variables. */
+uint8 uip_acc32[4];
+
+#if UIP_STATISTICS == 1
+struct uip_stats uip_stat;
+# define UIP_STAT(s) s
+#else
+# define UIP_STAT(s)
+#endif /* UIP_STATISTICS == 1 */
+
+/****************************************************************************
+ * Private Variables
+ ****************************************************************************/
+
+static const uip_ipaddr_t all_ones_addr =
+#ifdef CONFIG_NET_UIP_IPv6
+ {0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff};
+#else /* CONFIG_NET_UIP_IPv6 */
+ {0xffff,0xffff};
+#endif /* CONFIG_NET_UIP_IPv6 */
+
+static const uip_ipaddr_t all_zeroes_addr =
+#ifdef CONFIG_NET_UIP_IPv6
+ {0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000};
+#else /* CONFIG_NET_UIP_IPv6 */
+ {0x0000,0x0000};
+#endif /* CONFIG_NET_UIP_IPv6 */
+
+#if UIP_FIXEDETHADDR
+const struct uip_eth_addr uip_ethaddr =
+{{ UIP_ETHADDR0, UIP_ETHADDR1, UIP_ETHADDR2, UIP_ETHADDR3, UIP_ETHADDR4, UIP_ETHADDR5 }};
+#else
+struct uip_eth_addr uip_ethaddr = {{ 0,0,0,0,0,0 }};
+#endif
+
+static uint16 ipid; /* Ths ipid variable is an increasing number that is
+ * used for the IP ID field. */
+
+static uint8 iss[4]; /* The iss variable is used for the TCP initial
+ * sequence number. */
+
+#if UIP_ACTIVE_OPEN
+static uint16 lastport; /* Keeps track of the last port used for a new
+ * connection. */
+#endif /* UIP_ACTIVE_OPEN */
+
+/* Temporary variables. */
+static uint8 c, opt;
+static uint16 tmp16;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+#if !UIP_ARCH_ADD32
+static void uip_add32(uint8 *op32, uint16 op16)
+{
+ uip_acc32[3] = op32[3] + (op16 & 0xff);
+ uip_acc32[2] = op32[2] + (op16 >> 8);
+ uip_acc32[1] = op32[1];
+ uip_acc32[0] = op32[0];
+
+ if (uip_acc32[2] < (op16 >> 8)) {
+ ++uip_acc32[1];
+ if (uip_acc32[1] == 0) {
+ ++uip_acc32[0];
+ }
+ }
+
+ if (uip_acc32[3] < (op16 & 0xff)) {
+ ++uip_acc32[2];
+ if (uip_acc32[2] == 0) {
+ ++uip_acc32[1];
+ if (uip_acc32[1] == 0) {
+ ++uip_acc32[0];
+ }
+ }
+ }
+}
+#endif /* UIP_ARCH_ADD32 */
+
+#if !UIP_ARCH_CHKSUM
+static uint16 chksum(uint16 sum, const uint8 *data, uint16 len)
+{
+ uint16 t;
+ const uint8 *dataptr;
+ const uint8 *last_byte;
+
+ dataptr = data;
+ last_byte = data + len - 1;
+
+ while(dataptr < last_byte) {
+ /* At least two more bytes */
+ t = (dataptr[0] << 8) + dataptr[1];
+ sum += t;
+ if (sum < t) {
+ sum++; /* carry */
+ }
+ dataptr += 2;
+ }
+
+ if (dataptr == last_byte) {
+ t = (dataptr[0] << 8) + 0;
+ sum += t;
+ if (sum < t) {
+ sum++; /* carry */
+ }
+ }
+
+ /* Return sum in host byte order. */
+ return sum;
+}
+
+static uint16 upper_layer_chksum(uint8 proto)
+{
+ uint16 upper_layer_len;
+ uint16 sum;
+
+#ifdef CONFIG_NET_UIP_IPv6
+ upper_layer_len = (((uint16)(BUF->len[0]) << 8) + BUF->len[1]);
+#else /* CONFIG_NET_UIP_IPv6 */
+ upper_layer_len = (((uint16)(BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN;
+#endif /* CONFIG_NET_UIP_IPv6 */
+
+ /* First sum pseudoheader. */
+
+ /* IP protocol and length fields. This addition cannot carry. */
+ sum = upper_layer_len + proto;
+
+ /* Sum IP source and destination addresses. */
+ sum = chksum(sum, (uint8 *)&BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t));
+
+ /* Sum TCP header and data. */
+ sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], upper_layer_len);
+
+ return (sum == 0) ? 0xffff : htons(sum);
+}
+
+#ifdef CONFIG_NET_UIP_IPv6
+static uint16 uip_icmp6chksum(void)
+{
+ return upper_layer_chksum(UIP_PROTO_ICMP6);
+}
+#endif /* CONFIG_NET_UIP_IPv6 */
+
+#endif /* UIP_ARCH_CHKSUM */
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/* This function may be used at boot time to set the initial ip_id.*/
+
+void uip_setipid(uint16 id)
+{
+ ipid = id;
+}
+
+/* Calculate the Internet checksum over a buffer. */
+
+#if !UIP_ARCH_CHKSUM
+uint16 uip_chksum(uint16 *data, uint16 len)
+{
+ return htons(chksum(0, (uint8 *)data, len));
+}
+
+/* Calculate the IP header checksum of the packet header in uip_buf. */
+
+#ifndef UIP_ARCH_IPCHKSUM
+uint16 uip_ipchksum(void)
+{
+ uint16 sum;
+
+ sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN);
+ dbg("uip_ipchksum: sum 0x%04x\n", sum);
+ return (sum == 0) ? 0xffff : htons(sum);
+}
+#endif
+
+/* Calculate the TCP checksum of the packet in uip_buf and uip_appdata. */
+
+uint16 uip_tcpchksum(void)
+{
+ return upper_layer_chksum(UIP_PROTO_TCP);
+}
+
+/* Calculate the UDP checksum of the packet in uip_buf and uip_appdata. */
+
+#if UIP_UDP_CHECKSUMS
+uint16 uip_udpchksum(void)
+{
+ return upper_layer_chksum(UIP_PROTO_UDP);
+}
+#endif /* UIP_UDP_CHECKSUMS */
+#endif /* UIP_ARCH_CHKSUM */
+
+void uip_init(void)
+{
+ for(c = 0; c < UIP_LISTENPORTS; ++c) {
+ uip_listenports[c] = 0;
+ }
+ for(c = 0; c < UIP_CONNS; ++c) {
+ uip_conns[c].tcpstateflags = UIP_CLOSED;
+ }
+#if UIP_ACTIVE_OPEN
+ lastport = 1024;
+#endif /* UIP_ACTIVE_OPEN */
+
+#if UIP_UDP
+ for(c = 0; c < UIP_UDP_CONNS; ++c) {
+ uip_udp_conns[c].lport = 0;
+ }
+#endif /* UIP_UDP */
+
+ /* IPv4 initialization. */
+#if UIP_FIXEDADDR == 0
+ /* uip_hostaddr[0] = uip_hostaddr[1] = 0;*/
+#endif /* UIP_FIXEDADDR */
+
+}
+
+#if UIP_ACTIVE_OPEN
+struct uip_conn *uip_connect(uip_ipaddr_t *ripaddr, uint16 rport)
+{
+ register struct uip_conn *conn, *cconn;
+
+ /* Find an unused local port. */
+ again:
+ ++lastport;
+
+ if (lastport >= 32000) {
+ lastport = 4096;
+ }
+
+ /* Check if this port is already in use, and if so try to find
+ another one. */
+ for(c = 0; c < UIP_CONNS; ++c) {
+ conn = &uip_conns[c];
+ if (conn->tcpstateflags != UIP_CLOSED &&
+ conn->lport == htons(lastport)) {
+ goto again;
+ }
+ }
+
+ conn = 0;
+ for(c = 0; c < UIP_CONNS; ++c) {
+ cconn = &uip_conns[c];
+ if (cconn->tcpstateflags == UIP_CLOSED) {
+ conn = cconn;
+ break;
+ }
+ if (cconn->tcpstateflags == UIP_TIME_WAIT) {
+ if (conn == 0 || cconn->timer > conn->timer) {
+ conn = cconn;
+ }
+ }
+ }
+
+ if (conn == 0) {
+ return 0;
+ }
+
+ conn->tcpstateflags = UIP_SYN_SENT;
+
+ conn->snd_nxt[0] = iss[0];
+ conn->snd_nxt[1] = iss[1];
+ conn->snd_nxt[2] = iss[2];
+ conn->snd_nxt[3] = iss[3];
+
+ conn->initialmss = conn->mss = UIP_TCP_MSS;
+
+ conn->len = 1; /* TCP length of the SYN is one. */
+ conn->nrtx = 0;
+ conn->timer = 1; /* Send the SYN next time around. */
+ conn->rto = UIP_RTO;
+ conn->sa = 0;
+ conn->sv = 16; /* Initial value of the RTT variance. */
+ conn->lport = htons(lastport);
+ conn->rport = rport;
+ uip_ipaddr_copy(&conn->ripaddr, ripaddr);
+
+ return conn;
+}
+#endif /* UIP_ACTIVE_OPEN */
+
+#if UIP_UDP
+struct uip_udp_conn *
+uip_udp_new(uip_ipaddr_t *ripaddr, uint16 rport)
+{
+ register struct uip_udp_conn *conn;
+
+ /* Find an unused local port. */
+ again:
+ ++lastport;
+
+ if (lastport >= 32000) {
+ lastport = 4096;
+ }
+
+ for(c = 0; c < UIP_UDP_CONNS; ++c) {
+ if (uip_udp_conns[c].lport == htons(lastport)) {
+ goto again;
+ }
+ }
+
+
+ conn = 0;
+ for(c = 0; c < UIP_UDP_CONNS; ++c) {
+ if (uip_udp_conns[c].lport == 0) {
+ conn = &uip_udp_conns[c];
+ break;
+ }
+ }
+
+ if (conn == 0) {
+ return 0;
+ }
+
+ conn->lport = HTONS(lastport);
+ conn->rport = rport;
+ if (ripaddr == NULL) {
+ memset(conn->ripaddr, 0, sizeof(uip_ipaddr_t));
+ } else {
+ uip_ipaddr_copy(&conn->ripaddr, ripaddr);
+ }
+ conn->ttl = UIP_TTL;
+
+ return conn;
+}
+#endif /* UIP_UDP */
+
+void uip_unlisten(uint16 port)
+{
+ for(c = 0; c < UIP_LISTENPORTS; ++c) {
+ if (uip_listenports[c] == port) {
+ uip_listenports[c] = 0;
+ return;
+ }
+ }
+}
+
+void uip_listen(uint16 port)
+{
+ for(c = 0; c < UIP_LISTENPORTS; ++c) {
+ if (uip_listenports[c] == 0) {
+ uip_listenports[c] = port;
+ return;
+ }
+ }
+}
+
+/* XXX: IP fragment reassembly: not well-tested. */
+
+#if UIP_REASSEMBLY && !defined(CONFIG_NET_UIP_IPv6)
+#define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN)
+static uint8 uip_reassbuf[UIP_REASS_BUFSIZE];
+static uint8 uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)];
+static const uint8 bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
+static uint16 uip_reasslen;
+static uint8 uip_reassflags;
+#define UIP_REASS_FLAG_LASTFRAG 0x01
+static uint8 uip_reasstmr;
+
+#define IP_MF 0x20
+
+static uint8 uip_reass(void)
+{
+ uint16 offset, len;
+ uint16 i;
+
+ /* If ip_reasstmr is zero, no packet is present in the buffer, so we
+ write the IP header of the fragment into the reassembly
+ buffer. The timer is updated with the maximum age. */
+ if (uip_reasstmr == 0) {
+ memcpy(uip_reassbuf, &BUF->vhl, UIP_IPH_LEN);
+ uip_reasstmr = UIP_REASS_MAXAGE;
+ uip_reassflags = 0;
+ /* Clear the bitmap. */
+ memset(uip_reassbitmap, 0, sizeof(uip_reassbitmap));
+ }
+
+ /* Check if the incoming fragment matches the one currently present
+ in the reasembly buffer. If so, we proceed with copying the
+ fragment into the buffer. */
+ if (BUF->srcipaddr[0] == FBUF->srcipaddr[0] &&
+ BUF->srcipaddr[1] == FBUF->srcipaddr[1] &&
+ BUF->destipaddr[0] == FBUF->destipaddr[0] &&
+ BUF->destipaddr[1] == FBUF->destipaddr[1] &&
+ BUF->ipid[0] == FBUF->ipid[0] &&
+ BUF->ipid[1] == FBUF->ipid[1]) {
+
+ len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4;
+ offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8;
+
+ /* If the offset or the offset + fragment length overflows the
+ reassembly buffer, we discard the entire packet. */
+ if (offset > UIP_REASS_BUFSIZE ||
+ offset + len > UIP_REASS_BUFSIZE) {
+ uip_reasstmr = 0;
+ goto nullreturn;
+ }
+
+ /* Copy the fragment into the reassembly buffer, at the right
+ offset. */
+ memcpy(&uip_reassbuf[UIP_IPH_LEN + offset],
+ (char *)BUF + (int)((BUF->vhl & 0x0f) * 4),
+ len);
+
+ /* Update the bitmap. */
+ if (offset / (8 * 8) == (offset + len) / (8 * 8)) {
+ /* If the two endpoints are in the same byte, we only update
+ that byte. */
+
+ uip_reassbitmap[offset / (8 * 8)] |=
+ bitmap_bits[(offset / 8 ) & 7] &
+ ~bitmap_bits[((offset + len) / 8 ) & 7];
+ } else {
+ /* If the two endpoints are in different bytes, we update the
+ bytes in the endpoints and fill the stuff inbetween with
+ 0xff. */
+ uip_reassbitmap[offset / (8 * 8)] |=
+ bitmap_bits[(offset / 8 ) & 7];
+ for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) {
+ uip_reassbitmap[i] = 0xff;
+ }
+ uip_reassbitmap[(offset + len) / (8 * 8)] |=
+ ~bitmap_bits[((offset + len) / 8 ) & 7];
+ }
+
+ /* If this fragment has the More Fragments flag set to zero, we
+ know that this is the last fragment, so we can calculate the
+ size of the entire packet. We also set the
+ IP_REASS_FLAG_LASTFRAG flag to indicate that we have received
+ the final fragment. */
+
+ if ((BUF->ipoffset[0] & IP_MF) == 0) {
+ uip_reassflags |= UIP_REASS_FLAG_LASTFRAG;
+ uip_reasslen = offset + len;
+ }
+
+ /* Finally, we check if we have a full packet in the buffer. We do
+ this by checking if we have the last fragment and if all bits
+ in the bitmap are set. */
+ if (uip_reassflags & UIP_REASS_FLAG_LASTFRAG) {
+ /* Check all bytes up to and including all but the last byte in
+ the bitmap. */
+ for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) {
+ if (uip_reassbitmap[i] != 0xff) {
+ goto nullreturn;
+ }
+ }
+
+ /* Check the last byte in the bitmap. It should contain just the
+ right amount of bits. */
+ if (uip_reassbitmap[uip_reasslen / (8 * 8)] !=
+ (uint8)~bitmap_bits[uip_reasslen / 8 & 7]) {
+ goto nullreturn;
+ }
+
+ /* If we have come this far, we have a full packet in the
+ buffer, so we allocate a pbuf and copy the packet into it. We
+ also reset the timer. */
+ uip_reasstmr = 0;
+ memcpy(BUF, FBUF, uip_reasslen);
+
+ /* Pretend to be a "normal" (i.e., not fragmented) IP packet
+ from now on. */
+ BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
+ BUF->len[0] = uip_reasslen >> 8;
+ BUF->len[1] = uip_reasslen & 0xff;
+ BUF->ipchksum = 0;
+ BUF->ipchksum = ~(uip_ipchksum());
+
+ return uip_reasslen;
+ }
+ }
+
+ nullreturn:
+ return 0;
+}
+#endif /* UIP_REASSEMBLY */
+
+static void uip_add_rcv_nxt(uint16 n)
+{
+ uip_add32(uip_conn->rcv_nxt, n);
+ uip_conn->rcv_nxt[0] = uip_acc32[0];
+ uip_conn->rcv_nxt[1] = uip_acc32[1];
+ uip_conn->rcv_nxt[2] = uip_acc32[2];
+ uip_conn->rcv_nxt[3] = uip_acc32[3];
+}
+
+void uip_interrupt(uint8 flag)
+{
+ register struct uip_conn *uip_connr = uip_conn;
+
+#if UIP_UDP
+ if (flag == UIP_UDP_SEND_CONN)
+ {
+ goto udp_send;
+ }
+#endif /* UIP_UDP */
+
+ uip_sappdata = uip_appdata = &uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN];
+
+ /* Check if we were invoked because of a poll request for a
+ * particular connection.
+ */
+
+ if (flag == UIP_POLL_REQUEST)
+ {
+ if ((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED &&
+ !uip_outstanding(uip_connr))
+ {
+ uip_flags = UIP_POLL;
+ uip_event_signal();
+ uip_interrupt_event();
+ goto appsend;
+ }
+ goto drop;
+ }
+
+ /* Check if we were invoked because of the perodic timer fireing. */
+
+ else if (flag == UIP_TIMER)
+ {
+#if UIP_REASSEMBLY
+ if (uip_reasstmr != 0)
+ {
+ --uip_reasstmr;
+ }
+#endif /* UIP_REASSEMBLY */
+
+ /* Increase the initial sequence number */
+
+ if (++iss[3] == 0)
+ {
+ if (++iss[2] == 0)
+ {
+ if (++iss[1] == 0)
+ {
+ ++iss[0];
+ }
+ }
+ }
+
+ /* Reset the length variables. */
+
+ uip_len = 0;
+ uip_slen = 0;
+
+ /* Check if the connection is in a state in which we simply wait
+ * for the connection to time out. If so, we increase the
+ * connection's timer and remove the connection if it times
+ * out.
+ */
+
+ if (uip_connr->tcpstateflags == UIP_TIME_WAIT ||
+ uip_connr->tcpstateflags == UIP_FIN_WAIT_2)
+ {
+ ++(uip_connr->timer);
+ if (uip_connr->timer == UIP_TIME_WAIT_TIMEOUT)
+ {
+ uip_connr->tcpstateflags = UIP_CLOSED;
+ }
+ }
+ else if (uip_connr->tcpstateflags != UIP_CLOSED)
+ {
+ /* If the connection has outstanding data, we increase the
+ * connection's timer and see if it has reached the RTO value
+ * in which case we retransmit.
+ */
+
+ if (uip_outstanding(uip_connr))
+ {
+ if (uip_connr->timer-- == 0)
+ {
+ if (uip_connr->nrtx == UIP_MAXRTX ||
+ ((uip_connr->tcpstateflags == UIP_SYN_SENT ||
+ uip_connr->tcpstateflags == UIP_SYN_RCVD) &&
+ uip_connr->nrtx == UIP_MAXSYNRTX))
+ {
+ uip_connr->tcpstateflags = UIP_CLOSED;
+
+ /* We call uip_interrupt_event() with uip_flags set to
+ * UIP_TIMEDOUT to inform the application that the
+ * connection has timed out.
+ */
+
+ uip_flags = UIP_TIMEDOUT;
+ uip_event_signal();
+ uip_interrupt_event();
+
+ /* We also send a reset packet to the remote host. */
+
+ BUF->flags = TCP_RST | TCP_ACK;
+ goto tcp_send_nodata;
+ }
+
+ /* Exponential backoff. */
+
+ uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4 ? 4: uip_connr->nrtx);
+ ++(uip_connr->nrtx);
+
+ /* Ok, so we need to retransmit. We do this differently
+ * depending on which state we are in. In ESTABLISHED, we
+ * call upon the application so that it may prepare the
+ * data for the retransmit. In SYN_RCVD, we resend the
+ * SYNACK that we sent earlier and in LAST_ACK we have to
+ * retransmit our FINACK.
+ */
+
+ UIP_STAT(++uip_stat.tcp.rexmit);
+ switch(uip_connr->tcpstateflags & UIP_TS_MASK)
+ {
+ case UIP_SYN_RCVD:
+ /* In the SYN_RCVD state, we should retransmit our
+ * SYNACK.
+ */
+
+ goto tcp_send_synack;
+
+#if UIP_ACTIVE_OPEN
+ case UIP_SYN_SENT:
+ /* In the SYN_SENT state, we retransmit out SYN. */
+ BUF->flags = 0;
+ goto tcp_send_syn;
+#endif /* UIP_ACTIVE_OPEN */
+
+ case UIP_ESTABLISHED:
+ /* In the ESTABLISHED state, we call upon the application
+ * to do the actual retransmit after which we jump into
+ * the code for sending out the packet (the apprexmit
+ * label).
+ */
+
+ uip_flags = UIP_REXMIT;
+ uip_event_signal();
+ uip_interrupt_event();
+ goto apprexmit;
+
+ case UIP_FIN_WAIT_1:
+ case UIP_CLOSING:
+ case UIP_LAST_ACK:
+ /* In all these states we should retransmit a FINACK. */
+ goto tcp_send_finack;
+
+ }
+ }
+ }
+ else if ((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED)
+ {
+ /* If there was no need for a retransmission, we poll the
+ * application for new data.
+ */
+
+ uip_flags = UIP_POLL;
+ uip_event_signal();
+ uip_interrupt_event();
+ goto appsend;
+ }
+ }
+ goto drop;
+ }
+
+#if UIP_UDP
+ if (flag == UIP_UDP_TIMER)
+ {
+ if (uip_udp_conn->lport != 0)
+ {
+ uip_conn = NULL;
+ uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
+ uip_len = uip_slen = 0;
+ uip_flags = UIP_POLL;
+ uip_event_signal();
+ uip_interrupt_udp_event();
+ goto udp_send;
+ }
+ else
+ {
+ goto drop;
+ }
+ }
+#endif
+
+ /* This is where the input processing starts. */
+ UIP_STAT(++uip_stat.ip.recv);
+
+ /* Start of IP input header processing code. */
+
+#ifdef CONFIG_NET_UIP_IPv6
+ /* Check validity of the IP header. */
+ if ((BUF->vtc & 0xf0) != 0x60)
+ {
+ /* IP version and header length. */
+ UIP_STAT(++uip_stat.ip.drop);
+ UIP_STAT(++uip_stat.ip.vhlerr);
+ UIP_LOG("ipv6: invalid version.");
+ goto drop;
+ }
+#else /* CONFIG_NET_UIP_IPv6 */
+ /* Check validity of the IP header. */
+ if (BUF->vhl != 0x45)
+ {
+ /* IP version and header length. */
+ UIP_STAT(++uip_stat.ip.drop);
+ UIP_STAT(++uip_stat.ip.vhlerr);
+ UIP_LOG("ip: invalid version or header length.");
+ goto drop;
+ }
+#endif /* CONFIG_NET_UIP_IPv6 */
+
+ /* Check the size of the packet. If the size reported to us in
+ uip_len is smaller the size reported in the IP header, we assume
+ that the packet has been corrupted in transit. If the size of
+ uip_len is larger than the size reported in the IP packet header,
+ the packet has been padded and we set uip_len to the correct
+ value.. */
+
+ if ((BUF->len[0] << 8) + BUF->len[1] <= uip_len)
+ {
+ uip_len = (BUF->len[0] << 8) + BUF->len[1];
+#ifdef CONFIG_NET_UIP_IPv6
+ uip_len += 40; /* The length reported in the IPv6 header is the
+ length of the payload that follows the
+ header. However, uIP uses the uip_len variable
+ for holding the size of the entire packet,
+ including the IP header. For IPv4 this is not a
+ problem as the length field in the IPv4 header
+ contains the length of the entire packet. But
+ for IPv6 we need to add the size of the IPv6
+ header (40 bytes). */
+#endif /* CONFIG_NET_UIP_IPv6 */
+ }
+ else
+ {
+ UIP_LOG("ip: packet shorter than reported in IP header.");
+ goto drop;
+ }
+
+#ifndef CONFIG_NET_UIP_IPv6
+ /* Check the fragment flag. */
+
+ if ((BUF->ipoffset[0] & 0x3f) != 0 ||
+ BUF->ipoffset[1] != 0)
+ {
+#if UIP_REASSEMBLY
+ uip_len = uip_reass();
+ if (uip_len == 0)
+ {
+ goto drop;
+ }
+#else /* UIP_REASSEMBLY */
+ UIP_STAT(++uip_stat.ip.drop);
+ UIP_STAT(++uip_stat.ip.fragerr);
+ UIP_LOG("ip: fragment dropped.");
+ goto drop;
+#endif /* UIP_REASSEMBLY */
+ }
+#endif /* CONFIG_NET_UIP_IPv6 */
+
+ if (uip_ipaddr_cmp(uip_hostaddr, 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. */
+#if UIP_PINGADDRCONF && !CONFIG_NET_UIP_IPv6
+ if (BUF->proto == UIP_PROTO_ICMP)
+ {
+ UIP_LOG("ip: possible ping config packet received.");
+ goto icmp_input;
+ }
+ else
+ {
+ UIP_LOG("ip: packet dropped since no address assigned.");
+ goto drop;
+ }
+#endif /* UIP_PINGADDRCONF */
+
+ }
+ else
+ {
+ /* If IP broadcast support is configured, we check for a broadcast
+ UDP packet, which may be destined to us. */
+#if UIP_BROADCAST
+ dbg("UDP IP checksum 0x%04x\n", uip_ipchksum());
+ if (BUF->proto == UIP_PROTO_UDP &&
+ uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr)
+ /*&& uip_ipchksum() == 0xffff*/)
+ {
+ goto udp_input;
+ }
+#endif /* UIP_BROADCAST */
+
+ /* Check if the packet is destined for our IP address. */
+#ifndef CONFIG_NET_UIP_IPv6
+ if (!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr))
+ {
+ UIP_STAT(++uip_stat.ip.drop);
+ goto drop;
+ }
+#else /* CONFIG_NET_UIP_IPv6 */
+ /* For IPv6, packet reception is a little trickier as we need to
+ make sure that we listen to certain multicast addresses (all
+ 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))
+ {
+ UIP_STAT(++uip_stat.ip.drop);
+ goto drop;
+ }
+#endif /* CONFIG_NET_UIP_IPv6 */
+ }
+
+#ifndef CONFIG_NET_UIP_IPv6
+ if (uip_ipchksum() != 0xffff)
+ {
+ /* Compute and check the IP header checksum. */
+
+ UIP_STAT(++uip_stat.ip.drop);
+ UIP_STAT(++uip_stat.ip.chkerr);
+ UIP_LOG("ip: bad checksum.");
+ goto drop;
+ }
+#endif /* CONFIG_NET_UIP_IPv6 */
+
+ if (BUF->proto == UIP_PROTO_TCP)
+ {
+ /* Check for TCP packet. If so, proceed with TCP input processing. */
+
+ goto tcp_input;
+ }
+
+#if UIP_UDP
+ if (BUF->proto == UIP_PROTO_UDP)
+ {
+ goto udp_input;
+ }
+#endif /* UIP_UDP */
+
+#ifndef CONFIG_NET_UIP_IPv6
+ /* ICMPv4 processing code follows. */
+ if (BUF->proto != UIP_PROTO_ICMP)
+ {
+ /* We only allow ICMP packets from here. */
+
+ UIP_STAT(++uip_stat.ip.drop);
+ UIP_STAT(++uip_stat.ip.protoerr);
+ UIP_LOG("ip: neither tcp nor icmp.");
+ goto drop;
+ }
+
+#if UIP_PINGADDRCONF
+ icmp_input:
+#endif /* UIP_PINGADDRCONF */
+ UIP_STAT(++uip_stat.icmp.recv);
+
+ /* ICMP echo (i.e., ping) processing. This is simple, we only change
+ the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP
+ checksum before we return the packet. */
+ if (ICMPBUF->type != ICMP_ECHO)
+ {
+ UIP_STAT(++uip_stat.icmp.drop);
+ UIP_STAT(++uip_stat.icmp.typeerr);
+ UIP_LOG("icmp: not icmp echo.");
+ goto drop;
+ }
+
+ /* If we are configured to use ping IP address assignment, we use
+ 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];
+ }
+#endif /* UIP_PINGADDRCONF */
+
+ ICMPBUF->type = ICMP_ECHO_REPLY;
+
+ if (ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8)))
+ {
+ ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1;
+ }
+ else
+ {
+ ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8);
+ }
+
+ /* Swap IP addresses. */
+
+ uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
+ uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
+
+ UIP_STAT(++uip_stat.icmp.sent);
+ goto send;
+
+ /* End of IPv4 input header processing code. */
+#else /* !CONFIG_NET_UIP_IPv6 */
+
+ /* This is IPv6 ICMPv6 processing code. */
+ dbg("icmp6_input: length %d\n", uip_len);
+
+ if (BUF->proto != UIP_PROTO_ICMP6)
+ {
+ /* We only allow ICMPv6 packets from here. */
+
+ UIP_STAT(++uip_stat.ip.drop);
+ UIP_STAT(++uip_stat.ip.protoerr);
+ UIP_LOG("ip: neither tcp nor icmp6.");
+ goto drop;
+ }
+
+ UIP_STAT(++uip_stat.icmp.recv);
+
+ /* 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 (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]));
+ }
+
+ /* We should now send a neighbor advertisement back to where the
+ neighbor solicication came from. */
+ ICMPBUF->type = ICMP6_NEIGHBOR_ADVERTISEMENT;
+ ICMPBUF->flags = ICMP6_FLAG_S; /* Solicited flag. */
+
+ ICMPBUF->reserved1 = ICMPBUF->reserved2 = ICMPBUF->reserved3 = 0;
+
+ 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;
+ }
+ goto drop;
+ }
+ else if (ICMPBUF->type == ICMP6_ECHO)
+ {
+ /* ICMP echo (i.e., ping) processing. This is simple, we only
+ change the ICMP type from ECHO to ECHO_REPLY and update the
+ ICMP checksum before we return the packet. */
+
+ ICMPBUF->type = ICMP6_ECHO_REPLY;
+
+ uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
+ uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
+ ICMPBUF->icmpchksum = 0;
+ ICMPBUF->icmpchksum = ~uip_icmp6chksum();
+
+ UIP_STAT(++uip_stat.icmp.sent);
+ goto send;
+ }
+ else
+ {
+ dbg("Unknown icmp6 message type %d\n", ICMPBUF->type);
+ UIP_STAT(++uip_stat.icmp.drop);
+ UIP_STAT(++uip_stat.icmp.typeerr);
+ UIP_LOG("icmp: unknown ICMP message.");
+ goto drop;
+ }
+
+ /* End of IPv6 ICMP processing. */
+
+#endif /* !CONFIG_NET_UIP_IPv6 */
+
+#if UIP_UDP
+ /* UDP input processing. */
+ udp_input:
+ /* UDP processing is really just a hack. We don't do anything to the
+ UDP/IP headers, but let the UDP application do all the hard
+ work. If the application sets uip_slen, it has a packet to
+ send. */
+#if UIP_UDP_CHECKSUMS
+ uip_len = uip_len - UIP_IPUDPH_LEN;
+ uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
+ if (UDPBUF->udpchksum != 0 && uip_udpchksum() != 0xffff)
+ {
+ UIP_STAT(++uip_stat.udp.drop);
+ UIP_STAT(++uip_stat.udp.chkerr);
+ UIP_LOG("udp: bad checksum.");
+ goto drop;
+ }
+#else /* UIP_UDP_CHECKSUMS */
+ uip_len = uip_len - UIP_IPUDPH_LEN;
+#endif /* UIP_UDP_CHECKSUMS */
+
+ /* Demultiplex this UDP packet between the UDP "connections". */
+ for (uip_udp_conn = &uip_udp_conns[0];
+ uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS];
+ ++uip_udp_conn)
+ {
+ /* If the local UDP port is non-zero, the connection is considered
+ to be used. If so, the local port number is checked against the
+ destination port number in the received packet. If the two port
+ numbers match, the remote port number is checked if the
+ connection is bound to a remote port. Finally, if the
+ connection is bound to a remote IP address, the source IP
+ address of the packet is checked. */
+ if (uip_udp_conn->lport != 0 &&
+ 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)))
+ {
+ goto udp_found;
+ }
+ }
+ UIP_LOG("udp: no matching connection found");
+ goto drop;
+
+ udp_found:
+ uip_conn = NULL;
+ uip_flags = UIP_NEWDATA;
+ uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
+ uip_slen = 0;
+ uip_event_signal();
+ uip_interrupt_udp_event();
+
+ udp_send:
+ if (uip_slen == 0)
+ {
+ goto drop;
+ }
+ uip_len = uip_slen + UIP_IPUDPH_LEN;
+
+#ifdef CONFIG_NET_UIP_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 /* CONFIG_NET_UIP_IPv6 */
+ BUF->len[0] = (uip_len >> 8);
+ BUF->len[1] = (uip_len & 0xff);
+#endif /* CONFIG_NET_UIP_IPv6 */
+
+ BUF->ttl = uip_udp_conn->ttl;
+ BUF->proto = UIP_PROTO_UDP;
+
+ UDPBUF->udplen = HTONS(uip_slen + UIP_UDPH_LEN);
+ UDPBUF->udpchksum = 0;
+
+ 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_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN];
+
+#if UIP_UDP_CHECKSUMS
+ /* Calculate UDP checksum. */
+ UDPBUF->udpchksum = ~(uip_udpchksum());
+ if (UDPBUF->udpchksum == 0)
+ {
+ UDPBUF->udpchksum = 0xffff;
+ }
+#endif /* UIP_UDP_CHECKSUMS */
+
+ goto ip_send_nolen;
+#endif /* UIP_UDP */
+
+ /* TCP input processing. */
+ tcp_input:
+ UIP_STAT(++uip_stat.tcp.recv);
+
+ /* Start of TCP input header processing code. */
+
+ if (uip_tcpchksum() != 0xffff)
+ {
+ /* Compute and check the TCP checksum. */
+ UIP_STAT(++uip_stat.tcp.drop);
+ UIP_STAT(++uip_stat.tcp.chkerr);
+ UIP_LOG("tcp: bad checksum.");
+ goto drop;
+ }
+
+ /* Demultiplex this segment. */
+ /* First check any active connections. */
+ for (uip_connr = &uip_conns[0]; uip_connr <= &uip_conns[UIP_CONNS - 1];
+ ++uip_connr)
+ {
+ if (uip_connr->tcpstateflags != UIP_CLOSED &&
+ BUF->destport == uip_connr->lport &&
+ BUF->srcport == uip_connr->rport &&
+ uip_ipaddr_cmp(BUF->srcipaddr, uip_connr->ripaddr))
+ {
+ goto found;
+ }
+ }
+
+ /* If we didn't find and active connection that expected the packet,
+ either this packet is an old duplicate, or this is a SYN packet
+ destined for a connection in LISTEN. If the SYN flag isn't set,
+ it is an old packet and we send a RST. */
+ if ((BUF->flags & TCP_CTL) != TCP_SYN)
+ {
+ goto reset;
+ }
+
+ tmp16 = BUF->destport;
+
+ /* Next, check listening connections. */
+ for(c = 0; c < 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:
+
+ /* We do not send resets in response to resets. */
+ if (BUF->flags & TCP_RST)
+ {
+ goto drop;
+ }
+
+ UIP_STAT(++uip_stat.tcp.rst);
+
+ BUF->flags = TCP_RST | TCP_ACK;
+ uip_len = UIP_IPTCPH_LEN;
+ BUF->tcpoffset = 5 << 4;
+
+ /* Flip the seqno and ackno fields in the TCP header. */
+ c = BUF->seqno[3];
+ BUF->seqno[3] = BUF->ackno[3];
+ BUF->ackno[3] = c;
+
+ c = BUF->seqno[2];
+ BUF->seqno[2] = BUF->ackno[2];
+ BUF->ackno[2] = c;
+
+ c = BUF->seqno[1];
+ BUF->seqno[1] = BUF->ackno[1];
+ BUF->ackno[1] = c;
+
+ c = BUF->seqno[0];
+ BUF->seqno[0] = BUF->ackno[0];
+ BUF->ackno[0] = c;
+
+ /* We also have to increase the sequence number we are
+ acknowledging. If the least significant byte overflowed, we need
+ to propagate the carry to the other bytes as well. */
+ if (++BUF->ackno[3] == 0)
+ {
+ if (++BUF->ackno[2] == 0)
+ {
+ if (++BUF->ackno[1] == 0)
+ {
+ ++BUF->ackno[0];
+ }
+ }
+ }
+
+ /* Swap port numbers. */
+ tmp16 = BUF->srcport;
+ BUF->srcport = BUF->destport;
+ BUF->destport = tmp16;
+
+ /* Swap IP addresses. */
+ uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
+ uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
+
+ /* And send out the RST packet! */
+ goto tcp_send_noconn;
+
+ /* This label will be jumped to if we matched the incoming packet
+ with a connection in LISTEN. In that case, we should create a new
+ connection and send a SYNACK in return. */
+ found_listen:
+ /* First we check if there are any connections avaliable. Unused
+ connections are kept in the same table as used connections, but
+ unused ones have the tcpstate set to CLOSED. Also, connections in
+ TIME_WAIT are kept track of and we'll use the oldest one if no
+ CLOSED connections are found. Thanks to Eddie C. Dost for a very
+ nice algorithm for the TIME_WAIT search. */
+ uip_connr = 0;
+ for(c = 0; c < UIP_CONNS; ++c)
+ {
+ if (uip_conns[c].tcpstateflags == UIP_CLOSED)
+ {
+ uip_connr = &uip_conns[c];
+ break;
+ }
+ if (uip_conns[c].tcpstateflags == UIP_TIME_WAIT)
+ {
+ if (uip_connr == 0 || uip_conns[c].timer > uip_connr->timer)
+ {
+ uip_connr = &uip_conns[c];
+ }
+ }
+ }
+
+ if (uip_connr == 0)
+ {
+ /* All connections are used already, we drop packet and hope that
+ the remote end will retransmit the packet at a time when we
+ have more spare connections. */
+ UIP_STAT(++uip_stat.tcp.syndrop);
+ UIP_LOG("tcp: found no unused connections.");
+ goto drop;
+ }
+ uip_conn = uip_connr;
+
+ /* Fill in the necessary fields for the new connection. */
+ uip_connr->rto = uip_connr->timer = UIP_RTO;
+ uip_connr->sa = 0;
+ uip_connr->sv = 4;
+ uip_connr->nrtx = 0;
+ uip_connr->lport = BUF->destport;
+ uip_connr->rport = BUF->srcport;
+ uip_ipaddr_copy(uip_connr->ripaddr, BUF->srcipaddr);
+ uip_connr->tcpstateflags = UIP_SYN_RCVD;
+
+ uip_connr->snd_nxt[0] = iss[0];
+ uip_connr->snd_nxt[1] = iss[1];
+ uip_connr->snd_nxt[2] = iss[2];
+ uip_connr->snd_nxt[3] = iss[3];
+ uip_connr->len = 1;
+
+ /* rcv_nxt should be the seqno from the incoming packet + 1. */
+ uip_connr->rcv_nxt[3] = BUF->seqno[3];
+ uip_connr->rcv_nxt[2] = BUF->seqno[2];
+ uip_connr->rcv_nxt[1] = BUF->seqno[1];
+ uip_connr->rcv_nxt[0] = BUF->seqno[0];
+ uip_add_rcv_nxt(1);
+
+ /* Parse the TCP MSS option, if present. */
+ if ((BUF->tcpoffset & 0xf0) > 0x50)
+ {
+ for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;)
+ {
+ opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c];
+ if (opt == TCP_OPT_END)
+ {
+ /* End of options. */
+ break;
+ }
+ else if (opt == TCP_OPT_NOOP)
+ {
+ ++c;
+ /* NOP option. */
+ }
+ else if (opt == TCP_OPT_MSS &&
+ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN)
+ {
+ /* An MSS option with the right option length. */
+ tmp16 = ((uint16)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
+ (uint16)uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c];
+ uip_connr->initialmss = uip_connr->mss =
+ tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
+
+ /* And we are done processing options. */
+ break;
+ }
+ else
+ {
+ /* All other options have a length field, so that we easily
+ can skip past them. */
+ if (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0)
+ {
+ /* If the length field is zero, the options are malformed
+ and we don't process them further. */
+ break;
+ }
+ c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
+ }
+ }
+ }
+
+ /* Our response will be a SYNACK. */
+#if UIP_ACTIVE_OPEN
+ tcp_send_synack:
+ BUF->flags = TCP_ACK;
+
+ tcp_send_syn:
+ BUF->flags |= TCP_SYN;
+#else /* UIP_ACTIVE_OPEN */
+ tcp_send_synack:
+ BUF->flags = TCP_SYN | TCP_ACK;
+#endif /* UIP_ACTIVE_OPEN */
+
+ /* We send out the TCP Maximum Segment Size option with our
+ SYNACK. */
+ BUF->optdata[0] = TCP_OPT_MSS;
+ BUF->optdata[1] = TCP_OPT_MSS_LEN;
+ BUF->optdata[2] = (UIP_TCP_MSS) / 256;
+ BUF->optdata[3] = (UIP_TCP_MSS) & 255;
+ uip_len = UIP_IPTCPH_LEN + TCP_OPT_MSS_LEN;
+ BUF->tcpoffset = ((UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4) << 4;
+ goto tcp_send;
+
+ /* This label will be jumped to if we found an active connection. */
+ found:
+ uip_conn = uip_connr;
+ uip_flags = 0;
+
+ /* We do a very naive form of TCP reset processing; we just accept
+ * any RST and kill our connection. We should in fact check if the
+ * sequence number of this reset is wihtin our advertised window
+ * before we accept the reset.
+ */
+
+ if (BUF->flags & TCP_RST)
+ {
+ uip_connr->tcpstateflags = UIP_CLOSED;
+ UIP_LOG("tcp: got reset, aborting connection.");
+ uip_flags = UIP_ABORT;
+ uip_event_signal();
+ uip_interrupt_event();
+ goto drop;
+ }
+
+ /* Calculated 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
+ * calculated by subtracing the length of the TCP header (in
+ * c) and the length of the IP header (20 bytes).
+ */
+
+ uip_len = uip_len - c - UIP_IPH_LEN;
+
+ /* First, check if the sequence number of the incoming packet is
+ * what we're expecting next. If not, we send out an ACK with the
+ * correct numbers in.
+ */
+
+ if (!(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) &&
+ ((BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK))))
+ {
+ if ((uip_len > 0 || ((BUF->flags & (TCP_SYN | TCP_FIN)) != 0)) &&
+ (BUF->seqno[0] != uip_connr->rcv_nxt[0] ||
+ BUF->seqno[1] != uip_connr->rcv_nxt[1] ||
+ BUF->seqno[2] != uip_connr->rcv_nxt[2] ||
+ BUF->seqno[3] != uip_connr->rcv_nxt[3]))
+ {
+ goto tcp_send_ack;
+ }
+ }
+
+ /* Next, check if the incoming segment acknowledges any outstanding
+ data. If so, we update the sequence number, reset the length of
+ the outstanding data, calculate RTT estimations, and reset the
+ retransmission timer. */
+ if ((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr))
+ {
+ uip_add32(uip_connr->snd_nxt, uip_connr->len);
+
+ if (BUF->ackno[0] == uip_acc32[0] &&
+ BUF->ackno[1] == uip_acc32[1] &&
+ BUF->ackno[2] == uip_acc32[2] &&
+ BUF->ackno[3] == uip_acc32[3])
+ {
+ /* Update sequence number. */
+ uip_connr->snd_nxt[0] = uip_acc32[0];
+ uip_connr->snd_nxt[1] = uip_acc32[1];
+ 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;
+ m = uip_connr->rto - uip_connr->timer;
+
+ /* This is taken directly from VJs original code in his paper */
+ m = m - (uip_connr->sa >> 3);
+ uip_connr->sa += m;
+ if (m < 0)
+ {
+ m = -m;
+ }
+ m = m - (uip_connr->sv >> 2);
+ uip_connr->sv += m;
+ uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv;
+ }
+
+ /* Set the acknowledged flag. */
+ uip_flags = UIP_ACKDATA;
+
+ /* Reset the retransmission timer. */
+ uip_connr->timer = uip_connr->rto;
+
+ /* Reset length of outstanding data. */
+ uip_connr->len = 0;
+ }
+ }
+
+ /* Do different things depending on in what state the connection is. */
+ switch(uip_connr->tcpstateflags & UIP_TS_MASK)
+ {
+ /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not
+ implemented, since we force the application to close when the
+ peer sends a FIN (hence the application goes directly from
+ ESTABLISHED to LAST_ACK). */
+ case UIP_SYN_RCVD:
+ /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and
+ * we are waiting for an ACK that acknowledges the data we sent
+ * out the last time. Therefore, we want to have the UIP_ACKDATA
+ * flag set. If so, we enter the ESTABLISHED state.
+ */
+
+ if (uip_flags & UIP_ACKDATA)
+ {
+ uip_connr->tcpstateflags = UIP_ESTABLISHED;
+ uip_flags = UIP_CONNECTED;
+ uip_connr->len = 0;
+ if (uip_len > 0)
+ {
+ uip_flags |= UIP_NEWDATA;
+ uip_add_rcv_nxt(uip_len);
+ }
+ uip_slen = 0;
+ uip_event_signal();
+ uip_interrupt_event();
+ goto appsend;
+ }
+ goto drop;
+
+#if UIP_ACTIVE_OPEN
+ case UIP_SYN_SENT:
+ /* In SYN_SENT, we wait for a SYNACK that is sent in response to
+ our SYN. The rcv_nxt is set to sequence number in the SYNACK
+ plus one, and we send an ACK. We move into the ESTABLISHED
+ state. */
+ if ((uip_flags & UIP_ACKDATA) &&
+ (BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK))
+ {
+ /* Parse the TCP MSS option, if present. */
+ if ((BUF->tcpoffset & 0xf0) > 0x50)
+ {
+ for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;)
+ {
+ opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c];
+ if (opt == TCP_OPT_END)
+ {
+ /* End of options. */
+ break;
+ }
+ else if (opt == TCP_OPT_NOOP)
+ {
+ ++c;
+ /* NOP option. */
+ }
+ else if (opt == TCP_OPT_MSS &&
+ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN)
+ {
+ /* An MSS option with the right option length. */
+ tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
+ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c];
+ uip_connr->initialmss =
+ uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
+
+ /* And we are done processing options. */
+ break;
+ }
+ else
+ {
+ /* All other options have a length field, so that we easily
+ can skip past them. */
+ if (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0)
+ {
+ /* If the length field is zero, the options are malformed
+ and we don't process them further. */
+ break;
+ }
+ c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
+ }
+ }
+ }
+ uip_connr->tcpstateflags = UIP_ESTABLISHED;
+ uip_connr->rcv_nxt[0] = BUF->seqno[0];
+ uip_connr->rcv_nxt[1] = BUF->seqno[1];
+ uip_connr->rcv_nxt[2] = BUF->seqno[2];
+ uip_connr->rcv_nxt[3] = BUF->seqno[3];
+ uip_add_rcv_nxt(1);
+ uip_flags = UIP_CONNECTED | UIP_NEWDATA;
+ uip_connr->len = 0;
+ uip_len = 0;
+ uip_slen = 0;
+ uip_event_signal();
+ uip_interrupt_event();
+ goto appsend;
+ }
+
+ /* Inform the application that the connection failed */
+ uip_flags = UIP_ABORT;
+ uip_event_signal();
+ uip_interrupt_event();
+
+ /* The connection is closed after we send the RST */
+ uip_conn->tcpstateflags = UIP_CLOSED;
+ goto reset;
+#endif /* UIP_ACTIVE_OPEN */
+
+ case UIP_ESTABLISHED:
+ /* In the ESTABLISHED state, we call upon the application to feed
+ data into the uip_buf. If the UIP_ACKDATA flag is set, the
+ application should put new data into the buffer, otherwise we are
+ retransmitting an old segment, and the application should put that
+ data into the buffer.
+
+ If the incoming packet is a FIN, we should close the connection on
+ this side as well, and we send out a FIN and enter the LAST_ACK
+ state. We require that there is no outstanding data; otherwise the
+ sequence numbers will be screwed up. */
+
+ if (BUF->flags & TCP_FIN && !(uip_connr->tcpstateflags & UIP_STOPPED))
+ {
+ if (uip_outstanding(uip_connr))
+ {
+ goto drop;
+ }
+ uip_add_rcv_nxt(1 + uip_len);
+ uip_flags |= UIP_CLOSE;
+ if (uip_len > 0)
+ {
+ uip_flags |= UIP_NEWDATA;
+ }
+ uip_event_signal();
+ uip_interrupt_event();
+ uip_connr->len = 1;
+ uip_connr->tcpstateflags = UIP_LAST_ACK;
+ uip_connr->nrtx = 0;
+
+ tcp_send_finack:
+ BUF->flags = TCP_FIN | TCP_ACK;
+ goto tcp_send_nodata;
+ }
+
+ /* Check the URG flag. If this is set, the segment carries urgent
+ data that we must pass to the application. */
+ if ((BUF->flags & TCP_URG) != 0)
+ {
+#if UIP_URGDATA > 0
+ uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1];
+ if (uip_urglen > uip_len)
+ {
+ /* There is more urgent data in the next segment to come. */
+ uip_urglen = uip_len;
+ }
+ uip_add_rcv_nxt(uip_urglen);
+ uip_len -= uip_urglen;
+ uip_urgdata = uip_appdata;
+ uip_appdata += uip_urglen;
+ }
+ else
+ {
+ uip_urglen = 0;
+#else /* UIP_URGDATA > 0 */
+ uip_appdata = ((char *)uip_appdata) + ((BUF->urgp[0] << 8) | BUF->urgp[1]);
+ uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1];
+#endif /* UIP_URGDATA > 0 */
+ }
+
+ /* If uip_len > 0 we have TCP data in the packet, and we flag this
+ by setting the UIP_NEWDATA flag and update the sequence number
+ we acknowledge. If the application has stopped the dataflow
+ using uip_stop(), we must not accept any data packets from the
+ remote host. */
+ if (uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED))
+ {
+ uip_flags |= UIP_NEWDATA;
+ uip_add_rcv_nxt(uip_len);
+ }
+
+ /* Check if the available buffer space advertised by the other end
+ is smaller than the initial MSS for this connection. If so, we
+ set the current MSS to the window size to ensure that the
+ application does not send more data than the other end can
+ handle.
+
+ If the remote host advertises a zero window, we set the MSS to
+ the initial MSS so that the application will send an entire MSS
+ of data. This data will not be acknowledged by the receiver,
+ and the application will retransmit it. This is called the
+ "persistent timer" and uses the retransmission mechanim.
+ */
+ tmp16 = ((uint16)BUF->wnd[0] << 8) + (uint16)BUF->wnd[1];
+ if (tmp16 > uip_connr->initialmss || tmp16 == 0)
+ {
+ tmp16 = uip_connr->initialmss;
+ }
+ uip_connr->mss = tmp16;
+
+ /* If this packet constitutes an ACK for outstanding data (flagged
+ by the UIP_ACKDATA flag, we should call the application since it
+ might want to send more data. If the incoming packet had data
+ from the peer (as flagged by the UIP_NEWDATA flag), the
+ application must also be notified.
+
+ When the application is called, the global variable uip_len
+ contains the length of the incoming data. The application can
+ access the incoming data through the global pointer
+ uip_appdata, which usually points UIP_IPTCPH_LEN + UIP_LLH_LEN
+ bytes into the uip_buf array.
+
+ If the application wishes to send any data, this data should be
+ put into the uip_appdata and the length of the data should be
+ put into uip_len. If the application don't have any data to
+ send, uip_len must be set to 0. */
+ if (uip_flags & (UIP_NEWDATA | UIP_ACKDATA))
+ {
+ uip_slen = 0;
+ uip_event_signal();
+ uip_interrupt_event();
+
+ appsend:
+ if (uip_flags & UIP_ABORT)
+ {
+ uip_slen = 0;
+ uip_connr->tcpstateflags = UIP_CLOSED;
+ BUF->flags = TCP_RST | TCP_ACK;
+ goto tcp_send_nodata;
+ }
+
+ if (uip_flags & UIP_CLOSE)
+ {
+ uip_slen = 0;
+ uip_connr->len = 1;
+ uip_connr->tcpstateflags = UIP_FIN_WAIT_1;
+ uip_connr->nrtx = 0;
+ BUF->flags = TCP_FIN | TCP_ACK;
+ goto tcp_send_nodata;
+ }
+
+ /* If uip_slen > 0, the application has data to be sent. */
+ if (uip_slen > 0)
+ {
+ /* If the connection has acknowledged data, the contents of
+ the ->len variable should be discarded. */
+ if ((uip_flags & UIP_ACKDATA) != 0)
+ {
+ uip_connr->len = 0;
+ }
+
+ /* If the ->len variable is non-zero the connection has
+ already data in transit and cannot send anymore right
+ now. */
+ if (uip_connr->len == 0)
+ {
+ /* The application cannot send more than what is allowed by
+ the mss (the minumum of the MSS and the available
+ window). */
+ if (uip_slen > uip_connr->mss)
+ {
+ uip_slen = uip_connr->mss;
+ }
+
+ /* Remember how much data we send out now so that we know
+ when everything has been acknowledged. */
+ uip_connr->len = uip_slen;
+ }
+ else
+ {
+ /* If the application already had unacknowledged data, we
+ make sure that the application does not send (i.e.,
+ retransmit) out more than it previously sent out. */
+ uip_slen = uip_connr->len;
+ }
+ }
+ uip_connr->nrtx = 0;
+ apprexmit:
+ uip_appdata = uip_sappdata;
+
+ /* If the application has data to be sent, or if the incoming
+ packet had new data in it, we must send out a packet. */
+ if (uip_slen > 0 && uip_connr->len > 0)
+ {
+ /* Add the length of the IP and TCP headers. */
+ uip_len = uip_connr->len + UIP_TCPIP_HLEN;
+
+ /* We always set the ACK flag in response packets. */
+ BUF->flags = TCP_ACK | TCP_PSH;
+
+ /* Send the packet. */
+ goto tcp_send_noopts;
+ }
+
+ /* If there is no data to send, just send out a pure ACK if
+ there is newdata. */
+ if (uip_flags & UIP_NEWDATA)
+ {
+ uip_len = UIP_TCPIP_HLEN;
+ BUF->flags = TCP_ACK;
+ goto tcp_send_noopts;
+ }
+ }
+ goto drop;
+
+ case UIP_LAST_ACK:
+ /* We can close this connection if the peer has acknowledged our
+ FIN. This is indicated by the UIP_ACKDATA flag. */
+ if (uip_flags & UIP_ACKDATA)
+ {
+ uip_connr->tcpstateflags = UIP_CLOSED;
+ uip_flags = UIP_CLOSE;
+ uip_event_signal();
+ uip_interrupt_event();
+ }
+ break;
+
+ case UIP_FIN_WAIT_1:
+ /* The application has closed the connection, but the remote host
+ hasn't closed its end yet. Thus we do nothing but wait for a
+ FIN from the other side. */
+ if (uip_len > 0)
+ {
+ uip_add_rcv_nxt(uip_len);
+ }
+ if (BUF->flags & TCP_FIN)
+ {
+ if (uip_flags & UIP_ACKDATA)
+ {
+ uip_connr->tcpstateflags = UIP_TIME_WAIT;
+ uip_connr->timer = 0;
+ uip_connr->len = 0;
+ }
+ else
+ {
+ uip_connr->tcpstateflags = UIP_CLOSING;
+ }
+ uip_add_rcv_nxt(1);
+ uip_flags = UIP_CLOSE;
+ uip_event_signal();
+ uip_interrupt_event();
+ goto tcp_send_ack;
+ }
+ else if (uip_flags & UIP_ACKDATA)
+ {
+ uip_connr->tcpstateflags = UIP_FIN_WAIT_2;
+ uip_connr->len = 0;
+ goto drop;
+ }
+ if (uip_len > 0)
+ {
+ goto tcp_send_ack;
+ }
+ goto drop;
+
+ case UIP_FIN_WAIT_2:
+ if (uip_len > 0)
+ {
+ uip_add_rcv_nxt(uip_len);
+ }
+ if (BUF->flags & TCP_FIN)
+ {
+ uip_connr->tcpstateflags = UIP_TIME_WAIT;
+ uip_connr->timer = 0;
+ uip_add_rcv_nxt(1);
+ uip_flags = UIP_CLOSE;
+ uip_event_signal();
+ uip_interrupt_event();
+ goto tcp_send_ack;
+ }
+ if (uip_len > 0)
+ {
+ goto tcp_send_ack;
+ }
+ goto drop;
+
+ case UIP_TIME_WAIT:
+ goto tcp_send_ack;
+
+ case UIP_CLOSING:
+ if (uip_flags & UIP_ACKDATA)
+ {
+ uip_connr->tcpstateflags = UIP_TIME_WAIT;
+ uip_connr->timer = 0;
+ }
+ }
+ 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. */
+ BUF->ackno[0] = uip_connr->rcv_nxt[0];
+ BUF->ackno[1] = uip_connr->rcv_nxt[1];
+ BUF->ackno[2] = uip_connr->rcv_nxt[2];
+ BUF->ackno[3] = uip_connr->rcv_nxt[3];
+
+ BUF->seqno[0] = uip_connr->snd_nxt[0];
+ BUF->seqno[1] = uip_connr->snd_nxt[1];
+ BUF->seqno[2] = uip_connr->snd_nxt[2];
+ BUF->seqno[3] = uip_connr->snd_nxt[3];
+
+ BUF->proto = UIP_PROTO_TCP;
+
+ 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);
+
+ if (uip_connr->tcpstateflags & UIP_STOPPED)
+ {
+ /* If the connection has issued uip_stop(), we advertise a zero
+ window so that the remote host will stop sending data. */
+ BUF->wnd[0] = BUF->wnd[1] = 0;
+ }
+ else
+ {
+ BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8);
+ BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff);
+ }
+
+ tcp_send_noconn:
+ BUF->ttl = UIP_TTL;
+#ifdef CONFIG_NET_UIP_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 /* CONFIG_NET_UIP_IPv6 */
+ BUF->len[0] = (uip_len >> 8);
+ BUF->len[1] = (uip_len & 0xff);
+#endif /* CONFIG_NET_UIP_IPv6 */
+
+ BUF->urgp[0] = BUF->urgp[1] = 0;
+
+ /* Calculate TCP checksum. */
+ BUF->tcpchksum = 0;
+ BUF->tcpchksum = ~(uip_tcpchksum());
+
+#if UIP_UDP
+ ip_send_nolen:
+#endif /* UIP_UDP */
+
+#ifdef CONFIG_NET_UIP_IPv6
+ BUF->vtc = 0x60;
+ BUF->tcflow = 0x00;
+ BUF->flow = 0x00;
+#else /* CONFIG_NET_UIP_IPv6 */
+ BUF->vhl = 0x45;
+ BUF->tos = 0;
+ BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
+ ++ipid;
+ BUF->ipid[0] = ipid >> 8;
+ BUF->ipid[1] = ipid & 0xff;
+
+ /* Calculate IP checksum. */
+ BUF->ipchksum = 0;
+ BUF->ipchksum = ~(uip_ipchksum());
+ dbg("uip ip_send_nolen: chkecum 0x%04x\n", uip_ipchksum());
+#endif /* CONFIG_NET_UIP_IPv6 */
+
+ UIP_STAT(++uip_stat.tcp.sent);
+ send:
+ dbg("Sending packet with length %d (%d)\n", uip_len,
+ (BUF->len[0] << 8) | BUF->len[1]);
+
+ UIP_STAT(++uip_stat.ip.sent);
+
+ /* Return and let the caller do the actual transmission. */
+ uip_flags = 0;
+ return;
+ drop:
+ uip_len = 0;
+ uip_flags = 0;
+ return;
+}
+
+uint16 htons(uint16 val)
+{
+ return HTONS(val);
+}
+
+void uip_send(const void *data, int len)
+{
+ if (len > 0)
+ {
+ uip_slen = len;
+ if (data != uip_sappdata)
+ {
+ memcpy(uip_sappdata, (data), uip_slen);
+ }
+ }
+}
diff --git a/nuttx/netutils/Makefile b/nuttx/netutils/Makefile
new file mode 100644
index 000000000..0534f59d1
--- /dev/null
+++ b/nuttx/netutils/Makefile
@@ -0,0 +1,97 @@
+############################################################
+# Makefile
+#
+# Copyright (C) 2007 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name NuttX nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################
+
+-include $(TOPDIR)/Make.defs
+
+MKDEP = $(TOPDIR)/tools/mkdeps.sh
+
+ifeq ($(CONFIG_NET_UIP),y)
+include uiplib/Make.defs
+include dhcpc/Make.defs
+include resolv/Make.defs
+include smtp/Make.defs
+include telnetd/Make.defs
+include webclient/Make.defs
+include webserver/Make.defs
+endif
+
+ASRCS = $(UIPLIB_ASRCS) $(DHCPC_ASRCS) $(RESOLV_ASRCS) $(SMTP_ASRCS) \
+ $(TELNETD_ASRCS) $(WEBCLIENT_ASRCS) $(WEBSERVER_ASRCS)
+AOBJS = $(ASRCS:.S=$(OBJEXT))
+
+CSRCS = $(UIPLIB_CSRCS) $(DHCPC_CSRCS) $(RESOLV_CSRCS) $(SMTP_CSRCS) \
+ $(TELNETD_CSRCS) $(WEBCLIENT_CSRCS) $(WEBSERVER_CSRCS)
+COBJS = $(CSRCS:.c=$(OBJEXT))
+
+SRCS = $(ASRCS) $(CSRCS)
+OBJS = $(AOBJS) $(COBJS)
+
+BIN = libnetutils$(LIBEXT)
+
+VPATH = uiplib:dhcpc:resolv:smtp:telnetd:webclient:webserver
+
+all: $(BIN)
+
+$(AOBJS): %$(OBJEXT): %.S
+ $(CC) -c $(CFLAGS) -D__ASSEMBLY__ $< -o $@
+
+$(COBJS): %$(OBJEXT): %.c
+ $(CC) -c $(CFLAGS) $< -o $@
+
+$(BIN): $(OBJS)
+ ( for obj in $(OBJS) ; do \
+ $(AR) $@ $${obj} || \
+ { echo "$(AR) $@ $obj FAILED!" ; exit 1 ; } ; \
+ done ; )
+
+.depend: Makefile $(SRCS)
+ifeq ($(CONFIG_NET_UIP),y)
+ $(MKDEP) --dep-path uiplib --dep-path dhcpc --dep-path smtp --dep-path webclient \
+ --dep-path resolv --dep-path telnetd --dep-path webserver \
+ $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep
+endif
+ touch $@
+
+depend: .depend
+
+clean:
+ rm -f $(BIN) *.o *.rel *.asm *.lst *.sym *.adb *~
+ rm -f uiplib/*~ dhcpc/*~ resolv/*~ smtp/*~ telnetd/*~ webclient/*~ webserver/*~
+ if [ ! -z "$(OBJEXT)" ]; then rm -f *$(OBJEXT); fi
+
+distclean: clean
+ rm -f Make.dep .depend
+
+-include Make.dep
diff --git a/nuttx/netutils/README b/nuttx/netutils/README
new file mode 100644
index 000000000..9f6969b5f
--- /dev/null
+++ b/nuttx/netutils/README
@@ -0,0 +1,5 @@
+netutils
+^^^^^^^^
+
+This directory contains most of the network applications contained under the uIP-1.0 apps directory.
+As the uIP apps/README says, there applications "are not all heavily tested." \ No newline at end of file
diff --git a/nuttx/netutils/dhcpc/Make.defs b/nuttx/netutils/dhcpc/Make.defs
new file mode 100644
index 000000000..b4aa9acbf
--- /dev/null
+++ b/nuttx/netutils/dhcpc/Make.defs
@@ -0,0 +1,39 @@
+############################################################################
+# Make.defs
+#
+# Copyright (C) 2007 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name NuttX nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+ifeq ($(CONFIG_UIP_UDP),y)
+DHCPC_ASRCS =
+DHCPC_CSRCS = dhcpc.c
+endif \ No newline at end of file
diff --git a/nuttx/netutils/dhcpc/dhcpc.c b/nuttx/netutils/dhcpc/dhcpc.c
new file mode 100644
index 000000000..096649b68
--- /dev/null
+++ b/nuttx/netutils/dhcpc/dhcpc.c
@@ -0,0 +1,390 @@
+/************************************************************
+ * dhcpc.c
+ *
+ * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Based heavily on portions of uIP:
+ *
+ * Copyright (c) 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 NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************/
+
+/************************************************************
+ * Included Files
+ ************************************************************/
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+#include <time.h>
+#include <debug.h>
+
+#include <net/uip/uip.h>
+
+#include "dhcpc.h"
+
+/************************************************************
+ * Definitions
+ ************************************************************/
+
+/* CLK_TCK is the frequency of the system clock (typically 100Hz) */
+#define CLOCK_SECOND CLK_TCK
+
+#define STATE_INITIAL 0
+#define STATE_SENDING 1
+#define STATE_OFFER_RECEIVED 2
+#define STATE_CONFIG_RECEIVED 3
+
+#define BOOTP_BROADCAST 0x8000
+
+#define DHCP_REQUEST 1
+#define DHCP_REPLY 2
+#define DHCP_HTYPE_ETHERNET 1
+#define DHCP_HLEN_ETHERNET 6
+#define DHCP_MSG_LEN 236
+
+#define DHCPC_SERVER_PORT 67
+#define DHCPC_CLIENT_PORT 68
+
+#define DHCPDISCOVER 1
+#define DHCPOFFER 2
+#define DHCPREQUEST 3
+#define DHCPDECLINE 4
+#define DHCPACK 5
+#define DHCPNAK 6
+#define DHCPRELEASE 7
+
+#define DHCP_OPTION_SUBNET_MASK 1
+#define DHCP_OPTION_ROUTER 3
+#define DHCP_OPTION_DNS_SERVER 6
+#define DHCP_OPTION_REQ_IPADDR 50
+#define DHCP_OPTION_LEASE_TIME 51
+#define DHCP_OPTION_MSG_TYPE 53
+#define DHCP_OPTION_SERVER_ID 54
+#define DHCP_OPTION_REQ_LIST 55
+#define DHCP_OPTION_END 255
+
+/************************************************************
+ * Private Types
+ ************************************************************/
+
+struct dhcp_msg
+{
+ uint8 op, htype, hlen, hops;
+ uint8 xid[4];
+ uint16 secs, flags;
+ uint8 ciaddr[4];
+ uint8 yiaddr[4];
+ uint8 siaddr[4];
+ uint8 giaddr[4];
+ uint8 chaddr[16];
+#ifndef CONFIG_UIP_DHCP_LIGHT
+ uint8 sname[64];
+ uint8 file[128];
+#endif
+ uint8 options[312];
+};
+
+/************************************************************
+ * Private Data
+ ************************************************************/
+
+static struct dhcpc_state s;
+
+static const uint8 xid[4] = {0xad, 0xde, 0x12, 0x23};
+static const uint8 magic_cookie[4] = {99, 130, 83, 99};
+
+/************************************************************
+ * Private Functions
+ ************************************************************/
+
+static uint8 *add_msg_type(uint8 *optptr, uint8 type)
+{
+ *optptr++ = DHCP_OPTION_MSG_TYPE;
+ *optptr++ = 1;
+ *optptr++ = type;
+ return optptr;
+}
+
+static uint8 *add_server_id(uint8 *optptr)
+{
+ *optptr++ = DHCP_OPTION_SERVER_ID;
+ *optptr++ = 4;
+ memcpy(optptr, s.serverid, 4);
+ return optptr + 4;
+}
+
+static uint8 *add_req_ipaddr(uint8 *optptr)
+{
+ *optptr++ = DHCP_OPTION_REQ_IPADDR;
+ *optptr++ = 4;
+ memcpy(optptr, s.ipaddr, 4);
+ return optptr + 4;
+}
+
+static uint8 *add_req_options(uint8 *optptr)
+{
+ *optptr++ = DHCP_OPTION_REQ_LIST;
+ *optptr++ = 3;
+ *optptr++ = DHCP_OPTION_SUBNET_MASK;
+ *optptr++ = DHCP_OPTION_ROUTER;
+ *optptr++ = DHCP_OPTION_DNS_SERVER;
+ return optptr;
+}
+
+static uint8 *add_end(uint8 *optptr)
+{
+ *optptr++ = DHCP_OPTION_END;
+ return optptr;
+}
+
+static void create_msg(register struct dhcp_msg *m)
+{
+ m->op = DHCP_REQUEST;
+ m->htype = DHCP_HTYPE_ETHERNET;
+ m->hlen = s.mac_len;
+ m->hops = 0;
+ memcpy(m->xid, xid, sizeof(m->xid));
+ m->secs = 0;
+ m->flags = HTONS(BOOTP_BROADCAST); /* Broadcast bit. */
+ /* uip_ipaddr_copy(m->ciaddr, uip_hostaddr);*/
+ memcpy(m->ciaddr, uip_hostaddr, sizeof(m->ciaddr));
+ memset(m->yiaddr, 0, sizeof(m->yiaddr));
+ memset(m->siaddr, 0, sizeof(m->siaddr));
+ memset(m->giaddr, 0, sizeof(m->giaddr));
+ memcpy(m->chaddr, s.mac_addr, s.mac_len);
+ memset(&m->chaddr[s.mac_len], 0, sizeof(m->chaddr) - s.mac_len);
+#ifndef CONFIG_UIP_DHCP_LIGHT
+ memset(m->sname, 0, sizeof(m->sname));
+ memset(m->file, 0, sizeof(m->file));
+#endif
+
+ memcpy(m->options, magic_cookie, sizeof(magic_cookie));
+}
+
+static void send_discover(void)
+{
+ uint8 *end;
+ struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata;
+
+ create_msg(m);
+
+ end = add_msg_type(&m->options[4], DHCPDISCOVER);
+ end = add_req_options(end);
+ end = add_end(end);
+
+ uip_send(uip_appdata, end - (uint8 *)uip_appdata);
+}
+
+static void send_request(void)
+{
+ uint8 *end;
+ struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata;
+
+ create_msg(m);
+
+ end = add_msg_type(&m->options[4], DHCPREQUEST);
+ end = add_server_id(end);
+ end = add_req_ipaddr(end);
+ end = add_end(end);
+
+ uip_send(uip_appdata, end - (uint8 *)uip_appdata);
+}
+
+static uint8 parse_options(uint8 *optptr, int len)
+{
+ uint8 *end = optptr + len;
+ uint8 type = 0;
+
+ while (optptr < end)
+ {
+ switch(*optptr)
+ {
+ case DHCP_OPTION_SUBNET_MASK:
+ memcpy(s.netmask, optptr + 2, 4);
+ break;
+ case DHCP_OPTION_ROUTER:
+ memcpy(s.default_router, optptr + 2, 4);
+ break;
+ case DHCP_OPTION_DNS_SERVER:
+ memcpy(s.dnsaddr, optptr + 2, 4);
+ break;
+ case DHCP_OPTION_MSG_TYPE:
+ type = *(optptr + 2);
+ break;
+ case DHCP_OPTION_SERVER_ID:
+ memcpy(s.serverid, optptr + 2, 4);
+ break;
+ case DHCP_OPTION_LEASE_TIME:
+ memcpy(s.lease_time, optptr + 2, 4);
+ break;
+ case DHCP_OPTION_END:
+ return type;
+ }
+
+ optptr += optptr[1] + 2;
+ }
+ return type;
+}
+
+static uint8 parse_msg(void)
+{
+ struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata;
+
+ if (m->op == DHCP_REPLY &&
+ memcmp(m->xid, xid, sizeof(xid)) == 0 &&
+ memcmp(m->chaddr, s.mac_addr, s.mac_len) == 0)
+ {
+ memcpy(s.ipaddr, m->yiaddr, 4);
+ return parse_options(&m->options[4], uip_datalen());
+ }
+ return 0;
+}
+
+static void handle_dhcp(void)
+{
+restart:
+ s.state = STATE_SENDING;
+ s.ticks = CLOCK_SECOND;
+
+ do
+ {
+ /* Send the command */
+
+ send_discover();
+
+ /* Wait for the response */
+
+ uip_event_timedwait(UIP_NEWDATA, CLOCK_SECOND);
+
+ if (uip_newdata() && parse_msg() == DHCPOFFER)
+ {
+ s.state = STATE_OFFER_RECEIVED;
+ break;
+ }
+
+ if (s.ticks < CLOCK_SECOND * 60)
+ {
+ s.ticks *= 2;
+ }
+ }
+ while(s.state != STATE_OFFER_RECEIVED);
+
+ s.ticks = CLOCK_SECOND;
+
+ do
+ {
+ /* Send the request */
+
+ send_request();
+
+ /* Then wait to received the response */
+
+ uip_event_timedwait(UIP_NEWDATA, CLOCK_SECOND);
+
+ if (uip_newdata() && parse_msg() == DHCPACK)
+ {
+ s.state = STATE_CONFIG_RECEIVED;
+ break;
+ }
+
+ if (s.ticks <= CLOCK_SECOND * 10)
+ {
+ s.ticks += CLOCK_SECOND;
+ }
+ else
+ {
+ goto restart;
+ }
+ }
+ while(s.state != STATE_CONFIG_RECEIVED);
+
+ dbg("Got IP address %d.%d.%d.%d\n",
+ uip_ipaddr1(s.ipaddr), uip_ipaddr2(s.ipaddr),
+ uip_ipaddr3(s.ipaddr), uip_ipaddr4(s.ipaddr));
+ dbg("Got netmask %d.%d.%d.%d\n",
+ uip_ipaddr1(s.netmask), uip_ipaddr2(s.netmask),
+ uip_ipaddr3(s.netmask), uip_ipaddr4(s.netmask));
+ dbg("Got DNS server %d.%d.%d.%d\n",
+ uip_ipaddr1(s.dnsaddr), uip_ipaddr2(s.dnsaddr),
+ uip_ipaddr3(s.dnsaddr), uip_ipaddr4(s.dnsaddr));
+ dbg("Got default router %d.%d.%d.%d\n",
+ uip_ipaddr1(s.default_router), uip_ipaddr2(s.default_router),
+ uip_ipaddr3(s.default_router), uip_ipaddr4(s.default_router));
+ dbg("Lease expires in %ld seconds\n",
+ ntohs(s.lease_time[0])*65536ul + ntohs(s.lease_time[1]));
+
+ dhcpc_configured(&s);
+
+ pthread_exit(NULL);
+}
+
+/************************************************************
+ * Global Functions
+ ************************************************************/
+
+void dhcpc_init(const void *mac_addr, int mac_len)
+{
+ uip_ipaddr_t addr;
+
+ s.mac_addr = mac_addr;
+ s.mac_len = mac_len;
+
+ s.state = STATE_INITIAL;
+ uip_ipaddr(addr, 255,255,255,255);
+ s.conn = uip_udp_new(&addr, HTONS(DHCPC_SERVER_PORT));
+ if (s.conn != NULL)
+ {
+ uip_udp_bind(s.conn, HTONS(DHCPC_CLIENT_PORT));
+ }
+}
+
+/* This function is called by the UIP interrupt handling logic whenevent an
+ * event of interest occurs.
+ */
+
+void uip_interrupt_udp_event(void)
+{
+ handle_dhcp();
+}
+
+void dhcpc_request(void)
+{
+ uint16 ipaddr[2];
+
+ if (s.state == STATE_INITIAL)
+ {
+ uip_ipaddr(ipaddr, 0,0,0,0);
+ uip_sethostaddr(ipaddr);
+ }
+}
diff --git a/nuttx/netutils/dhcpc/dhcpc.h b/nuttx/netutils/dhcpc/dhcpc.h
new file mode 100644
index 000000000..b46ae4dfd
--- /dev/null
+++ b/nuttx/netutils/dhcpc/dhcpc.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 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
+ *
+ * @(#)$Id: dhcpc.h,v 1.1.1.1 2007-08-26 23:07:02 patacongo Exp $
+ */
+#ifndef __DHCPC_H__
+#define __DHCPC_H__
+
+#include <sys/types.h>
+
+struct dhcpc_state {
+ char state;
+ struct uip_udp_conn *conn;
+ uint16 ticks;
+ const void *mac_addr;
+ int mac_len;
+
+ uint8 serverid[4];
+
+ uint16 lease_time[2];
+ uint16 ipaddr[2];
+ uint16 netmask[2];
+ uint16 dnsaddr[2];
+ uint16 default_router[2];
+};
+
+void dhcpc_init(const void *mac_addr, int mac_len);
+void dhcpc_request(void);
+void dhcpc_configured(const struct dhcpc_state *s);
+
+#endif /* __DHCPC_H__ */
diff --git a/nuttx/netutils/resolv/Make.defs b/nuttx/netutils/resolv/Make.defs
new file mode 100644
index 000000000..e83757d36
--- /dev/null
+++ b/nuttx/netutils/resolv/Make.defs
@@ -0,0 +1,39 @@
+############################################################################
+# Make.defs
+#
+# Copyright (C) 2007 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name NuttX nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+ifeq ($(CONFIG_UIP_UDP),y)
+RESOLV_ASRCS =
+RESOLV_CSRCS = resolv.c
+endif
diff --git a/nuttx/netutils/resolv/resolv.c b/nuttx/netutils/resolv/resolv.c
new file mode 100644
index 000000000..0a38faea8
--- /dev/null
+++ b/nuttx/netutils/resolv/resolv.c
@@ -0,0 +1,450 @@
+/* uip-resolv.c
+ * DNS host name to IP address resolver.
+ * Author: Adam Dunkels <adam@dunkels.com>
+ *
+ * The uIP DNS resolver functions are used to lookup a hostname and
+ * map it to a numerical IP address. It maintains a list of resolved
+ * hostnames that can be queried with the resolv_lookup()
+ * function. New hostnames can be resolved using the resolv_query()
+ * function.
+ *
+ * When a hostname has been resolved (or found to be non-existant),
+ * the resolver code calls a callback function called resolv_found()
+ * that must be implemented by the module that uses the resolver.
+ *
+ * Copyright (c) 2002-2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: resolv.c,v 1.1.1.1 2007-08-26 23:07:05 patacongo Exp $
+ *
+ */
+
+#include <sys/types.h>
+#include <string.h>
+
+#include <net/uip/uip.h>
+#include <net/uip/resolv.h>
+
+#ifndef NULL
+#define NULL (void *)0
+#endif /* NULL */
+
+/** \internal The maximum number of retries when asking for a name. */
+#define MAX_RETRIES 8
+
+/** \internal The DNS message header. */
+struct dns_hdr {
+ uint16 id;
+ uint8 flags1, flags2;
+#define DNS_FLAG1_RESPONSE 0x80
+#define DNS_FLAG1_OPCODE_STATUS 0x10
+#define DNS_FLAG1_OPCODE_INVERSE 0x08
+#define DNS_FLAG1_OPCODE_STANDARD 0x00
+#define DNS_FLAG1_AUTHORATIVE 0x04
+#define DNS_FLAG1_TRUNC 0x02
+#define DNS_FLAG1_RD 0x01
+#define DNS_FLAG2_RA 0x80
+#define DNS_FLAG2_ERR_MASK 0x0f
+#define DNS_FLAG2_ERR_NONE 0x00
+#define DNS_FLAG2_ERR_NAME 0x03
+ uint16 numquestions;
+ uint16 numanswers;
+ uint16 numauthrr;
+ uint16 numextrarr;
+};
+
+/** \internal The DNS answer message structure. */
+struct dns_answer {
+ /* DNS answer record starts with either a domain name or a pointer
+ to a name already present somewhere in the packet. */
+ uint16 type;
+ uint16 class;
+ uint16 ttl[2];
+ uint16 len;
+ uip_ipaddr_t ipaddr;
+};
+
+struct namemap {
+#define STATE_UNUSED 0
+#define STATE_NEW 1
+#define STATE_ASKING 2
+#define STATE_DONE 3
+#define STATE_ERROR 4
+ uint8 state;
+ uint8 tmr;
+ uint8 retries;
+ uint8 seqno;
+ uint8 err;
+ char name[32];
+ uip_ipaddr_t ipaddr;
+};
+
+#ifndef CONFIG_UIP_RESOLV_ENTRIES
+#define RESOLV_ENTRIES 4
+#else /* CONFIG_UIP_RESOLV_ENTRIES */
+#define RESOLV_ENTRIES CONFIG_UIP_RESOLV_ENTRIES
+#endif /* CONFIG_UIP_RESOLV_ENTRIES */
+
+
+static struct namemap names[RESOLV_ENTRIES];
+
+static uint8 seqno;
+
+static struct uip_udp_conn *resolv_conn = NULL;
+
+
+/*---------------------------------------------------------------------------*/
+/** \internal
+ * Walk through a compact encoded DNS name and return the end of it.
+ *
+ * \return The end of the name.
+ */
+/*---------------------------------------------------------------------------*/
+static unsigned char *parse_name(unsigned char *query)
+{
+ unsigned char n;
+
+ do {
+ n = *query++;
+
+ while(n > 0)
+ {
+ ++query;
+ --n;
+ };
+ } while(*query != 0);
+ return query + 1;
+}
+
+/*---------------------------------------------------------------------------*/
+/** \internal
+ * Runs through the list of names to see if there are any that have
+ * not yet been queried and, if so, sends out a query.
+ */
+/*---------------------------------------------------------------------------*/
+static void
+check_entries(void)
+{
+ register struct dns_hdr *hdr;
+ char *query, *nptr, *nameptr;
+ static uint8 i;
+ static uint8 n;
+ register struct namemap *namemapptr;
+
+ for(i = 0; i < RESOLV_ENTRIES; ++i) {
+ namemapptr = &names[i];
+ if(namemapptr->state == STATE_NEW ||
+ namemapptr->state == STATE_ASKING) {
+ if(namemapptr->state == STATE_ASKING) {
+ if(--namemapptr->tmr == 0) {
+ if(++namemapptr->retries == MAX_RETRIES) {
+ namemapptr->state = STATE_ERROR;
+ resolv_found(namemapptr->name, NULL);
+ continue;
+ }
+ namemapptr->tmr = namemapptr->retries;
+ } else {
+ /* printf("Timer %d\n", namemapptr->tmr);*/
+ /* Its timer has not run out, so we move on to next
+ entry. */
+ continue;
+ }
+ } else {
+ namemapptr->state = STATE_ASKING;
+ namemapptr->tmr = 1;
+ namemapptr->retries = 0;
+ }
+ hdr = (struct dns_hdr *)uip_appdata;
+ memset(hdr, 0, sizeof(struct dns_hdr));
+ hdr->id = htons(i);
+ hdr->flags1 = DNS_FLAG1_RD;
+ hdr->numquestions = HTONS(1);
+ query = (char *)uip_appdata + 12;
+ nameptr = namemapptr->name;
+ --nameptr;
+ /* Convert hostname into suitable query format. */
+ do {
+ ++nameptr;
+ nptr = query;
+ ++query;
+ for(n = 0; *nameptr != '.' && *nameptr != 0; ++nameptr) {
+ *query = *nameptr;
+ ++query;
+ ++n;
+ }
+ *nptr = n;
+ } while(*nameptr != 0);
+ {
+ static unsigned char endquery[] =
+ {0,0,1,0,1};
+ memcpy(query, endquery, 5);
+ }
+ uip_udp_send((unsigned char)(query + 5 - (char *)uip_appdata));
+ break;
+ }
+ }
+}
+/*---------------------------------------------------------------------------*/
+/** \internal
+ * Called when new UDP data arrives.
+ */
+/*---------------------------------------------------------------------------*/
+static void
+newdata(void)
+{
+ unsigned char *nameptr;
+ struct dns_answer *ans;
+ struct dns_hdr *hdr;
+ static uint8 nquestions, nanswers;
+ static uint8 i;
+ register struct namemap *namemapptr;
+
+ hdr = (struct dns_hdr *)uip_appdata;
+ /* printf("ID %d\n", htons(hdr->id));
+ printf("Query %d\n", hdr->flags1 & DNS_FLAG1_RESPONSE);
+ printf("Error %d\n", hdr->flags2 & DNS_FLAG2_ERR_MASK);
+ printf("Num questions %d, answers %d, authrr %d, extrarr %d\n",
+ htons(hdr->numquestions),
+ htons(hdr->numanswers),
+ htons(hdr->numauthrr),
+ htons(hdr->numextrarr));
+ */
+
+ /* The ID in the DNS header should be our entry into the name
+ table. */
+ i = htons(hdr->id);
+ namemapptr = &names[i];
+ if(i < RESOLV_ENTRIES &&
+ namemapptr->state == STATE_ASKING) {
+
+ /* This entry is now finished. */
+ namemapptr->state = STATE_DONE;
+ namemapptr->err = hdr->flags2 & DNS_FLAG2_ERR_MASK;
+
+ /* Check for error. If so, call callback to inform. */
+ if(namemapptr->err != 0) {
+ namemapptr->state = STATE_ERROR;
+ resolv_found(namemapptr->name, NULL);
+ return;
+ }
+
+ /* We only care about the question(s) and the answers. The authrr
+ and the extrarr are simply discarded. */
+ nquestions = htons(hdr->numquestions);
+ nanswers = htons(hdr->numanswers);
+
+ /* Skip the name in the question. XXX: This should really be
+ checked agains the name in the question, to be sure that they
+ match. */
+ nameptr = parse_name((unsigned char *)uip_appdata + 12) + 4;
+
+ while(nanswers > 0) {
+ /* The first byte in the answer resource record determines if it
+ is a compressed record or a normal one. */
+ if(*nameptr & 0xc0) {
+ /* Compressed name. */
+ nameptr +=2;
+ /* printf("Compressed anwser\n");*/
+ } else {
+ /* Not compressed name. */
+ nameptr = parse_name(nameptr);
+ }
+
+ ans = (struct dns_answer *)nameptr;
+ /* printf("Answer: type %x, class %x, ttl %x, length %x\n",
+ htons(ans->type), htons(ans->class), (htons(ans->ttl[0])
+ << 16) | htons(ans->ttl[1]), htons(ans->len));*/
+
+ /* Check for IP address type and Internet class. Others are
+ discarded. */
+ if(ans->type == HTONS(1) &&
+ ans->class == HTONS(1) &&
+ ans->len == HTONS(4)) {
+ /* printf("IP address %d.%d.%d.%d\n",
+ htons(ans->ipaddr[0]) >> 8,
+ htons(ans->ipaddr[0]) & 0xff,
+ htons(ans->ipaddr[1]) >> 8,
+ htons(ans->ipaddr[1]) & 0xff);*/
+ /* XXX: we should really check that this IP address is the one
+ we want. */
+ namemapptr->ipaddr[0] = ans->ipaddr[0];
+ namemapptr->ipaddr[1] = ans->ipaddr[1];
+
+ resolv_found(namemapptr->name, namemapptr->ipaddr);
+ return;
+ } else {
+ nameptr = nameptr + 10 + htons(ans->len);
+ }
+ --nanswers;
+ }
+ }
+
+}
+
+/* This function is called by the UIP interrupt handling logic whenevent an
+ * event of interest occurs.
+ */
+
+void uip_interrupt_udp_event(void)
+{
+ if(uip_udp_conn->rport == HTONS(53))
+ {
+ if(uip_poll())
+ {
+ check_entries();
+ }
+ if(uip_newdata())
+ {
+ newdata();
+ }
+ }
+}
+
+/**
+ * Queues a name so that a question for the name will be sent out.
+ *
+ * \param name The hostname that is to be queried.
+ */
+/*---------------------------------------------------------------------------*/
+void
+resolv_query(char *name)
+{
+ static uint8 i;
+ static uint8 lseq, lseqi;
+ register struct namemap *nameptr;
+
+ lseq = lseqi = 0;
+
+ for(i = 0; i < RESOLV_ENTRIES; ++i) {
+ nameptr = &names[i];
+ if(nameptr->state == STATE_UNUSED) {
+ break;
+ }
+ if(seqno - nameptr->seqno > lseq) {
+ lseq = seqno - nameptr->seqno;
+ lseqi = i;
+ }
+ }
+
+ if(i == RESOLV_ENTRIES) {
+ i = lseqi;
+ nameptr = &names[i];
+ }
+
+ /* printf("Using entry %d\n", i);*/
+
+ strcpy(nameptr->name, name);
+ nameptr->state = STATE_NEW;
+ nameptr->seqno = seqno;
+ ++seqno;
+}
+/*---------------------------------------------------------------------------*/
+/**
+ * Look up a hostname in the array of known hostnames.
+ *
+ * \note This function only looks in the internal array of known
+ * hostnames, it does not send out a query for the hostname if none
+ * was found. The function resolv_query() can be used to send a query
+ * for a hostname.
+ *
+ * \return A pointer to a 4-byte representation of the hostname's IP
+ * address, or NULL if the hostname was not found in the array of
+ * hostnames.
+ */
+/*---------------------------------------------------------------------------*/
+uint16 *
+resolv_lookup(char *name)
+{
+ static uint8 i;
+ struct namemap *nameptr;
+
+ /* Walk through the list to see if the name is in there. If it is
+ not, we return NULL. */
+ for(i = 0; i < RESOLV_ENTRIES; ++i) {
+ nameptr = &names[i];
+ if(nameptr->state == STATE_DONE &&
+ strcmp(name, nameptr->name) == 0) {
+ return nameptr->ipaddr;
+ }
+ }
+ return NULL;
+}
+/*---------------------------------------------------------------------------*/
+/**
+ * Obtain the currently configured DNS server.
+ *
+ * \return A pointer to a 4-byte representation of the IP address of
+ * the currently configured DNS server or NULL if no DNS server has
+ * been configured.
+ */
+/*---------------------------------------------------------------------------*/
+uint16 *
+resolv_getserver(void)
+{
+ if(resolv_conn == NULL) {
+ return NULL;
+ }
+ return resolv_conn->ripaddr;
+}
+/*---------------------------------------------------------------------------*/
+/**
+ * Configure which DNS server to use for queries.
+ *
+ * \param dnsserver A pointer to a 4-byte representation of the IP
+ * address of the DNS server to be configured.
+ */
+/*---------------------------------------------------------------------------*/
+void
+resolv_conf(uint16 *dnsserver)
+{
+ if(resolv_conn != NULL) {
+ uip_udp_remove(resolv_conn);
+ }
+
+ resolv_conn = uip_udp_new(dnsserver, HTONS(53));
+}
+/*---------------------------------------------------------------------------*/
+/**
+ * Initalize the resolver.
+ */
+/*---------------------------------------------------------------------------*/
+void
+resolv_init(void)
+{
+ static uint8 i;
+
+ for(i = 0; i < RESOLV_ENTRIES; ++i) {
+ names[i].state = STATE_DONE;
+ }
+
+}
+/*---------------------------------------------------------------------------*/
+
+/** @} */
+/** @} */
diff --git a/nuttx/netutils/smtp/Make.defs b/nuttx/netutils/smtp/Make.defs
new file mode 100644
index 000000000..b749677c9
--- /dev/null
+++ b/nuttx/netutils/smtp/Make.defs
@@ -0,0 +1,38 @@
+############################################################################
+# Make.defs
+#
+# Copyright (C) 2007 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name NuttX nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+# Does not build
+# SMTP_ASRCS =
+# SMTP_CSRCS = smtp.c smtp-strings.c
diff --git a/nuttx/netutils/smtp/makestrings b/nuttx/netutils/smtp/makestrings
new file mode 100755
index 000000000..bea18a6c3
--- /dev/null
+++ b/nuttx/netutils/smtp/makestrings
@@ -0,0 +1,40 @@
+#!/usr/bin/perl
+
+
+sub stringify {
+ my $name = shift(@_);
+ open(OUTPUTC, "> $name.c");
+ open(OUTPUTH, "> $name.h");
+
+ open(FILE, "$name");
+
+ while(<FILE>) {
+ if(/(.+) "(.+)"/) {
+ $var = $1;
+ $data = $2;
+
+ $datan = $data;
+ $datan =~ s/\\r/\r/g;
+ $datan =~ s/\\n/\n/g;
+ $datan =~ s/\\01/\01/g;
+ $datan =~ s/\\0/\0/g;
+
+ printf(OUTPUTC "const char $var\[%d] = \n", length($datan) + 1);
+ printf(OUTPUTC "/* \"$data\" */\n");
+ printf(OUTPUTC "{");
+ for($j = 0; $j < length($datan); $j++) {
+ printf(OUTPUTC "%#02x, ", unpack("C", substr($datan, $j, 1)));
+ }
+ printf(OUTPUTC "};\n");
+
+ printf(OUTPUTH "extern const char $var\[%d];\n", length($datan) + 1);
+
+ }
+ }
+ close(OUTPUTC);
+ close(OUTPUTH);
+}
+stringify("smtp-strings");
+
+exit 0;
+
diff --git a/nuttx/netutils/smtp/smtp-strings b/nuttx/netutils/smtp/smtp-strings
new file mode 100644
index 000000000..27f639c2e
--- /dev/null
+++ b/nuttx/netutils/smtp/smtp-strings
@@ -0,0 +1,11 @@
+smtp_220 "220"
+smtp_helo "HELO "
+smtp_mail_from "MAIL FROM: "
+smtp_rcpt_to "RCPT TO: "
+smtp_data "DATA\r\n"
+smtp_to "To: "
+smtp_from "From: "
+smtp_subject "Subject: "
+smtp_quit "QUIT\r\n"
+smtp_crnl "\r\n"
+smtp_crnlperiodcrnl "\r\n.\r\n" \ No newline at end of file
diff --git a/nuttx/netutils/smtp/smtp-strings.c b/nuttx/netutils/smtp/smtp-strings.c
new file mode 100644
index 000000000..ab216ef0b
--- /dev/null
+++ b/nuttx/netutils/smtp/smtp-strings.c
@@ -0,0 +1,33 @@
+const char smtp_220[4] =
+/* "220" */
+{0x32, 0x32, 0x30, };
+const char smtp_helo[6] =
+/* "HELO " */
+{0x48, 0x45, 0x4c, 0x4f, 0x20, };
+const char smtp_mail_from[12] =
+/* "MAIL FROM: " */
+{0x4d, 0x41, 0x49, 0x4c, 0x20, 0x46, 0x52, 0x4f, 0x4d, 0x3a, 0x20, };
+const char smtp_rcpt_to[10] =
+/* "RCPT TO: " */
+{0x52, 0x43, 0x50, 0x54, 0x20, 0x54, 0x4f, 0x3a, 0x20, };
+const char smtp_data[7] =
+/* "DATA\r\n" */
+{0x44, 0x41, 0x54, 0x41, 0xd, 0xa, };
+const char smtp_to[5] =
+/* "To: " */
+{0x54, 0x6f, 0x3a, 0x20, };
+const char smtp_from[7] =
+/* "From: " */
+{0x46, 0x72, 0x6f, 0x6d, 0x3a, 0x20, };
+const char smtp_subject[10] =
+/* "Subject: " */
+{0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3a, 0x20, };
+const char smtp_quit[7] =
+/* "QUIT\r\n" */
+{0x51, 0x55, 0x49, 0x54, 0xd, 0xa, };
+const char smtp_crnl[3] =
+/* "\r\n" */
+{0xd, 0xa, };
+const char smtp_crnlperiodcrnl[6] =
+/* "\r\n.\r\n" */
+{0xd, 0xa, 0x2e, 0xd, 0xa, };
diff --git a/nuttx/netutils/smtp/smtp-strings.h b/nuttx/netutils/smtp/smtp-strings.h
new file mode 100644
index 000000000..4bff8583c
--- /dev/null
+++ b/nuttx/netutils/smtp/smtp-strings.h
@@ -0,0 +1,11 @@
+extern const char smtp_220[4];
+extern const char smtp_helo[6];
+extern const char smtp_mail_from[12];
+extern const char smtp_rcpt_to[10];
+extern const char smtp_data[7];
+extern const char smtp_to[5];
+extern const char smtp_from[7];
+extern const char smtp_subject[10];
+extern const char smtp_quit[7];
+extern const char smtp_crnl[3];
+extern const char smtp_crnlperiodcrnl[6];
diff --git a/nuttx/netutils/smtp/smtp.c b/nuttx/netutils/smtp/smtp.c
new file mode 100644
index 000000000..98dd468e3
--- /dev/null
+++ b/nuttx/netutils/smtp/smtp.c
@@ -0,0 +1,252 @@
+/* smtp.c
+ * smtp SMTP E-mail sender
+ * Author: Adam Dunkels <adam@dunkels.com>
+ *
+ * The Simple Mail Transfer Protocol (SMTP) as defined by RFC821 is
+ * the standard way of sending and transfering e-mail on the
+ * Internet. This simple example implementation is intended as an
+ * example of how to implement protocols in uIP, and is able to send
+ * out e-mail but has not been extensively tested.
+ *
+ * Copyright (c) 2004, 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. 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: smtp.c,v 1.1.1.1 2007-08-26 23:07:06 patacongo Exp $
+ */
+
+#include <sys/types.h>
+#include <string.h>
+
+#include <net/uip/uip.h>
+#include <net/uip/psock.h>
+#include <net/uip/smtp.h>
+
+#include "smtp-strings.h"
+
+static struct smtp_state s;
+
+static char *localhostname;
+static uip_ipaddr_t smtpserver;
+
+#define ISO_nl 0x0a
+#define ISO_cr 0x0d
+
+#define ISO_period 0x2e
+
+#define ISO_2 0x32
+#define ISO_3 0x33
+#define ISO_4 0x34
+#define ISO_5 0x35
+
+
+/*---------------------------------------------------------------------------*/
+static
+void smtp_thread(void)
+{
+ psock_readto(&s.psock, ISO_nl);
+
+ if(strncmp(s.inputbuffer, smtp_220, 3) != 0) {
+ PSOCK_CLOSE(&s.psock);
+ smtp_done(2);
+ pthread_exit(NULL);
+ }
+
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_helo);
+ PSOCK_SEND_STR(&s.psock, localhostname);
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl);
+
+ psock_readto(&s.psock, ISO_nl);
+
+ if(s.inputbuffer[0] != ISO_2) {
+ PSOCK_CLOSE(&s.psock);
+ smtp_done(3);
+ pthread_exit(NULL);
+ }
+
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_mail_from);
+ PSOCK_SEND_STR(&s.psock, s.from);
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl);
+
+ psock_readto(&s.psock, ISO_nl);
+
+ if(s.inputbuffer[0] != ISO_2) {
+ PSOCK_CLOSE(&s.psock);
+ smtp_done(4);
+ pthread_exit(NULL);
+ }
+
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_rcpt_to);
+ PSOCK_SEND_STR(&s.psock, s.to);
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl);
+
+ psock_readto(&s.psock, ISO_nl);
+
+ if(s.inputbuffer[0] != ISO_2) {
+ PSOCK_CLOSE(&s.psock);
+ smtp_done(5);
+ pthread_exit(NULL);
+ }
+
+ if(s.cc != 0) {
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_rcpt_to);
+ PSOCK_SEND_STR(&s.psock, s.cc);
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl);
+
+ psock_readto(&s.psock, ISO_nl);
+
+ if(s.inputbuffer[0] != ISO_2) {
+ PSOCK_CLOSE(&s.psock);
+ smtp_done(6);
+ pthread_exit(NULL);
+ }
+ }
+
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_data);
+
+ psock_readto(&s.psock, ISO_nl);
+
+ if(s.inputbuffer[0] != ISO_3) {
+ PSOCK_CLOSE(&s.psock);
+ smtp_done(7);
+ pthread_exit(NULL);
+ }
+
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_to);
+ PSOCK_SEND_STR(&s.psock, s.to);
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl);
+
+ if(s.cc != 0) {
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_cc);
+ PSOCK_SEND_STR(&s.psock, s.cc);
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl);
+ }
+
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_from);
+ PSOCK_SEND_STR(&s.psock, s.from);
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl);
+
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_subject);
+ PSOCK_SEND_STR(&s.psock, s.subject);
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl);
+
+ psock_send(&s.psock, s.msg, s.msglen);
+
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_crnlperiodcrnl);
+
+ psock_readto(&s.psock, ISO_nl);
+ if(s.inputbuffer[0] != ISO_2) {
+ PSOCK_CLOSE(&s.psock);
+ smtp_done(8);
+ pthread_exit(NULL);
+ }
+
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_quit);
+ smtp_done(SMTP_ERR_OK);
+}
+
+/* This function is called by the UIP interrupt handling logic whenevent an
+ * event of interest occurs.
+ */
+
+void uip_interrupt_event(void)
+{
+ if(uip_closed()) {
+ s.connected = 0;
+ return;
+ }
+ if(uip_aborted() || uip_timedout()) {
+ s.connected = 0;
+ smtp_done(1);
+ return;
+ }
+ smtp_thread();
+}
+
+/*---------------------------------------------------------------------------*/
+/**
+ * Specificy an SMTP server and hostname.
+ *
+ * This function is used to configure the SMTP module with an SMTP
+ * server and the hostname of the host.
+ *
+ * \param lhostname The hostname of the uIP host.
+ *
+ * \param server A pointer to a 4-byte array representing the IP
+ * address of the SMTP server to be configured.
+ */
+void
+smtp_configure(char *lhostname, void *server)
+{
+ localhostname = lhostname;
+ uip_ipaddr_copy(smtpserver, server);
+}
+/*---------------------------------------------------------------------------*/
+/**
+ * Send an e-mail.
+ *
+ * \param to The e-mail address of the receiver of the e-mail.
+ * \param cc The e-mail address of the CC: receivers of the e-mail.
+ * \param from The e-mail address of the sender of the e-mail.
+ * \param subject The subject of the e-mail.
+ * \param msg The actual e-mail message.
+ * \param msglen The length of the e-mail message.
+ */
+unsigned char
+smtp_send(char *to, char *cc, char *from,
+ char *subject, char *msg, uint16 msglen)
+{
+ struct uip_conn *conn;
+
+ conn = uip_connect(smtpserver, HTONS(25));
+ if(conn == NULL) {
+ return 0;
+ }
+ s.connected = 1;
+ s.to = to;
+ s.cc = cc;
+ s.from = from;
+ s.subject = subject;
+ s.msg = msg;
+ s.msglen = msglen;
+
+ psock_init(&s.psock, s.inputbuffer, sizeof(s.inputbuffer));
+
+ return 1;
+}
+/*---------------------------------------------------------------------------*/
+void
+smtp_init(void)
+{
+ s.connected = 0;
+}
+/*---------------------------------------------------------------------------*/
+/** @} */
+/** @} */
diff --git a/nuttx/netutils/telnetd/Make.defs b/nuttx/netutils/telnetd/Make.defs
new file mode 100644
index 000000000..7aafdfd27
--- /dev/null
+++ b/nuttx/netutils/telnetd/Make.defs
@@ -0,0 +1,37 @@
+############################################################################
+# Make.defs
+#
+# Copyright (C) 2007 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name Nuttx nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+TELNETD_ASRCS =
+TELNETD_CSRCS = telnetd.c shell.c
diff --git a/nuttx/netutils/telnetd/shell.c b/nuttx/netutils/telnetd/shell.c
new file mode 100644
index 000000000..2c1ddbaae
--- /dev/null
+++ b/nuttx/netutils/telnetd/shell.c
@@ -0,0 +1,123 @@
+ /*
+ * Copyright (c) 2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: shell.c,v 1.1.1.1 2007-08-26 23:07:06 patacongo Exp $
+ *
+ */
+
+#include "shell.h"
+
+#include <string.h>
+
+struct ptentry {
+ char *commandstr;
+ void (* pfunc)(char *str);
+};
+
+#define SHELL_PROMPT "uIP 1.0> "
+
+/*---------------------------------------------------------------------------*/
+static void
+parse(register char *str, struct ptentry *t)
+{
+ struct ptentry *p;
+ for(p = t; p->commandstr != NULL; ++p) {
+ if(strncmp(p->commandstr, str, strlen(p->commandstr)) == 0) {
+ break;
+ }
+ }
+
+ p->pfunc(str);
+}
+/*---------------------------------------------------------------------------*/
+static void
+inttostr(register char *str, unsigned int i)
+{
+ str[0] = '0' + i / 100;
+ if(str[0] == '0') {
+ str[0] = ' ';
+ }
+ str[1] = '0' + (i / 10) % 10;
+ if(str[0] == ' ' && str[1] == '0') {
+ str[1] = ' ';
+ }
+ str[2] = '0' + i % 10;
+ str[3] = ' ';
+ str[4] = 0;
+}
+/*---------------------------------------------------------------------------*/
+static void
+help(char *str)
+{
+ shell_output("Available commands:", "");
+ shell_output("stats - show network statistics", "");
+ shell_output("conn - show TCP connections", "");
+ shell_output("help, ? - show help", "");
+ shell_output("exit - exit shell", "");
+}
+/*---------------------------------------------------------------------------*/
+static void
+unknown(char *str)
+{
+ if(strlen(str) > 0) {
+ shell_output("Unknown command: ", str);
+ }
+}
+/*---------------------------------------------------------------------------*/
+static struct ptentry parsetab[] =
+ {{"stats", help},
+ {"conn", help},
+ {"help", help},
+ {"exit", shell_quit},
+ {"?", help},
+
+ /* Default action */
+ {NULL, unknown}};
+/*---------------------------------------------------------------------------*/
+void
+shell_init(void)
+{
+}
+/*---------------------------------------------------------------------------*/
+void
+shell_start(void)
+{
+ shell_output("uIP command shell", "");
+ shell_output("Type '?' and return for help", "");
+ shell_prompt(SHELL_PROMPT);
+}
+/*---------------------------------------------------------------------------*/
+void
+shell_input(char *cmd)
+{
+ parse(cmd, parsetab);
+ shell_prompt(SHELL_PROMPT);
+}
+/*---------------------------------------------------------------------------*/
diff --git a/nuttx/netutils/telnetd/shell.h b/nuttx/netutils/telnetd/shell.h
new file mode 100644
index 000000000..7d81849c7
--- /dev/null
+++ b/nuttx/netutils/telnetd/shell.h
@@ -0,0 +1,104 @@
+/**
+ * \file
+ * Interface for the Contiki shell.
+ * \author Adam Dunkels <adam@dunkels.com>
+ *
+ * Some of the functions declared in this file must be implemented as
+ * a shell back-end in the architecture specific files of a Contiki
+ * port.
+ */
+
+
+/*
+ * Copyright (c) 2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the Contiki desktop OS.
+ *
+ * $Id: shell.h,v 1.1.1.1 2007-08-26 23:07:06 patacongo Exp $
+ *
+ */
+#ifndef __SHELL_H__
+#define __SHELL_H__
+
+/**
+ * Initialize the shell.
+ *
+ * Called when the shell front-end process starts. This function may
+ * be used to start listening for signals.
+ */
+void shell_init(void);
+
+/**
+ * Start the shell back-end.
+ *
+ * Called by the front-end when a new shell is started.
+ */
+void shell_start(void);
+
+/**
+ * Process a shell command.
+ *
+ * This function will be called by the shell GUI / telnet server whan
+ * a command has been entered that should be processed by the shell
+ * back-end.
+ *
+ * \param command The command to be processed.
+ */
+void shell_input(char *command);
+
+/**
+ * Quit the shell.
+ *
+ */
+void shell_quit(char *);
+
+
+/**
+ * Print a string to the shell window.
+ *
+ * This function is implemented by the shell GUI / telnet server and
+ * can be called by the shell back-end to output a string in the
+ * shell window. The string is automatically appended with a linebreak.
+ *
+ * \param str1 The first half of the string to be output.
+ * \param str2 The second half of the string to be output.
+ */
+void shell_output(char *str1, char *str2);
+
+/**
+ * Print a prompt to the shell window.
+ *
+ * This function can be used by the shell back-end to print out a
+ * prompt to the shell window.
+ *
+ * \param prompt The prompt to be printed.
+ *
+ */
+void shell_prompt(char *prompt);
+
+#endif /* __SHELL_H__ */
diff --git a/nuttx/netutils/telnetd/telnetd.c b/nuttx/netutils/telnetd/telnetd.c
new file mode 100644
index 000000000..21700023c
--- /dev/null
+++ b/nuttx/netutils/telnetd/telnetd.c
@@ -0,0 +1,336 @@
+/*
+ * Copyright (c) 2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * $Id: telnetd.c,v 1.1.1.1 2007-08-26 23:07:06 patacongo Exp $
+ *
+ */
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <net/uip/uip.h>
+
+#include "telnetd.h"
+#include "shell.h"
+
+#define ISO_nl 0x0a
+#define ISO_cr 0x0d
+
+#define STATE_NORMAL 0
+#define STATE_IAC 1
+#define STATE_WILL 2
+#define STATE_WONT 3
+#define STATE_DO 4
+#define STATE_DONT 5
+#define STATE_CLOSE 6
+
+static struct telnetd_state s;
+
+#define TELNET_IAC 255
+#define TELNET_WILL 251
+#define TELNET_WONT 252
+#define TELNET_DO 253
+#define TELNET_DONT 254
+
+/*---------------------------------------------------------------------------*/
+void
+shell_quit(char *str)
+{
+ s.state = STATE_CLOSE;
+}
+
+/*---------------------------------------------------------------------------*/
+static void
+sendline(char *line)
+{
+ static unsigned int i;
+
+ for(i = 0; i < TELNETD_CONF_NUMLINES; ++i) {
+ if(s.lines[i] == NULL) {
+ s.lines[i] = line;
+ break;
+ }
+ }
+ if(i == TELNETD_CONF_NUMLINES) {
+ free(line);
+ }
+}
+/*---------------------------------------------------------------------------*/
+void
+shell_prompt(char *str)
+{
+ char *line;
+ line = (char*)malloc(TELNETD_CONF_LINELEN);
+ if(line != NULL) {
+ strncpy(line, str, TELNETD_CONF_LINELEN);
+ /* petsciiconv_toascii(line, TELNETD_CONF_LINELEN);*/
+ sendline(line);
+ }
+}
+/*---------------------------------------------------------------------------*/
+void
+shell_output(char *str1, char *str2)
+{
+ static unsigned len;
+ char *line;
+
+ line = (char*)malloc(TELNETD_CONF_LINELEN);
+ if(line != NULL) {
+ len = strlen(str1);
+ strncpy(line, str1, TELNETD_CONF_LINELEN);
+ if(len < TELNETD_CONF_LINELEN) {
+ strncpy(line + len, str2, TELNETD_CONF_LINELEN - len);
+ }
+ len = strlen(line);
+ if(len < TELNETD_CONF_LINELEN - 2) {
+ line[len] = ISO_cr;
+ line[len+1] = ISO_nl;
+ line[len+2] = 0;
+ }
+ /* petsciiconv_toascii(line, TELNETD_CONF_LINELEN);*/
+ sendline(line);
+ }
+}
+/*---------------------------------------------------------------------------*/
+void
+telnetd_init(void)
+{
+ uip_listen(HTONS(23));
+ shell_init();
+}
+/*---------------------------------------------------------------------------*/
+static void
+acked(void)
+{
+ static unsigned int i;
+
+ while(s.numsent > 0) {
+ free(s.lines[0]);
+ for(i = 1; i < TELNETD_CONF_NUMLINES; ++i) {
+ s.lines[i - 1] = s.lines[i];
+ }
+ s.lines[TELNETD_CONF_NUMLINES - 1] = NULL;
+ --s.numsent;
+ }
+}
+/*---------------------------------------------------------------------------*/
+static void
+senddata(void)
+{
+ static char *bufptr, *lineptr;
+ static int buflen, linelen;
+
+ bufptr = uip_appdata;
+ buflen = 0;
+ for(s.numsent = 0; s.numsent < TELNETD_CONF_NUMLINES &&
+ s.lines[s.numsent] != NULL ; ++s.numsent) {
+ lineptr = s.lines[s.numsent];
+ linelen = strlen(lineptr);
+ if(linelen > TELNETD_CONF_LINELEN) {
+ linelen = TELNETD_CONF_LINELEN;
+ }
+ if(buflen + linelen < uip_mss()) {
+ memcpy(bufptr, lineptr, linelen);
+ bufptr += linelen;
+ buflen += linelen;
+ } else {
+ break;
+ }
+ }
+ uip_send(uip_appdata, buflen);
+}
+/*---------------------------------------------------------------------------*/
+static void
+closed(void)
+{
+ static unsigned int i;
+
+ for(i = 0; i < TELNETD_CONF_NUMLINES; ++i) {
+ if(s.lines[i] != NULL) {
+ free(s.lines[i]);
+ }
+ }
+}
+/*---------------------------------------------------------------------------*/
+static void
+get_char(uint8 c)
+{
+ if(c == ISO_cr) {
+ return;
+ }
+
+ s.buf[(int)s.bufptr] = c;
+ if(s.buf[(int)s.bufptr] == ISO_nl ||
+ s.bufptr == sizeof(s.buf) - 1) {
+ if(s.bufptr > 0) {
+ s.buf[(int)s.bufptr] = 0;
+ /* petsciiconv_topetscii(s.buf, TELNETD_CONF_LINELEN);*/
+ }
+ shell_input(s.buf);
+ s.bufptr = 0;
+ } else {
+ ++s.bufptr;
+ }
+}
+/*---------------------------------------------------------------------------*/
+static void
+sendopt(uint8 option, uint8 value)
+{
+ char *line;
+ line = (char*)malloc(TELNETD_CONF_LINELEN);
+ if(line != NULL) {
+ line[0] = TELNET_IAC;
+ line[1] = option;
+ line[2] = value;
+ line[3] = 0;
+ sendline(line);
+ }
+}
+/*---------------------------------------------------------------------------*/
+static void
+newdata(void)
+{
+ uint16 len;
+ uint8 c;
+ char *dataptr;
+
+
+ len = uip_datalen();
+ dataptr = (char *)uip_appdata;
+
+ while(len > 0 && s.bufptr < sizeof(s.buf)) {
+ c = *dataptr;
+ ++dataptr;
+ --len;
+ switch(s.state) {
+ case STATE_IAC:
+ if(c == TELNET_IAC) {
+ get_char(c);
+ s.state = STATE_NORMAL;
+ } else {
+ switch(c) {
+ case TELNET_WILL:
+ s.state = STATE_WILL;
+ break;
+ case TELNET_WONT:
+ s.state = STATE_WONT;
+ break;
+ case TELNET_DO:
+ s.state = STATE_DO;
+ break;
+ case TELNET_DONT:
+ s.state = STATE_DONT;
+ break;
+ default:
+ s.state = STATE_NORMAL;
+ break;
+ }
+ }
+ break;
+ case STATE_WILL:
+ /* Reply with a DONT */
+ sendopt(TELNET_DONT, c);
+ s.state = STATE_NORMAL;
+ break;
+
+ case STATE_WONT:
+ /* Reply with a DONT */
+ sendopt(TELNET_DONT, c);
+ s.state = STATE_NORMAL;
+ break;
+ case STATE_DO:
+ /* Reply with a WONT */
+ sendopt(TELNET_WONT, c);
+ s.state = STATE_NORMAL;
+ break;
+ case STATE_DONT:
+ /* Reply with a WONT */
+ sendopt(TELNET_WONT, c);
+ s.state = STATE_NORMAL;
+ break;
+ case STATE_NORMAL:
+ if(c == TELNET_IAC) {
+ s.state = STATE_IAC;
+ } else {
+ get_char(c);
+ }
+ break;
+ }
+ }
+}
+
+/* This function is called by the UIP interrupt handling logic whenevent an
+ * event of interest occurs.
+ */
+
+void uip_interrupt_event(void)
+{
+ static unsigned int i;
+ if(uip_connected()) {
+ /* tcp_markconn(uip_conn, &s);*/
+ for(i = 0; i < TELNETD_CONF_NUMLINES; ++i) {
+ s.lines[i] = NULL;
+ }
+ s.bufptr = 0;
+ s.state = STATE_NORMAL;
+
+ shell_start();
+ }
+
+ if(s.state == STATE_CLOSE) {
+ s.state = STATE_NORMAL;
+ uip_close();
+ return;
+ }
+
+ if(uip_closed() ||
+ uip_aborted() ||
+ uip_timedout()) {
+ closed();
+ }
+
+ if(uip_acked()) {
+ acked();
+ }
+
+ if(uip_newdata()) {
+ newdata();
+ }
+
+ if(uip_rexmit() ||
+ uip_newdata() ||
+ uip_acked() ||
+ uip_connected() ||
+ uip_poll()) {
+ senddata();
+ }
+}
+/*---------------------------------------------------------------------------*/
diff --git a/nuttx/netutils/telnetd/telnetd.h b/nuttx/netutils/telnetd/telnetd.h
new file mode 100644
index 000000000..4eef0b726
--- /dev/null
+++ b/nuttx/netutils/telnetd/telnetd.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TELNETD_H__
+#define __TELNETD_H__
+
+#include <sys/types.h>
+#include <net/uip/uipopt.h>
+
+#ifndef TELNETD_CONF_LINELEN
+#define TELNETD_CONF_LINELEN 40
+#endif
+#ifndef TELNETD_CONF_NUMLINES
+#define TELNETD_CONF_NUMLINES 16
+#endif
+
+struct telnetd_state
+{
+ char *lines[TELNETD_CONF_NUMLINES];
+ char buf[TELNETD_CONF_LINELEN];
+ char bufptr;
+ uint8 numsent;
+ uint8 state;
+};
+
+#endif /* __TELNETD_H__ */
diff --git a/nuttx/netutils/uiplib/Make.defs b/nuttx/netutils/uiplib/Make.defs
new file mode 100644
index 000000000..2e3425761
--- /dev/null
+++ b/nuttx/netutils/uiplib/Make.defs
@@ -0,0 +1,37 @@
+############################################################################
+# Make.defs
+#
+# Copyright (C) 2007 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name NuttX nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+UIPLIB_ASRCS =
+UIPLIB_CSRCS = uiplib.c
diff --git a/nuttx/netutils/uiplib/uiplib.c b/nuttx/netutils/uiplib/uiplib.c
new file mode 100644
index 000000000..1b6f7528c
--- /dev/null
+++ b/nuttx/netutils/uiplib/uiplib.c
@@ -0,0 +1,73 @@
+/*
+ * 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.1.1.1 2007-08-26 23:07:05 patacongo Exp $
+ *
+ */
+
+#include <net/uip/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;
+}
+
+/*-----------------------------------------------------------------------------------*/
diff --git a/nuttx/netutils/uiplib/uiplib.h b/nuttx/netutils/uiplib/uiplib.h
new file mode 100644
index 000000000..a980e389e
--- /dev/null
+++ b/nuttx/netutils/uiplib/uiplib.h
@@ -0,0 +1,71 @@
+/**
+ * \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.1.1 2007-08-26 23:07:05 patacongo 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__ */
diff --git a/nuttx/netutils/webclient/Make.defs b/nuttx/netutils/webclient/Make.defs
new file mode 100644
index 000000000..a5bffd45a
--- /dev/null
+++ b/nuttx/netutils/webclient/Make.defs
@@ -0,0 +1,37 @@
+############################################################################
+# Make.defs
+#
+# Copyright (C) 2007 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name NuttX nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+WEBCLIENT_ASRCS =
+WEBCLIENT_CSRCS = webclient-strings.c webclient.c
diff --git a/nuttx/netutils/webclient/makestrings b/nuttx/netutils/webclient/makestrings
new file mode 100755
index 000000000..6dec075dd
--- /dev/null
+++ b/nuttx/netutils/webclient/makestrings
@@ -0,0 +1,40 @@
+#!/usr/bin/perl
+
+
+sub stringify {
+ my $name = shift(@_);
+ open(OUTPUTC, "> $name.c");
+ open(OUTPUTH, "> $name.h");
+
+ open(FILE, "$name");
+
+ while(<FILE>) {
+ if(/(.+) "(.+)"/) {
+ $var = $1;
+ $data = $2;
+
+ $datan = $data;
+ $datan =~ s/\\r/\r/g;
+ $datan =~ s/\\n/\n/g;
+ $datan =~ s/\\01/\01/g;
+ $datan =~ s/\\0/\0/g;
+
+ printf(OUTPUTC "const char $var\[%d] = \n", length($datan) + 1);
+ printf(OUTPUTC "/* \"$data\" */\n");
+ printf(OUTPUTC "{");
+ for($j = 0; $j < length($datan); $j++) {
+ printf(OUTPUTC "%#02x, ", unpack("C", substr($datan, $j, 1)));
+ }
+ printf(OUTPUTC "0 };\n");
+
+ printf(OUTPUTH "extern const char $var\[%d];\n", length($datan) + 1);
+
+ }
+ }
+ close(OUTPUTC);
+ close(OUTPUTH);
+}
+stringify("webclient-strings");
+
+exit 0;
+
diff --git a/nuttx/netutils/webclient/webclient-strings b/nuttx/netutils/webclient/webclient-strings
new file mode 100644
index 000000000..a33139723
--- /dev/null
+++ b/nuttx/netutils/webclient/webclient-strings
@@ -0,0 +1,31 @@
+http_http "http://"
+http_200 "200 "
+http_301 "301 "
+http_302 "302 "
+http_get "GET "
+http_10 "HTTP/1.0"
+http_11 "HTTP/1.1"
+http_content_type "content-type: "
+http_texthtml "text/html"
+http_location "location: "
+http_host "host: "
+http_crnl "\r\n"
+http_index_html "/index.html"
+http_404_html "/404.html"
+http_content_type_html "Content-type: text/html\r\n\r\n"
+http_content_type_css "Content-type: text/css\r\n\r\n"
+http_content_type_text "Content-type: text/text\r\n\r\n"
+http_content_type_png "Content-type: image/png\r\n\r\n"
+http_content_type_gif "Content-type: image/gif\r\n\r\n"
+http_content_type_jpg "Content-type: image/jpeg\r\n\r\n"
+http_content_type_binary "Content-type: application/octet-stream\r\n\r\n"
+http_html ".html"
+http_shtml ".shtml"
+http_htm ".htm"
+http_css ".css"
+http_png ".png"
+http_gif ".gif"
+http_jpg ".jpg"
+http_text ".text"
+http_txt ".txt"
+http_user_agent_fields "Connection: close\r\nUser-Agent: uIP/1.0 (; http://www.sics.se/~adam/uip/)\r\n\r\n"
diff --git a/nuttx/netutils/webclient/webclient-strings.c b/nuttx/netutils/webclient/webclient-strings.c
new file mode 100644
index 000000000..94723308e
--- /dev/null
+++ b/nuttx/netutils/webclient/webclient-strings.c
@@ -0,0 +1,93 @@
+const char http_http[8] =
+/* "http://" */
+{0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0 };
+const char http_200[5] =
+/* "200 " */
+{0x32, 0x30, 0x30, 0x20, 0 };
+const char http_301[5] =
+/* "301 " */
+{0x33, 0x30, 0x31, 0x20, 0 };
+const char http_302[5] =
+/* "302 " */
+{0x33, 0x30, 0x32, 0x20, 0 };
+const char http_get[5] =
+/* "GET " */
+{0x47, 0x45, 0x54, 0x20, 0 };
+const char http_10[9] =
+/* "HTTP/1.0" */
+{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0 };
+const char http_11[9] =
+/* "HTTP/1.1" */
+{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0 };
+const char http_content_type[15] =
+/* "content-type: " */
+{0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0 };
+const char http_texthtml[10] =
+/* "text/html" */
+{0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0 };
+const char http_location[11] =
+/* "location: " */
+{0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0 };
+const char http_host[7] =
+/* "host: " */
+{0x68, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0 };
+const char http_crnl[3] =
+/* "\r\n" */
+{0xd, 0xa, 0 };
+const char http_index_html[12] =
+/* "/index.html" */
+{0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0 };
+const char http_404_html[10] =
+/* "/404.html" */
+{0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0 };
+const char http_content_type_html[28] =
+/* "Content-type: text/html\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, 0xd, 0xa, 0 };
+const char http_content_type_css [27] =
+/* "Content-type: text/css\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x63, 0x73, 0x73, 0xd, 0xa, 0xd, 0xa, 0 };
+const char http_content_type_text[28] =
+/* "Content-type: text/text\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x74, 0x65, 0x78, 0x74, 0xd, 0xa, 0xd, 0xa, 0 };
+const char http_content_type_png [28] =
+/* "Content-type: image/png\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0xd, 0xa, 0xd, 0xa, 0 };
+const char http_content_type_gif [28] =
+/* "Content-type: image/gif\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, 0x69, 0x66, 0xd, 0xa, 0xd, 0xa, 0 };
+const char http_content_type_jpg [29] =
+/* "Content-type: image/jpeg\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x65, 0x67, 0xd, 0xa, 0xd, 0xa, 0 };
+const char http_content_type_binary[43] =
+/* "Content-type: application/octet-stream\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6f, 0x63, 0x74, 0x65, 0x74, 0x2d, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0xd, 0xa, 0xd, 0xa, 0 };
+const char http_html[6] =
+/* ".html" */
+{0x2e, 0x68, 0x74, 0x6d, 0x6c, 0 };
+const char http_shtml[7] =
+/* ".shtml" */
+{0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0 };
+const char http_htm[5] =
+/* ".htm" */
+{0x2e, 0x68, 0x74, 0x6d, 0 };
+const char http_css[5] =
+/* ".css" */
+{0x2e, 0x63, 0x73, 0x73, 0 };
+const char http_png[5] =
+/* ".png" */
+{0x2e, 0x70, 0x6e, 0x67, 0 };
+const char http_gif[5] =
+/* ".gif" */
+{0x2e, 0x67, 0x69, 0x66, 0 };
+const char http_jpg[5] =
+/* ".jpg" */
+{0x2e, 0x6a, 0x70, 0x67, 0 };
+const char http_text[6] =
+/* ".text" */
+{0x2e, 0x74, 0x65, 0x78, 0x74, 0 };
+const char http_txt[5] =
+/* ".txt" */
+{0x2e, 0x74, 0x78, 0x74, 0 };
+const char http_user_agent_fields[77] =
+/* "Connection: close\r\nUser-Agent: uIP/1.0 (; http://www.sics.se/~adam/uip/)\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0xd, 0xa, 0x55, 0x73, 0x65, 0x72, 0x2d, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x28, 0x3b, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x73, 0x69, 0x63, 0x73, 0x2e, 0x73, 0x65, 0x2f, 0x7e, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, 0x70, 0x2f, 0x29, 0xd, 0xa, 0xd, 0xa, 0 };
diff --git a/nuttx/netutils/webclient/webclient-strings.h b/nuttx/netutils/webclient/webclient-strings.h
new file mode 100644
index 000000000..9e3ec9347
--- /dev/null
+++ b/nuttx/netutils/webclient/webclient-strings.h
@@ -0,0 +1,31 @@
+extern const char http_http[8];
+extern const char http_200[5];
+extern const char http_301[5];
+extern const char http_302[5];
+extern const char http_get[5];
+extern const char http_10[9];
+extern const char http_11[9];
+extern const char http_content_type[15];
+extern const char http_texthtml[10];
+extern const char http_location[11];
+extern const char http_host[7];
+extern const char http_crnl[3];
+extern const char http_index_html[12];
+extern const char http_404_html[10];
+extern const char http_content_type_html[28];
+extern const char http_content_type_css [27];
+extern const char http_content_type_text[28];
+extern const char http_content_type_png [28];
+extern const char http_content_type_gif [28];
+extern const char http_content_type_jpg [29];
+extern const char http_content_type_binary[43];
+extern const char http_html[6];
+extern const char http_shtml[7];
+extern const char http_htm[5];
+extern const char http_css[5];
+extern const char http_png[5];
+extern const char http_gif[5];
+extern const char http_jpg[5];
+extern const char http_text[6];
+extern const char http_txt[5];
+extern const char http_user_agent_fields[77];
diff --git a/nuttx/netutils/webclient/webclient.c b/nuttx/netutils/webclient/webclient.c
new file mode 100644
index 000000000..30718e723
--- /dev/null
+++ b/nuttx/netutils/webclient/webclient.c
@@ -0,0 +1,450 @@
+/* webclient.c
+ * Implementation of the HTTP client.
+ * Author: Adam Dunkels <adam@dunkels.com>
+ *
+ * This example shows a HTTP client that is able to download web pages
+ * and files from web servers. It requires a number of callback
+ * functions to be implemented by the module that utilizes the code:
+ * webclient_datahandler(), webclient_connected(),
+ * webclient_timedout(), webclient_aborted(), webclient_closed().
+ *
+ * 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: webclient.c,v 1.1.1.1 2007-08-26 23:07:05 patacongo Exp $
+ *
+ */
+
+#include <sys/types.h>
+#include <string.h>
+
+#include <net/uip/uip.h>
+#include <net/uip/resolv.h>
+
+#include "uiplib/uiplib.h"
+#include "webclient.h"
+
+#define WEBCLIENT_TIMEOUT 100
+
+#define WEBCLIENT_STATE_STATUSLINE 0
+#define WEBCLIENT_STATE_HEADERS 1
+#define WEBCLIENT_STATE_DATA 2
+#define WEBCLIENT_STATE_CLOSE 3
+
+#define HTTPFLAG_NONE 0
+#define HTTPFLAG_OK 1
+#define HTTPFLAG_MOVED 2
+#define HTTPFLAG_ERROR 3
+
+
+#define ISO_nl 0x0a
+#define ISO_cr 0x0d
+#define ISO_space 0x20
+
+
+static struct webclient_state s;
+
+char *webclient_mimetype(void)
+{
+ return s.mimetype;
+}
+
+char *webclient_filename(void)
+{
+ return s.file;
+}
+
+char *webclient_hostname(void)
+{
+ return s.host;
+}
+
+unsigned shortwebclient_port(void)
+{
+ return s.port;
+}
+
+void webclient_init(void)
+{
+}
+
+static void init_connection(void)
+{
+ s.state = WEBCLIENT_STATE_STATUSLINE;
+
+ s.getrequestleft = sizeof(http_get) - 1 + 1 +
+ sizeof(http_10) - 1 +
+ sizeof(http_crnl) - 1 +
+ sizeof(http_host) - 1 +
+ sizeof(http_crnl) - 1 +
+ strlen(http_user_agent_fields) +
+ strlen(s.file) + strlen(s.host);
+ s.getrequestptr = 0;
+
+ s.httpheaderlineptr = 0;
+}
+
+void webclient_close(void)
+{
+ s.state = WEBCLIENT_STATE_CLOSE;
+}
+
+unsigned char webclient_get(char *host, uint16 port, char *file)
+{
+ struct uip_conn *conn;
+ uip_ipaddr_t *ipaddr;
+ static uip_ipaddr_t addr;
+
+ /* First check if the host is an IP address. */
+ ipaddr = &addr;
+ if (uiplib_ipaddrconv(host, (unsigned char *)addr) == 0) {
+ ipaddr = (uip_ipaddr_t *)resolv_lookup(host);
+
+ if (ipaddr == NULL) {
+ return 0;
+ }
+ }
+
+ conn = uip_connect(ipaddr, htons(port));
+
+ if (conn == NULL) {
+ return 0;
+ }
+
+ s.port = port;
+ strncpy(s.file, file, sizeof(s.file));
+ strncpy(s.host, host, sizeof(s.host));
+
+ init_connection();
+ return 1;
+}
+
+static char *copy_string(char *dest, const char *src, int len)
+{
+ strncpy(dest, src, len);
+ return dest + len;
+}
+
+static void senddata(void)
+{
+ uint16 len;
+ char *getrequest;
+ char *cptr;
+
+ if (s.getrequestleft > 0) {
+ cptr = getrequest = (char *)uip_appdata;
+
+ cptr = copy_string(cptr, http_get, sizeof(http_get) - 1);
+ cptr = copy_string(cptr, s.file, strlen(s.file));
+ *cptr++ = ISO_space;
+ cptr = copy_string(cptr, http_10, sizeof(http_10) - 1);
+
+ cptr = copy_string(cptr, http_crnl, sizeof(http_crnl) - 1);
+
+ cptr = copy_string(cptr, http_host, sizeof(http_host) - 1);
+ cptr = copy_string(cptr, s.host, strlen(s.host));
+ cptr = copy_string(cptr, http_crnl, sizeof(http_crnl) - 1);
+
+ cptr = copy_string(cptr, http_user_agent_fields,
+ strlen(http_user_agent_fields));
+
+ len = s.getrequestleft > uip_mss()?
+ uip_mss():
+ s.getrequestleft;
+ uip_send(&(getrequest[s.getrequestptr]), len);
+ }
+}
+
+static void acked(void)
+{
+ uint16 len;
+
+ if (s.getrequestleft > 0) {
+ len = s.getrequestleft > uip_mss()?
+ uip_mss():
+ s.getrequestleft;
+ s.getrequestleft -= len;
+ s.getrequestptr += len;
+ }
+}
+
+static uint16 parse_statusline(uint16 len)
+{
+ char *cptr;
+
+ while(len > 0 && s.httpheaderlineptr < sizeof(s.httpheaderline))
+ {
+ char *pappdata = (char*)uip_appdata;
+ s.httpheaderline[s.httpheaderlineptr] = *pappdata++;
+ uip_appdata = (void*)pappdata;
+ len--;
+
+ if (s.httpheaderline[s.httpheaderlineptr] == ISO_nl)
+ {
+ if ((strncmp(s.httpheaderline, http_10, sizeof(http_10) - 1) == 0) ||
+ (strncmp(s.httpheaderline, http_11, sizeof(http_11) - 1) == 0))
+ {
+ cptr = &(s.httpheaderline[9]);
+ s.httpflag = HTTPFLAG_NONE;
+ if (strncmp(cptr, http_200, sizeof(http_200) - 1) == 0)
+ {
+ /* 200 OK */
+ s.httpflag = HTTPFLAG_OK;
+ }
+ else if (strncmp(cptr, http_301, sizeof(http_301) - 1) == 0 ||
+ strncmp(cptr, http_302, sizeof(http_302) - 1) == 0)
+ {
+ /* 301 Moved permanently or 302 Found. Location: header line
+ * will contain thw new location.
+ */
+
+ s.httpflag = HTTPFLAG_MOVED;
+ }
+ else
+ {
+ s.httpheaderline[s.httpheaderlineptr - 1] = 0;
+ }
+ }
+ else
+ {
+ uip_abort();
+ webclient_aborted();
+ return 0;
+ }
+
+ /* We're done parsing the status line, so we reset the pointer
+ * and start parsing the HTTP headers.
+ */
+
+ s.httpheaderlineptr = 0;
+ s.state = WEBCLIENT_STATE_HEADERS;
+ break;
+ }
+ else
+ {
+ ++s.httpheaderlineptr;
+ }
+ }
+ return len;
+}
+
+static char casecmp(char *str1, const char *str2, char len)
+{
+ static char c;
+
+ while(len > 0) {
+ c = *str1;
+ /* Force lower-case characters. */
+ if (c & 0x40) {
+ c |= 0x20;
+ }
+ if (*str2 != c) {
+ return 1;
+ }
+ ++str1;
+ ++str2;
+ --len;
+ }
+ return 0;
+}
+
+static uint16 parse_headers(uint16 len)
+{
+ char *cptr;
+ static unsigned char i;
+
+ while(len > 0 && s.httpheaderlineptr < sizeof(s.httpheaderline))
+ {
+ char *pappdata = (char*)uip_appdata;
+ s.httpheaderline[s.httpheaderlineptr] = *pappdata++;
+ uip_appdata = (void*)pappdata;
+ len--;
+
+ if (s.httpheaderline[s.httpheaderlineptr] == ISO_nl)
+ {
+ /* We have an entire HTTP header line in s.httpheaderline, so
+ * we parse it.
+ */
+
+ if (s.httpheaderline[0] == ISO_cr)
+ {
+ /* This was the last header line (i.e., and empty "\r\n"), so
+ * we are done with the headers and proceed with the actual
+ * data.
+ */
+
+ s.state = WEBCLIENT_STATE_DATA;
+ return len;
+ }
+
+ s.httpheaderline[s.httpheaderlineptr - 1] = 0;
+
+ /* Check for specific HTTP header fields. */
+ if (casecmp(s.httpheaderline, http_content_type, sizeof(http_content_type) - 1) == 0)
+ {
+ /* Found Content-type field. */
+ cptr = strchr(s.httpheaderline, ';');
+ if (cptr != NULL)
+ {
+ *cptr = 0;
+ }
+ strncpy(s.mimetype, s.httpheaderline + sizeof(http_content_type) - 1, sizeof(s.mimetype));
+ }
+ else if (casecmp(s.httpheaderline, http_location, sizeof(http_location) - 1) == 0)
+ {
+ cptr = s.httpheaderline + sizeof(http_location) - 1;
+
+ if (strncmp(cptr, http_http, 7) == 0)
+ {
+ cptr += 7;
+ for(i = 0; i < s.httpheaderlineptr - 7; ++i)
+ {
+ if (*cptr == 0 || *cptr == '/' || *cptr == ' ' || *cptr == ':')
+ {
+ s.host[i] = 0;
+ break;
+ }
+ s.host[i] = *cptr;
+ ++cptr;
+ }
+ }
+ strncpy(s.file, cptr, sizeof(s.file));
+ }
+
+ /* We're done parsing, so we reset the pointer and start the
+ * next line.
+ */
+
+ s.httpheaderlineptr = 0;
+ }
+ else
+ {
+ ++s.httpheaderlineptr;
+ }
+ }
+ return len;
+}
+
+static void newdata(void)
+{
+ uint16 len;
+
+ len = uip_datalen();
+
+ if (s.state == WEBCLIENT_STATE_STATUSLINE) {
+ len = parse_statusline(len);
+ }
+
+ if (s.state == WEBCLIENT_STATE_HEADERS && len > 0) {
+ len = parse_headers(len);
+ }
+
+ if (len > 0 && s.state == WEBCLIENT_STATE_DATA &&
+ s.httpflag != HTTPFLAG_MOVED) {
+ webclient_datahandler((char *)uip_appdata, len);
+ }
+}
+
+/* This function is called by the UIP interrupt handling logic whenevent an
+ * event of interest occurs.
+ */
+
+void uip_interrupt_event(void)
+{
+ if (uip_connected())
+ {
+ s.timer = 0;
+ s.state = WEBCLIENT_STATE_STATUSLINE;
+ senddata();
+ webclient_connected();
+ return;
+ }
+
+ if (s.state == WEBCLIENT_STATE_CLOSE)
+ {
+ webclient_closed();
+ uip_abort();
+ return;
+ }
+
+ if (uip_aborted())
+ {
+ webclient_aborted();
+ }
+
+ if (uip_timedout())
+ {
+ webclient_timedout();
+ }
+
+ if (uip_acked())
+ {
+ s.timer = 0;
+ acked();
+ }
+
+ if (uip_newdata())
+ {
+ s.timer = 0;
+ newdata();
+ }
+
+ if (uip_rexmit() || uip_newdata() || uip_acked())
+ {
+ senddata();
+ }
+ else if (uip_poll())
+ {
+ ++s.timer;
+ if (s.timer == WEBCLIENT_TIMEOUT)
+ {
+ webclient_timedout();
+ uip_abort();
+ return;
+ }
+ }
+
+ if (uip_closed())
+ {
+ if (s.httpflag != HTTPFLAG_MOVED)
+ {
+ /* Send NULL data to signal EOF. */
+ webclient_datahandler(NULL, 0);
+ }
+ else
+ {
+ if (resolv_lookup(s.host) == NULL)
+ {
+ resolv_query(s.host);
+ }
+ webclient_get(s.host, s.port, s.file);
+ }
+ }
+}
diff --git a/nuttx/netutils/webclient/webclient.h b/nuttx/netutils/webclient/webclient.h
new file mode 100644
index 000000000..c6559e3f0
--- /dev/null
+++ b/nuttx/netutils/webclient/webclient.h
@@ -0,0 +1,214 @@
+/**
+ * webclient.h
+ * Header file for the HTTP client.
+ * Author: Adam Dunkels <adam@dunkels.com>
+ *
+ * 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: webclient.h,v 1.1.1.1 2007-08-26 23:07:04 patacongo Exp $
+ *
+ */
+#ifndef __WEBCLIENT_H__
+#define __WEBCLIENT_H__
+
+#include <sys/types.h>
+#include <net/uip/uipopt.h>
+
+#include "webclient-strings.h"
+
+#define WEBCLIENT_CONF_MAX_URLLEN 100
+
+struct webclient_state {
+ uint8 timer;
+ uint8 state;
+ uint8 httpflag;
+
+ uint16 port;
+ char host[40];
+ char file[WEBCLIENT_CONF_MAX_URLLEN];
+ uint16 getrequestptr;
+ uint16 getrequestleft;
+
+ char httpheaderline[200];
+ uint16 httpheaderlineptr;
+
+ char mimetype[32];
+};
+
+/**
+ * Callback function that is called from the webclient code when HTTP
+ * data has been received.
+ *
+ * This function must be implemented by the module that uses the
+ * webclient code. The function is called from the webclient module
+ * when HTTP data has been received. The function is not called when
+ * HTTP headers are received, only for the actual data.
+ *
+ * \note This function is called many times, repetedly, when data is
+ * being received, and not once when all data has been received.
+ *
+ * \param data A pointer to the data that has been received.
+ * \param len The length of the data that has been received.
+ */
+void webclient_datahandler(char *data, uint16 len);
+
+/**
+ * Callback function that is called from the webclient code when the
+ * HTTP connection has been connected to the web server.
+ *
+ * This function must be implemented by the module that uses the
+ * webclient code.
+ */
+void webclient_connected(void);
+
+/**
+ * Callback function that is called from the webclient code if the
+ * HTTP connection to the web server has timed out.
+ *
+ * This function must be implemented by the module that uses the
+ * webclient code.
+ */
+void webclient_timedout(void);
+
+/**
+ * Callback function that is called from the webclient code if the
+ * HTTP connection to the web server has been aborted by the web
+ * server.
+ *
+ * This function must be implemented by the module that uses the
+ * webclient code.
+ */
+void webclient_aborted(void);
+
+/**
+ * Callback function that is called from the webclient code when the
+ * HTTP connection to the web server has been closed.
+ *
+ * This function must be implemented by the module that uses the
+ * webclient code.
+ */
+void webclient_closed(void);
+
+/**
+ * Initialize the webclient module.
+ */
+void webclient_init(void);
+
+/**
+ * Open an HTTP connection to a web server and ask for a file using
+ * the GET method.
+ *
+ * This function opens an HTTP connection to the specified web server
+ * and requests the specified file using the GET method. When the HTTP
+ * connection has been connected, the webclient_connected() callback
+ * function is called and when the HTTP data arrives the
+ * webclient_datahandler() callback function is called.
+ *
+ * The callback function webclient_timedout() is called if the web
+ * server could not be contacted, and the webclient_aborted() callback
+ * function is called if the HTTP connection is aborted by the web
+ * server.
+ *
+ * When the HTTP request has been completed and the HTTP connection is
+ * closed, the webclient_closed() callback function will be called.
+ *
+ * \note If the function is passed a host name, it must already be in
+ * the resolver cache in order for the function to connect to the web
+ * server. It is therefore up to the calling module to implement the
+ * resolver calls and the signal handler used for reporting a resolv
+ * query answer.
+ *
+ * \param host A pointer to a string containing either a host name or
+ * a numerical IP address in dotted decimal notation (e.g., 192.168.23.1).
+ *
+ * \param port The port number to which to connect, in host byte order.
+ *
+ * \param file A pointer to the name of the file to get.
+ *
+ * \retval 0 if the host name could not be found in the cache, or
+ * if a TCP connection could not be created.
+ *
+ * \retval 1 if the connection was initiated.
+ */
+unsigned char webclient_get(char *host, uint16 port, char *file);
+
+/**
+ * Close the currently open HTTP connection.
+ */
+void webclient_close(void);
+
+/**
+ * Obtain the MIME type of the current HTTP data stream.
+ *
+ * \return A pointer to a string contaning the MIME type. The string
+ * may be empty if no MIME type was reported by the web server.
+ */
+char *webclient_mimetype(void);
+
+/**
+ * Obtain the filename of the current HTTP data stream.
+ *
+ * The filename of an HTTP request may be changed by the web server,
+ * and may therefore not be the same as when the original GET request
+ * was made with webclient_get(). This function is used for obtaining
+ * the current filename.
+ *
+ * \return A pointer to the current filename.
+ */
+char *webclient_filename(void);
+
+/**
+ * Obtain the hostname of the current HTTP data stream.
+ *
+ * The hostname of the web server of an HTTP request may be changed
+ * by the web server, and may therefore not be the same as when the
+ * original GET request was made with webclient_get(). This function
+ * is used for obtaining the current hostname.
+ *
+ * \return A pointer to the current hostname.
+ */
+char *webclient_hostname(void);
+
+/**
+ * Obtain the port number of the current HTTP data stream.
+ *
+ * The port number of an HTTP request may be changed by the web
+ * server, and may therefore not be the same as when the original GET
+ * request was made with webclient_get(). This function is used for
+ * obtaining the current port number.
+ *
+ * \return The port number of the current HTTP data stream, in host byte order.
+ */
+unsigned short webclient_port(void);
+
+#endif /* __WEBCLIENT_H__ */
+
+/** @} */
diff --git a/nuttx/netutils/webserver/Make.defs b/nuttx/netutils/webserver/Make.defs
new file mode 100644
index 000000000..94469f526
--- /dev/null
+++ b/nuttx/netutils/webserver/Make.defs
@@ -0,0 +1,37 @@
+############################################################################
+# Make.defs
+#
+# Copyright (C) 2007 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name NuttX nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+WEBSERVER_ASRCS =
+WEBSERVER_CSRCS = httpd.c http-strings.c httpd-fs.c httpd-cgi.c
diff --git a/nuttx/netutils/webserver/http-strings b/nuttx/netutils/webserver/http-strings
new file mode 100644
index 000000000..d0b9121be
--- /dev/null
+++ b/nuttx/netutils/webserver/http-strings
@@ -0,0 +1,35 @@
+http_http "http://"
+http_200 "200 "
+http_301 "301 "
+http_302 "302 "
+http_get "GET "
+http_10 "HTTP/1.0"
+http_11 "HTTP/1.1"
+http_content_type "content-type: "
+http_texthtml "text/html"
+http_location "location: "
+http_host "host: "
+http_crnl "\r\n"
+http_index_html "/index.html"
+http_404_html "/404.html"
+http_referer "Referer:"
+http_header_200 "HTTP/1.0 200 OK\r\nServer: uIP/1.0 http://www.sics.se/~adam/uip/\r\nConnection: close\r\n"
+http_header_404 "HTTP/1.0 404 Not found\r\nServer: uIP/1.0 http://www.sics.se/~adam/uip/\r\nConnection: close\r\n"
+http_content_type_plain "Content-type: text/plain\r\n\r\n"
+http_content_type_html "Content-type: text/html\r\n\r\n"
+http_content_type_css "Content-type: text/css\r\n\r\n"
+http_content_type_text "Content-type: text/text\r\n\r\n"
+http_content_type_png "Content-type: image/png\r\n\r\n"
+http_content_type_gif "Content-type: image/gif\r\n\r\n"
+http_content_type_jpg "Content-type: image/jpeg\r\n\r\n"
+http_content_type_binary "Content-type: application/octet-stream\r\n\r\n"
+http_html ".html"
+http_shtml ".shtml"
+http_htm ".htm"
+http_css ".css"
+http_png ".png"
+http_gif ".gif"
+http_jpg ".jpg"
+http_text ".txt"
+http_txt ".txt"
+
diff --git a/nuttx/netutils/webserver/http-strings.c b/nuttx/netutils/webserver/http-strings.c
new file mode 100644
index 000000000..0d822baf7
--- /dev/null
+++ b/nuttx/netutils/webserver/http-strings.c
@@ -0,0 +1,102 @@
+const char http_http[8] =
+/* "http://" */
+{0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, };
+const char http_200[5] =
+/* "200 " */
+{0x32, 0x30, 0x30, 0x20, };
+const char http_301[5] =
+/* "301 " */
+{0x33, 0x30, 0x31, 0x20, };
+const char http_302[5] =
+/* "302 " */
+{0x33, 0x30, 0x32, 0x20, };
+const char http_get[5] =
+/* "GET " */
+{0x47, 0x45, 0x54, 0x20, };
+const char http_10[9] =
+/* "HTTP/1.0" */
+{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, };
+const char http_11[9] =
+/* "HTTP/1.1" */
+{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, };
+const char http_content_type[15] =
+/* "content-type: " */
+{0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, };
+const char http_texthtml[10] =
+/* "text/html" */
+{0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, };
+const char http_location[11] =
+/* "location: " */
+{0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, };
+const char http_host[7] =
+/* "host: " */
+{0x68, 0x6f, 0x73, 0x74, 0x3a, 0x20, };
+const char http_crnl[3] =
+/* "\r\n" */
+{0xd, 0xa, };
+const char http_index_html[12] =
+/* "/index.html" */
+{0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, };
+const char http_404_html[10] =
+/* "/404.html" */
+{0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, };
+const char http_referer[9] =
+/* "Referer:" */
+{0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, 0x3a, };
+const char http_header_200[84] =
+/* "HTTP/1.0 200 OK\r\nServer: uIP/1.0 http://www.sics.se/~adam/uip/\r\nConnection: close\r\n" */
+{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x73, 0x69, 0x63, 0x73, 0x2e, 0x73, 0x65, 0x2f, 0x7e, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, 0x70, 0x2f, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0xd, 0xa, };
+const char http_header_404[91] =
+/* "HTTP/1.0 404 Not found\r\nServer: uIP/1.0 http://www.sics.se/~adam/uip/\r\nConnection: close\r\n" */
+{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x34, 0x30, 0x34, 0x20, 0x4e, 0x6f, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0xd, 0xa, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x73, 0x69, 0x63, 0x73, 0x2e, 0x73, 0x65, 0x2f, 0x7e, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, 0x70, 0x2f, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0xd, 0xa, };
+const char http_content_type_plain[29] =
+/* "Content-type: text/plain\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0xd, 0xa, 0xd, 0xa, };
+const char http_content_type_html[28] =
+/* "Content-type: text/html\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, 0xd, 0xa, };
+const char http_content_type_css [27] =
+/* "Content-type: text/css\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x63, 0x73, 0x73, 0xd, 0xa, 0xd, 0xa, };
+const char http_content_type_text[28] =
+/* "Content-type: text/text\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x74, 0x65, 0x78, 0x74, 0xd, 0xa, 0xd, 0xa, };
+const char http_content_type_png [28] =
+/* "Content-type: image/png\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0xd, 0xa, 0xd, 0xa, };
+const char http_content_type_gif [28] =
+/* "Content-type: image/gif\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, 0x69, 0x66, 0xd, 0xa, 0xd, 0xa, };
+const char http_content_type_jpg [29] =
+/* "Content-type: image/jpeg\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x65, 0x67, 0xd, 0xa, 0xd, 0xa, };
+const char http_content_type_binary[43] =
+/* "Content-type: application/octet-stream\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6f, 0x63, 0x74, 0x65, 0x74, 0x2d, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0xd, 0xa, 0xd, 0xa, };
+const char http_html[6] =
+/* ".html" */
+{0x2e, 0x68, 0x74, 0x6d, 0x6c, };
+const char http_shtml[7] =
+/* ".shtml" */
+{0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, };
+const char http_htm[5] =
+/* ".htm" */
+{0x2e, 0x68, 0x74, 0x6d, };
+const char http_css[5] =
+/* ".css" */
+{0x2e, 0x63, 0x73, 0x73, };
+const char http_png[5] =
+/* ".png" */
+{0x2e, 0x70, 0x6e, 0x67, };
+const char http_gif[5] =
+/* ".gif" */
+{0x2e, 0x67, 0x69, 0x66, };
+const char http_jpg[5] =
+/* ".jpg" */
+{0x2e, 0x6a, 0x70, 0x67, };
+const char http_text[5] =
+/* ".txt" */
+{0x2e, 0x74, 0x78, 0x74, };
+const char http_txt[5] =
+/* ".txt" */
+{0x2e, 0x74, 0x78, 0x74, };
diff --git a/nuttx/netutils/webserver/http-strings.h b/nuttx/netutils/webserver/http-strings.h
new file mode 100644
index 000000000..f121dd73a
--- /dev/null
+++ b/nuttx/netutils/webserver/http-strings.h
@@ -0,0 +1,34 @@
+extern const char http_http[8];
+extern const char http_200[5];
+extern const char http_301[5];
+extern const char http_302[5];
+extern const char http_get[5];
+extern const char http_10[9];
+extern const char http_11[9];
+extern const char http_content_type[15];
+extern const char http_texthtml[10];
+extern const char http_location[11];
+extern const char http_host[7];
+extern const char http_crnl[3];
+extern const char http_index_html[12];
+extern const char http_404_html[10];
+extern const char http_referer[9];
+extern const char http_header_200[84];
+extern const char http_header_404[91];
+extern const char http_content_type_plain[29];
+extern const char http_content_type_html[28];
+extern const char http_content_type_css [27];
+extern const char http_content_type_text[28];
+extern const char http_content_type_png [28];
+extern const char http_content_type_gif [28];
+extern const char http_content_type_jpg [29];
+extern const char http_content_type_binary[43];
+extern const char http_html[6];
+extern const char http_shtml[7];
+extern const char http_htm[5];
+extern const char http_css[5];
+extern const char http_png[5];
+extern const char http_gif[5];
+extern const char http_jpg[5];
+extern const char http_text[5];
+extern const char http_txt[5];
diff --git a/nuttx/netutils/webserver/httpd-cgi.c b/nuttx/netutils/webserver/httpd-cgi.c
new file mode 100644
index 000000000..5c9609ee7
--- /dev/null
+++ b/nuttx/netutils/webserver/httpd-cgi.c
@@ -0,0 +1,178 @@
+/* httpd-cgi.c
+ * Web server script interface
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * Copyright (c) 2001-2006, 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.
+ */
+
+#include <net/uip/uip.h>
+#include <net/uip/psock.h>
+#include <net/uip/httpd.h>
+
+#include "httpd-cgi.h"
+
+#include <stdio.h>
+#include <string.h>
+
+HTTPD_CGI_CALL(file, "file-stats", file_stats);
+HTTPD_CGI_CALL(tcp, "tcp-connections", tcp_stats);
+HTTPD_CGI_CALL(net, "net-stats", net_stats);
+
+static const struct httpd_cgi_call *calls[] = { &file, &tcp, &net, NULL };
+
+/*---------------------------------------------------------------------------*/
+static
+void nullfunction(struct httpd_state *s, char *ptr)
+{
+}
+
+/*---------------------------------------------------------------------------*/
+httpd_cgifunction
+httpd_cgi(char *name)
+{
+ const struct httpd_cgi_call **f;
+
+ /* Find the matching name in the table, return the function. */
+ for(f = calls; *f != NULL; ++f) {
+ if(strncmp((*f)->name, name, strlen((*f)->name)) == 0) {
+ return (*f)->function;
+ }
+ }
+#warning REVISIT -- must wait to return
+ return nullfunction;
+}
+/*---------------------------------------------------------------------------*/
+static unsigned short
+generate_file_stats(void *arg)
+{
+ char *f = (char *)arg;
+ return snprintf((char *)uip_appdata, UIP_APPDATA_SIZE, "%5u", httpd_fs_count(f));
+}
+/*---------------------------------------------------------------------------*/
+static
+void file_stats(struct httpd_state *s, char *ptr)
+{
+ psock_generator_send(&s->sout, generate_file_stats, strchr(ptr, ' ') + 1);
+}
+
+/*---------------------------------------------------------------------------*/
+static const char closed[] = /* "CLOSED",*/
+{0x43, 0x4c, 0x4f, 0x53, 0x45, 0x44, 0};
+static const char syn_rcvd[] = /* "SYN-RCVD",*/
+{0x53, 0x59, 0x4e, 0x2d, 0x52, 0x43, 0x56,
+ 0x44, 0};
+static const char syn_sent[] = /* "SYN-SENT",*/
+{0x53, 0x59, 0x4e, 0x2d, 0x53, 0x45, 0x4e,
+ 0x54, 0};
+static const char established[] = /* "ESTABLISHED",*/
+{0x45, 0x53, 0x54, 0x41, 0x42, 0x4c, 0x49, 0x53, 0x48,
+ 0x45, 0x44, 0};
+static const char fin_wait_1[] = /* "FIN-WAIT-1",*/
+{0x46, 0x49, 0x4e, 0x2d, 0x57, 0x41, 0x49,
+ 0x54, 0x2d, 0x31, 0};
+static const char fin_wait_2[] = /* "FIN-WAIT-2",*/
+{0x46, 0x49, 0x4e, 0x2d, 0x57, 0x41, 0x49,
+ 0x54, 0x2d, 0x32, 0};
+static const char closing[] = /* "CLOSING",*/
+{0x43, 0x4c, 0x4f, 0x53, 0x49,
+ 0x4e, 0x47, 0};
+static const char time_wait[] = /* "TIME-WAIT,"*/
+{0x54, 0x49, 0x4d, 0x45, 0x2d, 0x57, 0x41,
+ 0x49, 0x54, 0};
+static const char last_ack[] = /* "LAST-ACK"*/
+{0x4c, 0x41, 0x53, 0x54, 0x2d, 0x41, 0x43,
+ 0x4b, 0};
+
+static const char *states[] = {
+ closed,
+ syn_rcvd,
+ syn_sent,
+ established,
+ fin_wait_1,
+ fin_wait_2,
+ closing,
+ time_wait,
+ last_ack};
+
+
+static unsigned short
+generate_tcp_stats(void *arg)
+{
+ struct uip_conn *conn;
+ struct httpd_state *s = (struct httpd_state *)arg;
+
+ conn = &uip_conns[s->count];
+ return snprintf((char *)uip_appdata, UIP_APPDATA_SIZE,
+ "<tr><td>%d</td><td>%u.%u.%u.%u:%u</td><td>%s</td><td>%u</td><td>%u</td><td>%c %c</td></tr>\r\n",
+ htons(conn->lport),
+ htons(conn->ripaddr[0]) >> 8,
+ htons(conn->ripaddr[0]) & 0xff,
+ htons(conn->ripaddr[1]) >> 8,
+ htons(conn->ripaddr[1]) & 0xff,
+ htons(conn->rport),
+ states[conn->tcpstateflags & UIP_TS_MASK],
+ conn->nrtx,
+ conn->timer,
+ (uip_outstanding(conn))? '*':' ',
+ (uip_stopped(conn))? '!':' ');
+}
+/*---------------------------------------------------------------------------*/
+static
+void tcp_stats(struct httpd_state *s, char *ptr)
+{
+ for(s->count = 0; s->count < UIP_CONNS; ++s->count) {
+ if((uip_conns[s->count].tcpstateflags & UIP_TS_MASK) != UIP_CLOSED) {
+ psock_generator_send(&s->sout, generate_tcp_stats, s);
+ }
+ }
+}
+
+/*---------------------------------------------------------------------------*/
+static unsigned short
+generate_net_stats(void *arg)
+{
+ struct httpd_state *s = (struct httpd_state *)arg;
+ return snprintf((char *)uip_appdata, UIP_APPDATA_SIZE,
+ "%5u\n", ((uip_stats_t *)&uip_stat)[s->count]);
+}
+
+static
+void net_stats(struct httpd_state *s, char *ptr)
+{
+#if UIP_STATISTICS
+
+ for(s->count = 0; s->count < sizeof(uip_stat) / sizeof(uip_stats_t);
+ ++s->count) {
+ psock_generator_send(&s->sout, generate_net_stats, s);
+ }
+
+#endif /* UIP_STATISTICS */
+}
+
+/*---------------------------------------------------------------------------*/
+/** @} */
diff --git a/nuttx/netutils/webserver/httpd-cgi.h b/nuttx/netutils/webserver/httpd-cgi.h
new file mode 100644
index 000000000..bd22feb85
--- /dev/null
+++ b/nuttx/netutils/webserver/httpd-cgi.h
@@ -0,0 +1,67 @@
+/* httpd-cgi.h
+ * Web server script interface header file
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * 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.
+ */
+
+#ifndef __HTTPD_CGI_H__
+#define __HTTPD_CGI_H__
+
+#include <net/uip/psock.h>
+#include <net/uip/httpd.h>
+
+typedef void (* httpd_cgifunction)(struct httpd_state *, char *);
+
+httpd_cgifunction httpd_cgi(char *name);
+
+struct httpd_cgi_call {
+ const char *name;
+ const httpd_cgifunction function;
+};
+
+/**
+ * \brief HTTPD CGI function declaration
+ * \param name The C variable name of the function
+ * \param str The string name of the function, used in the script file
+ * \param function A pointer to the function that implements it
+ *
+ * This macro is used for declaring a HTTPD CGI
+ * function. This function is then added to the list of
+ * HTTPD CGI functions with the httpd_cgi_add() function.
+ *
+ * \hideinitializer
+ */
+#define HTTPD_CGI_CALL(name, str, function) \
+static void function(struct httpd_state *, char *); \
+static const struct httpd_cgi_call name = {str, function}
+
+void httpd_cgi_init(void);
+#endif /* __HTTPD_CGI_H__ */
+
+/** @} */
diff --git a/nuttx/netutils/webserver/httpd-fs.c b/nuttx/netutils/webserver/httpd-fs.c
new file mode 100644
index 000000000..679b65be2
--- /dev/null
+++ b/nuttx/netutils/webserver/httpd-fs.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2001, 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 lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: httpd-fs.c,v 1.1.1.1 2007-08-26 23:07:02 patacongo Exp $
+ */
+
+#include <sys/types.h>
+
+#include <net/uip/httpd.h>
+
+#include "httpd-fsdata.h"
+
+#ifndef NULL
+#define NULL 0
+#endif /* NULL */
+
+#include "httpd-fsdata.c"
+
+#if HTTPD_FS_STATISTICS
+static uint16 count[HTTPD_FS_NUMFILES];
+#endif /* HTTPD_FS_STATISTICS */
+
+/*-----------------------------------------------------------------------------------*/
+static uint8
+httpd_fs_strcmp(const char *str1, const char *str2)
+{
+ uint8 i;
+ i = 0;
+ loop:
+
+ if(str2[i] == 0 ||
+ str1[i] == '\r' ||
+ str1[i] == '\n') {
+ return 0;
+ }
+
+ if(str1[i] != str2[i]) {
+ return 1;
+ }
+
+
+ ++i;
+ goto loop;
+}
+/*-----------------------------------------------------------------------------------*/
+int
+httpd_fs_open(const char *name, struct httpd_fs_file *file)
+{
+#if HTTPD_FS_STATISTICS
+ uint16 i = 0;
+#endif /* HTTPD_FS_STATISTICS */
+ struct httpd_fsdata_file_noconst *f;
+
+ for(f = (struct httpd_fsdata_file_noconst *)HTTPD_FS_ROOT;
+ f != NULL;
+ f = (struct httpd_fsdata_file_noconst *)f->next) {
+
+ if(httpd_fs_strcmp(name, f->name) == 0) {
+ file->data = f->data;
+ file->len = f->len;
+#if HTTPD_FS_STATISTICS
+ ++count[i];
+#endif /* HTTPD_FS_STATISTICS */
+ return 1;
+ }
+#if HTTPD_FS_STATISTICS
+ ++i;
+#endif /* HTTPD_FS_STATISTICS */
+
+ }
+ return 0;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+httpd_fs_init(void)
+{
+#if HTTPD_FS_STATISTICS
+ uint16 i;
+ for(i = 0; i < HTTPD_FS_NUMFILES; i++) {
+ count[i] = 0;
+ }
+#endif /* HTTPD_FS_STATISTICS */
+}
+/*-----------------------------------------------------------------------------------*/
+#if HTTPD_FS_STATISTICS
+uint16 httpd_fs_count
+(char *name)
+{
+ struct httpd_fsdata_file_noconst *f;
+ uint16 i;
+
+ i = 0;
+ for(f = (struct httpd_fsdata_file_noconst *)HTTPD_FS_ROOT;
+ f != NULL;
+ f = (struct httpd_fsdata_file_noconst *)f->next) {
+
+ if(httpd_fs_strcmp(name, f->name) == 0) {
+ return count[i];
+ }
+ ++i;
+ }
+ return 0;
+}
+#endif /* HTTPD_FS_STATISTICS */
+/*-----------------------------------------------------------------------------------*/
diff --git a/nuttx/netutils/webserver/httpd-fsdata.c b/nuttx/netutils/webserver/httpd-fsdata.c
new file mode 100644
index 000000000..20327baba
--- /dev/null
+++ b/nuttx/netutils/webserver/httpd-fsdata.c
@@ -0,0 +1,617 @@
+static const unsigned char data_processes_shtml[] = {
+ /* /processes.shtml */
+ 0x2f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0,
+ 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65,
+ 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3c, 0x68, 0x31,
+ 0x3e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x70, 0x72,
+ 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x3c, 0x2f, 0x68,
+ 0x31, 0x3e, 0x3c, 0x62, 0x72, 0x3e, 0x3c, 0x74, 0x61, 0x62,
+ 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22,
+ 0x31, 0x30, 0x30, 0x25, 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x72,
+ 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x49, 0x44, 0x3c, 0x2f, 0x74,
+ 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x4e, 0x61, 0x6d, 0x65,
+ 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x50,
+ 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x3c, 0x2f, 0x74,
+ 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x50, 0x6f, 0x6c, 0x6c,
+ 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3c, 0x2f,
+ 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x45, 0x76, 0x65,
+ 0x6e, 0x74, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72,
+ 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x50,
+ 0x72, 0x6f, 0x63, 0x73, 0x74, 0x61, 0x74, 0x65, 0x3c, 0x2f,
+ 0x74, 0x68, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x25,
+ 0x21, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65,
+ 0x73, 0xa, 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x66, 0x6f, 0x6f,
+ 0x74, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0};
+
+static const unsigned char data_404_html[] = {
+ /* /404.html */
+ 0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
+ 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x20, 0x20, 0x3c,
+ 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, 0x22,
+ 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x63, 0x65, 0x6e,
+ 0x74, 0x65, 0x72, 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3c, 0x68, 0x31, 0x3e, 0x34, 0x30, 0x34, 0x20, 0x2d,
+ 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e,
+ 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x68, 0x33,
+ 0x3e, 0x47, 0x6f, 0x20, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65,
+ 0x66, 0x3d, 0x22, 0x2f, 0x22, 0x3e, 0x68, 0x65, 0x72, 0x65,
+ 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x65,
+ 0x61, 0x64, 0x2e, 0x3c, 0x2f, 0x68, 0x33, 0x3e, 0xa, 0x20,
+ 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65,
+ 0x72, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x2f, 0x62, 0x6f, 0x64,
+ 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e,
+0};
+
+static const unsigned char data_files_shtml[] = {
+ /* /files.shtml */
+ 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0,
+ 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65,
+ 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3c, 0x68, 0x31,
+ 0x3e, 0x46, 0x69, 0x6c, 0x65, 0x20, 0x73, 0x74, 0x61, 0x74,
+ 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x3c, 0x2f, 0x68, 0x31,
+ 0x3e, 0xa, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e,
+ 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69,
+ 0x64, 0x74, 0x68, 0x3d, 0x22, 0x33, 0x30, 0x30, 0x22, 0x3e,
+ 0xa, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c,
+ 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x69,
+ 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22,
+ 0x3e, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74,
+ 0x6d, 0x6c, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x74, 0x64,
+ 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x3e, 0x25, 0x21, 0x20, 0x66,
+ 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x73, 0x20,
+ 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d,
+ 0x6c, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64,
+ 0x3e, 0x3c, 0x69, 0x6d, 0x67, 0x20, 0x73, 0x72, 0x63, 0x3d,
+ 0x22, 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e, 0x70, 0x6e, 0x67,
+ 0x22, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x31,
+ 0x30, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x25, 0x21,
+ 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x74,
+ 0x73, 0x20, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68,
+ 0x74, 0x6d, 0x6c, 0xa, 0x3e, 0x20, 0x3c, 0x2f, 0x74, 0x64,
+ 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x72,
+ 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72,
+ 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73,
+ 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x2f, 0x66,
+ 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c,
+ 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa,
+ 0x3c, 0x74, 0x64, 0x3e, 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c,
+ 0x65, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x73, 0x20, 0x2f, 0x66,
+ 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c,
+ 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e,
+ 0x3c, 0x69, 0x6d, 0x67, 0x20, 0x73, 0x72, 0x63, 0x3d, 0x22,
+ 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e, 0x70, 0x6e, 0x67, 0x22,
+ 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x31, 0x30,
+ 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x25, 0x21, 0x20,
+ 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x73,
+ 0x20, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x68,
+ 0x74, 0x6d, 0x6c, 0xa, 0x3e, 0x20, 0x3c, 0x2f, 0x74, 0x64,
+ 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x72,
+ 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72,
+ 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x74, 0x63, 0x70, 0x2e, 0x73,
+ 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x2f, 0x74, 0x63, 0x70,
+ 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x3c, 0x2f, 0x61, 0x3e,
+ 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x3e,
+ 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74,
+ 0x61, 0x74, 0x73, 0x20, 0x2f, 0x74, 0x63, 0x70, 0x2e, 0x73,
+ 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e,
+ 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x69, 0x6d, 0x67, 0x20, 0x73,
+ 0x72, 0x63, 0x3d, 0x22, 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e,
+ 0x70, 0x6e, 0x67, 0x22, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68,
+ 0x74, 0x3d, 0x31, 0x30, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68,
+ 0x3d, 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73,
+ 0x74, 0x61, 0x74, 0x73, 0x20, 0x2f, 0x74, 0x63, 0x70, 0x2e,
+ 0x73, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3e, 0x20, 0x3c, 0x2f,
+ 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c,
+ 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x61, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x73, 0x74, 0x61,
+ 0x74, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e,
+ 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x73, 0x68, 0x74,
+ 0x6d, 0x6c, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x74, 0x64,
+ 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x3e, 0x25, 0x21, 0x20, 0x66,
+ 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x73, 0x20,
+ 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x73, 0x68, 0x74,
+ 0x6d, 0x6c, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74,
+ 0x64, 0x3e, 0x3c, 0x69, 0x6d, 0x67, 0x20, 0x73, 0x72, 0x63,
+ 0x3d, 0x22, 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e, 0x70, 0x6e,
+ 0x67, 0x22, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d,
+ 0x31, 0x30, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x25,
+ 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74, 0x61,
+ 0x74, 0x73, 0x20, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e,
+ 0x73, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3e, 0x20, 0x3c, 0x2f,
+ 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c,
+ 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x61, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x73, 0x74, 0x79,
+ 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0x22, 0x3e, 0x2f, 0x73,
+ 0x74, 0x79, 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0x3c, 0x2f,
+ 0x61, 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74,
+ 0x64, 0x3e, 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d,
+ 0x73, 0x74, 0x61, 0x74, 0x73, 0x20, 0x2f, 0x73, 0x74, 0x79,
+ 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0xa, 0x3c, 0x2f, 0x74,
+ 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x69, 0x6d, 0x67,
+ 0x20, 0x73, 0x72, 0x63, 0x3d, 0x22, 0x2f, 0x66, 0x61, 0x64,
+ 0x65, 0x2e, 0x70, 0x6e, 0x67, 0x22, 0x20, 0x68, 0x65, 0x69,
+ 0x67, 0x68, 0x74, 0x3d, 0x31, 0x30, 0x20, 0x77, 0x69, 0x64,
+ 0x74, 0x68, 0x3d, 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65,
+ 0x2d, 0x73, 0x74, 0x61, 0x74, 0x73, 0x20, 0x2f, 0x73, 0x74,
+ 0x79, 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0xa, 0x3e, 0x20,
+ 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e,
+ 0xa, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c,
+ 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x34,
+ 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x2f,
+ 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3c, 0x2f,
+ 0x61, 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74,
+ 0x64, 0x3e, 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d,
+ 0x73, 0x74, 0x61, 0x74, 0x73, 0x20, 0x2f, 0x34, 0x30, 0x34,
+ 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3c, 0x2f, 0x74, 0x64,
+ 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x69, 0x6d, 0x67, 0x20,
+ 0x73, 0x72, 0x63, 0x3d, 0x22, 0x2f, 0x66, 0x61, 0x64, 0x65,
+ 0x2e, 0x70, 0x6e, 0x67, 0x22, 0x20, 0x68, 0x65, 0x69, 0x67,
+ 0x68, 0x74, 0x3d, 0x31, 0x30, 0x20, 0x77, 0x69, 0x64, 0x74,
+ 0x68, 0x3d, 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d,
+ 0x73, 0x74, 0x61, 0x74, 0x73, 0x20, 0x2f, 0x34, 0x30, 0x34,
+ 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3e, 0x20, 0x3c, 0x2f,
+ 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c,
+ 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x61, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x66, 0x61, 0x64,
+ 0x65, 0x2e, 0x70, 0x6e, 0x67, 0x22, 0x3e, 0x2f, 0x66, 0x61,
+ 0x64, 0x65, 0x2e, 0x70, 0x6e, 0x67, 0x3c, 0x2f, 0x61, 0x3e,
+ 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x3e,
+ 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74,
+ 0x61, 0x74, 0x73, 0x20, 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e,
+ 0x70, 0x6e, 0x67, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c,
+ 0x74, 0x64, 0x3e, 0x3c, 0x69, 0x6d, 0x67, 0x20, 0x73, 0x72,
+ 0x63, 0x3d, 0x22, 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e, 0x70,
+ 0x6e, 0x67, 0x22, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74,
+ 0x3d, 0x31, 0x30, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d,
+ 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74,
+ 0x61, 0x74, 0x73, 0x20, 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e,
+ 0x70, 0x6e, 0x67, 0xa, 0x3e, 0x20, 0x3c, 0x2f, 0x74, 0x64,
+ 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x2f, 0x74,
+ 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0x3c, 0x2f, 0x63, 0x65,
+ 0x6e, 0x74, 0x65, 0x72, 0x3e, 0xa, 0x25, 0x21, 0x3a, 0x20,
+ 0x2f, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2e, 0x68, 0x74,
+ 0x6d, 0x6c, 0xa, 0};
+
+static const unsigned char data_footer_html[] = {
+ /* /footer.html */
+ 0x2f, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
+ 0x20, 0x20, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa,
+ 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0};
+
+static const unsigned char data_header_html[] = {
+ /* /header.html */
+ 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
+ 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20,
+ 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49,
+ 0x43, 0x20, 0x22, 0x2d, 0x2f, 0x2f, 0x57, 0x33, 0x43, 0x2f,
+ 0x2f, 0x44, 0x54, 0x44, 0x20, 0x48, 0x54, 0x4d, 0x4c, 0x20,
+ 0x34, 0x2e, 0x30, 0x31, 0x20, 0x54, 0x72, 0x61, 0x6e, 0x73,
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x2f, 0x45,
+ 0x4e, 0x22, 0x20, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72,
+ 0x67, 0x2f, 0x54, 0x52, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x34,
+ 0x2f, 0x6c, 0x6f, 0x6f, 0x73, 0x65, 0x2e, 0x64, 0x74, 0x64,
+ 0x22, 0x3e, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa,
+ 0x20, 0x20, 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x20,
+ 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e,
+ 0x57, 0x65, 0x6c, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x49, 0x50, 0x20, 0x77,
+ 0x65, 0x62, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x21,
+ 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x20,
+ 0x20, 0x20, 0x20, 0x3c, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x72,
+ 0x65, 0x6c, 0x3d, 0x22, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x73,
+ 0x68, 0x65, 0x65, 0x74, 0x22, 0x20, 0x74, 0x79, 0x70, 0x65,
+ 0x3d, 0x22, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x63, 0x73, 0x73,
+ 0x22, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x73, 0x74,
+ 0x79, 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0x22, 0x3e, 0x20,
+ 0x20, 0xa, 0x20, 0x20, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64,
+ 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20,
+ 0x62, 0x67, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x23,
+ 0x66, 0x66, 0x66, 0x65, 0x65, 0x63, 0x22, 0x20, 0x74, 0x65,
+ 0x78, 0x74, 0x3d, 0x22, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x22,
+ 0x3e, 0xa, 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20,
+ 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, 0x6e,
+ 0x75, 0x22, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76,
+ 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65,
+ 0x6e, 0x75, 0x62, 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x61, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x22, 0x3e, 0x46,
+ 0x72, 0x6f, 0x6e, 0x74, 0x20, 0x70, 0x61, 0x67, 0x65, 0x3c,
+ 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa,
+ 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61,
+ 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, 0x6e, 0x75, 0x62, 0x6f,
+ 0x78, 0x22, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66,
+ 0x3d, 0x22, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x68,
+ 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x46, 0x69, 0x6c, 0x65, 0x20,
+ 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73,
+ 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e,
+ 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c,
+ 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, 0x6e, 0x75, 0x62,
+ 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65,
+ 0x66, 0x3d, 0x22, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x73,
+ 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4e, 0x65, 0x74, 0x77,
+ 0x6f, 0x72, 0x6b, 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73,
+ 0x74, 0x69, 0x63, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f,
+ 0x64, 0x69, 0x76, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69,
+ 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d,
+ 0x65, 0x6e, 0x75, 0x62, 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x61,
+ 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x74, 0x63, 0x70,
+ 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4e, 0x65,
+ 0x74, 0x77, 0x6f, 0x72, 0x6b, 0xa, 0x20, 0x20, 0x63, 0x6f,
+ 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3c,
+ 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa,
+ 0x20, 0x20, 0x3c, 0x62, 0x72, 0x3e, 0xa, 0x20, 0x20, 0x3c,
+ 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0x20, 0x20, 0xa, 0x20,
+ 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73,
+ 0x73, 0x3d, 0x22, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
+ 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x3e, 0xa, 0};
+
+static const unsigned char data_index_html[] = {
+ /* /index.html */
+ 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
+ 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20,
+ 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49,
+ 0x43, 0x20, 0x22, 0x2d, 0x2f, 0x2f, 0x57, 0x33, 0x43, 0x2f,
+ 0x2f, 0x44, 0x54, 0x44, 0x20, 0x48, 0x54, 0x4d, 0x4c, 0x20,
+ 0x34, 0x2e, 0x30, 0x31, 0x20, 0x54, 0x72, 0x61, 0x6e, 0x73,
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x2f, 0x45,
+ 0x4e, 0x22, 0x20, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72,
+ 0x67, 0x2f, 0x54, 0x52, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x34,
+ 0x2f, 0x6c, 0x6f, 0x6f, 0x73, 0x65, 0x2e, 0x64, 0x74, 0x64,
+ 0x22, 0x3e, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa,
+ 0x20, 0x20, 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x20,
+ 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e,
+ 0x57, 0x65, 0x6c, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x49, 0x50, 0x20, 0x77,
+ 0x65, 0x62, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x21,
+ 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x20,
+ 0x20, 0x20, 0x20, 0x3c, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x72,
+ 0x65, 0x6c, 0x3d, 0x22, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x73,
+ 0x68, 0x65, 0x65, 0x74, 0x22, 0x20, 0x74, 0x79, 0x70, 0x65,
+ 0x3d, 0x22, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x63, 0x73, 0x73,
+ 0x22, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x73, 0x74,
+ 0x79, 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0x22, 0x3e, 0x20,
+ 0x20, 0xa, 0x20, 0x20, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64,
+ 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20,
+ 0x62, 0x67, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x23,
+ 0x66, 0x66, 0x66, 0x65, 0x65, 0x63, 0x22, 0x20, 0x74, 0x65,
+ 0x78, 0x74, 0x3d, 0x22, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x22,
+ 0x3e, 0xa, 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20,
+ 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, 0x6e,
+ 0x75, 0x22, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76,
+ 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65,
+ 0x6e, 0x75, 0x62, 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x61, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x22, 0x3e, 0x46,
+ 0x72, 0x6f, 0x6e, 0x74, 0x20, 0x70, 0x61, 0x67, 0x65, 0x3c,
+ 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa,
+ 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61,
+ 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, 0x6e, 0x75, 0x62, 0x6f,
+ 0x78, 0x22, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66,
+ 0x3d, 0x22, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x68,
+ 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x46, 0x69, 0x6c, 0x65, 0x20,
+ 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73,
+ 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e,
+ 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c,
+ 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, 0x6e, 0x75, 0x62,
+ 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65,
+ 0x66, 0x3d, 0x22, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x73,
+ 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4e, 0x65, 0x74, 0x77,
+ 0x6f, 0x72, 0x6b, 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73,
+ 0x74, 0x69, 0x63, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f,
+ 0x64, 0x69, 0x76, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69,
+ 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d,
+ 0x65, 0x6e, 0x75, 0x62, 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x61,
+ 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x74, 0x63, 0x70,
+ 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4e, 0x65,
+ 0x74, 0x77, 0x6f, 0x72, 0x6b, 0xa, 0x20, 0x20, 0x63, 0x6f,
+ 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3c,
+ 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa,
+ 0x20, 0x20, 0x3c, 0x62, 0x72, 0x3e, 0xa, 0x20, 0x20, 0x3c,
+ 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0xa, 0x20, 0x20, 0x3c,
+ 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d,
+ 0x22, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x62, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x22, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x70,
+ 0x3e, 0xa, 0x20, 0x20, 0x54, 0x68, 0x65, 0x73, 0x65, 0x20,
+ 0x77, 0x65, 0x62, 0x20, 0x70, 0x61, 0x67, 0x65, 0x73, 0x20,
+ 0x61, 0x72, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64,
+ 0x20, 0x62, 0x79, 0x20, 0x61, 0x20, 0x73, 0x6d, 0x61, 0x6c,
+ 0x6c, 0x20, 0x77, 0x65, 0x62, 0x20, 0x73, 0x65, 0x72, 0x76,
+ 0x65, 0x72, 0x20, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67,
+ 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x70, 0x20, 0x6f, 0x66,
+ 0xa, 0x20, 0x20, 0x74, 0x68, 0x65, 0x20, 0x3c, 0x61, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70,
+ 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x73, 0x69, 0x63,
+ 0x73, 0x2e, 0x73, 0x65, 0x2f, 0x7e, 0x61, 0x64, 0x61, 0x6d,
+ 0x2f, 0x75, 0x69, 0x70, 0x2f, 0x22, 0x3e, 0x75, 0x49, 0x50,
+ 0x20, 0x65, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x20,
+ 0x54, 0x43, 0x50, 0x2f, 0x49, 0x50, 0xa, 0x20, 0x20, 0x73,
+ 0x74, 0x61, 0x63, 0x6b, 0x3c, 0x2f, 0x61, 0x3e, 0x2e, 0xa,
+ 0x20, 0x20, 0x3c, 0x2f, 0x70, 0x3e, 0xa, 0x20, 0x20, 0x3c,
+ 0x70, 0x3e, 0xa, 0x20, 0x20, 0x43, 0x6c, 0x69, 0x63, 0x6b,
+ 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69,
+ 0x6e, 0x6b, 0x73, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x77, 0x65, 0x62, 0x20, 0x73, 0x65,
+ 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x74, 0x61, 0x74, 0x69,
+ 0x73, 0x74, 0x69, 0x63, 0x73, 0x2e, 0xa, 0x20, 0x20, 0x3c,
+ 0x2f, 0x70, 0x3e, 0xa, 0xa, 0x20, 0x20, 0x3c, 0x2f, 0x62,
+ 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d,
+ 0x6c, 0x3e, 0xa, 0};
+
+static const unsigned char data_style_css[] = {
+ /* /style.css */
+ 0x2f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0,
+ 0x68, 0x31, 0x20, 0xa, 0x7b, 0xa, 0x20, 0x20, 0x74, 0x65,
+ 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20,
+ 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0xa, 0x20, 0x20,
+ 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a,
+ 0x31, 0x34, 0x70, 0x74, 0x3b, 0xa, 0x20, 0x20, 0x66, 0x6f,
+ 0x6e, 0x74, 0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a,
+ 0x61, 0x72, 0x69, 0x61, 0x6c, 0x2c, 0x68, 0x65, 0x6c, 0x76,
+ 0x65, 0x74, 0x69, 0x63, 0x61, 0x3b, 0xa, 0x20, 0x20, 0x66,
+ 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74,
+ 0x3a, 0x62, 0x6f, 0x6c, 0x64, 0x3b, 0xa, 0x20, 0x20, 0x70,
+ 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x31, 0x30, 0x70,
+ 0x78, 0x3b, 0x20, 0xa, 0x7d, 0xa, 0xa, 0x62, 0x6f, 0x64,
+ 0x79, 0xa, 0x7b, 0xa, 0xa, 0x20, 0x20, 0x62, 0x61, 0x63,
+ 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x66, 0x66, 0x65,
+ 0x65, 0x63, 0x3b, 0xa, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x3b, 0xa, 0xa,
+ 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a,
+ 0x65, 0x3a, 0x38, 0x70, 0x74, 0x3b, 0xa, 0x20, 0x20, 0x66,
+ 0x6f, 0x6e, 0x74, 0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79,
+ 0x3a, 0x61, 0x72, 0x69, 0x61, 0x6c, 0x2c, 0x68, 0x65, 0x6c,
+ 0x76, 0x65, 0x74, 0x69, 0x63, 0x61, 0x3b, 0xa, 0x7d, 0xa,
+ 0xa, 0x2e, 0x6d, 0x65, 0x6e, 0x75, 0xa, 0x7b, 0xa, 0x20,
+ 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x34,
+ 0x70, 0x78, 0x3b, 0xa, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74,
+ 0x68, 0x3a, 0x36, 0x30, 0x25, 0x3b, 0xa, 0xa, 0x20, 0x20,
+ 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x32, 0x70,
+ 0x78, 0x3b, 0xa, 0x9, 0xa, 0x20, 0x20, 0x62, 0x6f, 0x72,
+ 0x64, 0x65, 0x72, 0x3a, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64,
+ 0x20, 0x31, 0x70, 0x78, 0x3b, 0xa, 0x20, 0x20, 0x62, 0x61,
+ 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x66, 0x66,
+ 0x63, 0x64, 0x32, 0x3b, 0xa, 0x20, 0x20, 0x74, 0x65, 0x78,
+ 0x74, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x6c, 0x65,
+ 0x66, 0x74, 0x3b, 0xa, 0x20, 0x20, 0xa, 0x20, 0x20, 0x66,
+ 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x39,
+ 0x70, 0x74, 0x3b, 0xa, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74,
+ 0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x61, 0x72,
+ 0x69, 0x61, 0x6c, 0x2c, 0x68, 0x65, 0x6c, 0x76, 0x65, 0x74,
+ 0x69, 0x63, 0x61, 0x3b, 0x20, 0x20, 0xa, 0x7d, 0xa, 0xa,
+ 0x64, 0x69, 0x76, 0x2e, 0x6d, 0x65, 0x6e, 0x75, 0x62, 0x6f,
+ 0x78, 0xa, 0x7b, 0xa, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74,
+ 0x68, 0x3a, 0x20, 0x32, 0x35, 0x25, 0x3b, 0xa, 0x20, 0x20,
+ 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x20, 0x30, 0x3b,
+ 0xa, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3a, 0x20,
+ 0x6c, 0x65, 0x66, 0x74, 0x3b, 0xa, 0x74, 0x65, 0x78, 0x74,
+ 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x63, 0x65,
+ 0x6e, 0x74, 0x65, 0x72, 0x3b, 0xa, 0x7d, 0xa, 0xa, 0x2e,
+ 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x62, 0x6c, 0x6f,
+ 0x63, 0x6b, 0xa, 0x7b, 0x20, 0x20, 0xa, 0x20, 0x20, 0x6d,
+ 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x34, 0x70, 0x78,
+ 0x3b, 0xa, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a,
+ 0x36, 0x30, 0x25, 0x3b, 0xa, 0xa, 0x20, 0x20, 0x70, 0x61,
+ 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x32, 0x70, 0x78, 0x3b,
+ 0xa, 0xa, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x3a, 0x20, 0x31, 0x70, 0x78, 0x20, 0x64, 0x6f, 0x74, 0x74,
+ 0x65, 0x64, 0x3b, 0xa, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b,
+ 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x3b,
+ 0xa, 0xa, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73,
+ 0x69, 0x7a, 0x65, 0x3a, 0x38, 0x70, 0x74, 0x3b, 0xa, 0x20,
+ 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x66, 0x61, 0x6d, 0x69,
+ 0x6c, 0x79, 0x3a, 0x61, 0x72, 0x69, 0x61, 0x6c, 0x2c, 0x68,
+ 0x65, 0x6c, 0x76, 0x65, 0x74, 0x69, 0x63, 0x61, 0x3b, 0x20,
+ 0x20, 0xa, 0xa, 0x7d, 0xa, 0xa, 0x70, 0x2e, 0x69, 0x6e,
+ 0x74, 0x72, 0x6f, 0xa, 0x7b, 0xa, 0x20, 0x20, 0x6d, 0x61,
+ 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x3a,
+ 0x32, 0x30, 0x70, 0x78, 0x3b, 0xa, 0x20, 0x20, 0x6d, 0x61,
+ 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74,
+ 0x3a, 0x32, 0x30, 0x70, 0x78, 0x3b, 0xa, 0xa, 0x20, 0x20,
+ 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a,
+ 0x31, 0x30, 0x70, 0x74, 0x3b, 0xa, 0x2f, 0x2a, 0x20, 0x20,
+ 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68,
+ 0x74, 0x3a, 0x62, 0x6f, 0x6c, 0x64, 0x3b, 0x20, 0x2a, 0x2f,
+ 0xa, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x66, 0x61,
+ 0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x61, 0x72, 0x69, 0x61, 0x6c,
+ 0x2c, 0x68, 0x65, 0x6c, 0x76, 0x65, 0x74, 0x69, 0x63, 0x61,
+ 0x3b, 0x20, 0x20, 0xa, 0x7d, 0xa, 0xa, 0x70, 0x2e, 0x63,
+ 0x6c, 0x69, 0x6e, 0x6b, 0xa, 0x7b, 0xa, 0x20, 0x20, 0x66,
+ 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x31,
+ 0x32, 0x70, 0x74, 0x3b, 0xa, 0x20, 0x20, 0x66, 0x6f, 0x6e,
+ 0x74, 0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x63,
+ 0x6f, 0x75, 0x72, 0x69, 0x65, 0x72, 0x2c, 0x6d, 0x6f, 0x6e,
+ 0x6f, 0x73, 0x70, 0x61, 0x63, 0x65, 0x3b, 0x20, 0x20, 0xa,
+ 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69,
+ 0x67, 0x6e, 0x3a, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3b,
+ 0xa, 0x7d, 0xa, 0xa, 0x70, 0x2e, 0x63, 0x6c, 0x69, 0x6e,
+ 0x6b, 0x39, 0xa, 0x7b, 0xa, 0x20, 0x20, 0x66, 0x6f, 0x6e,
+ 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x39, 0x70, 0x74,
+ 0x3b, 0xa, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x66,
+ 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x63, 0x6f, 0x75, 0x72,
+ 0x69, 0x65, 0x72, 0x2c, 0x6d, 0x6f, 0x6e, 0x6f, 0x73, 0x70,
+ 0x61, 0x63, 0x65, 0x3b, 0x20, 0x20, 0xa, 0x20, 0x20, 0x74,
+ 0x65, 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a,
+ 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0xa, 0x7d, 0xa,
+ 0xa, 0xa, 0x70, 0xa, 0x7b, 0xa, 0x20, 0x20, 0x70, 0x61,
+ 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x6c, 0x65, 0x66, 0x74,
+ 0x3a, 0x31, 0x30, 0x70, 0x78, 0x3b, 0xa, 0x7d, 0xa, 0xa,
+ 0x70, 0x2e, 0x72, 0x69, 0x67, 0x68, 0x74, 0xa, 0x7b, 0xa,
+ 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69,
+ 0x67, 0x6e, 0x3a, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3b, 0x20,
+ 0xa, 0x7d, 0xa, 0xa, 0};
+
+static const unsigned char data_tcp_shtml[] = {
+ /* /tcp.shtml */
+ 0x2f, 0x74, 0x63, 0x70, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0,
+ 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65,
+ 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3c, 0x68, 0x31,
+ 0x3e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x63,
+ 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+ 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0x3c, 0x62, 0x72, 0x3e, 0x3c,
+ 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, 0x74,
+ 0x68, 0x3d, 0x22, 0x31, 0x30, 0x30, 0x25, 0x22, 0x3e, 0xa,
+ 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x4c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, 0x74,
+ 0x68, 0x3e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x3c, 0x2f,
+ 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x53, 0x74, 0x61,
+ 0x74, 0x65, 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68,
+ 0x3e, 0x52, 0x65, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69,
+ 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x3c, 0x2f, 0x74, 0x68,
+ 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x54, 0x69, 0x6d, 0x65, 0x72,
+ 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x46,
+ 0x6c, 0x61, 0x67, 0x73, 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c,
+ 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x25, 0x21, 0x20, 0x74, 0x63,
+ 0x70, 0x2d, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0xa, 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x66,
+ 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c,
+0};
+
+static const unsigned char data_fade_png[] = {
+ /* /fade.png */
+ 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e, 0x70, 0x6e, 0x67, 0,
+ 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 00, 00,
+ 00, 0xd, 0x49, 0x48, 0x44, 0x52, 00, 00, 00, 0x4,
+ 00, 00, 00, 0xa, 0x8, 0x2, 00, 00, 00, 0x1c,
+ 0x99, 0x68, 0x59, 00, 00, 00, 0x9, 0x70, 0x48, 0x59,
+ 0x73, 00, 00, 0xb, 0x13, 00, 00, 0xb, 0x13, 0x1,
+ 00, 0x9a, 0x9c, 0x18, 00, 00, 00, 0x7, 0x74, 0x49,
+ 0x4d, 0x45, 0x7, 0xd6, 0x6, 0x8, 0x14, 0x1b, 0x39, 0xaf,
+ 0x5b, 0xc0, 0xe3, 00, 00, 00, 0x1d, 0x74, 0x45, 0x58,
+ 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 00, 0x43,
+ 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x54, 0x68, 0x65, 0x20, 0x47, 0x49, 0x4d, 0x50,
+ 0xef, 0x64, 0x25, 0x6e, 00, 00, 00, 0x3a, 0x49, 0x44,
+ 0x41, 0x54, 0x8, 0xd7, 0x75, 0x8c, 0x31, 0x12, 00, 0x10,
+ 0x10, 0xc4, 0x2e, 0x37, 0x9e, 0x40, 0x65, 0xfd, 0xff, 0x83,
+ 0xf4, 0xa, 0x1c, 0x8d, 0x54, 0x9b, 0xc9, 0xcc, 0x9a, 0x3d,
+ 0x90, 0x73, 0x71, 0x67, 0x91, 0xd4, 0x74, 0x36, 0xa9, 0x55,
+ 0x1, 0xf8, 0x29, 0x58, 0xc8, 0xbf, 0x48, 0xc4, 0x81, 0x74,
+ 0xb, 0xa3, 0xf, 0x7c, 0xdb, 0x4, 0xe8, 0x40, 0x5, 0xdf,
+ 0xa1, 0xf3, 0xfc, 0x73, 00, 00, 00, 00, 0x49, 0x45,
+ 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, 0};
+
+static const unsigned char data_stats_shtml[] = {
+ /* /stats.shtml */
+ 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0,
+ 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65,
+ 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3c, 0x68, 0x31,
+ 0x3e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x73,
+ 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x3c,
+ 0x2f, 0x68, 0x31, 0x3e, 0xa, 0x3c, 0x63, 0x65, 0x6e, 0x74,
+ 0x65, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65,
+ 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x33, 0x30,
+ 0x30, 0x22, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d,
+ 0x22, 0x30, 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x72, 0x3e, 0x3c,
+ 0x74, 0x64, 0x3e, 0x3c, 0x70, 0x72, 0x65, 0x3e, 0xa, 0x49,
+ 0x50, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20,
+ 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0xa, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20,
+ 0x73, 0x65, 0x6e, 0x74, 0xa, 0x9, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x64,
+ 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0xa, 0x49, 0x50, 0x20,
+ 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x20, 0x20, 0x20, 0x20,
+ 0x49, 0x50, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+ 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x6c, 0x65,
+ 0x6e, 0x67, 0x74, 0x68, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x49, 0x50,
+ 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x2c, 0x20, 0x68,
+ 0x69, 0x67, 0x68, 0x20, 0x62, 0x79, 0x74, 0x65, 0xa, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x49, 0x50, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74,
+ 0x68, 0x2c, 0x20, 0x6c, 0x6f, 0x77, 0x20, 0x62, 0x79, 0x74,
+ 0x65, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x49, 0x50, 0x20, 0x66, 0x72,
+ 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0xa, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x63, 0x68,
+ 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0xa, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x57, 0x72, 0x6f, 0x6e, 0x67, 0x20, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x63, 0x6f, 0x6c, 0xa, 0x49, 0x43, 0x4d, 0x50, 0x9,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65,
+ 0x74, 0x73, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65,
+ 0x64, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65,
+ 0x74, 0x73, 0x20, 0x73, 0x65, 0x6e, 0x74, 0xa, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x64,
+ 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0xa, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x54, 0x79, 0x70, 0x65, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72,
+ 0x73, 0xa, 0x54, 0x43, 0x50, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65,
+ 0x74, 0x73, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65,
+ 0x64, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65,
+ 0x74, 0x73, 0x20, 0x73, 0x65, 0x6e, 0x74, 0xa, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x64,
+ 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0xa, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x20, 0x65,
+ 0x72, 0x72, 0x6f, 0x72, 0x73, 0xa, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x44,
+ 0x61, 0x74, 0x61, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74,
+ 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20,
+ 0x41, 0x43, 0x4b, 0x73, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x65,
+ 0x73, 0x65, 0x74, 0x73, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x65,
+ 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x73, 0x73, 0x69,
+ 0x6f, 0x6e, 0x73, 0xa, 0x9, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x4e, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74,
+ 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x76, 0x61, 0x6c, 0x69, 0x61,
+ 0x62, 0x6c, 0x65, 0xa, 0x9, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
+ 0x20, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x20,
+ 0x74, 0x6f, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x20,
+ 0x70, 0x6f, 0x72, 0x74, 0x73, 0xa, 0x3c, 0x2f, 0x70, 0x72,
+ 0x65, 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64,
+ 0x3e, 0x3c, 0x70, 0x72, 0x65, 0x3e, 0x25, 0x21, 0x20, 0x6e,
+ 0x65, 0x74, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x73, 0xa, 0x3c,
+ 0x2f, 0x70, 0x72, 0x65, 0x3e, 0x3c, 0x2f, 0x74, 0x61, 0x62,
+ 0x6c, 0x65, 0x3e, 0xa, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74,
+ 0x65, 0x72, 0x3e, 0xa, 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x66,
+ 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c,
+ 0xa, 0};
+
+const struct httpd_fsdata_file file_processes_shtml[] =
+{{NULL, data_processes_shtml, data_processes_shtml + 17, sizeof(data_processes_shtml) - 17}};
+
+const struct httpd_fsdata_file file_404_html[] =
+{{file_processes_shtml, data_404_html, data_404_html + 10, sizeof(data_404_html) - 10}};
+
+const struct httpd_fsdata_file file_files_shtml[] =
+{{file_404_html, data_files_shtml, data_files_shtml + 13, sizeof(data_files_shtml) - 13}};
+
+const struct httpd_fsdata_file file_footer_html[] =
+{{file_files_shtml, data_footer_html, data_footer_html + 13, sizeof(data_footer_html) - 13}};
+
+const struct httpd_fsdata_file file_header_html[] =
+{{file_footer_html, data_header_html, data_header_html + 13, sizeof(data_header_html) - 13}};
+
+const struct httpd_fsdata_file file_index_html[] =
+{{file_header_html, data_index_html, data_index_html + 12, sizeof(data_index_html) - 12}};
+
+const struct httpd_fsdata_file file_style_css[] =
+{{file_index_html, data_style_css, data_style_css + 11, sizeof(data_style_css) - 11}};
+
+const struct httpd_fsdata_file file_tcp_shtml[] =
+{{file_style_css, data_tcp_shtml, data_tcp_shtml + 11, sizeof(data_tcp_shtml) - 11}};
+
+const struct httpd_fsdata_file file_fade_png[] =
+{{file_tcp_shtml, data_fade_png, data_fade_png + 10, sizeof(data_fade_png) - 10}};
+
+const struct httpd_fsdata_file file_stats_shtml[] =
+{{file_fade_png, data_stats_shtml, data_stats_shtml + 13, sizeof(data_stats_shtml) - 13}};
+
+#define HTTPD_FS_ROOT file_stats_shtml
+
+#define HTTPD_FS_NUMFILES 10
diff --git a/nuttx/netutils/webserver/httpd-fsdata.h b/nuttx/netutils/webserver/httpd-fsdata.h
new file mode 100644
index 000000000..bc36cbb54
--- /dev/null
+++ b/nuttx/netutils/webserver/httpd-fsdata.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2001, 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 lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: httpd-fsdata.h,v 1.1.1.1 2007-08-26 23:07:04 patacongo Exp $
+ */
+#ifndef __HTTPD_FSDATA_H__
+#define __HTTPD_FSDATA_H__
+
+#include <sys/types.h>
+#include <net/uip/uip.h>
+
+struct httpd_fsdata_file
+{
+ const struct httpd_fsdata_file *next;
+ const unsigned char *name;
+ const unsigned char *data;
+ const int len;
+#ifdef HTTPD_FS_STATISTICS
+#if HTTPD_FS_STATISTICS == 1
+ uint16 count;
+#endif /* HTTPD_FS_STATISTICS */
+#endif /* HTTPD_FS_STATISTICS */
+};
+
+struct httpd_fsdata_file_noconst {
+ struct httpd_fsdata_file *next;
+ char *name;
+ char *data;
+ int len;
+#ifdef HTTPD_FS_STATISTICS
+#if HTTPD_FS_STATISTICS == 1
+ uint16 count;
+#endif /* HTTPD_FS_STATISTICS */
+#endif /* HTTPD_FS_STATISTICS */
+};
+
+#endif /* __HTTPD_FSDATA_H__ */
diff --git a/nuttx/netutils/webserver/httpd.c b/nuttx/netutils/webserver/httpd.c
new file mode 100644
index 000000000..d6c855e61
--- /dev/null
+++ b/nuttx/netutils/webserver/httpd.c
@@ -0,0 +1,305 @@
+/* httpd
+ * httpd Web server
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * The uIP web server is a very simplistic implementation of an HTTP
+ * server. It can serve web pages and files from a read-only ROM
+ * filesystem, and provides a very small scripting language.
+ *
+ * Copyright (c) 2004, 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. 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.
+ */
+
+#include <stdlib.h>
+#include <net/uip/uip.h>
+#include <net/uip/httpd.h>
+
+#include "httpd-cgi.h"
+#include "http-strings.h"
+
+#include <string.h>
+
+#define STATE_WAITING 0
+#define STATE_OUTPUT 1
+
+#define ISO_nl 0x0a
+#define ISO_space 0x20
+#define ISO_bang 0x21
+#define ISO_percent 0x25
+#define ISO_period 0x2e
+#define ISO_slash 0x2f
+#define ISO_colon 0x3a
+
+static unsigned short generate_part_of_file(void *state)
+{
+ struct httpd_state *s = (struct httpd_state *)state;
+
+ if (s->file.len > uip_mss()) {
+ s->len = uip_mss();
+ } else {
+ s->len = s->file.len;
+ }
+ memcpy(uip_appdata, s->file.data, s->len);
+
+ return s->len;
+}
+
+static void send_file(struct httpd_state *s)
+{
+ do {
+ psock_generator_send(&s->sout, generate_part_of_file, s);
+ s->file.len -= s->len;
+ s->file.data += s->len;
+ } while(s->file.len > 0);
+#warning REVISIT must not return until file sent
+}
+
+static void send_part_of_file(struct httpd_state *s)
+{
+ psock_send(&s->sout, s->file.data, s->len);
+#warning REVISIT must not return until file sent
+}
+
+static void next_scriptstate(struct httpd_state *s)
+{
+ char *p;
+ p = strchr(s->scriptptr, ISO_nl) + 1;
+ s->scriptlen -= (unsigned short)(p - s->scriptptr);
+ s->scriptptr = p;
+}
+
+static void handle_script(struct httpd_state *s)
+{
+ char *ptr;
+
+ while(s->file.len > 0) {
+
+ /* Check if we should start executing a script. */
+ if (*s->file.data == ISO_percent &&
+ *(s->file.data + 1) == ISO_bang) {
+ s->scriptptr = s->file.data + 3;
+ s->scriptlen = s->file.len - 3;
+ if (*(s->scriptptr - 1) == ISO_colon) {
+ httpd_fs_open(s->scriptptr + 1, &s->file);
+ send_file(s);
+ } else {
+ httpd_cgi(s->scriptptr)(s, s->scriptptr);
+ }
+ next_scriptstate(s);
+
+ /* The script is over, so we reset the pointers and continue
+ sending the rest of the file. */
+ s->file.data = s->scriptptr;
+ s->file.len = s->scriptlen;
+ } else {
+ /* See if we find the start of script marker in the block of HTML
+ to be sent. */
+
+ if (s->file.len > uip_mss()) {
+ s->len = uip_mss();
+ } else {
+ s->len = s->file.len;
+ }
+
+ if (*s->file.data == ISO_percent) {
+ ptr = strchr(s->file.data + 1, ISO_percent);
+ } else {
+ ptr = strchr(s->file.data, ISO_percent);
+ }
+ if (ptr != NULL &&
+ ptr != s->file.data) {
+ s->len = (int)(ptr - s->file.data);
+ if (s->len >= uip_mss()) {
+ s->len = uip_mss();
+ }
+ }
+ send_part_of_file(s);
+ s->file.data += s->len;
+ s->file.len -= s->len;
+ }
+ }
+#warning REVISIT must not return until sent
+}
+
+static void send_headers(struct httpd_state *s, const char *statushdr)
+{
+ char *ptr;
+
+ PSOCK_SEND_STR(&s->sout, statushdr);
+
+ ptr = strrchr(s->filename, ISO_period);
+ if (ptr == NULL) {
+ PSOCK_SEND_STR(&s->sout, http_content_type_binary);
+ } else if (strncmp(http_html, ptr, 5) == 0 ||
+ strncmp(http_shtml, ptr, 6) == 0) {
+ PSOCK_SEND_STR(&s->sout, http_content_type_html);
+ } else if (strncmp(http_css, ptr, 4) == 0) {
+ PSOCK_SEND_STR(&s->sout, http_content_type_css);
+ } else if (strncmp(http_png, ptr, 4) == 0) {
+ PSOCK_SEND_STR(&s->sout, http_content_type_png);
+ } else if (strncmp(http_gif, ptr, 4) == 0) {
+ PSOCK_SEND_STR(&s->sout, http_content_type_gif);
+ } else if (strncmp(http_jpg, ptr, 4) == 0) {
+ PSOCK_SEND_STR(&s->sout, http_content_type_jpg);
+ } else {
+ PSOCK_SEND_STR(&s->sout, http_content_type_plain);
+ }
+#warning REVISIT must not return until sent
+}
+
+static void handle_output(struct httpd_state *s)
+{
+ char *ptr;
+
+ if (!httpd_fs_open(s->filename, &s->file))
+ {
+ httpd_fs_open(http_404_html, &s->file);
+ strcpy(s->filename, http_404_html);
+ send_headers(s, http_header_404);
+ send_file(s);
+ }
+ else
+ {
+ send_headers(s, http_header_200);
+ ptr = strchr(s->filename, ISO_period);
+ if (ptr != NULL && strncmp(ptr, http_shtml, 6) == 0)
+ {
+ handle_script(s);
+ }
+ else
+ {
+ send_file(s);
+ }
+ }
+ PSOCK_CLOSE(&s->sout);
+}
+
+static void handle_input(struct httpd_state *s)
+{
+ psock_readto(&s->sin, ISO_space);
+
+ if (strncmp(s->inputbuf, http_get, 4) != 0)
+ {
+ PSOCK_CLOSE(&s->sin);
+ return;
+ }
+
+ psock_readto(&s->sin, ISO_space);
+
+ if (s->inputbuf[0] != ISO_slash)
+ {
+ PSOCK_CLOSE(&s->sin);
+ return;
+ }
+
+ if (s->inputbuf[1] == ISO_space)
+ {
+ strncpy(s->filename, http_index_html, sizeof(s->filename));
+ }
+ else
+ {
+ s->inputbuf[psock_datalen(&s->sin) - 1] = 0;
+ strncpy(s->filename, &s->inputbuf[0], sizeof(s->filename));
+ }
+
+ s->state = STATE_OUTPUT;
+
+ while(1)
+ {
+ psock_readto(&s->sin, ISO_nl);
+
+ if (strncmp(s->inputbuf, http_referer, 8) == 0)
+ {
+ s->inputbuf[psock_datalen(&s->sin) - 2] = 0;
+ }
+ }
+}
+
+static void handle_connection(struct httpd_state *s)
+{
+ handle_input(s);
+ if (s->state == STATE_OUTPUT) {
+ handle_output(s);
+ }
+}
+
+/* This function is called by the UIP interrupt handling logic whenevent an
+ * event of interest occurs.
+ */
+
+void uip_interrupt_event(void)
+{
+ /* Get the private application specific data */
+ struct httpd_state *s = (struct httpd_state *)(uip_conn->private);
+
+ /* Has application specific data been allocate yet? */
+
+ if (!s)
+ {
+ /* No.. allocate it now */
+ s = (struct httpd_state *)malloc(sizeof(struct httpd_state));
+ if (!s)
+ {
+ return;
+ }
+
+ /* And assign the private instance to the connection */
+ uip_conn->private = s;
+ }
+
+ if (uip_closed() || uip_aborted() || uip_timedout()) {
+ } else if (uip_connected()) {
+ psock_init(&s->sin, s->inputbuf, sizeof(s->inputbuf) - 1);
+ psock_init(&s->sout, s->inputbuf, sizeof(s->inputbuf) - 1);
+ s->state = STATE_WAITING;
+ s->timer = 0;
+ handle_connection(s);
+ } else if (s != NULL) {
+ if (uip_poll()) {
+ ++s->timer;
+ if (s->timer >= 20) {
+ uip_abort();
+ }
+ } else {
+ s->timer = 0;
+ }
+ handle_connection(s);
+ } else {
+ uip_abort();
+ }
+}
+
+/* Initialize the web server
+ *
+ * This function initializes the web server and should be
+ * called at system boot-up.
+ */
+
+void httpd_init(void)
+{
+ uip_listen(HTONS(80));
+}
diff --git a/nuttx/netutils/webserver/makefsdata b/nuttx/netutils/webserver/makefsdata
new file mode 100755
index 000000000..b2109abdb
--- /dev/null
+++ b/nuttx/netutils/webserver/makefsdata
@@ -0,0 +1,78 @@
+#!/usr/bin/perl
+
+open(OUTPUT, "> httpd-fsdata.c");
+
+chdir("httpd-fs");
+
+opendir(DIR, ".");
+@files = grep { !/^\./ && !/(CVS|~)/ } readdir(DIR);
+closedir(DIR);
+
+foreach $file (@files) {
+
+ if(-d $file && $file !~ /^\./) {
+ print "Processing directory $file\n";
+ opendir(DIR, $file);
+ @newfiles = grep { !/^\./ && !/(CVS|~)/ } readdir(DIR);
+ closedir(DIR);
+ printf "Adding files @newfiles\n";
+ @files = (@files, map { $_ = "$file/$_" } @newfiles);
+ next;
+ }
+}
+
+foreach $file (@files) {
+ if(-f $file) {
+
+ print "Adding file $file\n";
+
+ open(FILE, $file) || die "Could not open file $file\n";
+
+ $file =~ s-^-/-;
+ $fvar = $file;
+ $fvar =~ s-/-_-g;
+ $fvar =~ s-\.-_-g;
+ # for AVR, add PROGMEM here
+ print(OUTPUT "static const unsigned char data".$fvar."[] = {\n");
+ print(OUTPUT "\t/* $file */\n\t");
+ for($j = 0; $j < length($file); $j++) {
+ printf(OUTPUT "%#02x, ", unpack("C", substr($file, $j, 1)));
+ }
+ printf(OUTPUT "0,\n");
+
+
+ $i = 0;
+ while(read(FILE, $data, 1)) {
+ if($i == 0) {
+ print(OUTPUT "\t");
+ }
+ printf(OUTPUT "%#02x, ", unpack("C", $data));
+ $i++;
+ if($i == 10) {
+ print(OUTPUT "\n");
+ $i = 0;
+ }
+ }
+ print(OUTPUT "0};\n\n");
+ close(FILE);
+ push(@fvars, $fvar);
+ push(@pfiles, $file);
+ }
+}
+
+for($i = 0; $i < @fvars; $i++) {
+ $file = $pfiles[$i];
+ $fvar = $fvars[$i];
+
+ if($i == 0) {
+ $prevfile = "NULL";
+ } else {
+ $prevfile = "file" . $fvars[$i - 1];
+ }
+ print(OUTPUT "const struct httpd_fsdata_file file".$fvar."[] = {{$prevfile, data$fvar, ");
+ print(OUTPUT "data$fvar + ". (length($file) + 1) .", ");
+ print(OUTPUT "sizeof(data$fvar) - ". (length($file) + 1) ."}};\n\n");
+}
+
+print(OUTPUT "#define HTTPD_FS_ROOT file$fvars[$i - 1]\n\n");
+print(OUTPUT "#define HTTPD_FS_NUMFILES $i\n");
diff --git a/nuttx/netutils/webserver/makestrings b/nuttx/netutils/webserver/makestrings
new file mode 100755
index 000000000..20f0e2429
--- /dev/null
+++ b/nuttx/netutils/webserver/makestrings
@@ -0,0 +1,40 @@
+#!/usr/bin/perl
+
+
+sub stringify {
+ my $name = shift(@_);
+ open(OUTPUTC, "> $name.c");
+ open(OUTPUTH, "> $name.h");
+
+ open(FILE, "$name");
+
+ while(<FILE>) {
+ if(/(.+) "(.+)"/) {
+ $var = $1;
+ $data = $2;
+
+ $datan = $data;
+ $datan =~ s/\\r/\r/g;
+ $datan =~ s/\\n/\n/g;
+ $datan =~ s/\\01/\01/g;
+ $datan =~ s/\\0/\0/g;
+
+ printf(OUTPUTC "const char $var\[%d] = \n", length($datan) + 1);
+ printf(OUTPUTC "/* \"$data\" */\n");
+ printf(OUTPUTC "{");
+ for($j = 0; $j < length($datan); $j++) {
+ printf(OUTPUTC "%#02x, ", unpack("C", substr($datan, $j, 1)));
+ }
+ printf(OUTPUTC "};\n");
+
+ printf(OUTPUTH "extern const char $var\[%d];\n", length($datan) + 1);
+
+ }
+ }
+ close(OUTPUTC);
+ close(OUTPUTH);
+}
+stringify("http-strings");
+
+exit 0;
+