X-Git-Url: https://git.rohieb.name/openwrt.git/blobdiff_plain/ced0222eb7ae70d05c1f41f7751a6037dd7a7f44..f0589f7290ba958bbefaf5394b155d37c72a185e:/package/uboot-lantiq/patches/300-httpd.patch diff --git a/package/uboot-lantiq/patches/300-httpd.patch b/package/uboot-lantiq/patches/300-httpd.patch index 25e84cde3..8c4c1ffb6 100644 --- a/package/uboot-lantiq/patches/300-httpd.patch +++ b/package/uboot-lantiq/patches/300-httpd.patch @@ -12,13 +12,33 @@ + +U_BOOT_CMD( + httpd, 1, 1, do_httpd, -+ "httpd\t- start webserver\n", "\n" ++ "httpd\t- start webserver", "" +); +#endif + int do_tftpb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { return netboot_common (TFTP, cmdtp, argc, argv); +--- /dev/null ++++ b/include/httpd.h +@@ -0,0 +1,17 @@ ++#ifndef _UIP_HTTPD_H__ ++#define _UIP_HTTPD_H__ ++ ++void HttpdStart (void); ++void HttpdHandler (void); ++ ++/* board specific implementation */ ++extern int do_http_upgrade(const unsigned char *data, const ulong size); ++ ++#define HTTP_PROGRESS_START 0 ++#define HTTP_PROGRESS_TIMEOUT 1 ++#define HTTP_PROGRESS_UPLOAD_READY 2 ++#define HTTP_PROGRESS_UGRADE_READY 3 ++#define HTTP_PROGRESS_UGRADE_FAILED 4 ++extern int do_http_progress(const int state); ++ ++#endif --- a/include/net.h +++ b/include/net.h @@ -383,7 +383,8 @@ extern int NetTimeOffset; /* offset ti @@ -31,6 +51,29 @@ /* Shutdown adapters and cleanup */ extern void NetStop(void); +--- a/net/Makefile ++++ b/net/Makefile +@@ -26,6 +26,10 @@ include $(TOPDIR)/config.mk + # CFLAGS += -DDEBUG + + LIB = $(obj)libnet.a ++UIPDIR = uip-0.9 ++RSADIR = uip-0.9 ++$(shell mkdir -p $(obj)$(UIPDIR)) ++$(shell mkdir -p $(obj)$(RSADIR)) + + COBJS-$(CONFIG_CMD_NET) += bootp.o + COBJS-$(CONFIG_CMD_DNS) += dns.o +@@ -36,6 +40,9 @@ COBJS-$(CONFIG_CMD_NET) += rarp.o + COBJS-$(CONFIG_CMD_SNTP) += sntp.o + COBJS-$(CONFIG_CMD_NET) += tftp.o + ++COBJS-$(CONFIG_CMD_HTTPD) += httpd.o $(UIPDIR)/fs.o $(UIPDIR)/httpd.o $(UIPDIR)/uip_arp.o $(UIPDIR)/uip_arch.o $(UIPDIR)/uip.o ++COBJS-$(CONFIG_CMD_RSA) += $(RSADIR)/bigint.o $(RSADIR)/base64.o $(RSADIR)/rmd160.o $(RSADIR)/rsa.o ++ + COBJS := $(COBJS-y) + SRCS := $(COBJS:.o=.c) + OBJS := $(addprefix $(obj),$(COBJS)) --- /dev/null +++ b/net/httpd.c @@ -0,0 +1,52 @@ @@ -86,49 +129,6 @@ +} + +#endif ---- /dev/null -+++ b/include/httpd.h -@@ -0,0 +1,17 @@ -+#ifndef _UIP_HTTPD_H__ -+#define _UIP_HTTPD_H__ -+ -+void HttpdStart (void); -+void HttpdHandler (void); -+ -+/* board specific implementation */ -+extern int do_http_upgrade(const unsigned char *data, const ulong size); -+ -+#define HTTP_PROGRESS_START 0 -+#define HTTP_PROGRESS_TIMEOUT 1 -+#define HTTP_PROGRESS_UPLOAD_READY 2 -+#define HTTP_PROGRESS_UGRADE_READY 3 -+#define HTTP_PROGRESS_UGRADE_FAILED 4 -+extern int do_http_progress(const int state); -+ -+#endif ---- a/net/Makefile -+++ b/net/Makefile -@@ -26,6 +26,10 @@ include $(TOPDIR)/config.mk - # CFLAGS += -DDEBUG - - LIB = $(obj)libnet.a -+UIPDIR = uip-0.9 -+RSADIR = uip-0.9 -+$(shell mkdir -p $(obj)$(UIPDIR)) -+$(shell mkdir -p $(obj)$(RSADIR)) - - COBJS-y += bootp.o - COBJS-$(CONFIG_CMD_DNS) += dns.o -@@ -36,6 +40,9 @@ COBJS-y += rarp.o - COBJS-$(CONFIG_CMD_SNTP) += sntp.o - COBJS-y += tftp.o - -+COBJS-$(CONFIG_CMD_HTTPD) += httpd.o $(UIPDIR)/fs.o $(UIPDIR)/httpd.o $(UIPDIR)/uip_arp.o $(UIPDIR)/uip_arch.o $(UIPDIR)/uip.o -+COBJS-$(CONFIG_CMD_RSA) += $(RSADIR)/bigint.o $(RSADIR)/base64.o $(RSADIR)/rmd160.o $(RSADIR)/rsa.o -+ - COBJS := $(COBJS-y) - SRCS := $(COBJS:.o=.c) - OBJS := $(addprefix $(obj),$(COBJS)) --- a/net/net.c +++ b/net/net.c @@ -95,6 +95,19 @@ @@ -149,9 +149,9 @@ +extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +#endif - #if defined(CONFIG_CMD_NET) + DECLARE_GLOBAL_DATA_PTR; -@@ -1310,6 +1323,13 @@ NetReceive(volatile uchar * inpkt, int l +@@ -1308,6 +1321,13 @@ NetReceive(volatile uchar * inpkt, int l debug("packet received\n"); @@ -165,7 +165,7 @@ NetRxPacket = inpkt; NetRxPacketLen = len; et = (Ethernet_t *)inpkt; -@@ -1952,3 +1972,162 @@ ushort getenv_VLAN(char *var) +@@ -1922,3 +1942,162 @@ ushort getenv_VLAN(char *var) { return (string_to_VLAN(getenv(var))); } @@ -329,6 +329,40 @@ + +#endif --- /dev/null ++++ b/net/rsa/Makefile +@@ -0,0 +1,31 @@ ++# ++# FONRSA & FONSIGN libraries unit testing ++# ++# This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. ++# ++# Execute in this directory ++# ++# Created: 20070422 Pablo Martin Medrano ++# ++# $Id: Makefile 389 2007-06-11 08:29:56Z pablo.martin $ ++# ++# FIXME: Put this in the main Makefile.am ++# ++all: fonsign dump_key ++ ++fonsign: ++ gcc -g sign_openssl.c -D__MAINTEST__ -o fonsign -lssl ++ ++dump_key: ++ gcc -o dump_key dump_key.c ++ ./dump_key > public_key.h ++ ++foncheckrsa: ++ gcc -g bigint.c fonrsa.c rmd160.c foncheckrsa.c base64.c log.c -o foncheckrsa ++ ++#private_fon_rsa_key.pem: ++# openssl genrsa -out private_fon_rsa_key.pem 4096 ++# openssl rsa -in private_fon_rsa_key.pem -pubout -out public_fon_rsa_key.pem ++ ++clean: ++ rm fonsign dump_key +--- /dev/null +++ b/net/rsa/base64.c @@ -0,0 +1,137 @@ +#include "base64.h" @@ -2674,40 +2708,6 @@ +#endif + --- /dev/null -+++ b/net/rsa/Makefile -@@ -0,0 +1,31 @@ -+# -+# FONRSA & FONSIGN libraries unit testing -+# -+# This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. -+# -+# Execute in this directory -+# -+# Created: 20070422 Pablo Martin Medrano -+# -+# $Id: Makefile 389 2007-06-11 08:29:56Z pablo.martin $ -+# -+# FIXME: Put this in the main Makefile.am -+# -+all: fonsign dump_key -+ -+fonsign: -+ gcc -g sign_openssl.c -D__MAINTEST__ -o fonsign -lssl -+ -+dump_key: -+ gcc -o dump_key dump_key.c -+ ./dump_key > public_key.h -+ -+foncheckrsa: -+ gcc -g bigint.c fonrsa.c rmd160.c foncheckrsa.c base64.c log.c -o foncheckrsa -+ -+#private_fon_rsa_key.pem: -+# openssl genrsa -out private_fon_rsa_key.pem 4096 -+# openssl rsa -in private_fon_rsa_key.pem -pubout -out public_fon_rsa_key.pem -+ -+clean: -+ rm fonsign dump_key ---- /dev/null +++ b/net/rsa/public_key.h @@ -0,0 +1,52 @@ +unsigned char public_key[] = { @@ -4040,6 +4040,63 @@ +#endif + --- /dev/null ++++ b/net/uip-0.9/Makefile +@@ -0,0 +1,54 @@ ++# 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: Makefile,v 1.8.2.2 2003/10/04 22:54:17 adam Exp $ ++# ++ ++CC=gcc ++CFLAGS=-Wall -fpack-struct -DDUMP=0 ++ ++all: uip ++ ++uip: uip.o uip_arch.o tapdev.o httpd.o main.o fs.o uip_arp.o ++ $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ ++ ++%.o: %.c ++ $(CC) $(CFLAGS) -c $^ -o $@ ++ ++clean: ++ rm -f *.o *~ *core uip ++ ++ ++ ++ ++ ++ +--- /dev/null +++ b/net/uip-0.9/fs.c @@ -0,0 +1,154 @@ +/** @@ -4197,52 +4254,135 @@ +#endif /* FS_STATISTICS */ +/*-----------------------------------------------------------------------------------*/ --- /dev/null -+++ b/net/uip-0.9/fsdata.c -@@ -0,0 +1,199 @@ -+static const char data_flashing_html[] = { -+ /* /flashing.html */ -+ 0x2f, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, -+ 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, 0x30, -+ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, -+ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, -+ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, -+ 0x70, 0x2f, 0x29, 0xd, 0xa, 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, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x3c, 0x62, -+ 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x3d, -+ 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30, -+ 0x70, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x20, 0x68, -+ 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x31, 0x30, 0x30, 0x25, -+ 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, -+ 0x66, 0x66, 0x66, 0x3b, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, -+ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, -+ 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, 0x62, 0x30, 0x33, 0x34, -+ 0x3b, 0x22, 0x3e, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, -+ 0x3e, 0x3c, 0x68, 0x31, 0x3e, 0x55, 0x70, 0x67, 0x72, 0x61, -+ 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, -+ 0x6d, 0x20, 0x2e, 0x2e, 0x2e, 0x2e, 0x3c, 0x2f, 0x68, 0x31, -+ 0x3e, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, -+ 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, -+ 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; ++++ b/net/uip-0.9/fs.h +@@ -0,0 +1,80 @@ ++/** ++ * \addtogroup httpd ++ * @{ ++ */ + -+static const char data_fail_html[] = { -+ /* /fail.html */ -+ 0x2f, 0x66, 0x61, 0x69, 0x6c, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, -+ 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, 0x30, -+ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, -+ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, -+ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, -+ 0x70, 0x2f, 0x29, 0xd, 0xa, 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, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9, -+ 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c, -+ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9, ++/** ++ * \file ++ * HTTP server read-only file system header file. ++ * \author Adam Dunkels ++ */ ++ ++/* ++ * 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 ++ * ++ * $Id: fs.h,v 1.6.2.3 2003/10/07 13:22:27 adam Exp $ ++ */ ++#ifndef __FS_H__ ++#define __FS_H__ ++ ++#include "uip.h" ++ ++/** ++ * An open file in the read-only file system. ++ */ ++struct fs_file { ++ char *data; /**< The actual file data. */ ++ int len; /**< The length of the file data. */ ++}; ++ ++/** ++ * Open a file in the read-only file system. ++ * ++ * \param name The name of the file. ++ * ++ * \param file The file pointer, which must be allocated by caller and ++ * will be filled in by the function. ++ */ ++int fs_open(const char *name, struct fs_file *file); ++ ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++u16_t fs_count(char *name); ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++ ++/** ++ * Initialize the read-only file system. ++ */ ++void fs_init(void); ++ ++#endif /* __FS_H__ */ +--- /dev/null ++++ b/net/uip-0.9/fsdata.c +@@ -0,0 +1,199 @@ ++static const char data_flashing_html[] = { ++ /* /flashing.html */ ++ 0x2f, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, ++ 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, 0x30, ++ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, ++ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, ++ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, ++ 0x70, 0x2f, 0x29, 0xd, 0xa, 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, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x3c, 0x62, ++ 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x3d, ++ 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30, ++ 0x70, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x20, 0x68, ++ 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x31, 0x30, 0x30, 0x25, ++ 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, ++ 0x66, 0x66, 0x66, 0x3b, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, ++ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, ++ 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, 0x62, 0x30, 0x33, 0x34, ++ 0x3b, 0x22, 0x3e, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, ++ 0x3e, 0x3c, 0x68, 0x31, 0x3e, 0x55, 0x70, 0x67, 0x72, 0x61, ++ 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, ++ 0x6d, 0x20, 0x2e, 0x2e, 0x2e, 0x2e, 0x3c, 0x2f, 0x68, 0x31, ++ 0x3e, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, ++ 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, ++ 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; ++ ++static const char data_fail_html[] = { ++ /* /fail.html */ ++ 0x2f, 0x66, 0x61, 0x69, 0x6c, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, ++ 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, 0x30, ++ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, ++ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, ++ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, ++ 0x70, 0x2f, 0x29, 0xd, 0xa, 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, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9, ++ 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c, ++ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9, + 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46, + 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49, + 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, @@ -4467,89 +4607,6 @@ + +#endif /* __FSDATA_H__ */ --- /dev/null -+++ b/net/uip-0.9/fs.h -@@ -0,0 +1,80 @@ -+/** -+ * \addtogroup httpd -+ * @{ -+ */ -+ -+/** -+ * \file -+ * HTTP server read-only file system header file. -+ * \author Adam Dunkels -+ */ -+ -+/* -+ * 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 -+ * -+ * $Id: fs.h,v 1.6.2.3 2003/10/07 13:22:27 adam Exp $ -+ */ -+#ifndef __FS_H__ -+#define __FS_H__ -+ -+#include "uip.h" -+ -+/** -+ * An open file in the read-only file system. -+ */ -+struct fs_file { -+ char *data; /**< The actual file data. */ -+ int len; /**< The length of the file data. */ -+}; -+ -+/** -+ * Open a file in the read-only file system. -+ * -+ * \param name The name of the file. -+ * -+ * \param file The file pointer, which must be allocated by caller and -+ * will be filled in by the function. -+ */ -+int fs_open(const char *name, struct fs_file *file); -+ -+#ifdef FS_STATISTICS -+#if FS_STATISTICS == 1 -+u16_t fs_count(char *name); -+#endif /* FS_STATISTICS */ -+#endif /* FS_STATISTICS */ -+ -+/** -+ * Initialize the read-only file system. -+ */ -+void fs_init(void); -+ -+#endif /* __FS_H__ */ ---- /dev/null +++ b/net/uip-0.9/httpd.c @@ -0,0 +1,278 @@ +#include "uip.h" @@ -5008,63 +5065,6 @@ + return 0; +} --- /dev/null -+++ b/net/uip-0.9/Makefile -@@ -0,0 +1,54 @@ -+# 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: Makefile,v 1.8.2.2 2003/10/04 22:54:17 adam Exp $ -+# -+ -+CC=gcc -+CFLAGS=-Wall -fpack-struct -DDUMP=0 -+ -+all: uip -+ -+uip: uip.o uip_arch.o tapdev.o httpd.o main.o fs.o uip_arp.o -+ $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ -+ -+%.o: %.c -+ $(CC) $(CFLAGS) -c $^ -o $@ -+ -+clean: -+ rm -f *.o *~ *core uip -+ -+ -+ -+ -+ -+ ---- /dev/null +++ b/net/uip-0.9/tapdev.c @@ -0,0 +1,192 @@ +/* @@ -5305,10 +5305,21 @@ + +#endif /* __TAPDEV_H__ */ --- /dev/null -+++ b/net/uip-0.9/uip_arch.c -@@ -0,0 +1,145 @@ ++++ b/net/uip-0.9/uip.c +@@ -0,0 +1,1503 @@ ++/** ++ * \addtogroup uip ++ * @{ ++ */ ++ ++/** ++ * \file ++ * The uIP TCP/IP stack code. ++ * \author Adam Dunkels ++ */ ++ +/* -+ * Copyright (c) 2001, Adam Dunkels. ++ * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without @@ -5337,3457 +5348,3446 @@ + * + * This file is part of the uIP TCP/IP stack. + * -+ * $Id: uip_arch.c,v 1.2.2.1 2003/10/04 22:54:17 adam Exp $ ++ * $Id: uip.c,v 1.62.2.10 2003/10/07 13:23:01 adam Exp $ + * + */ + ++/* ++This is a small implementation of the IP and TCP protocols (as well as ++some basic ICMP stuff). The implementation couples the IP, TCP and the ++application layers very tightly. To keep the size of the compiled code ++down, this code also features heavy usage of the goto statement. ++ ++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 upon 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, 40 bytes from the start of the buffer. The ++TCP/IP stack will calculate the checksums, and fill in the necessary ++header fields and finally send the packet back to the peer. ++*/ + +#include "uip.h" ++#include "uipopt.h" +#include "uip_arch.h" + ++/*-----------------------------------------------------------------------------------*/ ++/* Variable definitions. */ ++ ++ ++/* 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 unsigned short int uip_hostaddr[2] = ++ {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1), ++ HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)}; ++const unsigned short int uip_arp_draddr[2] = ++ {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1), ++ HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)}; ++const unsigned short int uip_arp_netmask[2] = ++ {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1), ++ HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)}; ++#else ++unsigned short int uip_hostaddr[2]; ++unsigned short int uip_arp_draddr[2], uip_arp_netmask[2]; ++#endif /* UIP_FIXEDADDR */ ++ ++u8_t uip_buf[UIP_BUFSIZE+2]; /* The packet buffer that contains ++ incoming packets. */ ++volatile u8_t *uip_appdata; /* The uip_appdata pointer points to ++ application data. */ ++volatile u8_t *uip_sappdata; /* The uip_appdata pointer points to the ++ application data which is to be sent. */ ++#if UIP_URGDATA > 0 ++volatile u8_t *uip_urgdata; /* The uip_urgdata pointer points to ++ urgent data (out-of-band data), if ++ present. */ ++volatile u8_t uip_urglen, uip_surglen; ++#endif /* UIP_URGDATA > 0 */ ++ ++volatile unsigned short int uip_len, uip_slen; ++ /* The uip_len is either 8 or 16 bits, ++ depending on the maximum packet ++ size. */ ++ ++volatile u8_t 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. */ ++unsigned short int 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 */ ++ ++ ++static unsigned short int ipid; /* Ths ipid variable is an increasing ++ number that is used for the IP ID ++ field. */ ++ ++static u8_t iss[4]; /* The iss variable is used for the TCP ++ initial sequence number. */ ++ ++#if UIP_ACTIVE_OPEN ++static unsigned short int lastport; /* Keeps track of the last port used for ++ a new connection. */ ++#endif /* UIP_ACTIVE_OPEN */ ++ ++/* Temporary variables. */ ++volatile u8_t uip_acc32[4]; ++static u8_t c, opt; ++static unsigned short int tmp16; ++ ++/* Structures and 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 ICMP_ECHO_REPLY 0 ++#define ICMP_ECHO 8 ++ ++/* Macros. */ +#define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) -+#define IP_PROTO_TCP 6 ++#define FBUF ((uip_tcpip_hdr *)&uip_reassbuf[0]) ++#define ICMPBUF ((uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN]) ++#define UDPBUF ((uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN]) ++ ++#if UIP_STATISTICS == 1 ++struct uip_stats uip_stat; ++#define UIP_STAT(s) s ++#else ++#define UIP_STAT(s) ++#endif /* UIP_STATISTICS == 1 */ ++ ++#if UIP_LOGGING == 1 ++extern void puts(const char *s); ++#define UIP_LOG(m) puts(m) ++#else ++#define UIP_LOG(m) ++#endif /* UIP_LOGGING == 1 */ + +/*-----------------------------------------------------------------------------------*/ +void -+uip_add32(u8_t *op32, u16_t op16) ++uip_init(void) +{ -+ -+ 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]; -+ } ++ for(c = 0; c < UIP_LISTENPORTS; ++c) { ++ uip_listenports[c] = 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]; -+ } -+ } ++ for(c = 0; c < UIP_CONNS; ++c) { ++ uip_conns[c].tcpstateflags = 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 */ ++ +} +/*-----------------------------------------------------------------------------------*/ -+u16_t -+uip_chksum(u16_t *sdata, u16_t len) ++#if UIP_ACTIVE_OPEN ++struct uip_conn * ++uip_connect(unsigned short int *ripaddr, unsigned short int rport) +{ -+ u16_t acc; ++ register struct uip_conn *conn, *cconn; + -+ for(acc = 0; len > 1; len -= 2) { -+ acc += *sdata; -+ if(acc < *sdata) { -+ /* Overflow, so we add the carry to acc (i.e., increase by -+ one). */ -+ ++acc; -+ } -+ ++sdata; ++ /* Find an unused local port. */ ++ again: ++ ++lastport; ++ ++ if(lastport >= 32000) { ++ lastport = 4096; + } + -+ /* add up any odd byte */ -+ if(len == 1) { -+ acc += htons(((u16_t)(*(u8_t *)sdata)) << 8); -+ if(acc < htons(((u16_t)(*(u8_t *)sdata)) << 8)) { -+ ++acc; ++ /* 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 != CLOSED && ++ conn->lport == htons(lastport)) { ++ goto again; + } + } + -+ return acc; -+} -+/*-----------------------------------------------------------------------------------*/ -+u16_t -+uip_ipchksum(void) -+{ -+ return uip_chksum((u16_t *)&uip_buf[UIP_LLH_LEN], 20); -+} -+/*-----------------------------------------------------------------------------------*/ -+u16_t -+uip_tcpchksum(void) -+{ -+ u16_t hsum, sum; + -+ -+ /* Compute the checksum of the TCP header. */ -+ hsum = uip_chksum((u16_t *)&uip_buf[20 + UIP_LLH_LEN], 20); ++ conn = 0; ++ for(c = 0; c < UIP_CONNS; ++c) { ++ cconn = &uip_conns[c]; ++ if(cconn->tcpstateflags == CLOSED) { ++ conn = cconn; ++ break; ++ } ++ if(cconn->tcpstateflags == TIME_WAIT) { ++ if(conn == 0 || ++ cconn->timer > uip_conn->timer) { ++ conn = cconn; ++ } ++ } ++ } + -+ /* Compute the checksum of the data in the TCP packet and add it to -+ the TCP header checksum. */ -+ sum = uip_chksum((u16_t *)uip_appdata, -+ (u16_t)(((((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - 40))); -+ -+ if((sum += hsum) < hsum) { -+ ++sum; ++ if(conn == 0) { ++ return 0; + } + -+ if((sum += BUF->srcipaddr[0]) < BUF->srcipaddr[0]) { -+ ++sum; -+ } -+ if((sum += BUF->srcipaddr[1]) < BUF->srcipaddr[1]) { -+ ++sum; -+ } -+ if((sum += BUF->destipaddr[0]) < BUF->destipaddr[0]) { -+ ++sum; ++ conn->tcpstateflags = 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; ++ conn->lport = htons(lastport); ++ conn->rport = rport; ++ conn->ripaddr[0] = ripaddr[0]; ++ conn->ripaddr[1] = ripaddr[1]; ++ ++ return conn; ++} ++#endif /* UIP_ACTIVE_OPEN */ ++/*-----------------------------------------------------------------------------------*/ ++#if UIP_UDP ++struct uip_udp_conn * ++uip_udp_new(unsigned short int *ripaddr, unsigned short int rport) ++{ ++ register struct uip_udp_conn *conn; ++ ++ /* Find an unused local port. */ ++ again: ++ ++lastport; ++ ++ if(lastport >= 32000) { ++ lastport = 4096; + } -+ if((sum += BUF->destipaddr[1]) < BUF->destipaddr[1]) { -+ ++sum; ++ ++ for(c = 0; c < UIP_UDP_CONNS; ++c) { ++ if(uip_udp_conns[c].lport == lastport) { ++ goto again; ++ } + } -+ if((sum += (u16_t)htons((u16_t)IP_PROTO_TCP)) < (u16_t)htons((u16_t)IP_PROTO_TCP)) { -+ ++sum; ++ ++ ++ conn = 0; ++ for(c = 0; c < UIP_UDP_CONNS; ++c) { ++ if(uip_udp_conns[c].lport == 0) { ++ conn = &uip_udp_conns[c]; ++ break; ++ } + } + -+ hsum = (u16_t)htons((((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - 20); -+ -+ if((sum += hsum) < hsum) { -+ ++sum; ++ if(conn == 0) { ++ return 0; + } + -+ return sum; ++ conn->lport = HTONS(lastport); ++ conn->rport = HTONS(rport); ++ conn->ripaddr[0] = ripaddr[0]; ++ conn->ripaddr[1] = ripaddr[1]; ++ ++ return conn; +} ++#endif /* UIP_UDP */ +/*-----------------------------------------------------------------------------------*/ ---- /dev/null -+++ b/net/uip-0.9/uip_arch.h -@@ -0,0 +1,130 @@ -+/** -+ * \defgroup uiparch Architecture specific uIP functions -+ * @{ -+ * -+ * The functions in the architecture specific module implement the IP -+ * check sum and 32-bit additions. -+ * -+ * The IP checksum calculation is the most computationally expensive -+ * operation in the TCP/IP stack and it therefore pays off to -+ * implement this in efficient assembler. The purpose of the uip-arch -+ * module is to let the checksum functions to be implemented in -+ * architecture specific assembler. -+ * -+ */ -+ -+/** -+ * \file -+ * Declarations of architecture specific functions. -+ * \author Adam Dunkels -+ */ ++void ++uip_unlisten(unsigned short int port) ++{ ++ for(c = 0; c < UIP_LISTENPORTS; ++c) { ++ if(uip_listenports[c] == port) { ++ uip_listenports[c] = 0; ++ return; ++ } ++ } ++} ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_listen(unsigned short int 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. */ + -+/* -+ * Copyright (c) 2001, Adam Dunkels. -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The name of the author may not be used to endorse or promote -+ * products derived from this software without specific prior -+ * written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS -+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * This file is part of the uIP TCP/IP stack. -+ * -+ * $Id: uip_arch.h,v 1.1.2.2 2003/10/06 15:10:22 adam Exp $ -+ * -+ */ ++#if UIP_REASSEMBLY ++#define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN) ++static u8_t uip_reassbuf[UIP_REASS_BUFSIZE]; ++static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)]; ++static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f, ++ 0x0f, 0x07, 0x03, 0x01}; ++static unsigned short int uip_reasslen; ++static u8_t uip_reassflags; ++#define UIP_REASS_FLAG_LASTFRAG 0x01 ++static u8_t uip_reasstmr; + -+#ifndef __UIP_ARCH_H__ -+#define __UIP_ARCH_H__ ++#define IP_HLEN 20 ++#define IP_MF 0x20 + -+#include "uip.h" ++static u8_t ++uip_reass(void) ++{ ++ unsigned short int offset, len; ++ unsigned short int i; + -+/** -+ * Carry out a 32-bit addition. -+ * -+ * Because not all architectures for which uIP is intended has native -+ * 32-bit arithmetic, uIP uses an external C function for doing the -+ * required 32-bit additions in the TCP protocol processing. This -+ * function should add the two arguments and place the result in the -+ * global variable uip_acc32. -+ * -+ * \note The 32-bit integer pointed to by the op32 parameter and the -+ * result in the uip_acc32 variable are in network byte order (big -+ * endian). -+ * -+ * \param op32 A pointer to a 4-byte array representing a 32-bit -+ * integer in network byte order (big endian). -+ * -+ * \param op16 A 16-bit integer in host byte order. -+ */ -+void uip_add32(u8_t *op32, u16_t op16); ++ /* 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, IP_HLEN); ++ uip_reasstmr = UIP_REASS_MAXAGE; ++ uip_reassflags = 0; ++ /* Clear the bitmap. */ ++ memset(uip_reassbitmap, sizeof(uip_reassbitmap), 0); ++ } + -+/** -+ * Calculate the Internet checksum over a buffer. -+ * -+ * The Internet checksum is the one's complement of the one's -+ * complement sum of all 16-bit words in the buffer. -+ * -+ * See RFC1071. -+ * -+ * \note This function is not called in the current version of uIP, -+ * but future versions might make use of it. -+ * -+ * \param buf A pointer to the buffer over which the checksum is to be -+ * computed. -+ * -+ * \param len The length of the buffer over which the checksum is to -+ * be computed. -+ * -+ * \return The Internet checksum of the buffer. -+ */ -+u16_t uip_chksum(u16_t *buf, u16_t len); ++ /* 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]) { + -+/** -+ * Calculate the IP header checksum of the packet header in uip_buf. -+ * -+ * The IP header checksum is the Internet checksum of the 20 bytes of -+ * the IP header. -+ * -+ * \return The IP header checksum of the IP header in the uip_buf -+ * buffer. -+ */ -+u16_t uip_ipchksum(void); ++ len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4; ++ offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8; + -+/** -+ * Calculate the TCP checksum of the packet in uip_buf and uip_appdata. -+ * -+ * The TCP checksum is the Internet checksum of data contents of the -+ * TCP segment, and a pseudo-header as defined in RFC793. -+ * -+ * \note The uip_appdata pointer that points to the packet data may -+ * point anywhere in memory, so it is not possible to simply calculate -+ * the Internet checksum of the contents of the uip_buf buffer. -+ * -+ * \return The TCP checksum of the TCP segment in uip_buf and pointed -+ * to by uip_appdata. -+ */ -+u16_t uip_tcpchksum(void); -+ -+/** @} */ -+ -+#endif /* __UIP_ARCH_H__ */ ---- /dev/null -+++ b/net/uip-0.9/uip_arp.c -@@ -0,0 +1,421 @@ -+/** -+ * \addtogroup uip -+ * @{ -+ */ -+ -+/** -+ * \defgroup uiparp uIP Address Resolution Protocol -+ * @{ -+ * -+ * 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. -+ */ -+ -+/** -+ * \file -+ * Implementation of the ARP Address Resolution Protocol. -+ * \author Adam Dunkels -+ * -+ */ -+ -+/* -+ * 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_arp.c,v 1.7.2.3 2003/10/06 22:42:30 adam Exp $ -+ * -+ */ -+ -+ -+#include "uip_arp.h" -+ -+struct arp_hdr { -+ struct uip_eth_hdr ethhdr; -+ u16_t hwtype; -+ u16_t protocol; -+ u8_t hwlen; -+ u8_t protolen; -+ u16_t opcode; -+ struct uip_eth_addr shwaddr; -+ u16_t sipaddr[2]; -+ struct uip_eth_addr dhwaddr; -+ u16_t dipaddr[2]; -+}; -+ -+struct ethip_hdr { -+ struct uip_eth_hdr ethhdr; -+ /* IP header. */ -+ u8_t vhl, -+ tos, -+ len[2], -+ ipid[2], -+ ipoffset[2], -+ ttl, -+ proto; -+ u16_t ipchksum; -+ u16_t srcipaddr[2], -+ destipaddr[2]; -+}; -+ -+#define ARP_REQUEST 1 -+#define ARP_REPLY 2 ++ /* 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; ++ } + -+#define ARP_HWTYPE_ETH 1 ++ /* Copy the fragment into the reassembly buffer, at the right ++ offset. */ ++ memcpy(&uip_reassbuf[IP_HLEN + 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. */ + -+struct arp_entry { -+ u16_t ipaddr[2]; -+ struct uip_eth_addr ethaddr; -+ u8_t time; -+}; ++ 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)] != ++ (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) { ++ goto nullreturn; ++ } + -+struct uip_eth_addr uip_ethaddr = {{UIP_ETHADDR0, -+ UIP_ETHADDR1, -+ UIP_ETHADDR2, -+ UIP_ETHADDR3, -+ UIP_ETHADDR4, -+ UIP_ETHADDR5}}; ++ /* 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); + -+static struct arp_entry arp_table[UIP_ARPTAB_SIZE]; -+static u16_t ipaddr[2]; -+static u8_t i, c; ++ /* 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()); + -+static u8_t arptime; -+static u8_t tmpage; ++ return uip_reasslen; ++ } ++ } + -+#define BUF ((struct arp_hdr *)&uip_buf[0]) -+#define IPBUF ((struct ethip_hdr *)&uip_buf[0]) -+/*-----------------------------------------------------------------------------------*/ -+/** -+ * Initialize the ARP module. -+ * -+ */ ++ nullreturn: ++ return 0; ++} ++#endif /* UIP_REASSEMBL */ +/*-----------------------------------------------------------------------------------*/ -+void -+uip_arp_init(void) ++static void ++uip_add_rcv_nxt(unsigned short int n) +{ -+ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { -+ memset(arp_table[i].ipaddr, 0, 4); -+ } ++ 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]; +} +/*-----------------------------------------------------------------------------------*/ -+/** -+ * 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) ++uip_process(u8_t flag) +{ -+ struct arp_entry *tabptr; ++ register struct uip_conn *uip_connr = uip_conn; + -+ ++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); -+ } -+ } ++ uip_appdata = &uip_buf[40 + UIP_LLH_LEN]; + -+} -+/*-----------------------------------------------------------------------------------*/ -+static void -+uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr) -+{ -+ register struct arp_entry *tabptr; -+ /* Walk through the ARP mapping table and try to find an entry to -+ update. If none is found, the IP -> MAC address mapping is -+ inserted in the ARP table. */ -+ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { ++ ++ /* Check if we were invoked because of the perodic timer fireing. */ ++ 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]; ++ } ++ } ++ } ++ uip_len = 0; ++ if(uip_connr->tcpstateflags == TIME_WAIT || ++ uip_connr->tcpstateflags == FIN_WAIT_2) { ++ ++(uip_connr->timer); ++ if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) { ++ uip_connr->tcpstateflags = CLOSED; ++ } ++ } else if(uip_connr->tcpstateflags != 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 == SYN_SENT || ++ uip_connr->tcpstateflags == SYN_RCVD) && ++ uip_connr->nrtx == UIP_MAXSYNRTX)) { ++ uip_connr->tcpstateflags = CLOSED; + -+ tabptr = &arp_table[i]; -+ /* Only check those entries that are actually in use. */ -+ if(tabptr->ipaddr[0] != 0 && -+ tabptr->ipaddr[1] != 0) { ++ /* We call UIP_APPCALL() with uip_flags set to ++ UIP_TIMEDOUT to inform the application that the ++ connection has timed out. */ ++ uip_flags = UIP_TIMEDOUT; ++ UIP_APPCALL(); + -+ /* Check if the source IP address of the incoming packet matches -+ the IP address in this ARP table entry. */ -+ if(ipaddr[0] == tabptr->ipaddr[0] && -+ ipaddr[1] == tabptr->ipaddr[1]) { -+ -+ /* An old entry found, update this and return. */ -+ memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); -+ tabptr->time = arptime; ++ /* We also send a reset packet to the remote host. */ ++ BUF->flags = TCP_RST | TCP_ACK; ++ goto tcp_send_nodata; ++ } + -+ return; ++ /* 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 & TS_MASK) { ++ case SYN_RCVD: ++ /* In the SYN_RCVD state, we should retransmit our ++ SYNACK. */ ++ goto tcp_send_synack; ++ ++#if UIP_ACTIVE_OPEN ++ case SYN_SENT: ++ /* In the SYN_SENT state, we retransmit out SYN. */ ++ BUF->flags = 0; ++ goto tcp_send_syn; ++#endif /* UIP_ACTIVE_OPEN */ ++ ++ case 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_len = 0; ++ uip_slen = 0; ++ uip_flags = UIP_REXMIT; ++ UIP_APPCALL(); ++ goto apprexmit; ++ ++ case FIN_WAIT_1: ++ case CLOSING: ++ case LAST_ACK: ++ /* In all these states we should retransmit a FINACK. */ ++ goto tcp_send_finack; ++ ++ } ++ } ++ } else if((uip_connr->tcpstateflags & TS_MASK) == ESTABLISHED) { ++ /* If there was no need for a retransmission, we poll the ++ application for new data. */ ++ uip_len = 0; ++ uip_slen = 0; ++ uip_flags = UIP_POLL; ++ UIP_APPCALL(); ++ goto appsend; + } + } ++ goto drop; + } -+ -+ /* 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 UIP_UDP ++ if(flag == UIP_UDP_TIMER) { ++ if(uip_udp_conn->lport != 0) { ++ uip_appdata = &uip_buf[UIP_LLH_LEN + 28]; ++ uip_len = uip_slen = 0; ++ uip_flags = UIP_POLL; ++ UIP_UDP_APPCALL(); ++ goto udp_send; ++ } else { ++ goto drop; + } + } ++#endif + -+ /* 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; -+ } ++ /* This is where the input processing starts. */ ++ UIP_STAT(++uip_stat.ip.recv); + -+ /* Now, i is the ARP table entry which we will fill with the new -+ information. */ -+ memcpy(tabptr->ipaddr, ipaddr, 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. -+ */ -+/*-----------------------------------------------------------------------------------*/ -+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_arp_netmask[0]) != -+ (uip_hostaddr[0] & uip_arp_netmask[0])) { -+ return; -+ } -+ if((IPBUF->srcipaddr[1] & uip_arp_netmask[1]) != -+ (uip_hostaddr[1] & uip_arp_netmask[1])) { -+ return; ++ ++ /* Start of IPv4 input header processing code. */ ++ ++ /* 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; + } -+ uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src)); + -+ return; -+} -+/*-----------------------------------------------------------------------------------*/ -+/** -+ * 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; ++ /* Check the size of the packet. If the size reported to us in ++ uip_len doesn't match the size reported in the IP header, there ++ has been a transmission error and we drop the packet. */ ++ ++ if(BUF->len[0] != (uip_len >> 8)) { /* IP length, high byte. */ ++ uip_len = (uip_len & 0xff) | (BUF->len[0] << 8); ++ } ++ if(BUF->len[1] != (uip_len & 0xff)) { /* IP length, low byte. */ ++ uip_len = (uip_len & 0xff00) | BUF->len[1]; + } + -+ uip_len = 0; ++ /* 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_STAT(++uip_stat.ip.drop); ++ UIP_STAT(++uip_stat.ip.fragerr); ++ UIP_LOG("ip: fragment dropped."); ++ goto drop; ++#endif /* UIP_REASSEMBLY */ ++ } + -+ switch(BUF->opcode) { -+ case HTONS(ARP_REQUEST): -+ /* ARP request. If it asked for our address, we send out a -+ reply. */ -+ if(BUF->dipaddr[0] == uip_hostaddr[0] && -+ BUF->dipaddr[1] == uip_hostaddr[1]) { -+ /* 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(BUF->dipaddr[0] == uip_hostaddr[0] && -+ BUF->dipaddr[1] == uip_hostaddr[1]) { -+ -+ uip_arp_update(BUF->sipaddr, &BUF->shwaddr); ++ /* 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 ++ if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) { ++ 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; + } -+ break; ++ } ++#endif /* UIP_PINGADDRCONF */ ++ ++ /* Check if the packet is destined for our IP address. */ ++ if(BUF->destipaddr[0] != uip_hostaddr[0]) { ++ UIP_STAT(++uip_stat.ip.drop); ++ UIP_LOG("ip: packet not for us."); ++ goto drop; ++ } ++ if(BUF->destipaddr[1] != uip_hostaddr[1]) { ++ UIP_STAT(++uip_stat.ip.drop); ++ UIP_LOG("ip: packet not for us."); ++ goto drop; + } + -+ 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(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; ++ } + -+ If not ARP table entry is found, we overwrite the original IP -+ packet with an ARP request for the IP address. */ ++ if(BUF->proto == UIP_PROTO_TCP) /* Check for TCP packet. If so, jump ++ to the tcp_input label. */ ++ goto tcp_input; + -+ /* Check if the destination address is on the local network. */ -+ if((IPBUF->destipaddr[0] & uip_arp_netmask[0]) != -+ (uip_hostaddr[0] & uip_arp_netmask[0]) || -+ (IPBUF->destipaddr[1] & uip_arp_netmask[1]) != -+ (uip_hostaddr[1] & uip_arp_netmask[1])) { -+ /* 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. */ -+ ipaddr[0] = uip_arp_draddr[0]; -+ ipaddr[1] = uip_arp_draddr[1]; -+ } else { -+ /* Else, we use the destination IP address. */ -+ ipaddr[0] = IPBUF->destipaddr[0]; -+ ipaddr[1] = IPBUF->destipaddr[1]; ++#if UIP_UDP ++ if(BUF->proto == UIP_PROTO_UDP) ++ goto udp_input; ++#endif /* UIP_UDP */ ++ ++ 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; + } -+ -+ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { -+ tabptr = &arp_table[i]; -+ if(ipaddr[0] == tabptr->ipaddr[0] && -+ ipaddr[1] == tabptr->ipaddr[1]) -+ break; ++ ++ //icmp_input: ++ 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(i == UIP_ARPTAB_SIZE) { -+ /* The destination address was not in our ARP table, so we -+ overwrite the IP packet with an ARP request. */ ++ /* 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. */ ++ 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; + -+ 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); -+ -+ BUF->dipaddr[0] = ipaddr[0]; -+ BUF->dipaddr[1] = ipaddr[1]; -+ BUF->sipaddr[0] = uip_hostaddr[0]; -+ BUF->sipaddr[1] = uip_hostaddr[1]; -+ 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_STAT(++uip_stat.icmp.sent); ++ goto send; + -+ uip_appdata = &uip_buf[40 + UIP_LLH_LEN]; -+ -+ uip_len = sizeof(struct arp_hdr); -+ return; ++ /* End of IPv4 input header processing code. */ ++ ++ ++#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 ++ if(uip_udpchksum() != 0xffff) { ++ UIP_STAT(++uip_stat.udp.drop); ++ UIP_STAT(++uip_stat.udp.chkerr); ++ UIP_LOG("udp: bad checksum."); ++ goto drop; ++ } ++#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(uip_udp_conn->lport != 0 && ++ UDPBUF->destport == uip_udp_conn->lport && ++ (uip_udp_conn->rport == 0 || ++ UDPBUF->srcport == uip_udp_conn->rport) && ++ BUF->srcipaddr[0] == uip_udp_conn->ripaddr[0] && ++ BUF->srcipaddr[1] == uip_udp_conn->ripaddr[1]) { ++ goto udp_found; ++ } ++ } ++ goto drop; ++ ++ udp_found: ++ uip_len = uip_len - 28; ++ uip_appdata = &uip_buf[UIP_LLH_LEN + 28]; ++ uip_flags = UIP_NEWDATA; ++ uip_slen = 0; ++ UIP_UDP_APPCALL(); ++ udp_send: ++ if(uip_slen == 0) { ++ goto drop; + } ++ uip_len = uip_slen + 28; + -+ /* Build an ethernet header. */ -+ memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6); -+ memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6); ++ BUF->len[0] = (uip_len >> 8); ++ BUF->len[1] = (uip_len & 0xff); + -+ IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP); ++ BUF->proto = UIP_PROTO_UDP; + -+ uip_len += sizeof(struct uip_eth_hdr); -+} -+/*-----------------------------------------------------------------------------------*/ ++ UDPBUF->udplen = HTONS(uip_slen + 8); ++ UDPBUF->udpchksum = 0; ++#if UIP_UDP_CHECKSUMS ++ /* Calculate UDP checksum. */ ++ UDPBUF->udpchksum = ~(uip_udpchksum()); ++ if(UDPBUF->udpchksum == 0) { ++ UDPBUF->udpchksum = 0xffff; ++ } ++#endif /* UIP_UDP_CHECKSUMS */ + -+/** @} */ -+/** @} */ ---- /dev/null -+++ b/net/uip-0.9/uip_arp.h -@@ -0,0 +1,201 @@ -+/** -+ * \addtogroup uip -+ * @{ -+ */ ++ BUF->srcport = uip_udp_conn->lport; ++ BUF->destport = uip_udp_conn->rport; + -+/** -+ * \addtogroup uiparp -+ * @{ -+ */ ++ BUF->srcipaddr[0] = uip_hostaddr[0]; ++ BUF->srcipaddr[1] = uip_hostaddr[1]; ++ BUF->destipaddr[0] = uip_udp_conn->ripaddr[0]; ++ BUF->destipaddr[1] = uip_udp_conn->ripaddr[1]; + -+/** -+ * \file -+ * Macros and definitions for the ARP module. -+ * \author Adam Dunkels -+ */ ++ uip_appdata = &uip_buf[UIP_LLH_LEN + 40]; ++ goto ip_send_nolen; ++#endif /* UIP_UDP */ + ++ /* TCP input processing. */ ++ tcp_input: ++ UIP_STAT(++uip_stat.tcp.recv); + -+/* -+ * 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_arp.h,v 1.3.2.2 2003/10/06 15:10:22 adam Exp $ -+ * -+ */ -+ -+#ifndef __UIP_ARP_H__ -+#define __UIP_ARP_H__ -+ -+#include "uip.h" -+ ++ /* 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]; ++uip_connr) { ++ if(uip_connr->tcpstateflags != CLOSED && ++ BUF->destport == uip_connr->lport && ++ BUF->srcport == uip_connr->rport && ++ BUF->srcipaddr[0] == uip_connr->ripaddr[0] && ++ BUF->srcipaddr[1] == uip_connr->ripaddr[1]) { ++ goto found; ++ } ++ } + -+/** -+ * Representation of a 48-bit Ethernet address. -+ */ -+struct uip_eth_addr { -+ u8_t addr[6]; -+}; ++ /* 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: + -+extern struct uip_eth_addr uip_ethaddr; ++ /* We do not send resets in response to resets. */ ++ if(BUF->flags & TCP_RST) ++ goto drop; + -+/** -+ * The Ethernet header. -+ */ -+struct uip_eth_hdr { -+ struct uip_eth_addr dest; -+ struct uip_eth_addr src; -+ u16_t type; -+}; ++ UIP_STAT(++uip_stat.tcp.rst); ++ ++ BUF->flags = TCP_RST | TCP_ACK; ++ uip_len = 40; ++ BUF->tcpoffset = 5 << 4; + -+#define UIP_ETHTYPE_ARP 0x0806 -+#define UIP_ETHTYPE_IP 0x0800 -+#define UIP_ETHTYPE_IP6 0x86dd ++ /* 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. */ ++ 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; + -+/* The uip_arp_init() function must be called before any of the other -+ ARP functions. */ -+void uip_arp_init(void); ++ ++ /* And send out the RST packet! */ ++ goto tcp_send_noconn; + -+/* 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); ++ /* 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 == CLOSED) { ++ uip_connr = &uip_conns[c]; ++ break; ++ } ++ if(uip_conns[c].tcpstateflags == TIME_WAIT) { ++ if(uip_connr == 0 || ++ uip_conns[c].timer > uip_connr->timer) { ++ uip_connr = &uip_conns[c]; ++ } ++ } ++ } + -+/* 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); ++ 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_connr->ripaddr[0] = BUF->srcipaddr[0]; ++ uip_connr->ripaddr[1] = BUF->srcipaddr[1]; ++ uip_connr->tcpstateflags = SYN_RCVD; + -+/* 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); ++ 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; + -+/* 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); ++ /* 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); + -+/** @} */ -+ -+/** -+ * \addtogroup uipconffunc -+ * @{ -+ */ -+ -+/** -+ * Set the default router's IP address. -+ * -+ * \param addr A pointer to a 4-byte array containing the IP address -+ * of the default router. -+ * -+ * \hideinitializer -+ */ -+#define uip_setdraddr(addr) do { uip_arp_draddr[0] = addr[0]; \ -+ uip_arp_draddr[1] = addr[1]; } while(0) -+ -+/** -+ * Set the netmask. -+ * -+ * \param addr A pointer to a 4-byte array containing the IP address -+ * of the netmask. -+ * -+ * \hideinitializer -+ */ -+#define uip_setnetmask(addr) do { uip_arp_netmask[0] = addr[0]; \ -+ uip_arp_netmask[1] = addr[1]; } while(0) -+ -+ -+/** -+ * Get the default router's IP address. -+ * -+ * \param addr A pointer to a 4-byte array that will be filled in with -+ * the IP address of the default router. -+ * -+ * \hideinitializer -+ */ -+#define uip_getdraddr(addr) do { addr[0] = uip_arp_draddr[0]; \ -+ addr[1] = uip_arp_draddr[1]; } while(0) -+ -+/** -+ * Get the netmask. -+ * -+ * \param addr A pointer to a 4-byte array that will be filled in with -+ * the value of the netmask. -+ * -+ * \hideinitializer -+ */ -+#define uip_getnetmask(addr) do { addr[0] = uip_arp_netmask[0]; \ -+ addr[1] = uip_arp_netmask[1]; } while(0) -+ -+ -+/** -+ * 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. -+ * -+ * \param eaddr A pointer to a struct uip_eth_addr containing the -+ * Ethernet MAC address of the Ethernet card. -+ * -+ * \hideinitializer -+ */ -+#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) -+ -+/** @} */ -+ -+/** -+ * \internal Internal variables that are set using the macros -+ * uip_setdraddr and uip_setnetmask. -+ */ -+extern u16_t uip_arp_draddr[2], uip_arp_netmask[2]; -+#endif /* __UIP_ARP_H__ */ -+ -+ ---- /dev/null -+++ b/net/uip-0.9/uip.c -@@ -0,0 +1,1503 @@ -+/** -+ * \addtogroup uip -+ * @{ -+ */ -+ -+/** -+ * \file -+ * The uIP TCP/IP stack code. -+ * \author Adam Dunkels -+ */ -+ -+/* -+ * 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.c,v 1.62.2.10 2003/10/07 13:23:01 adam Exp $ -+ * -+ */ -+ -+/* -+This is a small implementation of the IP and TCP protocols (as well as -+some basic ICMP stuff). The implementation couples the IP, TCP and the -+application layers very tightly. To keep the size of the compiled code -+down, this code also features heavy usage of the goto statement. -+ -+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 upon 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, 40 bytes from the start of the buffer. The -+TCP/IP stack will calculate the checksums, and fill in the necessary -+header fields and finally send the packet back to the peer. -+*/ -+ -+#include "uip.h" -+#include "uipopt.h" -+#include "uip_arch.h" -+ -+/*-----------------------------------------------------------------------------------*/ -+/* Variable definitions. */ -+ -+ -+/* 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 unsigned short int uip_hostaddr[2] = -+ {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1), -+ HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)}; -+const unsigned short int uip_arp_draddr[2] = -+ {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1), -+ HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)}; -+const unsigned short int uip_arp_netmask[2] = -+ {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1), -+ HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)}; -+#else -+unsigned short int uip_hostaddr[2]; -+unsigned short int uip_arp_draddr[2], uip_arp_netmask[2]; -+#endif /* UIP_FIXEDADDR */ -+ -+u8_t uip_buf[UIP_BUFSIZE+2]; /* The packet buffer that contains -+ incoming packets. */ -+volatile u8_t *uip_appdata; /* The uip_appdata pointer points to -+ application data. */ -+volatile u8_t *uip_sappdata; /* The uip_appdata pointer points to the -+ application data which is to be sent. */ -+#if UIP_URGDATA > 0 -+volatile u8_t *uip_urgdata; /* The uip_urgdata pointer points to -+ urgent data (out-of-band data), if -+ present. */ -+volatile u8_t uip_urglen, uip_surglen; -+#endif /* UIP_URGDATA > 0 */ -+ -+volatile unsigned short int uip_len, uip_slen; -+ /* The uip_len is either 8 or 16 bits, -+ depending on the maximum packet -+ size. */ -+ -+volatile u8_t 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. */ -+unsigned short int 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 */ -+ -+ -+static unsigned short int ipid; /* Ths ipid variable is an increasing -+ number that is used for the IP ID -+ field. */ -+ -+static u8_t iss[4]; /* The iss variable is used for the TCP -+ initial sequence number. */ -+ -+#if UIP_ACTIVE_OPEN -+static unsigned short int lastport; /* Keeps track of the last port used for -+ a new connection. */ -+#endif /* UIP_ACTIVE_OPEN */ -+ -+/* Temporary variables. */ -+volatile u8_t uip_acc32[4]; -+static u8_t c, opt; -+static unsigned short int tmp16; -+ -+/* Structures and 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 ICMP_ECHO_REPLY 0 -+#define ICMP_ECHO 8 -+ -+/* Macros. */ -+#define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) -+#define FBUF ((uip_tcpip_hdr *)&uip_reassbuf[0]) -+#define ICMPBUF ((uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN]) -+#define UDPBUF ((uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN]) -+ -+#if UIP_STATISTICS == 1 -+struct uip_stats uip_stat; -+#define UIP_STAT(s) s -+#else -+#define UIP_STAT(s) -+#endif /* UIP_STATISTICS == 1 */ -+ -+#if UIP_LOGGING == 1 -+extern void puts(const char *s); -+#define UIP_LOG(m) puts(m) -+#else -+#define UIP_LOG(m) -+#endif /* UIP_LOGGING == 1 */ -+ -+/*-----------------------------------------------------------------------------------*/ -+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 = 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(unsigned short int *ripaddr, unsigned short int 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 != CLOSED && -+ conn->lport == htons(lastport)) { -+ goto again; -+ } -+ } -+ -+ -+ conn = 0; -+ for(c = 0; c < UIP_CONNS; ++c) { -+ cconn = &uip_conns[c]; -+ if(cconn->tcpstateflags == CLOSED) { -+ conn = cconn; -+ break; -+ } -+ if(cconn->tcpstateflags == TIME_WAIT) { -+ if(conn == 0 || -+ cconn->timer > uip_conn->timer) { -+ conn = cconn; -+ } -+ } -+ } -+ -+ if(conn == 0) { -+ return 0; -+ } -+ -+ conn->tcpstateflags = 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; -+ conn->lport = htons(lastport); -+ conn->rport = rport; -+ conn->ripaddr[0] = ripaddr[0]; -+ conn->ripaddr[1] = ripaddr[1]; -+ -+ return conn; -+} -+#endif /* UIP_ACTIVE_OPEN */ -+/*-----------------------------------------------------------------------------------*/ -+#if UIP_UDP -+struct uip_udp_conn * -+uip_udp_new(unsigned short int *ripaddr, unsigned short int 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 == 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; ++ /* 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 == 0x00) { ++ /* End of options. */ ++ break; ++ } else if(opt == 0x01) { ++ ++c; ++ /* NOP option. */ ++ } else if(opt == 0x02 && ++ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) { ++ /* An MSS option with the right option length. */ ++ tmp16 = ((unsigned short int)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | ++ (unsigned short int)uip_buf[40 + 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]; ++ } + } + } -+ -+ if(conn == 0) { -+ return 0; -+ } + -+ conn->lport = HTONS(lastport); -+ conn->rport = HTONS(rport); -+ conn->ripaddr[0] = ripaddr[0]; -+ conn->ripaddr[1] = ripaddr[1]; -+ -+ return conn; -+} -+#endif /* UIP_UDP */ -+/*-----------------------------------------------------------------------------------*/ -+void -+uip_unlisten(unsigned short int port) -+{ -+ for(c = 0; c < UIP_LISTENPORTS; ++c) { -+ if(uip_listenports[c] == port) { -+ uip_listenports[c] = 0; -+ return; -+ } -+ } -+} -+/*-----------------------------------------------------------------------------------*/ -+void -+uip_listen(unsigned short int 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 -+#define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN) -+static u8_t uip_reassbuf[UIP_REASS_BUFSIZE]; -+static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)]; -+static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f, -+ 0x0f, 0x07, 0x03, 0x01}; -+static unsigned short int uip_reasslen; -+static u8_t uip_reassflags; -+#define UIP_REASS_FLAG_LASTFRAG 0x01 -+static u8_t uip_reasstmr; ++ /* 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] = 2; ++ BUF->optdata[1] = 4; ++ BUF->optdata[2] = (UIP_TCP_MSS) / 256; ++ BUF->optdata[3] = (UIP_TCP_MSS) & 255; ++ uip_len = 44; ++ BUF->tcpoffset = 6 << 4; ++ goto tcp_send; + -+#define IP_HLEN 20 -+#define IP_MF 0x20 ++ /* This label will be jumped to if we found an active connection. */ ++ found: ++ uip_conn = uip_connr; ++ uip_flags = 0; + -+static u8_t -+uip_reass(void) -+{ -+ unsigned short int offset, len; -+ unsigned short int i; ++ /* 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 = CLOSED; ++ UIP_LOG("tcp: got reset, aborting connection."); ++ uip_flags = UIP_ABORT; ++ UIP_APPCALL(); ++ 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 - 20; + -+ /* 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, IP_HLEN); -+ uip_reasstmr = UIP_REASS_MAXAGE; -+ uip_reassflags = 0; -+ /* Clear the bitmap. */ -+ memset(uip_reassbitmap, sizeof(uip_reassbitmap), 0); ++ /* 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_len > 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; + } + -+ /* 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; ++ /* 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]; ++ + -+ /* 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; -+ } ++ /* 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; + -+ /* Copy the fragment into the reassembly buffer, at the right -+ offset. */ -+ memcpy(&uip_reassbuf[IP_HLEN + 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]; ++ } ++ /* Set the acknowledged flag. */ ++ uip_flags = UIP_ACKDATA; ++ /* Reset the retransmission timer. */ ++ uip_connr->timer = uip_connr->rto; + } + -+ /* 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)] != -+ (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) { -+ goto nullreturn; ++ /* Do different things depending on in what state the connection is. */ ++ switch(uip_connr->tcpstateflags & 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 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 = 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_APPCALL(); ++ goto appsend; ++ } ++ goto drop; ++#if UIP_ACTIVE_OPEN ++ case 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_SYN | TCP_ACK)) { + -+ /* 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()); ++ /* Parse the TCP MSS option, if present. */ ++ if((BUF->tcpoffset & 0xf0) > 0x50) { ++ for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { ++ opt = uip_buf[40 + UIP_LLH_LEN + c]; ++ if(opt == 0x00) { ++ /* End of options. */ ++ break; ++ } else if(opt == 0x01) { ++ ++c; ++ /* NOP option. */ ++ } else if(opt == 0x02 && ++ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) { ++ /* 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; + -+ return uip_reasslen; ++ /* 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 = 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_APPCALL(); ++ goto appsend; + } -+ } ++ goto reset; ++#endif /* UIP_ACTIVE_OPEN */ ++ ++ case 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. + -+ nullreturn: -+ return 0; -+} -+#endif /* UIP_REASSEMBL */ -+/*-----------------------------------------------------------------------------------*/ -+static void -+uip_add_rcv_nxt(unsigned short int 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_process(u8_t flag) -+{ -+ register struct uip_conn *uip_connr = uip_conn; -+ -+ uip_appdata = &uip_buf[40 + UIP_LLH_LEN]; ++ 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. */ + -+ -+ /* Check if we were invoked because of the perodic timer fireing. */ -+ 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]; -+ } ++ if(BUF->flags & TCP_FIN) { ++ if(uip_outstanding(uip_connr)) { ++ goto drop; + } -+ } -+ uip_len = 0; -+ if(uip_connr->tcpstateflags == TIME_WAIT || -+ uip_connr->tcpstateflags == FIN_WAIT_2) { -+ ++(uip_connr->timer); -+ if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) { -+ uip_connr->tcpstateflags = CLOSED; ++ uip_add_rcv_nxt(1 + uip_len); ++ uip_flags = UIP_CLOSE; ++ if(uip_len > 0) { ++ uip_flags |= UIP_NEWDATA; + } -+ } else if(uip_connr->tcpstateflags != 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 == SYN_SENT || -+ uip_connr->tcpstateflags == SYN_RCVD) && -+ uip_connr->nrtx == UIP_MAXSYNRTX)) { -+ uip_connr->tcpstateflags = CLOSED; -+ -+ /* We call UIP_APPCALL() with uip_flags set to -+ UIP_TIMEDOUT to inform the application that the -+ connection has timed out. */ -+ uip_flags = UIP_TIMEDOUT; -+ UIP_APPCALL(); -+ -+ /* We also send a reset packet to the remote host. */ -+ BUF->flags = TCP_RST | TCP_ACK; -+ goto tcp_send_nodata; -+ } ++ UIP_APPCALL(); ++ uip_connr->len = 1; ++ uip_connr->tcpstateflags = LAST_ACK; ++ uip_connr->nrtx = 0; ++ tcp_send_finack: ++ BUF->flags = TCP_FIN | 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 & TS_MASK) { -+ case SYN_RCVD: -+ /* In the SYN_RCVD state, we should retransmit our -+ SYNACK. */ -+ goto tcp_send_synack; -+ -+#if UIP_ACTIVE_OPEN -+ case SYN_SENT: -+ /* In the SYN_SENT state, we retransmit out SYN. */ -+ BUF->flags = 0; -+ goto tcp_send_syn; -+#endif /* UIP_ACTIVE_OPEN */ -+ -+ case 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_len = 0; -+ uip_slen = 0; -+ uip_flags = UIP_REXMIT; -+ UIP_APPCALL(); -+ goto apprexmit; -+ -+ case FIN_WAIT_1: -+ case CLOSING: -+ case LAST_ACK: -+ /* In all these states we should retransmit a FINACK. */ -+ goto tcp_send_finack; -+ -+ } -+ } -+ } else if((uip_connr->tcpstateflags & TS_MASK) == ESTABLISHED) { -+ /* If there was no need for a retransmission, we poll the -+ application for new data. */ -+ uip_len = 0; -+ uip_slen = 0; -+ uip_flags = UIP_POLL; -+ UIP_APPCALL(); -+ goto appsend; ++ /* 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) { ++#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; + } -+ } -+ goto drop; -+ } -+#if UIP_UDP -+ if(flag == UIP_UDP_TIMER) { -+ if(uip_udp_conn->lport != 0) { -+ uip_appdata = &uip_buf[UIP_LLH_LEN + 28]; -+ uip_len = uip_slen = 0; -+ uip_flags = UIP_POLL; -+ UIP_UDP_APPCALL(); -+ goto udp_send; ++ uip_add_rcv_nxt(uip_urglen); ++ uip_len -= uip_urglen; ++ uip_urgdata = uip_appdata; ++ uip_appdata += uip_urglen; + } else { -+ goto drop; ++ uip_urglen = 0; ++#endif /* UIP_URGDATA > 0 */ ++ uip_appdata += (BUF->urgp[0] << 8) | BUF->urgp[1]; ++ uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1]; ++ } ++ ++ ++ /* 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); + } -+ } -+#endif + -+ /* This is where the input processing starts. */ -+ UIP_STAT(++uip_stat.ip.recv); ++ /* 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 = ((unsigned short int)BUF->wnd[0] << 8) + (unsigned short int)BUF->wnd[1]; ++ if(tmp16 > uip_connr->initialmss || ++ tmp16 == 0) { ++ tmp16 = uip_connr->initialmss; ++ } ++ uip_connr->mss = tmp16; + -+ /* Start of IPv4 input header processing code. */ -+ -+ /* 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; -+ } -+ -+ /* Check the size of the packet. If the size reported to us in -+ uip_len doesn't match the size reported in the IP header, there -+ has been a transmission error and we drop the packet. */ -+ -+ if(BUF->len[0] != (uip_len >> 8)) { /* IP length, high byte. */ -+ uip_len = (uip_len & 0xff) | (BUF->len[0] << 8); -+ } -+ if(BUF->len[1] != (uip_len & 0xff)) { /* IP length, low byte. */ -+ uip_len = (uip_len & 0xff00) | BUF->len[1]; -+ } ++ /* 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. + -+ /* 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_STAT(++uip_stat.ip.drop); -+ UIP_STAT(++uip_stat.ip.fragerr); -+ UIP_LOG("ip: fragment dropped."); -+ goto drop; -+#endif /* UIP_REASSEMBLY */ -+ } ++ 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 40 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_APPCALL(); + -+ /* 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 -+ if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) { -+ 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 */ -+ -+ /* Check if the packet is destined for our IP address. */ -+ if(BUF->destipaddr[0] != uip_hostaddr[0]) { -+ UIP_STAT(++uip_stat.ip.drop); -+ UIP_LOG("ip: packet not for us."); -+ goto drop; -+ } -+ if(BUF->destipaddr[1] != uip_hostaddr[1]) { -+ UIP_STAT(++uip_stat.ip.drop); -+ UIP_LOG("ip: packet not for us."); -+ goto drop; -+ } ++ appsend: ++ ++ if(uip_flags & UIP_ABORT) { ++ uip_slen = 0; ++ uip_connr->tcpstateflags = CLOSED; ++ BUF->flags = TCP_RST | TCP_ACK; ++ goto tcp_send_nodata; ++ } + -+ 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; -+ } ++ if(uip_flags & UIP_CLOSE) { ++ uip_slen = 0; ++ uip_connr->len = 1; ++ uip_connr->tcpstateflags = FIN_WAIT_1; ++ uip_connr->nrtx = 0; ++ BUF->flags = TCP_FIN | TCP_ACK; ++ goto tcp_send_nodata; ++ } + -+ if(BUF->proto == UIP_PROTO_TCP) /* Check for TCP packet. If so, jump -+ to the tcp_input label. */ -+ goto tcp_input; ++ /* If uip_slen > 0, the application has data to be sent. */ ++ if(uip_slen > 0) { + -+#if UIP_UDP -+ if(BUF->proto == UIP_PROTO_UDP) -+ goto udp_input; -+#endif /* UIP_UDP */ ++ /* 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(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; -+ } -+ -+ //icmp_input: -+ 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 the ->len variable is non-zero the connection has ++ already data in transit and cannot send anymore right ++ now. */ ++ if(uip_connr->len == 0) { + -+ /* 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. */ -+ 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; ++ /* 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; ++ } + -+ UIP_STAT(++uip_stat.icmp.sent); -+ goto send; ++ /* Remember how much data we send out now so that we know ++ when everything has been acknowledged. */ ++ uip_connr->len = uip_slen; ++ } else { + -+ /* End of IPv4 input header processing code. */ -+ ++ /* 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; ++ } ++ } else { ++ uip_connr->len = 0; ++ } ++ uip_connr->nrtx = 0; ++ apprexmit: ++ uip_appdata = uip_sappdata; + -+#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 -+ if(uip_udpchksum() != 0xffff) { -+ UIP_STAT(++uip_stat.udp.drop); -+ UIP_STAT(++uip_stat.udp.chkerr); -+ UIP_LOG("udp: bad checksum."); ++ /* 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 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 = CLOSED; ++ uip_flags = UIP_CLOSE; ++ UIP_APPCALL(); ++ } ++ break; ++ ++ case 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 = TIME_WAIT; ++ uip_connr->timer = 0; ++ uip_connr->len = 0; ++ } else { ++ uip_connr->tcpstateflags = CLOSING; ++ } ++ uip_add_rcv_nxt(1); ++ uip_flags = UIP_CLOSE; ++ UIP_APPCALL(); ++ goto tcp_send_ack; ++ } else if(uip_flags & UIP_ACKDATA) { ++ uip_connr->tcpstateflags = FIN_WAIT_2; ++ uip_connr->len = 0; ++ goto drop; ++ } ++ if(uip_len > 0) { ++ goto tcp_send_ack; ++ } + goto drop; -+ } -+#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(uip_udp_conn->lport != 0 && -+ UDPBUF->destport == uip_udp_conn->lport && -+ (uip_udp_conn->rport == 0 || -+ UDPBUF->srcport == uip_udp_conn->rport) && -+ BUF->srcipaddr[0] == uip_udp_conn->ripaddr[0] && -+ BUF->srcipaddr[1] == uip_udp_conn->ripaddr[1]) { -+ goto udp_found; ++ ++ case FIN_WAIT_2: ++ if(uip_len > 0) { ++ uip_add_rcv_nxt(uip_len); + } -+ } -+ goto drop; -+ -+ udp_found: -+ uip_len = uip_len - 28; -+ uip_appdata = &uip_buf[UIP_LLH_LEN + 28]; -+ uip_flags = UIP_NEWDATA; -+ uip_slen = 0; -+ UIP_UDP_APPCALL(); -+ udp_send: -+ if(uip_slen == 0) { -+ goto drop; -+ } -+ uip_len = uip_slen + 28; ++ if(BUF->flags & TCP_FIN) { ++ uip_connr->tcpstateflags = TIME_WAIT; ++ uip_connr->timer = 0; ++ uip_add_rcv_nxt(1); ++ uip_flags = UIP_CLOSE; ++ UIP_APPCALL(); ++ goto tcp_send_ack; ++ } ++ if(uip_len > 0) { ++ goto tcp_send_ack; ++ } ++ goto drop; + -+ BUF->len[0] = (uip_len >> 8); -+ BUF->len[1] = (uip_len & 0xff); ++ case TIME_WAIT: ++ goto tcp_send_ack; ++ ++ case CLOSING: ++ if(uip_flags & UIP_ACKDATA) { ++ uip_connr->tcpstateflags = TIME_WAIT; ++ uip_connr->timer = 0; ++ } ++ } ++ goto drop; + -+ BUF->proto = UIP_PROTO_UDP; + -+ UDPBUF->udplen = HTONS(uip_slen + 8); -+ UDPBUF->udpchksum = 0; -+#if UIP_UDP_CHECKSUMS -+ /* Calculate UDP checksum. */ -+ UDPBUF->udpchksum = ~(uip_udpchksum()); -+ if(UDPBUF->udpchksum == 0) { -+ UDPBUF->udpchksum = 0xffff; -+ } -+#endif /* UIP_UDP_CHECKSUMS */ ++ /* 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 = 40; ++ tcp_send_noopts: ++ BUF->tcpoffset = 5 << 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->srcport = uip_udp_conn->lport; -+ BUF->destport = uip_udp_conn->rport; ++ BUF->proto = UIP_PROTO_TCP; ++ ++ BUF->srcport = uip_connr->lport; ++ BUF->destport = uip_connr->rport; + + BUF->srcipaddr[0] = uip_hostaddr[0]; + BUF->srcipaddr[1] = uip_hostaddr[1]; -+ BUF->destipaddr[0] = uip_udp_conn->ripaddr[0]; -+ BUF->destipaddr[1] = uip_udp_conn->ripaddr[1]; ++ BUF->destipaddr[0] = uip_connr->ripaddr[0]; ++ BUF->destipaddr[1] = uip_connr->ripaddr[1]; + -+ uip_appdata = &uip_buf[UIP_LLH_LEN + 40]; -+ 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]; ++uip_connr) { -+ if(uip_connr->tcpstateflags != CLOSED && -+ BUF->destport == uip_connr->lport && -+ BUF->srcport == uip_connr->rport && -+ BUF->srcipaddr[0] == uip_connr->ripaddr[0] && -+ BUF->srcipaddr[1] == uip_connr->ripaddr[1]) { -+ goto found; -+ } ++ 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); + } + -+ /* 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: ++ tcp_send_noconn: + -+ /* We do not send resets in response to resets. */ -+ if(BUF->flags & TCP_RST) -+ goto drop; ++ BUF->len[0] = (uip_len >> 8); ++ BUF->len[1] = (uip_len & 0xff); + -+ UIP_STAT(++uip_stat.tcp.rst); ++ /* Calculate TCP checksum. */ ++ BUF->tcpchksum = 0; ++ BUF->tcpchksum = ~(uip_tcpchksum()); + -+ BUF->flags = TCP_RST | TCP_ACK; -+ uip_len = 40; -+ BUF->tcpoffset = 5 << 4; ++ //ip_send_nolen: + -+ /* 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; ++ BUF->vhl = 0x45; ++ BUF->tos = 0; ++ BUF->ipoffset[0] = BUF->ipoffset[1] = 0; ++ BUF->ttl = UIP_TTL; ++ ++ipid; ++ BUF->ipid[0] = ipid >> 8; ++ BUF->ipid[1] = ipid & 0xff; + -+ c = BUF->seqno[0]; -+ BUF->seqno[0] = BUF->ackno[0]; -+ BUF->ackno[0] = c; ++ /* Calculate IP checksum. */ ++ BUF->ipchksum = 0; ++ BUF->ipchksum = ~(uip_ipchksum()); + -+ /* 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. */ -+ 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; ++ UIP_STAT(++uip_stat.tcp.sent); ++ send: ++ UIP_STAT(++uip_stat.ip.sent); ++ /* Return and let the caller do the actual transmission. */ ++ return; ++ drop: ++ uip_len = 0; ++ return; ++} ++/*-----------------------------------------------------------------------------------*/ ++/*unsigned short int ++htons(unsigned short int val) ++{ ++ return HTONS(val); ++}*/ ++/*-----------------------------------------------------------------------------------*/ ++/** @} */ +--- /dev/null ++++ b/net/uip-0.9/uip.h +@@ -0,0 +1,1066 @@ ++/** ++ * \addtogroup uip ++ * @{ ++ */ + -+ -+ /* And send out the RST packet! */ -+ goto tcp_send_noconn; ++/** ++ * \file ++ * Header file for the uIP TCP/IP stack. ++ * \author Adam Dunkels ++ * ++ * 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. ++ * ++ */ + -+ /* 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 == CLOSED) { -+ uip_connr = &uip_conns[c]; -+ break; -+ } -+ if(uip_conns[c].tcpstateflags == 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_connr->ripaddr[0] = BUF->srcipaddr[0]; -+ uip_connr->ripaddr[1] = BUF->srcipaddr[1]; -+ uip_connr->tcpstateflags = SYN_RCVD; ++/* ++ * 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.36.2.7 2003/10/07 13:47:51 adam Exp $ ++ * ++ */ ++ ++#ifndef __UIP_H__ ++#define __UIP_H__ ++#include ++#include ++#include ++#include ++#include + -+ 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); ++#include "uipopt.h" + -+ /* 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 == 0x00) { -+ /* End of options. */ -+ break; -+ } else if(opt == 0x01) { -+ ++c; -+ /* NOP option. */ -+ } else if(opt == 0x02 && -+ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) { -+ /* An MSS option with the right option length. */ -+ tmp16 = ((unsigned short int)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | -+ (unsigned short int)uip_buf[40 + 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] = 2; -+ BUF->optdata[1] = 4; -+ BUF->optdata[2] = (UIP_TCP_MSS) / 256; -+ BUF->optdata[3] = (UIP_TCP_MSS) & 255; -+ uip_len = 44; -+ BUF->tcpoffset = 6 << 4; -+ goto tcp_send; ++/*-----------------------------------------------------------------------------------*/ ++/* First, the functions that should be called from the ++ * system. Initialization, the periodic timer and incoming packets are ++ * handled by the following three functions. ++ */ + -+ /* This label will be jumped to if we found an active connection. */ -+ found: -+ uip_conn = uip_connr; -+ uip_flags = 0; ++/** ++ * \defgroup uipconffunc uIP configuration functions ++ * @{ ++ * ++ * The uIP configuration functions are used for setting run-time ++ * parameters in uIP such as IP addresses. ++ */ + -+ /* 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 = CLOSED; -+ UIP_LOG("tcp: got reset, aborting connection."); -+ uip_flags = UIP_ABORT; -+ UIP_APPCALL(); -+ 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 - 20; ++/** ++ * 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. ++ * ++ * \param addr A pointer to a 4-byte representation of the IP address. ++ * ++ * \hideinitializer ++ */ ++#define uip_sethostaddr(addr) do { uip_hostaddr[0] = addr[0]; \ ++ uip_hostaddr[1] = addr[1]; } while(0) + -+ /* 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_len > 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; -+ } ++/** ++ * 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. ++ * ++ * \param addr A pointer to a 4-byte array that will be filled in with ++ * the currently configured IP address. ++ * ++ * \hideinitializer ++ */ ++#define uip_gethostaddr(addr) do { addr[0] = uip_hostaddr[0]; \ ++ addr[1] = uip_hostaddr[1]; } while(0) + -+ /* 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; ++/** ++ * \defgroup uipinit uIP initialization functions ++ * @{ ++ * ++ * The uIP initialization functions are used for booting uIP. ++ */ ++ ++/** ++ * uIP initialization function. ++ * ++ * This function should be called at boot up to initilize the uIP ++ * TCP/IP stack. ++ */ ++void uip_init(void); ++ ++/** @} */ ++ ++/** ++ * \defgroup uipdevfunc 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. ++ \code ++ uip_len = devicedriver_poll(); ++ if(uip_len > 0) { ++ uip_input(); ++ if(uip_len > 0) { ++ devicedriver_send(); ++ } ++ } ++ \endcode ++ * ++ * \note If you are writing a uIP device driver that needs ARP ++ * (Address Resolution Protocol), e.g., when running uIP over ++ * Ethernet, you will need to call the uIP ARP code before calling ++ * this function: ++ \code ++ #define BUF ((struct uip_eth_hdr *)&uip_buf[0]) ++ uip_len = ethernet_devicedrver_poll(); ++ if(uip_len > 0) { ++ if(BUF->type == HTONS(UIP_ETHTYPE_IP)) { ++ uip_arp_ipin(); ++ uip_input(); ++ if(uip_len > 0) { ++ uip_arp_out(); ++ ethernet_devicedriver_send(); + } -+ /* Set the acknowledged flag. */ -+ uip_flags = UIP_ACKDATA; -+ /* Reset the retransmission timer. */ -+ uip_connr->timer = uip_connr->rto; -+ } -+ -+ } -+ -+ /* Do different things depending on in what state the connection is. */ -+ switch(uip_connr->tcpstateflags & 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 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 = ESTABLISHED; -+ uip_flags = UIP_CONNECTED; -+ uip_connr->len = 0; ++ } else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) { ++ uip_arp_arpin(); + if(uip_len > 0) { -+ uip_flags |= UIP_NEWDATA; -+ uip_add_rcv_nxt(uip_len); ++ ethernet_devicedriver_send(); + } -+ uip_slen = 0; -+ UIP_APPCALL(); -+ goto appsend; + } -+ goto drop; -+#if UIP_ACTIVE_OPEN -+ case 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_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[40 + UIP_LLH_LEN + c]; -+ if(opt == 0x00) { -+ /* End of options. */ -+ break; -+ } else if(opt == 0x01) { -+ ++c; -+ /* NOP option. */ -+ } else if(opt == 0x02 && -+ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) { -+ /* 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; ++ \endcode ++ * ++ * \hideinitializer ++ */ ++#define uip_input() uip_process(UIP_DATA) + -+ /* 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 = 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_APPCALL(); -+ goto appsend; ++/** ++ * 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: ++ \code ++ for(i = 0; i < UIP_CONNS; ++i) { ++ uip_periodic(i); ++ if(uip_len > 0) { ++ devicedriver_send(); + } -+ goto reset; -+#endif /* UIP_ACTIVE_OPEN */ -+ -+ case 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. ++ } ++ \endcode ++ * ++ * \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: ++ \code ++ for(i = 0; i < UIP_CONNS; ++i) { ++ uip_periodic(i); ++ if(uip_len > 0) { ++ uip_arp_out(); ++ ethernet_devicedriver_send(); ++ } ++ } ++ \endcode ++ * ++ * \param conn The number of the connection which is to be periodically polled. ++ * ++ * \hideinitializer ++ */ ++#define uip_periodic(conn) do { uip_conn = &uip_conns[conn]; \ ++ uip_process(UIP_TIMER); } while (0) + -+ If 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. */ ++/** ++ * 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. ++ * ++ * \param conn A pointer to the uip_conn struct for the connection to ++ * be processed. ++ * ++ * \hideinitializer ++ */ ++#define uip_periodic_conn(conn) do { uip_conn = conn; \ ++ uip_process(UIP_TIMER); } while (0) + -+ if(BUF->flags & TCP_FIN) { -+ 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_APPCALL(); -+ uip_connr->len = 1; -+ uip_connr->tcpstateflags = LAST_ACK; -+ uip_connr->nrtx = 0; -+ tcp_send_finack: -+ BUF->flags = TCP_FIN | TCP_ACK; -+ goto tcp_send_nodata; ++#if UIP_UDP ++/** ++ * Periodic processing for a UDP connection identified by its number. ++ * ++ * This function is essentially the same as uip_prerioic(), but for ++ * UDP connections. It is called in a similar fashion as the ++ * uip_periodic() function: ++ \code ++ for(i = 0; i < UIP_UDP_CONNS; i++) { ++ uip_udp_periodic(i); ++ if(uip_len > 0) { ++ devicedriver_send(); ++ } ++ } ++ \endcode ++ * ++ * \note As for the uip_periodic() function, special care has to be ++ * taken when using uIP together with ARP and Ethernet: ++ \code ++ for(i = 0; i < UIP_UDP_CONNS; i++) { ++ uip_udp_periodic(i); ++ if(uip_len > 0) { ++ uip_arp_out(); ++ ethernet_devicedriver_send(); + } ++ } ++ \endcode ++ * ++ * \param conn The number of the UDP connection to be processed. ++ * ++ * \hideinitializer ++ */ ++#define uip_udp_periodic(conn) do { uip_udp_conn = &uip_udp_conns[conn]; \ ++ uip_process(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. ++ * ++ * \param conn A pointer to the uip_udp_conn struct for the connection ++ * to be processed. ++ * ++ * \hideinitializer ++ */ ++#define uip_udp_periodic_conn(conn) do { uip_udp_conn = conn; \ ++ uip_process(UIP_UDP_TIMER); } while (0) ++ ++ ++#endif /* UIP_UDP */ ++ ++/** ++ * 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: ++ \code ++ void ++ devicedriver_send(void) ++ { ++ hwsend(&uip_buf[0], UIP_LLH_LEN); ++ hwsend(&uip_buf[UIP_LLH_LEN], 40); ++ hwsend(uip_appdata, uip_len - 40 - UIP_LLH_LEN); ++ } ++ \endcode ++ */ ++extern u8_t uip_buf[UIP_BUFSIZE+2]; ++ ++/** @} */ + -+ /* 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) { -+#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; -+#endif /* UIP_URGDATA > 0 */ -+ uip_appdata += (BUF->urgp[0] << 8) | BUF->urgp[1]; -+ uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1]; -+ } -+ -+ -+ /* 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); -+ } ++/*-----------------------------------------------------------------------------------*/ ++/* Functions that are used by the uIP application program. Opening and ++ * closing connections, sending and receiving data, etc. is all ++ * handled by the functions below. ++*/ ++/** ++ * \defgroup uipappfunc uIP application functions ++ * @{ ++ * ++ * Functions used by an application running of top of uIP. ++ */ + -+ /* 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. ++/** ++ * 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. ++ * ++ \code ++ uip_listen(HTONS(80)); ++ \endcode ++ * ++ * \param port A 16-bit port number in network byte order. ++ */ ++void uip_listen(u16_t port); + -+ 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 = ((unsigned short int)BUF->wnd[0] << 8) + (unsigned short int)BUF->wnd[1]; -+ if(tmp16 > uip_connr->initialmss || -+ tmp16 == 0) { -+ tmp16 = uip_connr->initialmss; -+ } -+ uip_connr->mss = tmp16; ++/** ++ * 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. ++ * ++ \code ++ uip_unlisten(HTONS(80)); ++ \endcode ++ * ++ * \param port A 16-bit port number in network byte order. ++ */ ++void uip_unlisten(u16_t port); + -+ /* 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. ++/** ++ * 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 convertion using HTONS() or htons() is necessary. ++ * ++ \code ++ u16_t ipaddr[2]; + -+ 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 40 bytes into the uip_buf -+ array. ++ uip_ipaddr(ipaddr, 192,168,1,2); ++ uip_connect(ipaddr, HTONS(80)); ++ \endcode ++ * ++ * \param ripaddr A pointer to a 4-byte array representing the IP ++ * address of the remote hot. ++ * ++ * \param 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(u16_t *ripaddr, u16_t port); + -+ 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_APPCALL(); + -+ appsend: -+ -+ if(uip_flags & UIP_ABORT) { -+ uip_slen = 0; -+ uip_connr->tcpstateflags = 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 = FIN_WAIT_1; -+ uip_connr->nrtx = 0; -+ BUF->flags = TCP_FIN | TCP_ACK; -+ goto tcp_send_nodata; -+ } ++/** ++ * \internal ++ * ++ * Check if a connection has outstanding (i.e., unacknowledged) data. ++ * ++ * \param conn A pointer to the uip_conn structure for the connection. ++ * ++ * \hideinitializer ++ */ ++#define uip_outstanding(conn) ((conn)->len) + -+ /* If uip_slen > 0, the application has data to be sent. */ -+ if(uip_slen > 0) { ++/** ++ * 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. ++ * ++ * \param data A pointer to the data which is to be sent. ++ * ++ * \param len The maximum amount of data bytes to be sent. ++ * ++ * \hideinitializer ++ */ ++#define uip_send(data, len) do { uip_sappdata = (data); uip_slen = (len);} while(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; -+ } ++/** ++ * 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. ++ * ++ * \hideinitializer ++ */ ++#define uip_datalen() uip_len + -+ /* 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 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. ++ * ++ * \hideinitializer ++ */ ++#define uip_urgdatalen() uip_urglen + -+ /* 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; -+ } ++/** ++ * Close the current connection. ++ * ++ * This function will close the current connection in a nice way. ++ * ++ * \hideinitializer ++ */ ++#define uip_close() (uip_flags = UIP_CLOSE) + -+ /* Remember how much data we send out now so that we know -+ when everything has been acknowledged. */ -+ uip_connr->len = uip_slen; -+ } else { ++/** ++ * 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. ++ * ++ * \hideinitializer ++ */ ++#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. ++ * ++ * \hideinitializer ++ */ ++#define uip_stop() (uip_conn->tcpstateflags |= UIP_STOPPED) + -+ /* 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; -+ } -+ } else { -+ uip_connr->len = 0; -+ } -+ uip_connr->nrtx = 0; -+ apprexmit: -+ uip_appdata = uip_sappdata; ++/** ++ * Find out if the current connection has been previously stopped with ++ * uip_stop(). ++ * ++ * \hideinitializer ++ */ ++#define uip_stopped(conn) ((conn)->tcpstateflags & UIP_STOPPED) + -+ /* 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 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 = CLOSED; -+ uip_flags = UIP_CLOSE; -+ UIP_APPCALL(); -+ } -+ break; -+ -+ case 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 = TIME_WAIT; -+ uip_connr->timer = 0; -+ uip_connr->len = 0; -+ } else { -+ uip_connr->tcpstateflags = CLOSING; -+ } -+ uip_add_rcv_nxt(1); -+ uip_flags = UIP_CLOSE; -+ UIP_APPCALL(); -+ goto tcp_send_ack; -+ } else if(uip_flags & UIP_ACKDATA) { -+ uip_connr->tcpstateflags = FIN_WAIT_2; -+ uip_connr->len = 0; -+ goto drop; -+ } -+ if(uip_len > 0) { -+ goto tcp_send_ack; -+ } -+ goto drop; -+ -+ case FIN_WAIT_2: -+ if(uip_len > 0) { -+ uip_add_rcv_nxt(uip_len); -+ } -+ if(BUF->flags & TCP_FIN) { -+ uip_connr->tcpstateflags = TIME_WAIT; -+ uip_connr->timer = 0; -+ uip_add_rcv_nxt(1); -+ uip_flags = UIP_CLOSE; -+ UIP_APPCALL(); -+ goto tcp_send_ack; -+ } -+ if(uip_len > 0) { -+ goto tcp_send_ack; -+ } -+ goto drop; ++/** ++ * 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. ++ * ++ * \hideinitializer ++ */ ++#define uip_restart() do { uip_flags |= UIP_NEWDATA; \ ++ uip_conn->tcpstateflags &= ~UIP_STOPPED; \ ++ } while(0) + -+ case TIME_WAIT: -+ goto tcp_send_ack; -+ -+ case CLOSING: -+ if(uip_flags & UIP_ACKDATA) { -+ uip_connr->tcpstateflags = 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 = 40; -+ tcp_send_noopts: -+ BUF->tcpoffset = 5 << 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]; ++/* uIP tests that can be made to determine in what state the current ++ connection is, and what the application function should do. */ + -+ BUF->proto = UIP_PROTO_TCP; -+ -+ BUF->srcport = uip_connr->lport; -+ BUF->destport = uip_connr->rport; ++/** ++ * 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. ++ * ++ * \hideinitializer ++ */ ++#define uip_newdata() (uip_flags & UIP_NEWDATA) + -+ BUF->srcipaddr[0] = uip_hostaddr[0]; -+ BUF->srcipaddr[1] = uip_hostaddr[1]; -+ BUF->destipaddr[0] = uip_connr->ripaddr[0]; -+ BUF->destipaddr[1] = uip_connr->ripaddr[1]; -+ ++/** ++ * 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. ++ * ++ * \hideinitializer ++ */ ++#define uip_acked() (uip_flags & UIP_ACKDATA) + -+ 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); -+ } ++/** ++ * 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()). ++ * ++ * \hideinitializer ++ */ ++#define uip_connected() (uip_flags & UIP_CONNECTED) + -+ tcp_send_noconn: ++/** ++ * 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. ++ * ++ * \hideinitializer ++ */ ++#define uip_closed() (uip_flags & UIP_CLOSE) + -+ BUF->len[0] = (uip_len >> 8); -+ BUF->len[1] = (uip_len & 0xff); ++/** ++ * Has the connection been aborted by the other end? ++ * ++ * Non-zero if the current connection has been aborted (reset) by the ++ * remote host. ++ * ++ * \hideinitializer ++ */ ++#define uip_aborted() (uip_flags & UIP_ABORT) + -+ /* Calculate TCP checksum. */ -+ BUF->tcpchksum = 0; -+ BUF->tcpchksum = ~(uip_tcpchksum()); -+ -+ //ip_send_nolen: ++/** ++ * Has the connection timed out? ++ * ++ * Non-zero if the current connection has been aborted due to too many ++ * retransmissions. ++ * ++ * \hideinitializer ++ */ ++#define uip_timedout() (uip_flags & UIP_TIMEDOUT) + -+ BUF->vhl = 0x45; -+ BUF->tos = 0; -+ BUF->ipoffset[0] = BUF->ipoffset[1] = 0; -+ BUF->ttl = UIP_TTL; -+ ++ipid; -+ BUF->ipid[0] = ipid >> 8; -+ BUF->ipid[1] = ipid & 0xff; -+ -+ /* Calculate IP checksum. */ -+ BUF->ipchksum = 0; -+ BUF->ipchksum = ~(uip_ipchksum()); ++/** ++ * 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. ++ * ++ * \hideinitializer ++ */ ++#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. ++ * ++ * \hideinitializer ++ */ ++#define uip_poll() (uip_flags & UIP_POLL) + -+ UIP_STAT(++uip_stat.tcp.sent); -+ send: -+ UIP_STAT(++uip_stat.ip.sent); -+ /* Return and let the caller do the actual transmission. */ -+ return; -+ drop: -+ uip_len = 0; -+ return; -+} -+/*-----------------------------------------------------------------------------------*/ -+/*unsigned short int -+htons(unsigned short int val) -+{ -+ return HTONS(val); -+}*/ -+/*-----------------------------------------------------------------------------------*/ -+/** @} */ ---- /dev/null -+++ b/net/uip-0.9/uip.h -@@ -0,0 +1,1066 @@ +/** -+ * \addtogroup uip -+ * @{ ++ * Get the initial maxium segment size (MSS) of the current ++ * connection. ++ * ++ * \hideinitializer + */ ++#define uip_initialmss() (uip_conn->initialmss) + +/** -+ * \file -+ * Header file for the uIP TCP/IP stack. -+ * \author Adam Dunkels ++ * Get the current maxium segment size that can be sent on the current ++ * connection. + * -+ * 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. ++ * 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()). + * ++ * \hideinitializer + */ ++#define uip_mss() (uip_conn->mss) + -+ -+/* -+ * Copyright (c) 2001-2003, Adam Dunkels. -+ * All rights reserved. ++/** ++ * Set up a new UDP connection. + * -+ * 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. ++ * \param ripaddr A pointer to a 4-byte structure representing the IP ++ * address of the remote host. + * -+ * 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. ++ * \param rport The remote port number in network byte order. + * -+ * This file is part of the uIP TCP/IP stack. ++ * \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(u16_t *ripaddr, u16_t rport); ++ ++/** ++ * Removed a UDP connection. + * -+ * $Id: uip.h,v 1.36.2.7 2003/10/07 13:47:51 adam Exp $ ++ * \param conn A pointer to the uip_udp_conn structure for the connection. + * ++ * \hideinitializer + */ ++#define uip_udp_remove(conn) (conn)->lport = 0 + -+#ifndef __UIP_H__ -+#define __UIP_H__ -+#include -+#include -+#include -+#include -+#include -+ ++/** ++ * 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. ++ * ++ * \param len The length of the data in the uip_buf buffer. ++ * ++ * \hideinitializer ++ */ ++#define uip_udp_send(len) uip_slen = (len) + -+#include "uipopt.h" ++/** @} */ + -+/*-----------------------------------------------------------------------------------*/ -+/* First, the functions that should be called from the -+ * system. Initialization, the periodic timer and incoming packets are -+ * handled by the following three functions. -+ */ ++/* uIP convenience and converting functions. */ + +/** -+ * \defgroup uipconffunc uIP configuration functions ++ * \defgroup uipconvfunc uIP conversion functions + * @{ + * -+ * The uIP configuration functions are used for setting run-time -+ * parameters in uIP such as IP addresses. ++ * These functions can be used for converting between different data ++ * formats used by uIP. + */ -+ ++ +/** -+ * Set the IP address of this host. ++ * Pack an IP address into a 4-byte array which is used by uIP to ++ * represent IP addresses. + * -+ * 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: ++ \code ++ u16_t ipaddr[2]; ++ ++ uip_ipaddr(&ipaddr, 192,168,1,2); ++ \endcode + * -+ * \param addr A pointer to a 4-byte representation of the IP address. ++ * \param addr A pointer to a 4-byte array that will be filled in with ++ * the IP addres. ++ * \param addr0 The first octet of the IP address. ++ * \param addr1 The second octet of the IP address. ++ * \param addr2 The third octet of the IP address. ++ * \param addr3 The forth octet of the IP address. + * + * \hideinitializer + */ -+#define uip_sethostaddr(addr) do { uip_hostaddr[0] = addr[0]; \ -+ uip_hostaddr[1] = addr[1]; } while(0) ++#define uip_ipaddr(addr, addr0,addr1,addr2,addr3) do { \ ++ (addr)[0] = HTONS(((addr0) << 8) | (addr1)); \ ++ (addr)[1] = HTONS(((addr2) << 8) | (addr3)); \ ++ } while(0) + +/** -+ * 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. ++ * Convert 16-bit quantity from host byte order to network byte order. + * -+ * \param addr A pointer to a 4-byte array that will be filled in with -+ * the currently configured IP address. ++ * 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. + * + * \hideinitializer + */ -+#define uip_gethostaddr(addr) do { addr[0] = uip_hostaddr[0]; \ -+ addr[1] = uip_hostaddr[1]; } while(0) ++#ifndef HTONS ++# if BYTE_ORDER == BIG_ENDIAN ++# define HTONS(n) (n) ++# else /* BYTE_ORDER == BIG_ENDIAN */ ++# define HTONS(n) ((((u16_t)((n) & 0xff)) << 8) | (((n) & 0xff00) >> 8)) ++# endif /* BYTE_ORDER == BIG_ENDIAN */ ++#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 ++u16_t htons(u16_t val); ++#endif /* htons */ ++ ++/** @} */ ++ ++/** ++ * 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 volatile u8_t *uip_appdata; ++extern volatile u8_t *uip_sappdata; ++ ++#if UIP_URGDATA > 0 ++/* u8_t *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 volatile u8_t *uip_urgdata; ++#endif /* UIP_URGDATA > 0 */ ++ ++ ++/* u[8|16]_t uip_len: ++ * ++ * When the application is called, uip_len contains the length of any ++ * new data that has been received from the remote host. The ++ * application should set this variable to the size of any data that ++ * the application wishes to send. When the network device driver ++ * output function is called, uip_len should contain the length of the ++ * outgoing packet. ++ */ ++extern volatile u16_t uip_len, uip_slen; ++ ++#if UIP_URGDATA > 0 ++extern volatile u8_t uip_urglen, uip_surglen; ++#endif /* UIP_URGDATA > 0 */ ++ ++ ++/** ++ * 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 appstate field whos purpose ++ * is to let the application store application-specific state (e.g., ++ * file pointers) for the connection. The size of this field is ++ * configured in the "uipopt.h" header file. ++ */ ++struct uip_conn { ++ u16_t ripaddr[2]; /**< The IP address of the remote host. */ ++ ++ u16_t lport; /**< The local TCP port, in network byte order. */ ++ u16_t rport; /**< The local remote TCP port, in network byte ++ order. */ ++ ++ u8_t rcv_nxt[4]; /**< The sequence number that we expect to ++ receive next. */ ++ u8_t snd_nxt[4]; /**< The sequence number that was last sent by ++ us. */ ++ u16_t len; /**< Length of the data that was previously sent. */ ++ u16_t mss; /**< Current maximum segment size for the ++ connection. */ ++ u16_t initialmss; /**< Initial maximum segment size for the ++ connection. */ ++ u8_t sa; /**< Retransmission time-out calculation state ++ variable. */ ++ u8_t sv; /**< Retransmission time-out calculation state ++ variable. */ ++ u8_t rto; /**< Retransmission time-out. */ ++ u8_t tcpstateflags; /**< TCP state and flags. */ ++ u8_t timer; /**< The retransmission timer. */ ++ u8_t nrtx; /**< The number of retransmissions for the last ++ segment sent. */ ++ ++ /** The application state. */ ++ u8_t appstate[UIP_APPSTATE_SIZE]; ++}; + -+/** @} */ + ++/* Pointer to the current connection. */ ++extern struct uip_conn *uip_conn; ++/* The array containing all uIP connections. */ ++extern struct uip_conn uip_conns[UIP_CONNS]; +/** -+ * \defgroup uipinit uIP initialization functions ++ * \addtogroup uiparch + * @{ -+ * -+ * The uIP initialization functions are used for booting uIP. + */ + +/** -+ * uIP initialization function. -+ * -+ * This function should be called at boot up to initilize the uIP -+ * TCP/IP stack. ++ * 4-byte array used for the 32-bit sequence number calculations. + */ -+void uip_init(void); ++extern volatile u8_t uip_acc32[4]; + +/** @} */ + -+/** -+ * \defgroup uipdevfunc uIP device driver functions -+ * @{ -+ * -+ * These functions are used by a network device driver for interacting -+ * with uIP. -+ */ + ++#if UIP_UDP +/** -+ * 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. -+ \code -+ uip_len = devicedriver_poll(); -+ if(uip_len > 0) { -+ uip_input(); -+ if(uip_len > 0) { -+ devicedriver_send(); -+ } -+ } -+ \endcode -+ * -+ * \note If you are writing a uIP device driver that needs ARP -+ * (Address Resolution Protocol), e.g., when running uIP over -+ * Ethernet, you will need to call the uIP ARP code before calling -+ * this function: -+ \code -+ #define BUF ((struct uip_eth_hdr *)&uip_buf[0]) -+ uip_len = ethernet_devicedrver_poll(); -+ if(uip_len > 0) { -+ if(BUF->type == HTONS(UIP_ETHTYPE_IP)) { -+ uip_arp_ipin(); -+ uip_input(); -+ if(uip_len > 0) { -+ uip_arp_out(); -+ ethernet_devicedriver_send(); -+ } -+ } else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) { -+ uip_arp_arpin(); -+ if(uip_len > 0) { -+ ethernet_devicedriver_send(); -+ } -+ } -+ \endcode -+ * -+ * \hideinitializer ++ * Representation of a uIP UDP connection. + */ -+#define uip_input() uip_process(UIP_DATA) ++struct uip_udp_conn { ++ u16_t ripaddr[2]; /**< The IP address of the remote peer. */ ++ u16_t lport; /**< The local port number in network byte order. */ ++ u16_t rport; /**< The remote port number in network byte order. */ ++}; ++ ++extern struct uip_udp_conn *uip_udp_conn; ++extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; ++#endif /* UIP_UDP */ + +/** -+ * 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: -+ \code -+ for(i = 0; i < UIP_CONNS; ++i) { -+ uip_periodic(i); -+ if(uip_len > 0) { -+ devicedriver_send(); -+ } -+ } -+ \endcode -+ * -+ * \note If you are writing a uIP device driver that needs ARP -+ * (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: -+ \code -+ for(i = 0; i < UIP_CONNS; ++i) { -+ uip_periodic(i); -+ if(uip_len > 0) { -+ uip_arp_out(); -+ ethernet_devicedriver_send(); -+ } -+ } -+ \endcode -+ * -+ * \param conn The number of the connection which is to be periodically polled. ++ * The structure holding the TCP/IP statistics that are gathered if ++ * UIP_STATISTICS is set to 1. + * -+ * \hideinitializer + */ -+#define uip_periodic(conn) do { uip_conn = &uip_conns[conn]; \ -+ uip_process(UIP_TIMER); } while (0) ++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. */ ++}; + +/** -+ * 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. -+ * -+ * \param conn A pointer to the uip_conn struct for the connection to -+ * be processed. ++ * The uIP TCP/IP statistics. + * -+ * \hideinitializer ++ * This is the variable in which the uIP TCP/IP statistics are gathered. + */ -+#define uip_periodic_conn(conn) do { uip_conn = conn; \ -+ uip_process(UIP_TIMER); } while (0) ++extern struct uip_stats uip_stat; + -+#if UIP_UDP -+/** -+ * Periodic processing for a UDP connection identified by its number. -+ * -+ * This function is essentially the same as uip_prerioic(), but for -+ * UDP connections. It is called in a similar fashion as the -+ * uip_periodic() function: -+ \code -+ for(i = 0; i < UIP_UDP_CONNS; i++) { -+ uip_udp_periodic(i); -+ if(uip_len > 0) { -+ devicedriver_send(); -+ } -+ } -+ \endcode -+ * -+ * \note As for the uip_periodic() function, special care has to be -+ * taken when using uIP together with ARP and Ethernet: -+ \code -+ for(i = 0; i < UIP_UDP_CONNS; i++) { -+ uip_udp_periodic(i); -+ if(uip_len > 0) { -+ uip_arp_out(); -+ ethernet_devicedriver_send(); -+ } -+ } -+ \endcode -+ * -+ * \param conn The number of the UDP connection to be processed. ++ ++/*-----------------------------------------------------------------------------------*/ ++/* All the stuff below this point is internal to uIP and should not be ++ * used directly by an application or by a device driver. ++ */ ++/*-----------------------------------------------------------------------------------*/ ++/* u8_t uip_flags: + * -+ * \hideinitializer ++ * When the application is called, uip_flags will contain the flags ++ * that are defined in this file. Please read below for more ++ * infomation. + */ -+#define uip_udp_periodic(conn) do { uip_udp_conn = &uip_udp_conns[conn]; \ -+ uip_process(UIP_UDP_TIMER); } while (0) ++extern volatile u8_t uip_flags; ++ ++/* The following flags may be set in the global variable uip_flags ++ before calling the application callback. The UIP_ACKDATA and ++ UIP_NEWDATA 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 through the uIP functions/macros. */ ++ ++#define UIP_ACKDATA 1 /* Signifies that the outstanding data was ++ acked and the application should send ++ out new data instead of retransmitting ++ the last data. */ ++#define UIP_NEWDATA 2 /* Flags the fact that the peer has sent ++ us new data. */ ++#define UIP_REXMIT 4 /* Tells the application to retransmit the ++ data that was last sent. */ ++#define UIP_POLL 8 /* Used for polling the application, to ++ check if the application has data that ++ it wants to send. */ ++#define UIP_CLOSE 16 /* 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 32 /* 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 64 /* 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. */ + -+/** -+ * 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. -+ * -+ * \param conn A pointer to the uip_udp_conn struct for the connection -+ * to be processed. ++#define UIP_TIMEDOUT 128 /* The connection has been aborted due to ++ too many retransmissions. */ ++ ++ ++/* uip_process(flag): + * -+ * \hideinitializer ++ * The actual uIP function which does all the work. + */ -+#define uip_udp_periodic_conn(conn) do { uip_udp_conn = conn; \ -+ uip_process(UIP_UDP_TIMER); } while (0) ++void uip_process(u8_t flag); + ++/* The following flags are passed as an argument to the uip_process() ++ function. They are used to distinguish between the two cases where ++ uip_process() is called. It can be called either because we have ++ incoming data that should be processed, or because the periodic ++ timer has fired. */ + ++#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. */ ++#if UIP_UDP ++#define UIP_UDP_TIMER 3 +#endif /* UIP_UDP */ + -+/** -+ * 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: -+ \code -+ void -+ devicedriver_send(void) -+ { -+ hwsend(&uip_buf[0], UIP_LLH_LEN); -+ hwsend(&uip_buf[UIP_LLH_LEN], 40); -+ hwsend(uip_appdata, uip_len - 40 - UIP_LLH_LEN); -+ } -+ \endcode -+ */ -+extern u8_t uip_buf[UIP_BUFSIZE+2]; ++/* The TCP states used in the uip_conn->tcpstateflags. */ ++#define CLOSED 0 ++#define SYN_RCVD 1 ++#define SYN_SENT 2 ++#define ESTABLISHED 3 ++#define FIN_WAIT_1 4 ++#define FIN_WAIT_2 5 ++#define CLOSING 6 ++#define TIME_WAIT 7 ++#define LAST_ACK 8 ++#define TS_MASK 15 ++ ++#define UIP_STOPPED 16 + -+/** @} */ ++#define UIP_TCPIP_HLEN 40 + -+/*-----------------------------------------------------------------------------------*/ -+/* Functions that are used by the uIP application program. Opening and -+ * closing connections, sending and receiving data, etc. is all -+ * handled by the functions below. -+*/ -+/** -+ * \defgroup uipappfunc uIP application functions -+ * @{ -+ * -+ * Functions used by an application running of top of uIP. -+ */ ++/* The TCP and IP headers. */ ++typedef struct { ++ /* IP header. */ ++ u8_t vhl, ++ tos, ++ len[2], ++ ipid[2], ++ ipoffset[2], ++ ttl, ++ proto; ++ u16_t ipchksum; ++ u16_t srcipaddr[2], ++ destipaddr[2]; ++ ++ /* TCP header. */ ++ u16_t srcport, ++ destport; ++ u8_t seqno[4], ++ ackno[4], ++ tcpoffset, ++ flags, ++ wnd[2]; ++ u16_t tcpchksum; ++ u8_t urgp[2]; ++ u8_t optdata[4]; ++} uip_tcpip_hdr; + -+/** -+ * 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. ++/* The ICMP and IP headers. */ ++typedef struct { ++ /* IP header. */ ++ u8_t vhl, ++ tos, ++ len[2], ++ ipid[2], ++ ipoffset[2], ++ ttl, ++ proto; ++ u16_t ipchksum; ++ u16_t srcipaddr[2], ++ destipaddr[2]; ++ /* ICMP (echo) header. */ ++ u8_t type, icode; ++ u16_t icmpchksum; ++ u16_t id, seqno; ++} uip_icmpip_hdr; ++ ++ ++/* The UDP and IP headers. */ ++typedef struct { ++ /* IP header. */ ++ u8_t vhl, ++ tos, ++ len[2], ++ ipid[2], ++ ipoffset[2], ++ ttl, ++ proto; ++ u16_t ipchksum; ++ u16_t srcipaddr[2], ++ destipaddr[2]; ++ ++ /* UDP header. */ ++ u16_t srcport, ++ destport; ++ u16_t udplen; ++ u16_t udpchksum; ++} uip_udpip_hdr; ++ ++#define UIP_PROTO_ICMP 1 ++#define UIP_PROTO_TCP 6 ++#define UIP_PROTO_UDP 17 ++ ++#if UIP_FIXEDADDR ++extern const u16_t uip_hostaddr[2]; ++#else /* UIP_FIXEDADDR */ ++extern u16_t uip_hostaddr[2]; ++#endif /* UIP_FIXEDADDR */ ++ ++#endif /* __UIP_H__ */ ++ ++ ++/** @} */ ++ +--- /dev/null ++++ b/net/uip-0.9/uip_arch.c +@@ -0,0 +1,145 @@ ++/* ++ * Copyright (c) 2001, Adam Dunkels. ++ * All rights reserved. + * -+ \code -+ uip_listen(HTONS(80)); -+ \endcode ++ * 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. + * -+ * \param port A 16-bit port number in network byte order. -+ */ -+void uip_listen(u16_t port); -+ -+/** -+ * Stop listening to the specified port. ++ * 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. + * -+ * \note Since this function expects the port number in network byte -+ * order, a conversion using HTONS() or htons() is necessary. ++ * This file is part of the uIP TCP/IP stack. + * -+ \code -+ uip_unlisten(HTONS(80)); -+ \endcode ++ * $Id: uip_arch.c,v 1.2.2.1 2003/10/04 22:54:17 adam Exp $ + * -+ * \param port A 16-bit port number in network byte order. + */ -+void uip_unlisten(u16_t port); + -+/** -+ * Connect to a remote host using TCP. -+ * -+ * This function is used to start a new connection to the specified -+ * port on the specied host. It allocates a new connection identifier, -+ * 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 convertion using HTONS() or htons() is necessary. -+ * -+ \code -+ u16_t ipaddr[2]; + -+ uip_ipaddr(ipaddr, 192,168,1,2); -+ uip_connect(ipaddr, HTONS(80)); -+ \endcode -+ * -+ * \param ripaddr A pointer to a 4-byte array representing the IP -+ * address of the remote hot. -+ * -+ * \param 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(u16_t *ripaddr, u16_t port); ++#include "uip.h" ++#include "uip_arch.h" ++ ++#define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) ++#define IP_PROTO_TCP 6 ++ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_add32(u8_t *op32, u16_t 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]; ++ } ++ } ++ } ++} ++/*-----------------------------------------------------------------------------------*/ ++u16_t ++uip_chksum(u16_t *sdata, u16_t len) ++{ ++ u16_t acc; ++ ++ for(acc = 0; len > 1; len -= 2) { ++ acc += *sdata; ++ if(acc < *sdata) { ++ /* Overflow, so we add the carry to acc (i.e., increase by ++ one). */ ++ ++acc; ++ } ++ ++sdata; ++ } ++ ++ /* add up any odd byte */ ++ if(len == 1) { ++ acc += htons(((u16_t)(*(u8_t *)sdata)) << 8); ++ if(acc < htons(((u16_t)(*(u8_t *)sdata)) << 8)) { ++ ++acc; ++ } ++ } ++ ++ return acc; ++} ++/*-----------------------------------------------------------------------------------*/ ++u16_t ++uip_ipchksum(void) ++{ ++ return uip_chksum((u16_t *)&uip_buf[UIP_LLH_LEN], 20); ++} ++/*-----------------------------------------------------------------------------------*/ ++u16_t ++uip_tcpchksum(void) ++{ ++ u16_t hsum, sum; + ++ ++ /* Compute the checksum of the TCP header. */ ++ hsum = uip_chksum((u16_t *)&uip_buf[20 + UIP_LLH_LEN], 20); + ++ /* Compute the checksum of the data in the TCP packet and add it to ++ the TCP header checksum. */ ++ sum = uip_chksum((u16_t *)uip_appdata, ++ (u16_t)(((((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - 40))); + -+/** -+ * \internal -+ * -+ * Check if a connection has outstanding (i.e., unacknowledged) data. -+ * -+ * \param conn A pointer to the uip_conn structure for the connection. -+ * -+ * \hideinitializer -+ */ -+#define uip_outstanding(conn) ((conn)->len) ++ if((sum += hsum) < hsum) { ++ ++sum; ++ } ++ ++ if((sum += BUF->srcipaddr[0]) < BUF->srcipaddr[0]) { ++ ++sum; ++ } ++ if((sum += BUF->srcipaddr[1]) < BUF->srcipaddr[1]) { ++ ++sum; ++ } ++ if((sum += BUF->destipaddr[0]) < BUF->destipaddr[0]) { ++ ++sum; ++ } ++ if((sum += BUF->destipaddr[1]) < BUF->destipaddr[1]) { ++ ++sum; ++ } ++ if((sum += (u16_t)htons((u16_t)IP_PROTO_TCP)) < (u16_t)htons((u16_t)IP_PROTO_TCP)) { ++ ++sum; ++ } + ++ hsum = (u16_t)htons((((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - 20); ++ ++ if((sum += hsum) < hsum) { ++ ++sum; ++ } ++ ++ return sum; ++} ++/*-----------------------------------------------------------------------------------*/ +--- /dev/null ++++ b/net/uip-0.9/uip_arch.h +@@ -0,0 +1,130 @@ +/** -+ * 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. ++ * \defgroup uiparch Architecture specific uIP functions ++ * @{ + * -+ * 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. -+ * -+ * \param data A pointer to the data which is to be sent. ++ * The functions in the architecture specific module implement the IP ++ * check sum and 32-bit additions. + * -+ * \param len The maximum amount of data bytes to be sent. ++ * The IP checksum calculation is the most computationally expensive ++ * operation in the TCP/IP stack and it therefore pays off to ++ * implement this in efficient assembler. The purpose of the uip-arch ++ * module is to let the checksum functions to be implemented in ++ * architecture specific assembler. + * -+ * \hideinitializer + */ -+#define uip_send(data, len) do { uip_sappdata = (data); uip_slen = (len);} while(0) + +/** -+ * 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. -+ * -+ * \hideinitializer ++ * \file ++ * Declarations of architecture specific functions. ++ * \author Adam Dunkels + */ -+#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. ++/* ++ * Copyright (c) 2001, Adam Dunkels. ++ * All rights reserved. + * -+ * \hideinitializer -+ */ -+#define uip_urgdatalen() uip_urglen -+ -+/** -+ * Close the current connection. ++ * 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 function will close the current connection in a nice way. ++ * 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. + * -+ * \hideinitializer -+ */ -+#define uip_close() (uip_flags = UIP_CLOSE) -+ -+/** -+ * Abort the current connection. ++ * This file is part of the uIP TCP/IP stack. + * -+ * This function will abort (reset) the current connection, and is -+ * usually used when an error has occured that prevents using the -+ * uip_close() function. ++ * $Id: uip_arch.h,v 1.1.2.2 2003/10/06 15:10:22 adam Exp $ + * -+ * \hideinitializer + */ -+#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. -+ * -+ * \hideinitializer -+ */ -+#define uip_stop() (uip_conn->tcpstateflags |= UIP_STOPPED) ++#ifndef __UIP_ARCH_H__ ++#define __UIP_ARCH_H__ + -+/** -+ * Find out if the current connection has been previously stopped with -+ * uip_stop(). -+ * -+ * \hideinitializer -+ */ -+#define uip_stopped(conn) ((conn)->tcpstateflags & UIP_STOPPED) ++#include "uip.h" + +/** -+ * Restart the current connection, if is has previously been stopped -+ * with uip_stop(). ++ * Carry out a 32-bit addition. + * -+ * This function will open the receiver's window again so that we -+ * start receiving data for the current connection. ++ * 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. + * -+ * \hideinitializer -+ */ -+#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 new incoming data available? ++ * \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). + * -+ * 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. ++ * \param op32 A pointer to a 4-byte array representing a 32-bit ++ * integer in network byte order (big endian). + * -+ * \hideinitializer ++ * \param op16 A 16-bit integer in host byte order. + */ -+#define uip_newdata() (uip_flags & UIP_NEWDATA) ++void uip_add32(u8_t *op32, u16_t op16); + +/** -+ * Has previously sent data been acknowledged? ++ * Calculate the Internet checksum over a buffer. + * -+ * 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. ++ * The Internet checksum is the one's complement of the one's ++ * complement sum of all 16-bit words in the buffer. + * -+ * \hideinitializer ++ * See RFC1071. ++ * ++ * \note This function is not called in the current version of uIP, ++ * but future versions might make use of it. ++ * ++ * \param buf A pointer to the buffer over which the checksum is to be ++ * computed. ++ * ++ * \param len The length of the buffer over which the checksum is to ++ * be computed. ++ * ++ * \return The Internet checksum of the buffer. + */ -+#define uip_acked() (uip_flags & UIP_ACKDATA) ++u16_t uip_chksum(u16_t *buf, u16_t len); + +/** -+ * Has the connection just been connected? ++ * Calculate the IP header checksum of the packet header in uip_buf. + * -+ * 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()). ++ * The IP header checksum is the Internet checksum of the 20 bytes of ++ * the IP header. + * -+ * \hideinitializer ++ * \return The IP header checksum of the IP header in the uip_buf ++ * buffer. + */ -+#define uip_connected() (uip_flags & UIP_CONNECTED) ++u16_t uip_ipchksum(void); + +/** -+ * Has the connection been closed by the other end? ++ * Calculate the TCP checksum of the packet in uip_buf and uip_appdata. + * -+ * Is non-zero if the connection has been closed by the remote -+ * host. The application may then do the necessary clean-ups. ++ * The TCP checksum is the Internet checksum of data contents of the ++ * TCP segment, and a pseudo-header as defined in RFC793. + * -+ * \hideinitializer ++ * \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. + */ -+#define uip_closed() (uip_flags & UIP_CLOSE) ++u16_t uip_tcpchksum(void); ++ ++/** @} */ + ++#endif /* __UIP_ARCH_H__ */ +--- /dev/null ++++ b/net/uip-0.9/uip_arp.c +@@ -0,0 +1,421 @@ +/** -+ * Has the connection been aborted by the other end? -+ * -+ * Non-zero if the current connection has been aborted (reset) by the -+ * remote host. -+ * -+ * \hideinitializer ++ * \addtogroup uip ++ * @{ + */ -+#define uip_aborted() (uip_flags & UIP_ABORT) + +/** -+ * Has the connection timed out? ++ * \defgroup uiparp uIP Address Resolution Protocol ++ * @{ ++ * ++ * 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. + * -+ * Non-zero if the current connection has been aborted due to too many -+ * retransmissions. ++ * \note This ARP implementation only supports Ethernet. ++ */ ++ ++/** ++ * \file ++ * Implementation of the ARP Address Resolution Protocol. ++ * \author Adam Dunkels + * -+ * \hideinitializer + */ -+#define uip_timedout() (uip_flags & UIP_TIMEDOUT) + -+/** -+ * Do we need to retransmit previously data? ++/* ++ * Copyright (c) 2001-2003, Adam Dunkels. ++ * All rights reserved. + * -+ * 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. ++ * 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_arp.c,v 1.7.2.3 2003/10/06 22:42:30 adam Exp $ + * -+ * \hideinitializer + */ -+#define uip_rexmit() (uip_flags & UIP_REXMIT) + ++ ++#include "uip_arp.h" ++ ++struct arp_hdr { ++ struct uip_eth_hdr ethhdr; ++ u16_t hwtype; ++ u16_t protocol; ++ u8_t hwlen; ++ u8_t protolen; ++ u16_t opcode; ++ struct uip_eth_addr shwaddr; ++ u16_t sipaddr[2]; ++ struct uip_eth_addr dhwaddr; ++ u16_t dipaddr[2]; ++}; ++ ++struct ethip_hdr { ++ struct uip_eth_hdr ethhdr; ++ /* IP header. */ ++ u8_t vhl, ++ tos, ++ len[2], ++ ipid[2], ++ ipoffset[2], ++ ttl, ++ proto; ++ u16_t ipchksum; ++ u16_t srcipaddr[2], ++ destipaddr[2]; ++}; ++ ++#define ARP_REQUEST 1 ++#define ARP_REPLY 2 ++ ++#define ARP_HWTYPE_ETH 1 ++ ++struct arp_entry { ++ u16_t ipaddr[2]; ++ struct uip_eth_addr ethaddr; ++ u8_t time; ++}; ++ ++struct uip_eth_addr uip_ethaddr = {{UIP_ETHADDR0, ++ UIP_ETHADDR1, ++ UIP_ETHADDR2, ++ UIP_ETHADDR3, ++ UIP_ETHADDR4, ++ UIP_ETHADDR5}}; ++ ++static struct arp_entry arp_table[UIP_ARPTAB_SIZE]; ++static u16_t ipaddr[2]; ++static u8_t i, c; ++ ++static u8_t arptime; ++static u8_t tmpage; ++ ++#define BUF ((struct arp_hdr *)&uip_buf[0]) ++#define IPBUF ((struct ethip_hdr *)&uip_buf[0]) ++/*-----------------------------------------------------------------------------------*/ +/** -+ * Is the connection being polled by uIP? ++ * Initialize the ARP module. + * -+ * 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. ++ */ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_arp_init(void) ++{ ++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { ++ memset(arp_table[i].ipaddr, 0, 4); ++ } ++} ++/*-----------------------------------------------------------------------------------*/ ++/** ++ * Periodic ARP processing function. + * -+ * The polling event can be used for sending data without having to -+ * wait for the remote host to send data. ++ * 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. + * -+ * \hideinitializer -+ */ -+#define uip_poll() (uip_flags & UIP_POLL) ++ */ ++/*-----------------------------------------------------------------------------------*/ ++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(u16_t *ipaddr, struct uip_eth_addr *ethaddr) ++{ ++ register struct arp_entry *tabptr; ++ /* Walk through the ARP mapping table and try to find an entry to ++ 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(ipaddr[0] == tabptr->ipaddr[0] && ++ ipaddr[1] == tabptr->ipaddr[1]) { ++ ++ /* An old entry found, update this and return. */ ++ memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); ++ tabptr->time = arptime; ++ ++ return; ++ } ++ } ++ } + -+/** -+ * Get the initial maxium segment size (MSS) of the current -+ * connection. -+ * -+ * \hideinitializer -+ */ -+#define uip_initialmss() (uip_conn->initialmss) ++ /* If we get here, no existing ARP table entry was found, so we ++ create one. */ + -+/** -+ * 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()). -+ * -+ * \hideinitializer -+ */ -+#define uip_mss() (uip_conn->mss) ++ /* 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; ++ } ++ } + -+/** -+ * Set up a new UDP connection. -+ * -+ * \param ripaddr A pointer to a 4-byte structure representing the IP -+ * address of the remote host. -+ * -+ * \param 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(u16_t *ripaddr, u16_t rport); ++ /* 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; ++ } + ++ /* Now, i is the ARP table entry which we will fill with the new ++ information. */ ++ memcpy(tabptr->ipaddr, ipaddr, 4); ++ memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); ++ tabptr->time = arptime; ++} ++/*-----------------------------------------------------------------------------------*/ +/** -+ * Removed a UDP connection. ++ * ARP processing for incoming IP packets + * -+ * \param conn A pointer to the uip_udp_conn structure for the connection. ++ * 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. + * -+ * \hideinitializer ++ * 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. + */ -+#define uip_udp_remove(conn) (conn)->lport = 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_arp_netmask[0]) != ++ (uip_hostaddr[0] & uip_arp_netmask[0])) { ++ return; ++ } ++ if((IPBUF->srcipaddr[1] & uip_arp_netmask[1]) != ++ (uip_hostaddr[1] & uip_arp_netmask[1])) { ++ return; ++ } ++ uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src)); ++ ++ return; ++} ++/*-----------------------------------------------------------------------------------*/ +/** -+ * Send a UDP datagram of length len on the current connection. ++ * ARP processing for incoming ARP packets. + * -+ * 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. ++ * 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. + * -+ * \param len The length of the data in 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. + * -+ * \hideinitializer ++ * 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. + */ -+#define uip_udp_send(len) uip_slen = (len) -+ -+/** @} */ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_arp_arpin(void) ++{ + -+/* uIP convenience and converting functions. */ ++ if(uip_len < sizeof(struct arp_hdr)) { ++ uip_len = 0; ++ return; ++ } + -+/** -+ * \defgroup uipconvfunc uIP conversion functions -+ * @{ -+ * -+ * These functions can be used for converting between different data -+ * formats used by uIP. -+ */ -+ -+/** -+ * Pack an IP address into a 4-byte array which is used by uIP to -+ * represent IP addresses. -+ * -+ * Example: -+ \code -+ u16_t ipaddr[2]; ++ uip_len = 0; + -+ uip_ipaddr(&ipaddr, 192,168,1,2); -+ \endcode -+ * -+ * \param addr A pointer to a 4-byte array that will be filled in with -+ * the IP addres. -+ * \param addr0 The first octet of the IP address. -+ * \param addr1 The second octet of the IP address. -+ * \param addr2 The third octet of the IP address. -+ * \param addr3 The forth octet of the IP address. -+ * -+ * \hideinitializer -+ */ -+#define uip_ipaddr(addr, addr0,addr1,addr2,addr3) do { \ -+ (addr)[0] = HTONS(((addr0) << 8) | (addr1)); \ -+ (addr)[1] = HTONS(((addr2) << 8) | (addr3)); \ -+ } while(0) ++ switch(BUF->opcode) { ++ case HTONS(ARP_REQUEST): ++ /* ARP request. If it asked for our address, we send out a ++ reply. */ ++ if(BUF->dipaddr[0] == uip_hostaddr[0] && ++ BUF->dipaddr[1] == uip_hostaddr[1]) { ++ /* The reply opcode is 2. */ ++ BUF->opcode = HTONS(2); + -+/** -+ * 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. -+ * -+ * \hideinitializer -+ */ -+#ifndef HTONS -+# if BYTE_ORDER == BIG_ENDIAN -+# define HTONS(n) (n) -+# else /* BYTE_ORDER == BIG_ENDIAN */ -+# define HTONS(n) ((((u16_t)((n) & 0xff)) << 8) | (((n) & 0xff00) >> 8)) -+# endif /* BYTE_ORDER == BIG_ENDIAN */ -+#endif /* HTONS */ ++ 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]; + -+/** -+ * 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 -+u16_t htons(u16_t val); -+#endif /* htons */ ++ 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(BUF->dipaddr[0] == uip_hostaddr[0] && ++ BUF->dipaddr[1] == uip_hostaddr[1]) { + -+/** @} */ ++ uip_arp_update(BUF->sipaddr, &BUF->shwaddr); ++ } ++ break; ++ } + ++ return; ++} ++/*-----------------------------------------------------------------------------------*/ +/** -+ * Pointer to the application data in the packet buffer. ++ * Prepend Ethernet header to an outbound IP packet and see if we need ++ * to send out an ARP request. + * -+ * 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 volatile u8_t *uip_appdata; -+extern volatile u8_t *uip_sappdata; -+ -+#if UIP_URGDATA > 0 -+/* u8_t *uip_urgdata: ++ * 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. + * -+ * This pointer points to any urgent data that has been received. Only -+ * present if compiled with support for urgent data (UIP_URGDATA). ++ * 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. + */ -+extern volatile u8_t *uip_urgdata; -+#endif /* UIP_URGDATA > 0 */ ++/*-----------------------------------------------------------------------------------*/ ++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. */ + -+/* u[8|16]_t uip_len: -+ * -+ * When the application is called, uip_len contains the length of any -+ * new data that has been received from the remote host. The -+ * application should set this variable to the size of any data that -+ * the application wishes to send. When the network device driver -+ * output function is called, uip_len should contain the length of the -+ * outgoing packet. -+ */ -+extern volatile u16_t uip_len, uip_slen; ++ /* Check if the destination address is on the local network. */ ++ if((IPBUF->destipaddr[0] & uip_arp_netmask[0]) != ++ (uip_hostaddr[0] & uip_arp_netmask[0]) || ++ (IPBUF->destipaddr[1] & uip_arp_netmask[1]) != ++ (uip_hostaddr[1] & uip_arp_netmask[1])) { ++ /* 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. */ ++ ipaddr[0] = uip_arp_draddr[0]; ++ ipaddr[1] = uip_arp_draddr[1]; ++ } else { ++ /* Else, we use the destination IP address. */ ++ ipaddr[0] = IPBUF->destipaddr[0]; ++ ipaddr[1] = IPBUF->destipaddr[1]; ++ } ++ ++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { ++ tabptr = &arp_table[i]; ++ if(ipaddr[0] == tabptr->ipaddr[0] && ++ ipaddr[1] == tabptr->ipaddr[1]) ++ break; ++ } + -+#if UIP_URGDATA > 0 -+extern volatile u8_t uip_urglen, uip_surglen; -+#endif /* UIP_URGDATA > 0 */ ++ 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); ++ ++ BUF->dipaddr[0] = ipaddr[0]; ++ BUF->dipaddr[1] = ipaddr[1]; ++ BUF->sipaddr[0] = uip_hostaddr[0]; ++ BUF->sipaddr[1] = uip_hostaddr[1]; ++ 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[40 + UIP_LLH_LEN]; ++ ++ uip_len = sizeof(struct arp_hdr); ++ return; ++ } + -+/** -+ * 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 appstate field whos purpose -+ * is to let the application store application-specific state (e.g., -+ * file pointers) for the connection. The size of this field is -+ * configured in the "uipopt.h" header file. -+ */ -+struct uip_conn { -+ u16_t ripaddr[2]; /**< The IP address of the remote host. */ -+ -+ u16_t lport; /**< The local TCP port, in network byte order. */ -+ u16_t rport; /**< The local remote TCP port, in network byte -+ order. */ ++ /* Build an ethernet header. */ ++ memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6); ++ memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6); + -+ u8_t rcv_nxt[4]; /**< The sequence number that we expect to -+ receive next. */ -+ u8_t snd_nxt[4]; /**< The sequence number that was last sent by -+ us. */ -+ u16_t len; /**< Length of the data that was previously sent. */ -+ u16_t mss; /**< Current maximum segment size for the -+ connection. */ -+ u16_t initialmss; /**< Initial maximum segment size for the -+ connection. */ -+ u8_t sa; /**< Retransmission time-out calculation state -+ variable. */ -+ u8_t sv; /**< Retransmission time-out calculation state -+ variable. */ -+ u8_t rto; /**< Retransmission time-out. */ -+ u8_t tcpstateflags; /**< TCP state and flags. */ -+ u8_t timer; /**< The retransmission timer. */ -+ u8_t nrtx; /**< The number of retransmissions for the last -+ segment sent. */ -+ -+ /** The application state. */ -+ u8_t appstate[UIP_APPSTATE_SIZE]; -+}; ++ IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP); + ++ uip_len += sizeof(struct uip_eth_hdr); ++} ++/*-----------------------------------------------------------------------------------*/ + -+/* Pointer to the current connection. */ -+extern struct uip_conn *uip_conn; -+/* The array containing all uIP connections. */ -+extern struct uip_conn uip_conns[UIP_CONNS]; ++/** @} */ ++/** @} */ +--- /dev/null ++++ b/net/uip-0.9/uip_arp.h +@@ -0,0 +1,201 @@ +/** -+ * \addtogroup uiparch ++ * \addtogroup uip + * @{ + */ + +/** -+ * 4-byte array used for the 32-bit sequence number calculations. ++ * \addtogroup uiparp ++ * @{ + */ -+extern volatile u8_t uip_acc32[4]; -+ -+/** @} */ -+ -+ -+#if UIP_UDP ++ +/** -+ * Representation of a uIP UDP connection. ++ * \file ++ * Macros and definitions for the ARP module. ++ * \author Adam Dunkels + */ -+struct uip_udp_conn { -+ u16_t ripaddr[2]; /**< The IP address of the remote peer. */ -+ u16_t lport; /**< The local port number in network byte order. */ -+ u16_t rport; /**< The remote port number in network byte order. */ -+}; -+ -+extern struct uip_udp_conn *uip_udp_conn; -+extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; -+#endif /* UIP_UDP */ ++ + -+/** -+ * The structure holding the TCP/IP statistics that are gathered if -+ * UIP_STATISTICS is set to 1. ++/* ++ * Copyright (c) 2001-2003, Adam Dunkels. ++ * All rights reserved. + * -+ */ -+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. */ -+}; -+ -+/** -+ * The uIP TCP/IP statistics. ++ * 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_arp.h,v 1.3.2.2 2003/10/06 15:10:22 adam Exp $ + * -+ * This is the variable in which the uIP TCP/IP statistics are gathered. + */ -+extern struct uip_stats uip_stat; + ++#ifndef __UIP_ARP_H__ ++#define __UIP_ARP_H__ + -+/*-----------------------------------------------------------------------------------*/ -+/* All the stuff below this point is internal to uIP and should not be -+ * used directly by an application or by a device driver. -+ */ -+/*-----------------------------------------------------------------------------------*/ -+/* u8_t uip_flags: -+ * -+ * When the application is called, uip_flags will contain the flags -+ * that are defined in this file. Please read below for more -+ * infomation. ++#include "uip.h" ++ ++ ++/** ++ * Representation of a 48-bit Ethernet address. + */ -+extern volatile u8_t uip_flags; ++struct uip_eth_addr { ++ u8_t addr[6]; ++}; + -+/* The following flags may be set in the global variable uip_flags -+ before calling the application callback. The UIP_ACKDATA and -+ UIP_NEWDATA 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 through the uIP functions/macros. */ ++extern struct uip_eth_addr uip_ethaddr; + -+#define UIP_ACKDATA 1 /* Signifies that the outstanding data was -+ acked and the application should send -+ out new data instead of retransmitting -+ the last data. */ -+#define UIP_NEWDATA 2 /* Flags the fact that the peer has sent -+ us new data. */ -+#define UIP_REXMIT 4 /* Tells the application to retransmit the -+ data that was last sent. */ -+#define UIP_POLL 8 /* Used for polling the application, to -+ check if the application has data that -+ it wants to send. */ -+#define UIP_CLOSE 16 /* 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 32 /* 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 64 /* 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. */ ++/** ++ * The Ethernet header. ++ */ ++struct uip_eth_hdr { ++ struct uip_eth_addr dest; ++ struct uip_eth_addr src; ++ u16_t type; ++}; + -+#define UIP_TIMEDOUT 128 /* The connection has been aborted due to -+ too many retransmissions. */ ++#define UIP_ETHTYPE_ARP 0x0806 ++#define UIP_ETHTYPE_IP 0x0800 ++#define UIP_ETHTYPE_IP6 0x86dd + + -+/* uip_process(flag): -+ * -+ * The actual uIP function which does all the work. -+ */ -+void uip_process(u8_t flag); ++/* The uip_arp_init() function must be called before any of the other ++ ARP functions. */ ++void uip_arp_init(void); + -+/* The following flags are passed as an argument to the uip_process() -+ function. They are used to distinguish between the two cases where -+ uip_process() is called. It can be called either because we have -+ incoming data that should be processed, or because the periodic -+ timer has fired. */ ++/* 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_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. */ -+#if UIP_UDP -+#define UIP_UDP_TIMER 3 -+#endif /* UIP_UDP */ ++/* 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 TCP states used in the uip_conn->tcpstateflags. */ -+#define CLOSED 0 -+#define SYN_RCVD 1 -+#define SYN_SENT 2 -+#define ESTABLISHED 3 -+#define FIN_WAIT_1 4 -+#define FIN_WAIT_2 5 -+#define CLOSING 6 -+#define TIME_WAIT 7 -+#define LAST_ACK 8 -+#define TS_MASK 15 -+ -+#define UIP_STOPPED 16 ++/* 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); + -+#define UIP_TCPIP_HLEN 40 ++/* 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); + -+/* The TCP and IP headers. */ -+typedef struct { -+ /* IP header. */ -+ u8_t vhl, -+ tos, -+ len[2], -+ ipid[2], -+ ipoffset[2], -+ ttl, -+ proto; -+ u16_t ipchksum; -+ u16_t srcipaddr[2], -+ destipaddr[2]; -+ -+ /* TCP header. */ -+ u16_t srcport, -+ destport; -+ u8_t seqno[4], -+ ackno[4], -+ tcpoffset, -+ flags, -+ wnd[2]; -+ u16_t tcpchksum; -+ u8_t urgp[2]; -+ u8_t optdata[4]; -+} uip_tcpip_hdr; ++/** @} */ + -+/* The ICMP and IP headers. */ -+typedef struct { -+ /* IP header. */ -+ u8_t vhl, -+ tos, -+ len[2], -+ ipid[2], -+ ipoffset[2], -+ ttl, -+ proto; -+ u16_t ipchksum; -+ u16_t srcipaddr[2], -+ destipaddr[2]; -+ /* ICMP (echo) header. */ -+ u8_t type, icode; -+ u16_t icmpchksum; -+ u16_t id, seqno; -+} uip_icmpip_hdr; ++/** ++ * \addtogroup uipconffunc ++ * @{ ++ */ + ++/** ++ * Set the default router's IP address. ++ * ++ * \param addr A pointer to a 4-byte array containing the IP address ++ * of the default router. ++ * ++ * \hideinitializer ++ */ ++#define uip_setdraddr(addr) do { uip_arp_draddr[0] = addr[0]; \ ++ uip_arp_draddr[1] = addr[1]; } while(0) + -+/* The UDP and IP headers. */ -+typedef struct { -+ /* IP header. */ -+ u8_t vhl, -+ tos, -+ len[2], -+ ipid[2], -+ ipoffset[2], -+ ttl, -+ proto; -+ u16_t ipchksum; -+ u16_t srcipaddr[2], -+ destipaddr[2]; -+ -+ /* UDP header. */ -+ u16_t srcport, -+ destport; -+ u16_t udplen; -+ u16_t udpchksum; -+} uip_udpip_hdr; ++/** ++ * Set the netmask. ++ * ++ * \param addr A pointer to a 4-byte array containing the IP address ++ * of the netmask. ++ * ++ * \hideinitializer ++ */ ++#define uip_setnetmask(addr) do { uip_arp_netmask[0] = addr[0]; \ ++ uip_arp_netmask[1] = addr[1]; } while(0) + -+#define UIP_PROTO_ICMP 1 -+#define UIP_PROTO_TCP 6 -+#define UIP_PROTO_UDP 17 + -+#if UIP_FIXEDADDR -+extern const u16_t uip_hostaddr[2]; -+#else /* UIP_FIXEDADDR */ -+extern u16_t uip_hostaddr[2]; -+#endif /* UIP_FIXEDADDR */ ++/** ++ * Get the default router's IP address. ++ * ++ * \param addr A pointer to a 4-byte array that will be filled in with ++ * the IP address of the default router. ++ * ++ * \hideinitializer ++ */ ++#define uip_getdraddr(addr) do { addr[0] = uip_arp_draddr[0]; \ ++ addr[1] = uip_arp_draddr[1]; } while(0) ++ ++/** ++ * Get the netmask. ++ * ++ * \param addr A pointer to a 4-byte array that will be filled in with ++ * the value of the netmask. ++ * ++ * \hideinitializer ++ */ ++#define uip_getnetmask(addr) do { addr[0] = uip_arp_netmask[0]; \ ++ addr[1] = uip_arp_netmask[1]; } while(0) + -+#endif /* __UIP_H__ */ + ++/** ++ * 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. ++ * ++ * \param eaddr A pointer to a struct uip_eth_addr containing the ++ * Ethernet MAC address of the Ethernet card. ++ * ++ * \hideinitializer ++ */ ++#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) + +/** @} */ + ++/** ++ * \internal Internal variables that are set using the macros ++ * uip_setdraddr and uip_setnetmask. ++ */ ++extern u16_t uip_arp_draddr[2], uip_arp_netmask[2]; ++#endif /* __UIP_ARP_H__ */ ++ ++ --- /dev/null +++ b/net/uip-0.9/uipopt.h @@ -0,0 +1,557 @@