|
|
@@ -19,6 +19,26 @@
|
|
|
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 <[email protected]>
|
|
|
++#
|
|
|
++# $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 <[email protected]>
|
|
|
-+#
|
|
|
-+# $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 <[email protected]>
|
|
|
++ */
|
|
|
++
|
|
|
++/*
|
|
|
++ * 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 <[email protected]>
|
|
|
++ *
|
|
|
++ * $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 <[email protected]>
|
|
|
-+ */
|
|
|
-+
|
|
|
-+/*
|
|
|
-+ * 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 <[email protected]>
|
|
|
-+ *
|
|
|
-+ * $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 <[email protected]>
|
|
|
++ */
|
|
|
++
|
|
|
+/*
|
|
|
-+ * 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 <[email protected]>
|
|
|
-+ */
|
|
|
++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 <[email protected]>
|
|
|
-+ *
|
|
|
-+ */
|
|
|
-+
|
|
|
-+/*
|
|
|
-+ * 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 <[email protected]>
|
|
|
-+ */
|
|
|
++ 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 <[email protected]>
|
|
|
-+ */
|
|
|
-+
|
|
|
-+/*
|
|
|
-+ * 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 <[email protected]>
|
|
|
++ *
|
|
|
++ * 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 <linux/types.h>
|
|
|
++#include <linux/string.h>
|
|
|
++#include <linux/ctype.h>
|
|
|
++#include <malloc.h>
|
|
|
++#include <common.h>
|
|
|
+
|
|
|
-+ 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 <[email protected]>
|
|
|
++ * 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 <linux/types.h>
|
|
|
-+#include <linux/string.h>
|
|
|
-+#include <linux/ctype.h>
|
|
|
-+#include <malloc.h>
|
|
|
-+#include <common.h>
|
|
|
-+
|
|
|
++/**
|
|
|
++ * 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 <[email protected]>
|
|
|
+ */
|
|
|
-+#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 <[email protected]>
|
|
|
+ *
|
|
|
-+ * \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 <[email protected]>
|
|
|
+ */
|
|
|
-+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 @@
|