| package/uboot-lantiq/patches/300-httpd.patch |
| 19 | 19 | int do_tftpb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) |
| 20 | 20 | { |
| 21 | 21 | return netboot_common (TFTP, cmdtp, argc, argv); |
| 22 | | +++ b/include/httpd.h |
| 23 | | @@ -0,0 +1,17 @@ |
| 24 | | +#ifndef _UIP_HTTPD_H__ |
| 25 | | +#define _UIP_HTTPD_H__ |
| 26 | | + |
| 27 | | +void HttpdStart (void); |
| 28 | | +void HttpdHandler (void); |
| 29 | | + |
| 30 | | +/* board specific implementation */ |
| 31 | | +extern int do_http_upgrade(const unsigned char *data, const ulong size); |
| 32 | | + |
| 33 | | +#define HTTP_PROGRESS_START 0 |
| 34 | | +#define HTTP_PROGRESS_TIMEOUT 1 |
| 35 | | +#define HTTP_PROGRESS_UPLOAD_READY 2 |
| 36 | | +#define HTTP_PROGRESS_UGRADE_READY 3 |
| 37 | | +#define HTTP_PROGRESS_UGRADE_FAILED 4 |
| 38 | | +extern int do_http_progress(const int state); |
| 39 | | + |
| 40 | | +#endif |
| 41 | 22 | --- a/include/net.h |
| 42 | 23 | +++ b/include/net.h |
| 43 | 24 | @@ -383,7 +383,8 @@ extern int NetTimeOffset; /* offset ti |
| ... | ... | |
| 51 | 31 | /* Shutdown adapters and cleanup */ |
| 52 | 32 | extern void NetStop(void); |
| 53 | 33 | |
| 54 | | +++ b/net/Makefile |
| 55 | | @@ -26,6 +26,10 @@ include $(TOPDIR)/config.mk |
| 56 | | # CFLAGS += -DDEBUG |
| 57 | | |
| 58 | | LIB = $(obj)libnet.a |
| 59 | | +UIPDIR = uip-0.9 |
| 60 | | +RSADIR = uip-0.9 |
| 61 | | +$(shell mkdir -p $(obj)$(UIPDIR)) |
| 62 | | +$(shell mkdir -p $(obj)$(RSADIR)) |
| 63 | | |
| 64 | | COBJS-$(CONFIG_CMD_NET) += bootp.o |
| 65 | | COBJS-$(CONFIG_CMD_DNS) += dns.o |
| 66 | | @@ -36,6 +40,9 @@ COBJS-$(CONFIG_CMD_NET) += rarp.o |
| 67 | | COBJS-$(CONFIG_CMD_SNTP) += sntp.o |
| 68 | | COBJS-$(CONFIG_CMD_NET) += tftp.o |
| 69 | | |
| 70 | | +COBJS-$(CONFIG_CMD_HTTPD) += httpd.o $(UIPDIR)/fs.o $(UIPDIR)/httpd.o $(UIPDIR)/uip_arp.o $(UIPDIR)/uip_arch.o $(UIPDIR)/uip.o |
| 71 | | +COBJS-$(CONFIG_CMD_RSA) += $(RSADIR)/bigint.o $(RSADIR)/base64.o $(RSADIR)/rmd160.o $(RSADIR)/rsa.o |
| 72 | | + |
| 73 | | COBJS := $(COBJS-y) |
| 74 | | SRCS := $(COBJS:.o=.c) |
| 75 | | OBJS := $(addprefix $(obj),$(COBJS)) |
| 76 | 34 | --- /dev/null |
| 77 | 35 | +++ b/net/httpd.c |
| 78 | 36 | @@ -0,0 +1,52 @@ |
| ... | ... | |
| 129 | 86 | +} |
| 130 | 87 | + |
| 131 | 88 | +#endif |
| 89 | --- /dev/null |
| 90 | @@ -0,0 +1,17 @@ |
| 91 | +#ifndef _UIP_HTTPD_H__ |
| 92 | +#define _UIP_HTTPD_H__ |
| 93 | + |
| 94 | +void HttpdStart (void); |
| 95 | +void HttpdHandler (void); |
| 96 | + |
| 97 | +/* board specific implementation */ |
| 98 | +extern int do_http_upgrade(const unsigned char *data, const ulong size); |
| 99 | + |
| 100 | +#define HTTP_PROGRESS_START 0 |
| 101 | +#define HTTP_PROGRESS_TIMEOUT 1 |
| 102 | +#define HTTP_PROGRESS_UPLOAD_READY 2 |
| 103 | +#define HTTP_PROGRESS_UGRADE_READY 3 |
| 104 | +#define HTTP_PROGRESS_UGRADE_FAILED 4 |
| 105 | +extern int do_http_progress(const int state); |
| 106 | + |
| 107 | +#endif |
| 108 | --- a/net/Makefile |
| 109 | @@ -26,6 +26,10 @@ include $(TOPDIR)/config.mk |
| 110 | # CFLAGS += -DDEBUG |
| 111 | |
| 112 | LIB = $(obj)libnet.a |
| 113 | +UIPDIR = uip-0.9 |
| 114 | +RSADIR = uip-0.9 |
| 115 | +$(shell mkdir -p $(obj)$(UIPDIR)) |
| 116 | +$(shell mkdir -p $(obj)$(RSADIR)) |
| 117 | |
| 118 | COBJS-y += bootp.o |
| 119 | COBJS-$(CONFIG_CMD_DNS) += dns.o |
| 120 | @@ -36,6 +40,9 @@ COBJS-y += rarp.o |
| 121 | COBJS-$(CONFIG_CMD_SNTP) += sntp.o |
| 122 | COBJS-y += tftp.o |
| 123 | |
| 124 | +COBJS-$(CONFIG_CMD_HTTPD) += httpd.o $(UIPDIR)/fs.o $(UIPDIR)/httpd.o $(UIPDIR)/uip_arp.o $(UIPDIR)/uip_arch.o $(UIPDIR)/uip.o |
| 125 | +COBJS-$(CONFIG_CMD_RSA) += $(RSADIR)/bigint.o $(RSADIR)/base64.o $(RSADIR)/rmd160.o $(RSADIR)/rsa.o |
| 126 | + |
| 127 | COBJS := $(COBJS-y) |
| 128 | SRCS := $(COBJS:.o=.c) |
| 129 | OBJS := $(addprefix $(obj),$(COBJS)) |
| 132 | 130 | --- a/net/net.c |
| 133 | 131 | +++ b/net/net.c |
| 134 | 132 | @@ -95,6 +95,19 @@ |
| ... | ... | |
| 149 | 149 | +extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); |
| 150 | 150 | +#endif |
| 151 | 151 | |
| 152 | | DECLARE_GLOBAL_DATA_PTR; |
| 152 | #if defined(CONFIG_CMD_NET) |
| 153 | 153 | |
| 154 | | @@ -1308,6 +1321,13 @@ NetReceive(volatile uchar * inpkt, int l |
| 154 | @@ -1310,6 +1323,13 @@ NetReceive(volatile uchar * inpkt, int l |
| 155 | 155 | |
| 156 | 156 | debug("packet received\n"); |
| 157 | 157 | |
| ... | ... | |
| 165 | 165 | NetRxPacket = inpkt; |
| 166 | 166 | NetRxPacketLen = len; |
| 167 | 167 | et = (Ethernet_t *)inpkt; |
| 168 | | @@ -1922,3 +1942,162 @@ ushort getenv_VLAN(char *var) |
| 168 | @@ -1952,3 +1972,162 @@ ushort getenv_VLAN(char *var) |
| 169 | 169 | { |
| 170 | 170 | return (string_to_VLAN(getenv(var))); |
| 171 | 171 | } |
| ... | ... | |
| 329 | 329 | + |
| 330 | 330 | +#endif |
| 331 | 331 | --- /dev/null |
| 332 | | +++ b/net/rsa/Makefile |
| 333 | | @@ -0,0 +1,31 @@ |
| 334 | | +# |
| 335 | | +# FONRSA & FONSIGN libraries unit testing |
| 336 | | +# |
| 337 | | +# This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. |
| 338 | | +# |
| 339 | | +# Execute in this directory |
| 340 | | +# |
| 341 | | +# Created: 20070422 Pablo Martin Medrano <pablo@fon.com> |
| 342 | | +# |
| 343 | | +# $Id: Makefile 389 2007-06-11 08:29:56Z pablo.martin $ |
| 344 | | +# |
| 345 | | +# FIXME: Put this in the main Makefile.am |
| 346 | | +# |
| 347 | | +all: fonsign dump_key |
| 348 | | + |
| 349 | | +fonsign: |
| 350 | | + gcc -g sign_openssl.c -D__MAINTEST__ -o fonsign -lssl |
| 351 | | + |
| 352 | | +dump_key: |
| 353 | | + gcc -o dump_key dump_key.c |
| 354 | | + ./dump_key > public_key.h |
| 355 | | + |
| 356 | | +foncheckrsa: |
| 357 | | + gcc -g bigint.c fonrsa.c rmd160.c foncheckrsa.c base64.c log.c -o foncheckrsa |
| 358 | | + |
| 359 | | +#private_fon_rsa_key.pem: |
| 360 | | +# openssl genrsa -out private_fon_rsa_key.pem 4096 |
| 361 | | +# openssl rsa -in private_fon_rsa_key.pem -pubout -out public_fon_rsa_key.pem |
| 362 | | + |
| 363 | | +clean: |
| 364 | | + rm fonsign dump_key |
| 365 | 332 | +++ b/net/rsa/base64.c |
| 366 | 333 | @@ -0,0 +1,137 @@ |
| 367 | 334 | +#include "base64.h" |
| ... | ... | |
| 2708 | 2674 | +#endif |
| 2709 | 2675 | + |
| 2710 | 2676 | --- /dev/null |
| 2677 | @@ -0,0 +1,31 @@ |
| 2678 | +# |
| 2679 | +# FONRSA & FONSIGN libraries unit testing |
| 2680 | +# |
| 2681 | +# This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. |
| 2682 | +# |
| 2683 | +# Execute in this directory |
| 2684 | +# |
| 2685 | +# Created: 20070422 Pablo Martin Medrano <pablo@fon.com> |
| 2686 | +# |
| 2687 | +# $Id: Makefile 389 2007-06-11 08:29:56Z pablo.martin $ |
| 2688 | +# |
| 2689 | +# FIXME: Put this in the main Makefile.am |
| 2690 | +# |
| 2691 | +all: fonsign dump_key |
| 2692 | + |
| 2693 | +fonsign: |
| 2694 | + gcc -g sign_openssl.c -D__MAINTEST__ -o fonsign -lssl |
| 2695 | + |
| 2696 | +dump_key: |
| 2697 | + gcc -o dump_key dump_key.c |
| 2698 | + ./dump_key > public_key.h |
| 2699 | + |
| 2700 | +foncheckrsa: |
| 2701 | + gcc -g bigint.c fonrsa.c rmd160.c foncheckrsa.c base64.c log.c -o foncheckrsa |
| 2702 | + |
| 2703 | +#private_fon_rsa_key.pem: |
| 2704 | +# openssl genrsa -out private_fon_rsa_key.pem 4096 |
| 2705 | +# openssl rsa -in private_fon_rsa_key.pem -pubout -out public_fon_rsa_key.pem |
| 2706 | + |
| 2707 | +clean: |
| 2708 | + rm fonsign dump_key |
| 2709 | --- /dev/null |
| 2711 | 2710 | +++ b/net/rsa/public_key.h |
| 2712 | 2711 | @@ -0,0 +1,52 @@ |
| 2713 | 2712 | +unsigned char public_key[] = { |
| ... | ... | |
| 4040 | 4040 | +#endif |
| 4041 | 4041 | + |
| 4042 | 4042 | --- /dev/null |
| 4043 | | +++ b/net/uip-0.9/Makefile |
| 4044 | | @@ -0,0 +1,54 @@ |
| 4045 | | +# Copyright (c) 2001, Adam Dunkels. |
| 4046 | | +# All rights reserved. |
| 4047 | | +# |
| 4048 | | +# Redistribution and use in source and binary forms, with or without |
| 4049 | | +# modification, are permitted provided that the following conditions |
| 4050 | | +# are met: |
| 4051 | | +# 1. Redistributions of source code must retain the above copyright |
| 4052 | | +# notice, this list of conditions and the following disclaimer. |
| 4053 | | +# 2. Redistributions in binary form must reproduce the above copyright |
| 4054 | | +# notice, this list of conditions and the following disclaimer in the |
| 4055 | | +# documentation and/or other materials provided with the distribution. |
| 4056 | | +# 3. All advertising materials mentioning features or use of this software |
| 4057 | | +# must display the following acknowledgement: |
| 4058 | | +# This product includes software developed by Adam Dunkels. |
| 4059 | | +# 4. The name of the author may not be used to endorse or promote |
| 4060 | | +# products derived from this software without specific prior |
| 4061 | | +# written permission. |
| 4062 | | +# |
| 4063 | | +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS |
| 4064 | | +# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 4065 | | +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 4066 | | +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
| 4067 | | +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 4068 | | +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
| 4069 | | +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 4070 | | +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| 4071 | | +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| 4072 | | +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 4073 | | +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 4074 | | +# |
| 4075 | | +# This file is part of the uIP TCP/IP stack. |
| 4076 | | +# |
| 4077 | | +# $Id: Makefile,v 1.8.2.2 2003/10/04 22:54:17 adam Exp $ |
| 4078 | | +# |
| 4079 | | + |
| 4080 | | +CC=gcc |
| 4081 | | +CFLAGS=-Wall -fpack-struct -DDUMP=0 |
| 4082 | | + |
| 4083 | | +all: uip |
| 4084 | | + |
| 4085 | | +uip: uip.o uip_arch.o tapdev.o httpd.o main.o fs.o uip_arp.o |
| 4086 | | + $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ |
| 4087 | | + |
| 4088 | | +%.o: %.c |
| 4089 | | + $(CC) $(CFLAGS) -c $^ -o $@ |
| 4090 | | + |
| 4091 | | +clean: |
| 4092 | | + rm -f *.o *~ *core uip |
| 4093 | | + |
| 4094 | | + |
| 4095 | | + |
| 4096 | | + |
| 4097 | | + |
| 4098 | | + |
| 4099 | 4043 | +++ b/net/uip-0.9/fs.c |
| 4100 | 4044 | @@ -0,0 +1,154 @@ |
| 4101 | 4045 | +/** |
| ... | ... | |
| 4254 | 4197 | +#endif /* FS_STATISTICS */ |
| 4255 | 4198 | +/*-----------------------------------------------------------------------------------*/ |
| 4256 | 4199 | --- /dev/null |
| 4257 | | +++ b/net/uip-0.9/fs.h |
| 4258 | | @@ -0,0 +1,80 @@ |
| 4259 | | +/** |
| 4260 | | + * \addtogroup httpd |
| 4261 | | + * @{ |
| 4262 | | + */ |
| 4263 | | + |
| 4264 | | +/** |
| 4265 | | + * \file |
| 4266 | | + * HTTP server read-only file system header file. |
| 4267 | | + * \author Adam Dunkels <adam@dunkels.com> |
| 4268 | | + */ |
| 4269 | | + |
| 4270 | | +/* |
| 4271 | | + * Copyright (c) 2001, Swedish Institute of Computer Science. |
| 4272 | | + * All rights reserved. |
| 4273 | | + * |
| 4274 | | + * Redistribution and use in source and binary forms, with or without |
| 4275 | | + * modification, are permitted provided that the following conditions |
| 4276 | | + * are met: |
| 4277 | | + * 1. Redistributions of source code must retain the above copyright |
| 4278 | | + * notice, this list of conditions and the following disclaimer. |
| 4279 | | + * 2. Redistributions in binary form must reproduce the above copyright |
| 4280 | | + * notice, this list of conditions and the following disclaimer in the |
| 4281 | | + * documentation and/or other materials provided with the distribution. |
| 4282 | | + * 3. Neither the name of the Institute nor the names of its contributors |
| 4283 | | + * may be used to endorse or promote products derived from this software |
| 4284 | | + * without specific prior written permission. |
| 4285 | | + * |
| 4286 | | + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND |
| 4287 | | + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 4288 | | + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 4289 | | + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE |
| 4290 | | + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 4291 | | + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 4292 | | + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 4293 | | + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 4294 | | + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 4295 | | + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 4296 | | + * SUCH DAMAGE. |
| 4297 | | + * |
| 4298 | | + * This file is part of the lwIP TCP/IP stack. |
| 4299 | | + * |
| 4300 | | + * Author: Adam Dunkels <adam@sics.se> |
| 4301 | | + * |
| 4302 | | + * $Id: fs.h,v 1.6.2.3 2003/10/07 13:22:27 adam Exp $ |
| 4303 | | + */ |
| 4304 | | +#ifndef __FS_H__ |
| 4305 | | +#define __FS_H__ |
| 4306 | | + |
| 4307 | | +#include "uip.h" |
| 4308 | | + |
| 4309 | | +/** |
| 4310 | | + * An open file in the read-only file system. |
| 4311 | | + */ |
| 4312 | | +struct fs_file { |
| 4313 | | + char *data; /**< The actual file data. */ |
| 4314 | | + int len; /**< The length of the file data. */ |
| 4315 | | +}; |
| 4316 | | + |
| 4317 | | +/** |
| 4318 | | + * Open a file in the read-only file system. |
| 4319 | | + * |
| 4320 | | + * \param name The name of the file. |
| 4321 | | + * |
| 4322 | | + * \param file The file pointer, which must be allocated by caller and |
| 4323 | | + * will be filled in by the function. |
| 4324 | | + */ |
| 4325 | | +int fs_open(const char *name, struct fs_file *file); |
| 4326 | | + |
| 4327 | | +#ifdef FS_STATISTICS |
| 4328 | | +#if FS_STATISTICS == 1 |
| 4329 | | +u16_t fs_count(char *name); |
| 4330 | | +#endif /* FS_STATISTICS */ |
| 4331 | | +#endif /* FS_STATISTICS */ |
| 4332 | | + |
| 4333 | | +/** |
| 4334 | | + * Initialize the read-only file system. |
| 4335 | | + */ |
| 4336 | | +void fs_init(void); |
| 4337 | | + |
| 4338 | | +#endif /* __FS_H__ */ |
| 4339 | | +++ b/net/uip-0.9/fsdata.c |
| 4340 | | @@ -0,0 +1,199 @@ |
| 4341 | | +static const char data_flashing_html[] = { |
| 4342 | | + /* /flashing.html */ |
| 4343 | | + 0x2f, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, |
| 4344 | | + 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, |
| 4345 | | + 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, |
| 4346 | | + 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, |
| 4347 | | + 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, |
| 4348 | | + 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, |
| 4349 | | + 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, |
| 4350 | | + 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, |
| 4351 | | + 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, |
| 4352 | | + 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, |
| 4353 | | + 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x3c, 0x62, |
| 4354 | | + 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x3d, |
| 4355 | | + 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30, |
| 4356 | | + 0x70, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x20, 0x68, |
| 4357 | | + 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x31, 0x30, 0x30, 0x25, |
| 4358 | | + 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, |
| 4359 | | + 0x66, 0x66, 0x66, 0x3b, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, |
| 4360 | | + 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, |
| 4361 | | + 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, 0x62, 0x30, 0x33, 0x34, |
| 4362 | | + 0x3b, 0x22, 0x3e, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, |
| 4363 | | + 0x3e, 0x3c, 0x68, 0x31, 0x3e, 0x55, 0x70, 0x67, 0x72, 0x61, |
| 4364 | | + 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, |
| 4365 | | + 0x6d, 0x20, 0x2e, 0x2e, 0x2e, 0x2e, 0x3c, 0x2f, 0x68, 0x31, |
| 4366 | | + 0x3e, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, |
| 4367 | | + 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, |
| 4368 | | + 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; |
| 4200 | @@ -0,0 +1,199 @@ |
| 4201 | +static const char data_flashing_html[] = { |
| 4202 | + /* /flashing.html */ |
| 4203 | + 0x2f, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, |
| 4204 | + 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, |
| 4205 | + 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, |
| 4206 | + 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, |
| 4207 | + 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, |
| 4208 | + 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, |
| 4209 | + 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, |
| 4210 | + 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, |
| 4211 | + 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, |
| 4212 | + 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, |
| 4213 | + 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x3c, 0x62, |
| 4214 | + 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x3d, |
| 4215 | + 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30, |
| 4216 | + 0x70, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x20, 0x68, |
| 4217 | + 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x31, 0x30, 0x30, 0x25, |
| 4218 | + 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, |
| 4219 | + 0x66, 0x66, 0x66, 0x3b, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, |
| 4220 | + 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, |
| 4221 | + 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, 0x62, 0x30, 0x33, 0x34, |
| 4222 | + 0x3b, 0x22, 0x3e, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, |
| 4223 | + 0x3e, 0x3c, 0x68, 0x31, 0x3e, 0x55, 0x70, 0x67, 0x72, 0x61, |
| 4224 | + 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, |
| 4225 | + 0x6d, 0x20, 0x2e, 0x2e, 0x2e, 0x2e, 0x3c, 0x2f, 0x68, 0x31, |
| 4226 | + 0x3e, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, |
| 4227 | + 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, |
| 4228 | + 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; |
| 4369 | 4229 | + |
| 4370 | 4230 | +static const char data_fail_html[] = { |
| 4371 | 4231 | + /* /fail.html */ |
| ... | ... | |
| 4607 | 4467 | + |
| 4608 | 4468 | +#endif /* __FSDATA_H__ */ |
| 4609 | 4469 | --- /dev/null |
| 4470 | @@ -0,0 +1,80 @@ |
| 4471 | +/** |
| 4472 | + * \addtogroup httpd |
| 4473 | + * @{ |
| 4474 | + */ |
| 4475 | + |
| 4476 | +/** |
| 4477 | + * \file |
| 4478 | + * HTTP server read-only file system header file. |
| 4479 | + * \author Adam Dunkels <adam@dunkels.com> |
| 4480 | + */ |
| 4481 | + |
| 4482 | +/* |
| 4483 | + * Copyright (c) 2001, Swedish Institute of Computer Science. |
| 4484 | + * All rights reserved. |
| 4485 | + * |
| 4486 | + * Redistribution and use in source and binary forms, with or without |
| 4487 | + * modification, are permitted provided that the following conditions |
| 4488 | + * are met: |
| 4489 | + * 1. Redistributions of source code must retain the above copyright |
| 4490 | + * notice, this list of conditions and the following disclaimer. |
| 4491 | + * 2. Redistributions in binary form must reproduce the above copyright |
| 4492 | + * notice, this list of conditions and the following disclaimer in the |
| 4493 | + * documentation and/or other materials provided with the distribution. |
| 4494 | + * 3. Neither the name of the Institute nor the names of its contributors |
| 4495 | + * may be used to endorse or promote products derived from this software |
| 4496 | + * without specific prior written permission. |
| 4497 | + * |
| 4498 | + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND |
| 4499 | + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 4500 | + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 4501 | + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE |
| 4502 | + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 4503 | + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 4504 | + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 4505 | + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 4506 | + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 4507 | + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 4508 | + * SUCH DAMAGE. |
| 4509 | + * |
| 4510 | + * This file is part of the lwIP TCP/IP stack. |
| 4511 | + * |
| 4512 | + * Author: Adam Dunkels <adam@sics.se> |
| 4513 | + * |
| 4514 | + * $Id: fs.h,v 1.6.2.3 2003/10/07 13:22:27 adam Exp $ |
| 4515 | + */ |
| 4516 | +#ifndef __FS_H__ |
| 4517 | +#define __FS_H__ |
| 4518 | + |
| 4519 | +#include "uip.h" |
| 4520 | + |
| 4521 | +/** |
| 4522 | + * An open file in the read-only file system. |
| 4523 | + */ |
| 4524 | +struct fs_file { |
| 4525 | + char *data; /**< The actual file data. */ |
| 4526 | + int len; /**< The length of the file data. */ |
| 4527 | +}; |
| 4528 | + |
| 4529 | +/** |
| 4530 | + * Open a file in the read-only file system. |
| 4531 | + * |
| 4532 | + * \param name The name of the file. |
| 4533 | + * |
| 4534 | + * \param file The file pointer, which must be allocated by caller and |
| 4535 | + * will be filled in by the function. |
| 4536 | + */ |
| 4537 | +int fs_open(const char *name, struct fs_file *file); |
| 4538 | + |
| 4539 | +#ifdef FS_STATISTICS |
| 4540 | +#if FS_STATISTICS == 1 |
| 4541 | +u16_t fs_count(char *name); |
| 4542 | +#endif /* FS_STATISTICS */ |
| 4543 | +#endif /* FS_STATISTICS */ |
| 4544 | + |
| 4545 | +/** |
| 4546 | + * Initialize the read-only file system. |
| 4547 | + */ |
| 4548 | +void fs_init(void); |
| 4549 | + |
| 4550 | +#endif /* __FS_H__ */ |
| 4551 | --- /dev/null |
| 4610 | 4552 | +++ b/net/uip-0.9/httpd.c |
| 4611 | 4553 | @@ -0,0 +1,278 @@ |
| 4612 | 4554 | +#include "uip.h" |
| ... | ... | |
| 5065 | 5008 | + return 0; |
| 5066 | 5009 | +} |
| 5067 | 5010 | --- /dev/null |
| 5011 | @@ -0,0 +1,54 @@ |
| 5012 | +# Copyright (c) 2001, Adam Dunkels. |
| 5013 | +# All rights reserved. |
| 5014 | +# |
| 5015 | +# Redistribution and use in source and binary forms, with or without |
| 5016 | +# modification, are permitted provided that the following conditions |
| 5017 | +# are met: |
| 5018 | +# 1. Redistributions of source code must retain the above copyright |
| 5019 | +# notice, this list of conditions and the following disclaimer. |
| 5020 | +# 2. Redistributions in binary form must reproduce the above copyright |
| 5021 | +# notice, this list of conditions and the following disclaimer in the |
| 5022 | +# documentation and/or other materials provided with the distribution. |
| 5023 | +# 3. All advertising materials mentioning features or use of this software |
| 5024 | +# must display the following acknowledgement: |
| 5025 | +# This product includes software developed by Adam Dunkels. |
| 5026 | +# 4. The name of the author may not be used to endorse or promote |
| 5027 | +# products derived from this software without specific prior |
| 5028 | +# written permission. |
| 5029 | +# |
| 5030 | +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS |
| 5031 | +# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 5032 | +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 5033 | +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
| 5034 | +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 5035 | +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
| 5036 | +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 5037 | +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| 5038 | +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| 5039 | +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 5040 | +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 5041 | +# |
| 5042 | +# This file is part of the uIP TCP/IP stack. |
| 5043 | +# |
| 5044 | +# $Id: Makefile,v 1.8.2.2 2003/10/04 22:54:17 adam Exp $ |
| 5045 | +# |
| 5046 | + |
| 5047 | +CC=gcc |
| 5048 | +CFLAGS=-Wall -fpack-struct -DDUMP=0 |
| 5049 | + |
| 5050 | +all: uip |
| 5051 | + |
| 5052 | +uip: uip.o uip_arch.o tapdev.o httpd.o main.o fs.o uip_arp.o |
| 5053 | + $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ |
| 5054 | + |
| 5055 | +%.o: %.c |
| 5056 | + $(CC) $(CFLAGS) -c $^ -o $@ |
| 5057 | + |
| 5058 | +clean: |
| 5059 | + rm -f *.o *~ *core uip |
| 5060 | + |
| 5061 | + |
| 5062 | + |
| 5063 | + |
| 5064 | + |
| 5065 | + |
| 5066 | --- /dev/null |
| 5068 | 5067 | +++ b/net/uip-0.9/tapdev.c |
| 5069 | 5068 | @@ -0,0 +1,192 @@ |
| 5070 | 5069 | +/* |
| ... | ... | |
| 5305 | 5305 | + |
| 5306 | 5306 | +#endif /* __TAPDEV_H__ */ |
| 5307 | 5307 | --- /dev/null |
| 5308 | | +++ b/net/uip-0.9/uip.c |
| 5309 | | @@ -0,0 +1,1503 @@ |
| 5310 | | +/** |
| 5311 | | + * \addtogroup uip |
| 5312 | | + * @{ |
| 5313 | | + */ |
| 5314 | | + |
| 5315 | | +/** |
| 5316 | | + * \file |
| 5317 | | + * The uIP TCP/IP stack code. |
| 5318 | | + * \author Adam Dunkels <adam@dunkels.com> |
| 5319 | | + */ |
| 5320 | | + |
| 5308 | @@ -0,0 +1,145 @@ |
| 5321 | 5309 | +/* |
| 5322 | | + * Copyright (c) 2001-2003, Adam Dunkels. |
| 5310 | + * Copyright (c) 2001, Adam Dunkels. |
| 5323 | 5311 | + * All rights reserved. |
| 5324 | 5312 | + * |
| 5325 | 5313 | + * Redistribution and use in source and binary forms, with or without |
| ... | ... | |
| 5348 | 5337 | + * |
| 5349 | 5338 | + * This file is part of the uIP TCP/IP stack. |
| 5350 | 5339 | + * |
| 5351 | | + * $Id: uip.c,v 1.62.2.10 2003/10/07 13:23:01 adam Exp $ |
| 5340 | + * $Id: uip_arch.c,v 1.2.2.1 2003/10/04 22:54:17 adam Exp $ |
| 5352 | 5341 | + * |
| 5353 | 5342 | + */ |
| 5354 | 5343 | + |
| 5355 | | +/* |
| 5356 | | +This is a small implementation of the IP and TCP protocols (as well as |
| 5357 | | +some basic ICMP stuff). The implementation couples the IP, TCP and the |
| 5358 | | +application layers very tightly. To keep the size of the compiled code |
| 5359 | | +down, this code also features heavy usage of the goto statement. |
| 5360 | | + |
| 5361 | | +The principle is that we have a small buffer, called the uip_buf, in |
| 5362 | | +which the device driver puts an incoming packet. The TCP/IP stack |
| 5363 | | +parses the headers in the packet, and calls upon the application. If |
| 5364 | | +the remote host has sent data to the application, this data is present |
| 5365 | | +in the uip_buf and the application read the data from there. It is up |
| 5366 | | +to the application to put this data into a byte stream if needed. The |
| 5367 | | +application will not be fed with data that is out of sequence. |
| 5368 | | + |
| 5369 | | +If the application whishes to send data to the peer, it should put its |
| 5370 | | +data into the uip_buf, 40 bytes from the start of the buffer. The |
| 5371 | | +TCP/IP stack will calculate the checksums, and fill in the necessary |
| 5372 | | +header fields and finally send the packet back to the peer. |
| 5373 | | +*/ |
| 5374 | 5344 | + |
| 5375 | 5345 | +#include "uip.h" |
| 5376 | | +#include "uipopt.h" |
| 5377 | 5346 | +#include "uip_arch.h" |
| 5378 | 5347 | + |
| 5379 | | +/*-----------------------------------------------------------------------------------*/ |
| 5380 | | +/* Variable definitions. */ |
| 5381 | | + |
| 5382 | | + |
| 5383 | | +/* 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 */ |
| 5384 | | +#if UIP_FIXEDADDR > 0 |
| 5385 | | +const unsigned short int uip_hostaddr[2] = |
| 5386 | | + {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1), |
| 5387 | | + HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)}; |
| 5388 | | +const unsigned short int uip_arp_draddr[2] = |
| 5389 | | + {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1), |
| 5390 | | + HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)}; |
| 5391 | | +const unsigned short int uip_arp_netmask[2] = |
| 5392 | | + {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1), |
| 5393 | | + HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)}; |
| 5394 | | +#else |
| 5395 | | +unsigned short int uip_hostaddr[2]; |
| 5396 | | +unsigned short int uip_arp_draddr[2], uip_arp_netmask[2]; |
| 5397 | | +#endif /* UIP_FIXEDADDR */ |
| 5398 | | + |
| 5399 | | +u8_t uip_buf[UIP_BUFSIZE+2]; /* The packet buffer that contains |
| 5400 | | + incoming packets. */ |
| 5401 | | +volatile u8_t *uip_appdata; /* The uip_appdata pointer points to |
| 5402 | | + application data. */ |
| 5403 | | +volatile u8_t *uip_sappdata; /* The uip_appdata pointer points to the |
| 5404 | | + application data which is to be sent. */ |
| 5405 | | +#if UIP_URGDATA > 0 |
| 5406 | | +volatile u8_t *uip_urgdata; /* The uip_urgdata pointer points to |
| 5407 | | + urgent data (out-of-band data), if |
| 5408 | | + present. */ |
| 5409 | | +volatile u8_t uip_urglen, uip_surglen; |
| 5410 | | +#endif /* UIP_URGDATA > 0 */ |
| 5411 | | + |
| 5412 | | +volatile unsigned short int uip_len, uip_slen; |
| 5413 | | + /* The uip_len is either 8 or 16 bits, |
| 5414 | | + depending on the maximum packet |
| 5415 | | + size. */ |
| 5416 | | + |
| 5417 | | +volatile u8_t uip_flags; /* The uip_flags variable is used for |
| 5418 | | + communication between the TCP/IP stack |
| 5419 | | + and the application program. */ |
| 5420 | | +struct uip_conn *uip_conn; /* uip_conn always points to the current |
| 5421 | | + connection. */ |
| 5422 | | + |
| 5423 | | +struct uip_conn uip_conns[UIP_CONNS]; |
| 5424 | | + /* The uip_conns array holds all TCP |
| 5425 | | + connections. */ |
| 5426 | | +unsigned short int uip_listenports[UIP_LISTENPORTS]; |
| 5427 | | + /* The uip_listenports list all currently |
| 5428 | | + listning ports. */ |
| 5429 | | +#if UIP_UDP |
| 5430 | | +struct uip_udp_conn *uip_udp_conn; |
| 5431 | | +struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; |
| 5432 | | +#endif /* UIP_UDP */ |
| 5433 | | + |
| 5434 | | + |
| 5435 | | +static unsigned short int ipid; /* Ths ipid variable is an increasing |
| 5436 | | + number that is used for the IP ID |
| 5437 | | + field. */ |
| 5438 | | + |
| 5439 | | +static u8_t iss[4]; /* The iss variable is used for the TCP |
| 5440 | | + initial sequence number. */ |
| 5441 | | + |
| 5442 | | +#if UIP_ACTIVE_OPEN |
| 5443 | | +static unsigned short int lastport; /* Keeps track of the last port used for |
| 5444 | | + a new connection. */ |
| 5445 | | +#endif /* UIP_ACTIVE_OPEN */ |
| 5446 | | + |
| 5447 | | +/* Temporary variables. */ |
| 5448 | | +volatile u8_t uip_acc32[4]; |
| 5449 | | +static u8_t c, opt; |
| 5450 | | +static unsigned short int tmp16; |
| 5451 | | + |
| 5452 | | +/* Structures and definitions. */ |
| 5453 | | +#define TCP_FIN 0x01 |
| 5454 | | +#define TCP_SYN 0x02 |
| 5455 | | +#define TCP_RST 0x04 |
| 5456 | | +#define TCP_PSH 0x08 |
| 5457 | | +#define TCP_ACK 0x10 |
| 5458 | | +#define TCP_URG 0x20 |
| 5459 | | +#define TCP_CTL 0x3f |
| 5460 | | + |
| 5461 | | +#define ICMP_ECHO_REPLY 0 |
| 5462 | | +#define ICMP_ECHO 8 |
| 5463 | | + |
| 5464 | | +/* Macros. */ |
| 5465 | 5348 | +#define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) |
| 5466 | | +#define FBUF ((uip_tcpip_hdr *)&uip_reassbuf[0]) |
| 5467 | | +#define ICMPBUF ((uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN]) |
| 5468 | | +#define UDPBUF ((uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN]) |
| 5469 | | + |
| 5470 | | +#if UIP_STATISTICS == 1 |
| 5471 | | +struct uip_stats uip_stat; |
| 5472 | | +#define UIP_STAT(s) s |
| 5473 | | +#else |
| 5474 | | +#define UIP_STAT(s) |
| 5475 | | +#endif /* UIP_STATISTICS == 1 */ |
| 5476 | | + |
| 5477 | | +#if UIP_LOGGING == 1 |
| 5478 | | +extern void puts(const char *s); |
| 5479 | | +#define UIP_LOG(m) puts(m) |
| 5480 | | +#else |
| 5481 | | +#define UIP_LOG(m) |
| 5482 | | +#endif /* UIP_LOGGING == 1 */ |
| 5349 | +#define IP_PROTO_TCP 6 |
| 5483 | 5350 | + |
| 5484 | 5351 | +/*-----------------------------------------------------------------------------------*/ |
| 5485 | 5352 | +void |
| 5486 | | +uip_init(void) |
| 5353 | +uip_add32(u8_t *op32, u16_t op16) |
| 5487 | 5354 | +{ |
| 5488 | | + for(c = 0; c < UIP_LISTENPORTS; ++c) { |
| 5489 | | + uip_listenports[c] = 0; |
| 5490 | | + } |
| 5491 | | + for(c = 0; c < UIP_CONNS; ++c) { |
| 5492 | | + uip_conns[c].tcpstateflags = CLOSED; |
| 5493 | | + } |
| 5494 | | +#if UIP_ACTIVE_OPEN |
| 5495 | | + lastport = 1024; |
| 5496 | | +#endif /* UIP_ACTIVE_OPEN */ |
| 5497 | | + |
| 5498 | | +#if UIP_UDP |
| 5499 | | + for(c = 0; c < UIP_UDP_CONNS; ++c) { |
| 5500 | | + uip_udp_conns[c].lport = 0; |
| 5501 | | + } |
| 5502 | | +#endif /* UIP_UDP */ |
| 5503 | 5355 | + |
| 5504 | | + |
| 5505 | | + /* IPv4 initialization. */ |
| 5506 | | +#if UIP_FIXEDADDR == 0 |
| 5507 | | + uip_hostaddr[0] = uip_hostaddr[1] = 0; |
| 5508 | | +#endif /* UIP_FIXEDADDR */ |
| 5509 | | + |
| 5510 | | +} |
| 5511 | | +/*-----------------------------------------------------------------------------------*/ |
| 5512 | | +#if UIP_ACTIVE_OPEN |
| 5513 | | +struct uip_conn * |
| 5514 | | +uip_connect(unsigned short int *ripaddr, unsigned short int rport) |
| 5515 | | +{ |
| 5516 | | + register struct uip_conn *conn, *cconn; |
| 5356 | + uip_acc32[3] = op32[3] + (op16 & 0xff); |
| 5357 | + uip_acc32[2] = op32[2] + (op16 >> 8); |
| 5358 | + uip_acc32[1] = op32[1]; |
| 5359 | + uip_acc32[0] = op32[0]; |
| 5517 | 5360 | + |
| 5518 | | + /* Find an unused local port. */ |
| 5519 | | + again: |
| 5520 | | + ++lastport; |
| 5521 | | + |
| 5522 | | + if(lastport >= 32000) { |
| 5523 | | + lastport = 4096; |
| 5524 | | + } |
| 5525 | | + |
| 5526 | | + /* Check if this port is already in use, and if so try to find |
| 5527 | | + another one. */ |
| 5528 | | + for(c = 0; c < UIP_CONNS; ++c) { |
| 5529 | | + conn = &uip_conns[c]; |
| 5530 | | + if(conn->tcpstateflags != CLOSED && |
| 5531 | | + conn->lport == htons(lastport)) { |
| 5532 | | + goto again; |
| 5361 | + if(uip_acc32[2] < (op16 >> 8)) { |
| 5362 | + ++uip_acc32[1]; |
| 5363 | + if(uip_acc32[1] == 0) { |
| 5364 | + ++uip_acc32[0]; |
| 5533 | 5365 | + } |
| 5534 | 5366 | + } |
| 5535 | | + |
| 5536 | | + |
| 5537 | | + conn = 0; |
| 5538 | | + for(c = 0; c < UIP_CONNS; ++c) { |
| 5539 | | + cconn = &uip_conns[c]; |
| 5540 | | + if(cconn->tcpstateflags == CLOSED) { |
| 5541 | | + conn = cconn; |
| 5542 | | + break; |
| 5543 | | + } |
| 5544 | | + if(cconn->tcpstateflags == TIME_WAIT) { |
| 5545 | | + if(conn == 0 || |
| 5546 | | + cconn->timer > uip_conn->timer) { |
| 5547 | | + conn = cconn; |
| 5367 | + |
| 5368 | + |
| 5369 | + if(uip_acc32[3] < (op16 & 0xff)) { |
| 5370 | + ++uip_acc32[2]; |
| 5371 | + if(uip_acc32[2] == 0) { |
| 5372 | + ++uip_acc32[1]; |
| 5373 | + if(uip_acc32[1] == 0) { |
| 5374 | + ++uip_acc32[0]; |
| 5548 | 5375 | + } |
| 5549 | 5376 | + } |
| 5550 | 5377 | + } |
| 5551 | | + |
| 5552 | | + if(conn == 0) { |
| 5553 | | + return 0; |
| 5554 | | + } |
| 5555 | | + |
| 5556 | | + conn->tcpstateflags = SYN_SENT; |
| 5557 | | + |
| 5558 | | + conn->snd_nxt[0] = iss[0]; |
| 5559 | | + conn->snd_nxt[1] = iss[1]; |
| 5560 | | + conn->snd_nxt[2] = iss[2]; |
| 5561 | | + conn->snd_nxt[3] = iss[3]; |
| 5562 | | + |
| 5563 | | + conn->initialmss = conn->mss = UIP_TCP_MSS; |
| 5564 | | + |
| 5565 | | + conn->len = 1; /* TCP length of the SYN is one. */ |
| 5566 | | + conn->nrtx = 0; |
| 5567 | | + conn->timer = 1; /* Send the SYN next time around. */ |
| 5568 | | + conn->rto = UIP_RTO; |
| 5569 | | + conn->sa = 0; |
| 5570 | | + conn->sv = 16; |
| 5571 | | + conn->lport = htons(lastport); |
| 5572 | | + conn->rport = rport; |
| 5573 | | + conn->ripaddr[0] = ripaddr[0]; |
| 5574 | | + conn->ripaddr[1] = ripaddr[1]; |
| 5575 | | + |
| 5576 | | + return conn; |
| 5577 | 5378 | +} |
| 5578 | | +#endif /* UIP_ACTIVE_OPEN */ |
| 5579 | 5379 | +/*-----------------------------------------------------------------------------------*/ |
| 5580 | | +#if UIP_UDP |
| 5581 | | +struct uip_udp_conn * |
| 5582 | | +uip_udp_new(unsigned short int *ripaddr, unsigned short int rport) |
| 5380 | +u16_t |
| 5381 | +uip_chksum(u16_t *sdata, u16_t len) |
| 5583 | 5382 | +{ |
| 5584 | | + register struct uip_udp_conn *conn; |
| 5585 | | + |
| 5586 | | + /* Find an unused local port. */ |
| 5587 | | + again: |
| 5588 | | + ++lastport; |
| 5589 | | + |
| 5590 | | + if(lastport >= 32000) { |
| 5591 | | + lastport = 4096; |
| 5592 | | + } |
| 5383 | + u16_t acc; |
| 5593 | 5384 | + |
| 5594 | | + for(c = 0; c < UIP_UDP_CONNS; ++c) { |
| 5595 | | + if(uip_udp_conns[c].lport == lastport) { |
| 5596 | | + goto again; |
| 5385 | + for(acc = 0; len > 1; len -= 2) { |
| 5386 | + acc += *sdata; |
| 5387 | + if(acc < *sdata) { |
| 5388 | + /* Overflow, so we add the carry to acc (i.e., increase by |
| 5389 | + one). */ |
| 5390 | + ++acc; |
| 5597 | 5391 | + } |
| 5392 | + ++sdata; |
| 5598 | 5393 | + } |
| 5599 | 5394 | + |
| 5600 | | + |
| 5601 | | + conn = 0; |
| 5602 | | + for(c = 0; c < UIP_UDP_CONNS; ++c) { |
| 5603 | | + if(uip_udp_conns[c].lport == 0) { |
| 5604 | | + conn = &uip_udp_conns[c]; |
| 5605 | | + break; |
| 5395 | + /* add up any odd byte */ |
| 5396 | + if(len == 1) { |
| 5397 | + acc += htons(((u16_t)(*(u8_t *)sdata)) << 8); |
| 5398 | + if(acc < htons(((u16_t)(*(u8_t *)sdata)) << 8)) { |
| 5399 | + ++acc; |
| 5606 | 5400 | + } |
| 5607 | 5401 | + } |
| 5608 | 5402 | + |
| 5609 | | + if(conn == 0) { |
| 5610 | | + return 0; |
| 5611 | | + } |
| 5612 | | + |
| 5613 | | + conn->lport = HTONS(lastport); |
| 5614 | | + conn->rport = HTONS(rport); |
| 5615 | | + conn->ripaddr[0] = ripaddr[0]; |
| 5616 | | + conn->ripaddr[1] = ripaddr[1]; |
| 5617 | | + |
| 5618 | | + return conn; |
| 5403 | + return acc; |
| 5619 | 5404 | +} |
| 5620 | | +#endif /* UIP_UDP */ |
| 5621 | 5405 | +/*-----------------------------------------------------------------------------------*/ |
| 5622 | | +void |
| 5623 | | +uip_unlisten(unsigned short int port) |
| 5406 | +u16_t |
| 5407 | +uip_ipchksum(void) |
| 5624 | 5408 | +{ |
| 5625 | | + for(c = 0; c < UIP_LISTENPORTS; ++c) { |
| 5626 | | + if(uip_listenports[c] == port) { |
| 5627 | | + uip_listenports[c] = 0; |
| 5628 | | + return; |
| 5629 | | + } |
| 5630 | | + } |
| 5409 | + return uip_chksum((u16_t *)&uip_buf[UIP_LLH_LEN], 20); |
| 5631 | 5410 | +} |
| 5632 | 5411 | +/*-----------------------------------------------------------------------------------*/ |
| 5633 | | +void |
| 5634 | | +uip_listen(unsigned short int port) |
| 5412 | +u16_t |
| 5413 | +uip_tcpchksum(void) |
| 5635 | 5414 | +{ |
| 5636 | | + for(c = 0; c < UIP_LISTENPORTS; ++c) { |
| 5637 | | + if(uip_listenports[c] == 0) { |
| 5638 | | + uip_listenports[c] = port; |
| 5639 | | + return; |
| 5640 | | + } |
| 5641 | | + } |
| 5642 | | +} |
| 5643 | | +/*-----------------------------------------------------------------------------------*/ |
| 5644 | | +/* XXX: IP fragment reassembly: not well-tested. */ |
| 5645 | | + |
| 5646 | | +#if UIP_REASSEMBLY |
| 5647 | | +#define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN) |
| 5648 | | +static u8_t uip_reassbuf[UIP_REASS_BUFSIZE]; |
| 5649 | | +static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)]; |
| 5650 | | +static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f, |
| 5651 | | + 0x0f, 0x07, 0x03, 0x01}; |
| 5652 | | +static unsigned short int uip_reasslen; |
| 5653 | | +static u8_t uip_reassflags; |
| 5654 | | +#define UIP_REASS_FLAG_LASTFRAG 0x01 |
| 5655 | | +static u8_t uip_reasstmr; |
| 5415 | + u16_t hsum, sum; |
| 5656 | 5416 | + |
| 5657 | | +#define IP_HLEN 20 |
| 5658 | | +#define IP_MF 0x20 |
| 5417 | + |
| 5418 | + /* Compute the checksum of the TCP header. */ |
| 5419 | + hsum = uip_chksum((u16_t *)&uip_buf[20 + UIP_LLH_LEN], 20); |
| 5659 | 5420 | + |
| 5660 | | +static u8_t |
| 5661 | | +uip_reass(void) |
| 5662 | | +{ |
| 5663 | | + unsigned short int offset, len; |
| 5664 | | + unsigned short int i; |
| 5421 | + /* Compute the checksum of the data in the TCP packet and add it to |
| 5422 | + the TCP header checksum. */ |
| 5423 | + sum = uip_chksum((u16_t *)uip_appdata, |
| 5424 | + (u16_t)(((((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - 40))); |
| 5665 | 5425 | + |
| 5666 | | + /* If ip_reasstmr is zero, no packet is present in the buffer, so we |
| 5667 | | + write the IP header of the fragment into the reassembly |
| 5668 | | + buffer. The timer is updated with the maximum age. */ |
| 5669 | | + if(uip_reasstmr == 0) { |
| 5670 | | + memcpy(uip_reassbuf, &BUF->vhl, IP_HLEN); |
| 5671 | | + uip_reasstmr = UIP_REASS_MAXAGE; |
| 5672 | | + uip_reassflags = 0; |
| 5673 | | + /* Clear the bitmap. */ |
| 5674 | | + memset(uip_reassbitmap, sizeof(uip_reassbitmap), 0); |
| 5426 | + if((sum += hsum) < hsum) { |
| 5427 | + ++sum; |
| 5428 | + } |
| 5429 | + |
| 5430 | + if((sum += BUF->srcipaddr[0]) < BUF->srcipaddr[0]) { |
| 5431 | + ++sum; |
| 5432 | + } |
| 5433 | + if((sum += BUF->srcipaddr[1]) < BUF->srcipaddr[1]) { |
| 5434 | + ++sum; |
| 5435 | + } |
| 5436 | + if((sum += BUF->destipaddr[0]) < BUF->destipaddr[0]) { |
| 5437 | + ++sum; |
| 5438 | + } |
| 5439 | + if((sum += BUF->destipaddr[1]) < BUF->destipaddr[1]) { |
| 5440 | + ++sum; |
| 5441 | + } |
| 5442 | + if((sum += (u16_t)htons((u16_t)IP_PROTO_TCP)) < (u16_t)htons((u16_t)IP_PROTO_TCP)) { |
| 5443 | + ++sum; |
| 5675 | 5444 | + } |
| 5676 | 5445 | + |
| 5677 | | + /* Check if the incoming fragment matches the one currently present |
| 5678 | | + in the reasembly buffer. If so, we proceed with copying the |
| 5679 | | + fragment into the buffer. */ |
| 5680 | | + if(BUF->srcipaddr[0] == FBUF->srcipaddr[0] && |
| 5681 | | + BUF->srcipaddr[1] == FBUF->srcipaddr[1] && |
| 5682 | | + BUF->destipaddr[0] == FBUF->destipaddr[0] && |
| 5683 | | + BUF->destipaddr[1] == FBUF->destipaddr[1] && |
| 5684 | | + BUF->ipid[0] == FBUF->ipid[0] && |
| 5685 | | + BUF->ipid[1] == FBUF->ipid[1]) { |
| 5446 | + hsum = (u16_t)htons((((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - 20); |
| 5447 | + |
| 5448 | + if((sum += hsum) < hsum) { |
| 5449 | + ++sum; |
| 5450 | + } |
| 5451 | + |
| 5452 | + return sum; |
| 5453 | +} |
| 5454 | +/*-----------------------------------------------------------------------------------*/ |
| 5455 | --- /dev/null |
| 5456 | @@ -0,0 +1,130 @@ |
| 5457 | +/** |
| 5458 | + * \defgroup uiparch Architecture specific uIP functions |
| 5459 | + * @{ |
| 5460 | + * |
| 5461 | + * The functions in the architecture specific module implement the IP |
| 5462 | + * check sum and 32-bit additions. |
| 5463 | + * |
| 5464 | + * The IP checksum calculation is the most computationally expensive |
| 5465 | + * operation in the TCP/IP stack and it therefore pays off to |
| 5466 | + * implement this in efficient assembler. The purpose of the uip-arch |
| 5467 | + * module is to let the checksum functions to be implemented in |
| 5468 | + * architecture specific assembler. |
| 5469 | + * |
| 5470 | + */ |
| 5686 | 5471 | + |
| 5687 | | + len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4; |
| 5688 | | + offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8; |
| 5472 | +/** |
| 5473 | + * \file |
| 5474 | + * Declarations of architecture specific functions. |
| 5475 | + * \author Adam Dunkels <adam@dunkels.com> |
| 5476 | + */ |
| 5689 | 5477 | + |
| 5690 | | + /* If the offset or the offset + fragment length overflows the |
| 5691 | | + reassembly buffer, we discard the entire packet. */ |
| 5692 | | + if(offset > UIP_REASS_BUFSIZE || |
| 5693 | | + offset + len > UIP_REASS_BUFSIZE) { |
| 5694 | | + uip_reasstmr = 0; |
| 5695 | | + goto nullreturn; |
| 5696 | | + } |
| 5478 | +/* |
| 5479 | + * Copyright (c) 2001, Adam Dunkels. |
| 5480 | + * All rights reserved. |
| 5481 | + * |
| 5482 | + * Redistribution and use in source and binary forms, with or without |
| 5483 | + * modification, are permitted provided that the following conditions |
| 5484 | + * are met: |
| 5485 | + * 1. Redistributions of source code must retain the above copyright |
| 5486 | + * notice, this list of conditions and the following disclaimer. |
| 5487 | + * 2. Redistributions in binary form must reproduce the above copyright |
| 5488 | + * notice, this list of conditions and the following disclaimer in the |
| 5489 | + * documentation and/or other materials provided with the distribution. |
| 5490 | + * 3. The name of the author may not be used to endorse or promote |
| 5491 | + * products derived from this software without specific prior |
| 5492 | + * written permission. |
| 5493 | + * |
| 5494 | + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS |
| 5495 | + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 5496 | + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 5497 | + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
| 5498 | + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 5499 | + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
| 5500 | + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 5501 | + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| 5502 | + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| 5503 | + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 5504 | + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 5505 | + * |
| 5506 | + * This file is part of the uIP TCP/IP stack. |
| 5507 | + * |
| 5508 | + * $Id: uip_arch.h,v 1.1.2.2 2003/10/06 15:10:22 adam Exp $ |
| 5509 | + * |
| 5510 | + */ |
| 5697 | 5511 | + |
| 5698 | | + /* Copy the fragment into the reassembly buffer, at the right |
| 5699 | | + offset. */ |
| 5700 | | + memcpy(&uip_reassbuf[IP_HLEN + offset], |
| 5701 | | + (char *)BUF + (int)((BUF->vhl & 0x0f) * 4), |
| 5702 | | + len); |
| 5703 | | + |
| 5704 | | + /* Update the bitmap. */ |
| 5705 | | + if(offset / (8 * 8) == (offset + len) / (8 * 8)) { |
| 5706 | | + /* If the two endpoints are in the same byte, we only update |
| 5707 | | + that byte. */ |
| 5708 | | + |
| 5709 | | + uip_reassbitmap[offset / (8 * 8)] |= |
| 5710 | | + bitmap_bits[(offset / 8 ) & 7] & |
| 5711 | | + ~bitmap_bits[((offset + len) / 8 ) & 7]; |
| 5712 | | + } else { |
| 5713 | | + /* If the two endpoints are in different bytes, we update the |
| 5714 | | + bytes in the endpoints and fill the stuff inbetween with |
| 5715 | | + 0xff. */ |
| 5716 | | + uip_reassbitmap[offset / (8 * 8)] |= |
| 5717 | | + bitmap_bits[(offset / 8 ) & 7]; |
| 5718 | | + for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) { |
| 5719 | | + uip_reassbitmap[i] = 0xff; |
| 5720 | | + } |
| 5721 | | + uip_reassbitmap[(offset + len) / (8 * 8)] |= |
| 5722 | | + ~bitmap_bits[((offset + len) / 8 ) & 7]; |
| 5723 | | + } |
| 5724 | | + |
| 5725 | | + /* If this fragment has the More Fragments flag set to zero, we |
| 5726 | | + know that this is the last fragment, so we can calculate the |
| 5727 | | + size of the entire packet. We also set the |
| 5728 | | + IP_REASS_FLAG_LASTFRAG flag to indicate that we have received |
| 5729 | | + the final fragment. */ |
| 5512 | +#ifndef __UIP_ARCH_H__ |
| 5513 | +#define __UIP_ARCH_H__ |
| 5730 | 5514 | + |
| 5731 | | + if((BUF->ipoffset[0] & IP_MF) == 0) { |
| 5732 | | + uip_reassflags |= UIP_REASS_FLAG_LASTFRAG; |
| 5733 | | + uip_reasslen = offset + len; |
| 5734 | | + } |
| 5735 | | + |
| 5736 | | + /* Finally, we check if we have a full packet in the buffer. We do |
| 5737 | | + this by checking if we have the last fragment and if all bits |
| 5738 | | + in the bitmap are set. */ |
| 5739 | | + if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) { |
| 5740 | | + /* Check all bytes up to and including all but the last byte in |
| 5741 | | + the bitmap. */ |
| 5742 | | + for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) { |
| 5743 | | + if(uip_reassbitmap[i] != 0xff) { |
| 5744 | | + goto nullreturn; |
| 5745 | | + } |
| 5746 | | + } |
| 5747 | | + /* Check the last byte in the bitmap. It should contain just the |
| 5748 | | + right amount of bits. */ |
| 5749 | | + if(uip_reassbitmap[uip_reasslen / (8 * 8)] != |
| 5750 | | + (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) { |
| 5751 | | + goto nullreturn; |
| 5752 | | + } |
| 5515 | +#include "uip.h" |
| 5753 | 5516 | + |
| 5754 | | + /* If we have come this far, we have a full packet in the |
| 5755 | | + buffer, so we allocate a pbuf and copy the packet into it. We |
| 5756 | | + also reset the timer. */ |
| 5757 | | + uip_reasstmr = 0; |
| 5758 | | + memcpy(BUF, FBUF, uip_reasslen); |
| 5517 | +/** |
| 5518 | + * Carry out a 32-bit addition. |
| 5519 | + * |
| 5520 | + * Because not all architectures for which uIP is intended has native |
| 5521 | + * 32-bit arithmetic, uIP uses an external C function for doing the |
| 5522 | + * required 32-bit additions in the TCP protocol processing. This |
| 5523 | + * function should add the two arguments and place the result in the |
| 5524 | + * global variable uip_acc32. |
| 5525 | + * |
| 5526 | + * \note The 32-bit integer pointed to by the op32 parameter and the |
| 5527 | + * result in the uip_acc32 variable are in network byte order (big |
| 5528 | + * endian). |
| 5529 | + * |
| 5530 | + * \param op32 A pointer to a 4-byte array representing a 32-bit |
| 5531 | + * integer in network byte order (big endian). |
| 5532 | + * |
| 5533 | + * \param op16 A 16-bit integer in host byte order. |
| 5534 | + */ |
| 5535 | +void uip_add32(u8_t *op32, u16_t op16); |
| 5759 | 5536 | + |
| 5760 | | + /* Pretend to be a "normal" (i.e., not fragmented) IP packet |
| 5761 | | + from now on. */ |
| 5762 | | + BUF->ipoffset[0] = BUF->ipoffset[1] = 0; |
| 5763 | | + BUF->len[0] = uip_reasslen >> 8; |
| 5764 | | + BUF->len[1] = uip_reasslen & 0xff; |
| 5765 | | + BUF->ipchksum = 0; |
| 5766 | | + BUF->ipchksum = ~(uip_ipchksum()); |
| 5537 | +/** |
| 5538 | + * Calculate the Internet checksum over a buffer. |
| 5539 | + * |
| 5540 | + * The Internet checksum is the one's complement of the one's |
| 5541 | + * complement sum of all 16-bit words in the buffer. |
| 5542 | + * |
| 5543 | + * See RFC1071. |
| 5544 | + * |
| 5545 | + * \note This function is not called in the current version of uIP, |
| 5546 | + * but future versions might make use of it. |
| 5547 | + * |
| 5548 | + * \param buf A pointer to the buffer over which the checksum is to be |
| 5549 | + * computed. |
| 5550 | + * |
| 5551 | + * \param len The length of the buffer over which the checksum is to |
| 5552 | + * be computed. |
| 5553 | + * |
| 5554 | + * \return The Internet checksum of the buffer. |
| 5555 | + */ |
| 5556 | +u16_t uip_chksum(u16_t *buf, u16_t len); |
| 5767 | 5557 | + |
| 5768 | | + return uip_reasslen; |
| 5769 | | + } |
| 5770 | | + } |
| 5558 | +/** |
| 5559 | + * Calculate the IP header checksum of the packet header in uip_buf. |
| 5560 | + * |
| 5561 | + * The IP header checksum is the Internet checksum of the 20 bytes of |
| 5562 | + * the IP header. |
| 5563 | + * |
| 5564 | + * \return The IP header checksum of the IP header in the uip_buf |
| 5565 | + * buffer. |
| 5566 | + */ |
| 5567 | +u16_t uip_ipchksum(void); |
| 5771 | 5568 | + |
| 5772 | | + nullreturn: |
| 5773 | | + return 0; |
| 5774 | | +} |
| 5775 | | +#endif /* UIP_REASSEMBL */ |
| 5569 | +/** |
| 5570 | + * Calculate the TCP checksum of the packet in uip_buf and uip_appdata. |
| 5571 | + * |
| 5572 | + * The TCP checksum is the Internet checksum of data contents of the |
| 5573 | + * TCP segment, and a pseudo-header as defined in RFC793. |
| 5574 | + * |
| 5575 | + * \note The uip_appdata pointer that points to the packet data may |
| 5576 | + * point anywhere in memory, so it is not possible to simply calculate |
| 5577 | + * the Internet checksum of the contents of the uip_buf buffer. |
| 5578 | + * |
| 5579 | + * \return The TCP checksum of the TCP segment in uip_buf and pointed |
| 5580 | + * to by uip_appdata. |
| 5581 | + */ |
| 5582 | +u16_t uip_tcpchksum(void); |
| 5583 | + |
| 5584 | +/** @} */ |
| 5585 | + |
| 5586 | +#endif /* __UIP_ARCH_H__ */ |
| 5587 | --- /dev/null |
| 5588 | @@ -0,0 +1,421 @@ |
| 5589 | +/** |
| 5590 | + * \addtogroup uip |
| 5591 | + * @{ |
| 5592 | + */ |
| 5593 | + |
| 5594 | +/** |
| 5595 | + * \defgroup uiparp uIP Address Resolution Protocol |
| 5596 | + * @{ |
| 5597 | + * |
| 5598 | + * The Address Resolution Protocol ARP is used for mapping between IP |
| 5599 | + * addresses and link level addresses such as the Ethernet MAC |
| 5600 | + * addresses. ARP uses broadcast queries to ask for the link level |
| 5601 | + * address of a known IP address and the host which is configured with |
| 5602 | + * the IP address for which the query was meant, will respond with its |
| 5603 | + * link level address. |
| 5604 | + * |
| 5605 | + * \note This ARP implementation only supports Ethernet. |
| 5606 | + */ |
| 5607 | + |
| 5608 | +/** |
| 5609 | + * \file |
| 5610 | + * Implementation of the ARP Address Resolution Protocol. |
| 5611 | + * \author Adam Dunkels <adam@dunkels.com> |
| 5612 | + * |
| 5613 | + */ |
| 5614 | + |
| 5615 | +/* |
| 5616 | + * Copyright (c) 2001-2003, Adam Dunkels. |
| 5617 | + * All rights reserved. |
| 5618 | + * |
| 5619 | + * Redistribution and use in source and binary forms, with or without |
| 5620 | + * modification, are permitted provided that the following conditions |
| 5621 | + * are met: |
| 5622 | + * 1. Redistributions of source code must retain the above copyright |
| 5623 | + * notice, this list of conditions and the following disclaimer. |
| 5624 | + * 2. Redistributions in binary form must reproduce the above copyright |
| 5625 | + * notice, this list of conditions and the following disclaimer in the |
| 5626 | + * documentation and/or other materials provided with the distribution. |
| 5627 | + * 3. The name of the author may not be used to endorse or promote |
| 5628 | + * products derived from this software without specific prior |
| 5629 | + * written permission. |
| 5630 | + * |
| 5631 | + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS |
| 5632 | + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 5633 | + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 5634 | + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
| 5635 | + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 5636 | + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
| 5637 | + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 5638 | + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| 5639 | + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| 5640 | + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 5641 | + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 5642 | + * |
| 5643 | + * This file is part of the uIP TCP/IP stack. |
| 5644 | + * |
| 5645 | + * $Id: uip_arp.c,v 1.7.2.3 2003/10/06 22:42:30 adam Exp $ |
| 5646 | + * |
| 5647 | + */ |
| 5648 | + |
| 5649 | + |
| 5650 | +#include "uip_arp.h" |
| 5651 | + |
| 5652 | +struct arp_hdr { |
| 5653 | + struct uip_eth_hdr ethhdr; |
| 5654 | + u16_t hwtype; |
| 5655 | + u16_t protocol; |
| 5656 | + u8_t hwlen; |
| 5657 | + u8_t protolen; |
| 5658 | + u16_t opcode; |
| 5659 | + struct uip_eth_addr shwaddr; |
| 5660 | + u16_t sipaddr[2]; |
| 5661 | + struct uip_eth_addr dhwaddr; |
| 5662 | + u16_t dipaddr[2]; |
| 5663 | +}; |
| 5664 | + |
| 5665 | +struct ethip_hdr { |
| 5666 | + struct uip_eth_hdr ethhdr; |
| 5667 | + /* IP header. */ |
| 5668 | + u8_t vhl, |
| 5669 | + tos, |
| 5670 | + len[2], |
| 5671 | + ipid[2], |
| 5672 | + ipoffset[2], |
| 5673 | + ttl, |
| 5674 | + proto; |
| 5675 | + u16_t ipchksum; |
| 5676 | + u16_t srcipaddr[2], |
| 5677 | + destipaddr[2]; |
| 5678 | +}; |
| 5679 | + |
| 5680 | +#define ARP_REQUEST 1 |
| 5681 | +#define ARP_REPLY 2 |
| 5682 | + |
| 5683 | +#define ARP_HWTYPE_ETH 1 |
| 5684 | + |
| 5685 | +struct arp_entry { |
| 5686 | + u16_t ipaddr[2]; |
| 5687 | + struct uip_eth_addr ethaddr; |
| 5688 | + u8_t time; |
| 5689 | +}; |
| 5690 | + |
| 5691 | +struct uip_eth_addr uip_ethaddr = {{UIP_ETHADDR0, |
| 5692 | + UIP_ETHADDR1, |
| 5693 | + UIP_ETHADDR2, |
| 5694 | + UIP_ETHADDR3, |
| 5695 | + UIP_ETHADDR4, |
| 5696 | + UIP_ETHADDR5}}; |
| 5697 | + |
| 5698 | +static struct arp_entry arp_table[UIP_ARPTAB_SIZE]; |
| 5699 | +static u16_t ipaddr[2]; |
| 5700 | +static u8_t i, c; |
| 5701 | + |
| 5702 | +static u8_t arptime; |
| 5703 | +static u8_t tmpage; |
| 5704 | + |
| 5705 | +#define BUF ((struct arp_hdr *)&uip_buf[0]) |
| 5706 | +#define IPBUF ((struct ethip_hdr *)&uip_buf[0]) |
| 5776 | 5707 | +/*-----------------------------------------------------------------------------------*/ |
| 5777 | | +static void |
| 5778 | | +uip_add_rcv_nxt(unsigned short int n) |
| 5708 | +/** |
| 5709 | + * Initialize the ARP module. |
| 5710 | + * |
| 5711 | + */ |
| 5712 | +/*-----------------------------------------------------------------------------------*/ |
| 5713 | +void |
| 5714 | +uip_arp_init(void) |
| 5779 | 5715 | +{ |
| 5780 | | + uip_add32(uip_conn->rcv_nxt, n); |
| 5781 | | + uip_conn->rcv_nxt[0] = uip_acc32[0]; |
| 5782 | | + uip_conn->rcv_nxt[1] = uip_acc32[1]; |
| 5783 | | + uip_conn->rcv_nxt[2] = uip_acc32[2]; |
| 5784 | | + uip_conn->rcv_nxt[3] = uip_acc32[3]; |
| 5716 | + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { |
| 5717 | + memset(arp_table[i].ipaddr, 0, 4); |
| 5718 | + } |
| 5785 | 5719 | +} |
| 5786 | 5720 | +/*-----------------------------------------------------------------------------------*/ |
| 5721 | +/** |
| 5722 | + * Periodic ARP processing function. |
| 5723 | + * |
| 5724 | + * This function performs periodic timer processing in the ARP module |
| 5725 | + * and should be called at regular intervals. The recommended interval |
| 5726 | + * is 10 seconds between the calls. |
| 5727 | + * |
| 5728 | + */ |
| 5729 | +/*-----------------------------------------------------------------------------------*/ |
| 5787 | 5730 | +void |
| 5788 | | +uip_process(u8_t flag) |
| 5731 | +uip_arp_timer(void) |
| 5789 | 5732 | +{ |
| 5790 | | + register struct uip_conn *uip_connr = uip_conn; |
| 5791 | | + |
| 5792 | | + uip_appdata = &uip_buf[40 + UIP_LLH_LEN]; |
| 5793 | | + |
| 5733 | + struct arp_entry *tabptr; |
| 5794 | 5734 | + |
| 5795 | | + /* Check if we were invoked because of the perodic timer fireing. */ |
| 5796 | | + if(flag == UIP_TIMER) { |
| 5797 | | +#if UIP_REASSEMBLY |
| 5798 | | + if(uip_reasstmr != 0) { |
| 5799 | | + --uip_reasstmr; |
| 5735 | + ++arptime; |
| 5736 | + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { |
| 5737 | + tabptr = &arp_table[i]; |
| 5738 | + if((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 && |
| 5739 | + arptime - tabptr->time >= UIP_ARP_MAXAGE) { |
| 5740 | + memset(tabptr->ipaddr, 0, 4); |
| 5800 | 5741 | + } |
| 5801 | | +#endif /* UIP_REASSEMBLY */ |
| 5802 | | + /* Increase the initial sequence number. */ |
| 5803 | | + if(++iss[3] == 0) { |
| 5804 | | + if(++iss[2] == 0) { |
| 5805 | | + if(++iss[1] == 0) { |
| 5806 | | + ++iss[0]; |
| 5807 | | + } |
| 5808 | | + } |
| 5809 | | + } |
| 5810 | | + uip_len = 0; |
| 5811 | | + if(uip_connr->tcpstateflags == TIME_WAIT || |
| 5812 | | + uip_connr->tcpstateflags == FIN_WAIT_2) { |
| 5813 | | + ++(uip_connr->timer); |
| 5814 | | + if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) { |
| 5815 | | + uip_connr->tcpstateflags = CLOSED; |
| 5816 | | + } |
| 5817 | | + } else if(uip_connr->tcpstateflags != CLOSED) { |
| 5818 | | + /* If the connection has outstanding data, we increase the |
| 5819 | | + connection's timer and see if it has reached the RTO value |
| 5820 | | + in which case we retransmit. */ |
| 5821 | | + if(uip_outstanding(uip_connr)) { |
| 5822 | | + if(uip_connr->timer-- == 0) { |
| 5823 | | + if(uip_connr->nrtx == UIP_MAXRTX || |
| 5824 | | + ((uip_connr->tcpstateflags == SYN_SENT || |
| 5825 | | + uip_connr->tcpstateflags == SYN_RCVD) && |
| 5826 | | + uip_connr->nrtx == UIP_MAXSYNRTX)) { |
| 5827 | | + uip_connr->tcpstateflags = CLOSED; |
| 5742 | + } |
| 5828 | 5743 | + |
| 5829 | | + /* We call UIP_APPCALL() with uip_flags set to |
| 5830 | | + UIP_TIMEDOUT to inform the application that the |
| 5831 | | + connection has timed out. */ |
| 5832 | | + uip_flags = UIP_TIMEDOUT; |
| 5833 | | + UIP_APPCALL(); |
| 5744 | +} |
| 5745 | +/*-----------------------------------------------------------------------------------*/ |
| 5746 | +static void |
| 5747 | +uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr) |
| 5748 | +{ |
| 5749 | + register struct arp_entry *tabptr; |
| 5750 | + /* Walk through the ARP mapping table and try to find an entry to |
| 5751 | + update. If none is found, the IP -> MAC address mapping is |
| 5752 | + inserted in the ARP table. */ |
| 5753 | + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { |
| 5834 | 5754 | + |
| 5835 | | + /* We also send a reset packet to the remote host. */ |
| 5836 | | + BUF->flags = TCP_RST | TCP_ACK; |
| 5837 | | + goto tcp_send_nodata; |
| 5838 | | + } |
| 5755 | + tabptr = &arp_table[i]; |
| 5756 | + /* Only check those entries that are actually in use. */ |
| 5757 | + if(tabptr->ipaddr[0] != 0 && |
| 5758 | + tabptr->ipaddr[1] != 0) { |
| 5839 | 5759 | + |
| 5840 | | + /* Exponential backoff. */ |
| 5841 | | + uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4? |
| 5842 | | + 4: |
| 5843 | | + uip_connr->nrtx); |
| 5844 | | + ++(uip_connr->nrtx); |
| 5845 | | + |
| 5846 | | + /* Ok, so we need to retransmit. We do this differently |
| 5847 | | + depending on which state we are in. In ESTABLISHED, we |
| 5848 | | + call upon the application so that it may prepare the |
| 5849 | | + data for the retransmit. In SYN_RCVD, we resend the |
| 5850 | | + SYNACK that we sent earlier and in LAST_ACK we have to |
| 5851 | | + retransmit our FINACK. */ |
| 5852 | | + UIP_STAT(++uip_stat.tcp.rexmit); |
| 5853 | | + switch(uip_connr->tcpstateflags & TS_MASK) { |
| 5854 | | + case SYN_RCVD: |
| 5855 | | + /* In the SYN_RCVD state, we should retransmit our |
| 5856 | | + SYNACK. */ |
| 5857 | | + goto tcp_send_synack; |
| 5858 | | + |
| 5859 | | +#if UIP_ACTIVE_OPEN |
| 5860 | | + case SYN_SENT: |
| 5861 | | + /* In the SYN_SENT state, we retransmit out SYN. */ |
| 5862 | | + BUF->flags = 0; |
| 5863 | | + goto tcp_send_syn; |
| 5864 | | +#endif /* UIP_ACTIVE_OPEN */ |
| 5865 | | + |
| 5866 | | + case ESTABLISHED: |
| 5867 | | + /* In the ESTABLISHED state, we call upon the application |
| 5868 | | + to do the actual retransmit after which we jump into |
| 5869 | | + the code for sending out the packet (the apprexmit |
| 5870 | | + label). */ |
| 5871 | | + uip_len = 0; |
| 5872 | | + uip_slen = 0; |
| 5873 | | + uip_flags = UIP_REXMIT; |
| 5874 | | + UIP_APPCALL(); |
| 5875 | | + goto apprexmit; |
| 5876 | | + |
| 5877 | | + case FIN_WAIT_1: |
| 5878 | | + case CLOSING: |
| 5879 | | + case LAST_ACK: |
| 5880 | | + /* In all these states we should retransmit a FINACK. */ |
| 5881 | | + goto tcp_send_finack; |
| 5882 | | + |
| 5883 | | + } |
| 5884 | | + } |
| 5885 | | + } else if((uip_connr->tcpstateflags & TS_MASK) == ESTABLISHED) { |
| 5886 | | + /* If there was no need for a retransmission, we poll the |
| 5887 | | + application for new data. */ |
| 5888 | | + uip_len = 0; |
| 5889 | | + uip_slen = 0; |
| 5890 | | + uip_flags = UIP_POLL; |
| 5891 | | + UIP_APPCALL(); |
| 5892 | | + goto appsend; |
| 5760 | + /* Check if the source IP address of the incoming packet matches |
| 5761 | + the IP address in this ARP table entry. */ |
| 5762 | + if(ipaddr[0] == tabptr->ipaddr[0] && |
| 5763 | + ipaddr[1] == tabptr->ipaddr[1]) { |
| 5764 | + |
| 5765 | + /* An old entry found, update this and return. */ |
| 5766 | + memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); |
| 5767 | + tabptr->time = arptime; |
| 5768 | + |
| 5769 | + return; |
| 5893 | 5770 | + } |
| 5894 | 5771 | + } |
| 5895 | | + goto drop; |
| 5896 | | + } |
| 5897 | | +#if UIP_UDP |
| 5898 | | + if(flag == UIP_UDP_TIMER) { |
| 5899 | | + if(uip_udp_conn->lport != 0) { |
| 5900 | | + uip_appdata = &uip_buf[UIP_LLH_LEN + 28]; |
| 5901 | | + uip_len = uip_slen = 0; |
| 5902 | | + uip_flags = UIP_POLL; |
| 5903 | | + UIP_UDP_APPCALL(); |
| 5904 | | + goto udp_send; |
| 5905 | | + } else { |
| 5906 | | + goto drop; |
| 5907 | | + } |
| 5908 | 5772 | + } |
| 5909 | | +#endif |
| 5910 | | + |
| 5911 | | + /* This is where the input processing starts. */ |
| 5912 | | + UIP_STAT(++uip_stat.ip.recv); |
| 5913 | 5773 | + |
| 5774 | + /* If we get here, no existing ARP table entry was found, so we |
| 5775 | + create one. */ |
| 5914 | 5776 | + |
| 5915 | | + /* Start of IPv4 input header processing code. */ |
| 5916 | | + |
| 5917 | | + /* Check validity of the IP header. */ |
| 5918 | | + if(BUF->vhl != 0x45) { /* IP version and header length. */ |
| 5919 | | + UIP_STAT(++uip_stat.ip.drop); |
| 5920 | | + UIP_STAT(++uip_stat.ip.vhlerr); |
| 5921 | | + UIP_LOG("ip: invalid version or header length."); |
| 5922 | | + goto drop; |
| 5923 | | + } |
| 5924 | | + |
| 5925 | | + /* Check the size of the packet. If the size reported to us in |
| 5926 | | + uip_len doesn't match the size reported in the IP header, there |
| 5927 | | + has been a transmission error and we drop the packet. */ |
| 5928 | | + |
| 5929 | | + if(BUF->len[0] != (uip_len >> 8)) { /* IP length, high byte. */ |
| 5930 | | + uip_len = (uip_len & 0xff) | (BUF->len[0] << 8); |
| 5931 | | + } |
| 5932 | | + if(BUF->len[1] != (uip_len & 0xff)) { /* IP length, low byte. */ |
| 5933 | | + uip_len = (uip_len & 0xff00) | BUF->len[1]; |
| 5934 | | + } |
| 5935 | | + |
| 5936 | | + /* Check the fragment flag. */ |
| 5937 | | + if((BUF->ipoffset[0] & 0x3f) != 0 || |
| 5938 | | + BUF->ipoffset[1] != 0) { |
| 5939 | | +#if UIP_REASSEMBLY |
| 5940 | | + uip_len = uip_reass(); |
| 5941 | | + if(uip_len == 0) { |
| 5942 | | + goto drop; |
| 5777 | + /* First, we try to find an unused entry in the ARP table. */ |
| 5778 | + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { |
| 5779 | + tabptr = &arp_table[i]; |
| 5780 | + if(tabptr->ipaddr[0] == 0 && |
| 5781 | + tabptr->ipaddr[1] == 0) { |
| 5782 | + break; |
| 5943 | 5783 | + } |
| 5944 | | +#else |
| 5945 | | + UIP_STAT(++uip_stat.ip.drop); |
| 5946 | | + UIP_STAT(++uip_stat.ip.fragerr); |
| 5947 | | + UIP_LOG("ip: fragment dropped."); |
| 5948 | | + goto drop; |
| 5949 | | +#endif /* UIP_REASSEMBLY */ |
| 5950 | 5784 | + } |
| 5951 | 5785 | + |
| 5952 | | + /* If we are configured to use ping IP address configuration and |
| 5953 | | + hasn't been assigned an IP address yet, we accept all ICMP |
| 5954 | | + packets. */ |
| 5955 | | +#if UIP_PINGADDRCONF |
| 5956 | | + if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) { |
| 5957 | | + if(BUF->proto == UIP_PROTO_ICMP) { |
| 5958 | | + UIP_LOG("ip: possible ping config packet received."); |
| 5959 | | + goto icmp_input; |
| 5960 | | + } else { |
| 5961 | | + UIP_LOG("ip: packet dropped since no address assigned."); |
| 5962 | | + goto drop; |
| 5786 | + /* If no unused entry is found, we try to find the oldest entry and |
| 5787 | + throw it away. */ |
| 5788 | + if(i == UIP_ARPTAB_SIZE) { |
| 5789 | + tmpage = 0; |
| 5790 | + c = 0; |
| 5791 | + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { |
| 5792 | + tabptr = &arp_table[i]; |
| 5793 | + if(arptime - tabptr->time > tmpage) { |
| 5794 | + tmpage = arptime - tabptr->time; |
| 5795 | + c = i; |
| 5796 | + } |
| 5963 | 5797 | + } |
| 5798 | + i = c; |
| 5964 | 5799 | + } |
| 5965 | | +#endif /* UIP_PINGADDRCONF */ |
| 5966 | | + |
| 5967 | | + /* Check if the packet is destined for our IP address. */ |
| 5968 | | + if(BUF->destipaddr[0] != uip_hostaddr[0]) { |
| 5969 | | + UIP_STAT(++uip_stat.ip.drop); |
| 5970 | | + UIP_LOG("ip: packet not for us."); |
| 5971 | | + goto drop; |
| 5800 | + |
| 5801 | + /* Now, i is the ARP table entry which we will fill with the new |
| 5802 | + information. */ |
| 5803 | + memcpy(tabptr->ipaddr, ipaddr, 4); |
| 5804 | + memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); |
| 5805 | + tabptr->time = arptime; |
| 5806 | +} |
| 5807 | +/*-----------------------------------------------------------------------------------*/ |
| 5808 | +/** |
| 5809 | + * ARP processing for incoming IP packets |
| 5810 | + * |
| 5811 | + * This function should be called by the device driver when an IP |
| 5812 | + * packet has been received. The function will check if the address is |
| 5813 | + * in the ARP cache, and if so the ARP cache entry will be |
| 5814 | + * refreshed. If no ARP cache entry was found, a new one is created. |
| 5815 | + * |
| 5816 | + * This function expects an IP packet with a prepended Ethernet header |
| 5817 | + * in the uip_buf[] buffer, and the length of the packet in the global |
| 5818 | + * variable uip_len. |
| 5819 | + */ |
| 5820 | +/*-----------------------------------------------------------------------------------*/ |
| 5821 | +void |
| 5822 | +uip_arp_ipin(void) |
| 5823 | +{ |
| 5824 | + uip_len -= sizeof(struct uip_eth_hdr); |
| 5825 | + |
| 5826 | + /* Only insert/update an entry if the source IP address of the |
| 5827 | + incoming IP packet comes from a host on the local network. */ |
| 5828 | + if((IPBUF->srcipaddr[0] & uip_arp_netmask[0]) != |
| 5829 | + (uip_hostaddr[0] & uip_arp_netmask[0])) { |
| 5830 | + return; |
| 5972 | 5831 | + } |
| 5973 | | + if(BUF->destipaddr[1] != uip_hostaddr[1]) { |
| 5974 | | + UIP_STAT(++uip_stat.ip.drop); |
| 5975 | | + UIP_LOG("ip: packet not for us."); |
| 5976 | | + goto drop; |
| 5832 | + if((IPBUF->srcipaddr[1] & uip_arp_netmask[1]) != |
| 5833 | + (uip_hostaddr[1] & uip_arp_netmask[1])) { |
| 5834 | + return; |
| 5977 | 5835 | + } |
| 5836 | + uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src)); |
| 5837 | + |
| 5838 | + return; |
| 5839 | +} |
| 5840 | +/*-----------------------------------------------------------------------------------*/ |
| 5841 | +/** |
| 5842 | + * ARP processing for incoming ARP packets. |
| 5843 | + * |
| 5844 | + * This function should be called by the device driver when an ARP |
| 5845 | + * packet has been received. The function will act differently |
| 5846 | + * depending on the ARP packet type: if it is a reply for a request |
| 5847 | + * that we previously sent out, the ARP cache will be filled in with |
| 5848 | + * the values from the ARP reply. If the incoming ARP packet is an ARP |
| 5849 | + * request for our IP address, an ARP reply packet is created and put |
| 5850 | + * into the uip_buf[] buffer. |
| 5851 | + * |
| 5852 | + * When the function returns, the value of the global variable uip_len |
| 5853 | + * indicates whether the device driver should send out a packet or |
| 5854 | + * not. If uip_len is zero, no packet should be sent. If uip_len is |
| 5855 | + * non-zero, it contains the length of the outbound packet that is |
| 5856 | + * present in the uip_buf[] buffer. |
| 5857 | + * |
| 5858 | + * This function expects an ARP packet with a prepended Ethernet |
| 5859 | + * header in the uip_buf[] buffer, and the length of the packet in the |
| 5860 | + * global variable uip_len. |
| 5861 | + */ |
| 5862 | +/*-----------------------------------------------------------------------------------*/ |
| 5863 | +void |
| 5864 | +uip_arp_arpin(void) |
| 5865 | +{ |
| 5978 | 5866 | + |
| 5979 | | + if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header |
| 5980 | | + checksum. */ |
| 5981 | | + UIP_STAT(++uip_stat.ip.drop); |
| 5982 | | + UIP_STAT(++uip_stat.ip.chkerr); |
| 5983 | | + UIP_LOG("ip: bad checksum."); |
| 5984 | | + goto drop; |
| 5867 | + if(uip_len < sizeof(struct arp_hdr)) { |
| 5868 | + uip_len = 0; |
| 5869 | + return; |
| 5985 | 5870 | + } |
| 5986 | 5871 | + |
| 5987 | | + if(BUF->proto == UIP_PROTO_TCP) /* Check for TCP packet. If so, jump |
| 5988 | | + to the tcp_input label. */ |
| 5989 | | + goto tcp_input; |
| 5990 | | + |
| 5991 | | +#if UIP_UDP |
| 5992 | | + if(BUF->proto == UIP_PROTO_UDP) |
| 5993 | | + goto udp_input; |
| 5994 | | +#endif /* UIP_UDP */ |
| 5872 | + uip_len = 0; |
| 5995 | 5873 | + |
| 5996 | | + if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from |
| 5997 | | + here. */ |
| 5998 | | + UIP_STAT(++uip_stat.ip.drop); |
| 5999 | | + UIP_STAT(++uip_stat.ip.protoerr); |
| 6000 | | + UIP_LOG("ip: neither tcp nor icmp."); |
| 6001 | | + goto drop; |
| 6002 | | + } |
| 6003 | | + |
| 6004 | | + //icmp_input: |
| 6005 | | + UIP_STAT(++uip_stat.icmp.recv); |
| 6006 | | + |
| 6007 | | + /* ICMP echo (i.e., ping) processing. This is simple, we only change |
| 6008 | | + the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP |
| 6009 | | + checksum before we return the packet. */ |
| 6010 | | + if(ICMPBUF->type != ICMP_ECHO) { |
| 6011 | | + UIP_STAT(++uip_stat.icmp.drop); |
| 6012 | | + UIP_STAT(++uip_stat.icmp.typeerr); |
| 6013 | | + UIP_LOG("icmp: not icmp echo."); |
| 6014 | | + goto drop; |
| 6015 | | + } |
| 5874 | + switch(BUF->opcode) { |
| 5875 | + case HTONS(ARP_REQUEST): |
| 5876 | + /* ARP request. If it asked for our address, we send out a |
| 5877 | + reply. */ |
| 5878 | + if(BUF->dipaddr[0] == uip_hostaddr[0] && |
| 5879 | + BUF->dipaddr[1] == uip_hostaddr[1]) { |
| 5880 | + /* The reply opcode is 2. */ |
| 5881 | + BUF->opcode = HTONS(2); |
| 6016 | 5882 | + |
| 6017 | | + /* If we are configured to use ping IP address assignment, we use |
| 6018 | | + the destination IP address of this ping packet and assign it to |
| 6019 | | + ourself. */ |
| 6020 | | +#if UIP_PINGADDRCONF |
| 6021 | | + if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) { |
| 6022 | | + uip_hostaddr[0] = BUF->destipaddr[0]; |
| 6023 | | + uip_hostaddr[1] = BUF->destipaddr[1]; |
| 5883 | + memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6); |
| 5884 | + memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); |
| 5885 | + memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); |
| 5886 | + memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6); |
| 5887 | + |
| 5888 | + BUF->dipaddr[0] = BUF->sipaddr[0]; |
| 5889 | + BUF->dipaddr[1] = BUF->sipaddr[1]; |
| 5890 | + BUF->sipaddr[0] = uip_hostaddr[0]; |
| 5891 | + BUF->sipaddr[1] = uip_hostaddr[1]; |
| 5892 | + |
| 5893 | + BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); |
| 5894 | + uip_len = sizeof(struct arp_hdr); |
| 5895 | + } |
| 5896 | + break; |
| 5897 | + case HTONS(ARP_REPLY): |
| 5898 | + /* ARP reply. We insert or update the ARP table if it was meant |
| 5899 | + for us. */ |
| 5900 | + if(BUF->dipaddr[0] == uip_hostaddr[0] && |
| 5901 | + BUF->dipaddr[1] == uip_hostaddr[1]) { |
| 5902 | + |
| 5903 | + uip_arp_update(BUF->sipaddr, &BUF->shwaddr); |
| 5904 | + } |
| 5905 | + break; |
| 6024 | 5906 | + } |
| 6025 | | +#endif /* UIP_PINGADDRCONF */ |
| 6026 | | + |
| 6027 | | + ICMPBUF->type = ICMP_ECHO_REPLY; |
| 6028 | | + |
| 6029 | | + if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) { |
| 6030 | | + ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1; |
| 5907 | + |
| 5908 | + return; |
| 5909 | +} |
| 5910 | +/*-----------------------------------------------------------------------------------*/ |
| 5911 | +/** |
| 5912 | + * Prepend Ethernet header to an outbound IP packet and see if we need |
| 5913 | + * to send out an ARP request. |
| 5914 | + * |
| 5915 | + * This function should be called before sending out an IP packet. The |
| 5916 | + * function checks the destination IP address of the IP packet to see |
| 5917 | + * what Ethernet MAC address that should be used as a destination MAC |
| 5918 | + * address on the Ethernet. |
| 5919 | + * |
| 5920 | + * If the destination IP address is in the local network (determined |
| 5921 | + * by logical ANDing of netmask and our IP address), the function |
| 5922 | + * checks the ARP cache to see if an entry for the destination IP |
| 5923 | + * address is found. If so, an Ethernet header is prepended and the |
| 5924 | + * function returns. If no ARP cache entry is found for the |
| 5925 | + * destination IP address, the packet in the uip_buf[] is replaced by |
| 5926 | + * an ARP request packet for the IP address. The IP packet is dropped |
| 5927 | + * and it is assumed that they higher level protocols (e.g., TCP) |
| 5928 | + * eventually will retransmit the dropped packet. |
| 5929 | + * |
| 5930 | + * If the destination IP address is not on the local network, the IP |
| 5931 | + * address of the default router is used instead. |
| 5932 | + * |
| 5933 | + * When the function returns, a packet is present in the uip_buf[] |
| 5934 | + * buffer, and the length of the packet is in the global variable |
| 5935 | + * uip_len. |
| 5936 | + */ |
| 5937 | +/*-----------------------------------------------------------------------------------*/ |
| 5938 | +void |
| 5939 | +uip_arp_out(void) |
| 5940 | +{ |
| 5941 | + struct arp_entry *tabptr; |
| 5942 | + /* Find the destination IP address in the ARP table and construct |
| 5943 | + the Ethernet header. If the destination IP addres isn't on the |
| 5944 | + local network, we use the default router's IP address instead. |
| 5945 | + |
| 5946 | + If not ARP table entry is found, we overwrite the original IP |
| 5947 | + packet with an ARP request for the IP address. */ |
| 5948 | + |
| 5949 | + /* Check if the destination address is on the local network. */ |
| 5950 | + if((IPBUF->destipaddr[0] & uip_arp_netmask[0]) != |
| 5951 | + (uip_hostaddr[0] & uip_arp_netmask[0]) || |
| 5952 | + (IPBUF->destipaddr[1] & uip_arp_netmask[1]) != |
| 5953 | + (uip_hostaddr[1] & uip_arp_netmask[1])) { |
| 5954 | + /* Destination address was not on the local network, so we need to |
| 5955 | + use the default router's IP address instead of the destination |
| 5956 | + address when determining the MAC address. */ |
| 5957 | + ipaddr[0] = uip_arp_draddr[0]; |
| 5958 | + ipaddr[1] = uip_arp_draddr[1]; |
| 6031 | 5959 | + } else { |
| 6032 | | + ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8); |
| 5960 | + /* Else, we use the destination IP address. */ |
| 5961 | + ipaddr[0] = IPBUF->destipaddr[0]; |
| 5962 | + ipaddr[1] = IPBUF->destipaddr[1]; |
| 5963 | + } |
| 5964 | + |
| 5965 | + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { |
| 5966 | + tabptr = &arp_table[i]; |
| 5967 | + if(ipaddr[0] == tabptr->ipaddr[0] && |
| 5968 | + ipaddr[1] == tabptr->ipaddr[1]) |
| 5969 | + break; |
| 6033 | 5970 | + } |
| 6034 | | + |
| 6035 | | + /* Swap IP addresses. */ |
| 6036 | | + tmp16 = BUF->destipaddr[0]; |
| 6037 | | + BUF->destipaddr[0] = BUF->srcipaddr[0]; |
| 6038 | | + BUF->srcipaddr[0] = tmp16; |
| 6039 | | + tmp16 = BUF->destipaddr[1]; |
| 6040 | | + BUF->destipaddr[1] = BUF->srcipaddr[1]; |
| 6041 | | + BUF->srcipaddr[1] = tmp16; |
| 6042 | | + |
| 6043 | | + UIP_STAT(++uip_stat.icmp.sent); |
| 6044 | | + goto send; |
| 6045 | 5971 | + |
| 6046 | | + /* End of IPv4 input header processing code. */ |
| 6047 | | + |
| 5972 | + if(i == UIP_ARPTAB_SIZE) { |
| 5973 | + /* The destination address was not in our ARP table, so we |
| 5974 | + overwrite the IP packet with an ARP request. */ |
| 6048 | 5975 | + |
| 6049 | | +#if UIP_UDP |
| 6050 | | + /* UDP input processing. */ |
| 6051 | | + udp_input: |
| 6052 | | + /* UDP processing is really just a hack. We don't do anything to the |
| 6053 | | + UDP/IP headers, but let the UDP application do all the hard |
| 6054 | | + work. If the application sets uip_slen, it has a packet to |
| 6055 | | + send. */ |
| 6056 | | +#if UIP_UDP_CHECKSUMS |
| 6057 | | + if(uip_udpchksum() != 0xffff) { |
| 6058 | | + UIP_STAT(++uip_stat.udp.drop); |
| 6059 | | + UIP_STAT(++uip_stat.udp.chkerr); |
| 6060 | | + UIP_LOG("udp: bad checksum."); |
| 6061 | | + goto drop; |
| 6062 | | + } |
| 6063 | | +#endif /* UIP_UDP_CHECKSUMS */ |
| 5976 | + memset(BUF->ethhdr.dest.addr, 0xff, 6); |
| 5977 | + memset(BUF->dhwaddr.addr, 0x00, 6); |
| 5978 | + memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); |
| 5979 | + memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); |
| 5980 | + |
| 5981 | + BUF->dipaddr[0] = ipaddr[0]; |
| 5982 | + BUF->dipaddr[1] = ipaddr[1]; |
| 5983 | + BUF->sipaddr[0] = uip_hostaddr[0]; |
| 5984 | + BUF->sipaddr[1] = uip_hostaddr[1]; |
| 5985 | + BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */ |
| 5986 | + BUF->hwtype = HTONS(ARP_HWTYPE_ETH); |
| 5987 | + BUF->protocol = HTONS(UIP_ETHTYPE_IP); |
| 5988 | + BUF->hwlen = 6; |
| 5989 | + BUF->protolen = 4; |
| 5990 | + BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); |
| 6064 | 5991 | + |
| 6065 | | + /* Demultiplex this UDP packet between the UDP "connections". */ |
| 6066 | | + for(uip_udp_conn = &uip_udp_conns[0]; |
| 6067 | | + uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS]; |
| 6068 | | + ++uip_udp_conn) { |
| 6069 | | + if(uip_udp_conn->lport != 0 && |
| 6070 | | + UDPBUF->destport == uip_udp_conn->lport && |
| 6071 | | + (uip_udp_conn->rport == 0 || |
| 6072 | | + UDPBUF->srcport == uip_udp_conn->rport) && |
| 6073 | | + BUF->srcipaddr[0] == uip_udp_conn->ripaddr[0] && |
| 6074 | | + BUF->srcipaddr[1] == uip_udp_conn->ripaddr[1]) { |
| 6075 | | + goto udp_found; |
| 6076 | | + } |
| 6077 | | + } |
| 6078 | | + goto drop; |
| 6079 | | + |
| 6080 | | + udp_found: |
| 6081 | | + uip_len = uip_len - 28; |
| 6082 | | + uip_appdata = &uip_buf[UIP_LLH_LEN + 28]; |
| 6083 | | + uip_flags = UIP_NEWDATA; |
| 6084 | | + uip_slen = 0; |
| 6085 | | + UIP_UDP_APPCALL(); |
| 6086 | | + udp_send: |
| 6087 | | + if(uip_slen == 0) { |
| 6088 | | + goto drop; |
| 5992 | + uip_appdata = &uip_buf[40 + UIP_LLH_LEN]; |
| 5993 | + |
| 5994 | + uip_len = sizeof(struct arp_hdr); |
| 5995 | + return; |
| 6089 | 5996 | + } |
| 6090 | | + uip_len = uip_slen + 28; |
| 6091 | 5997 | + |
| 6092 | | + BUF->len[0] = (uip_len >> 8); |
| 6093 | | + BUF->len[1] = (uip_len & 0xff); |
| 5998 | + /* Build an ethernet header. */ |
| 5999 | + memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6); |
| 6000 | + memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6); |
| 6094 | 6001 | + |
| 6095 | | + BUF->proto = UIP_PROTO_UDP; |
| 6002 | + IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP); |
| 6096 | 6003 | + |
| 6097 | | + UDPBUF->udplen = HTONS(uip_slen + 8); |
| 6098 | | + UDPBUF->udpchksum = 0; |
| 6099 | | +#if UIP_UDP_CHECKSUMS |
| 6100 | | + /* Calculate UDP checksum. */ |
| 6101 | | + UDPBUF->udpchksum = ~(uip_udpchksum()); |
| 6102 | | + if(UDPBUF->udpchksum == 0) { |
| 6103 | | + UDPBUF->udpchksum = 0xffff; |
| 6104 | | + } |
| 6105 | | +#endif /* UIP_UDP_CHECKSUMS */ |
| 6004 | + uip_len += sizeof(struct uip_eth_hdr); |
| 6005 | +} |
| 6006 | +/*-----------------------------------------------------------------------------------*/ |
| 6106 | 6007 | + |
| 6107 | | + BUF->srcport = uip_udp_conn->lport; |
| 6108 | | + BUF->destport = uip_udp_conn->rport; |
| 6008 | +/** @} */ |
| 6009 | +/** @} */ |
| 6010 | --- /dev/null |
| 6011 | @@ -0,0 +1,201 @@ |
| 6012 | +/** |
| 6013 | + * \addtogroup uip |
| 6014 | + * @{ |
| 6015 | + */ |
| 6109 | 6016 | + |
| 6110 | | + BUF->srcipaddr[0] = uip_hostaddr[0]; |
| 6111 | | + BUF->srcipaddr[1] = uip_hostaddr[1]; |
| 6112 | | + BUF->destipaddr[0] = uip_udp_conn->ripaddr[0]; |
| 6113 | | + BUF->destipaddr[1] = uip_udp_conn->ripaddr[1]; |
| 6017 | +/** |
| 6018 | + * \addtogroup uiparp |
| 6019 | + * @{ |
| 6020 | + */ |
| 6114 | 6021 | + |
| 6115 | | + uip_appdata = &uip_buf[UIP_LLH_LEN + 40]; |
| 6116 | | + goto ip_send_nolen; |
| 6117 | | +#endif /* UIP_UDP */ |
| 6022 | +/** |
| 6023 | + * \file |
| 6024 | + * Macros and definitions for the ARP module. |
| 6025 | + * \author Adam Dunkels <adam@dunkels.com> |
| 6026 | + */ |
| 6118 | 6027 | + |
| 6119 | | + /* TCP input processing. */ |
| 6120 | | + tcp_input: |
| 6121 | | + UIP_STAT(++uip_stat.tcp.recv); |
| 6122 | 6028 | + |
| 6123 | | + /* Start of TCP input header processing code. */ |
| 6124 | | + |
| 6125 | | + if(uip_tcpchksum() != 0xffff) { /* Compute and check the TCP |
| 6126 | | + checksum. */ |
| 6127 | | + UIP_STAT(++uip_stat.tcp.drop); |
| 6128 | | + UIP_STAT(++uip_stat.tcp.chkerr); |
| 6129 | | + UIP_LOG("tcp: bad checksum."); |
| 6130 | | + goto drop; |
| 6131 | | + } |
| 6132 | | + |
| 6133 | | + /* Demultiplex this segment. */ |
| 6134 | | + /* First check any active connections. */ |
| 6135 | | + for(uip_connr = &uip_conns[0]; uip_connr < &uip_conns[UIP_CONNS]; ++uip_connr) { |
| 6136 | | + if(uip_connr->tcpstateflags != CLOSED && |
| 6137 | | + BUF->destport == uip_connr->lport && |
| 6138 | | + BUF->srcport == uip_connr->rport && |
| 6139 | | + BUF->srcipaddr[0] == uip_connr->ripaddr[0] && |
| 6140 | | + BUF->srcipaddr[1] == uip_connr->ripaddr[1]) { |
| 6141 | | + goto found; |
| 6142 | | + } |
| 6143 | | + } |
| 6144 | | + |
| 6145 | | + /* If we didn't find and active connection that expected the packet, |
| 6146 | | + either this packet is an old duplicate, or this is a SYN packet |
| 6147 | | + destined for a connection in LISTEN. If the SYN flag isn't set, |
| 6148 | | + it is an old packet and we send a RST. */ |
| 6149 | | + if((BUF->flags & TCP_CTL) != TCP_SYN) |
| 6150 | | + goto reset; |
| 6151 | | + |
| 6152 | | + tmp16 = BUF->destport; |
| 6153 | | + /* Next, check listening connections. */ |
| 6154 | | + for(c = 0; c < UIP_LISTENPORTS; ++c) { |
| 6155 | | + if(tmp16 == uip_listenports[c]) |
| 6156 | | + goto found_listen; |
| 6157 | | + } |
| 6158 | | + |
| 6159 | | + /* No matching connection found, so we send a RST packet. */ |
| 6160 | | + UIP_STAT(++uip_stat.tcp.synrst); |
| 6161 | | + reset: |
| 6029 | +/* |
| 6030 | + * Copyright (c) 2001-2003, Adam Dunkels. |
| 6031 | + * All rights reserved. |
| 6032 | + * |
| 6033 | + * Redistribution and use in source and binary forms, with or without |
| 6034 | + * modification, are permitted provided that the following conditions |
| 6035 | + * are met: |
| 6036 | + * 1. Redistributions of source code must retain the above copyright |
| 6037 | + * notice, this list of conditions and the following disclaimer. |
| 6038 | + * 2. Redistributions in binary form must reproduce the above copyright |
| 6039 | + * notice, this list of conditions and the following disclaimer in the |
| 6040 | + * documentation and/or other materials provided with the distribution. |
| 6041 | + * 3. The name of the author may not be used to endorse or promote |
| 6042 | + * products derived from this software without specific prior |
| 6043 | + * written permission. |
| 6044 | + * |
| 6045 | + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS |
| 6046 | + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 6047 | + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 6048 | + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
| 6049 | + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 6050 | + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
| 6051 | + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 6052 | + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| 6053 | + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| 6054 | + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 6055 | + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 6056 | + * |
| 6057 | + * This file is part of the uIP TCP/IP stack. |
| 6058 | + * |
| 6059 | + * $Id: uip_arp.h,v 1.3.2.2 2003/10/06 15:10:22 adam Exp $ |
| 6060 | + * |
| 6061 | + */ |
| 6162 | 6062 | + |
| 6163 | | + /* We do not send resets in response to resets. */ |
| 6164 | | + if(BUF->flags & TCP_RST) |
| 6165 | | + goto drop; |
| 6063 | +#ifndef __UIP_ARP_H__ |
| 6064 | +#define __UIP_ARP_H__ |
| 6166 | 6065 | + |
| 6167 | | + UIP_STAT(++uip_stat.tcp.rst); |
| 6168 | | + |
| 6169 | | + BUF->flags = TCP_RST | TCP_ACK; |
| 6170 | | + uip_len = 40; |
| 6171 | | + BUF->tcpoffset = 5 << 4; |
| 6066 | +#include "uip.h" |
| 6172 | 6067 | + |
| 6173 | | + /* Flip the seqno and ackno fields in the TCP header. */ |
| 6174 | | + c = BUF->seqno[3]; |
| 6175 | | + BUF->seqno[3] = BUF->ackno[3]; |
| 6176 | | + BUF->ackno[3] = c; |
| 6177 | | + |
| 6178 | | + c = BUF->seqno[2]; |
| 6179 | | + BUF->seqno[2] = BUF->ackno[2]; |
| 6180 | | + BUF->ackno[2] = c; |
| 6181 | | + |
| 6182 | | + c = BUF->seqno[1]; |
| 6183 | | + BUF->seqno[1] = BUF->ackno[1]; |
| 6184 | | + BUF->ackno[1] = c; |
| 6185 | | + |
| 6186 | | + c = BUF->seqno[0]; |
| 6187 | | + BUF->seqno[0] = BUF->ackno[0]; |
| 6188 | | + BUF->ackno[0] = c; |
| 6189 | 6068 | + |
| 6190 | | + /* We also have to increase the sequence number we are |
| 6191 | | + acknowledging. If the least significant byte overflowed, we need |
| 6192 | | + to propagate the carry to the other bytes as well. */ |
| 6193 | | + if(++BUF->ackno[3] == 0) { |
| 6194 | | + if(++BUF->ackno[2] == 0) { |
| 6195 | | + if(++BUF->ackno[1] == 0) { |
| 6196 | | + ++BUF->ackno[0]; |
| 6197 | | + } |
| 6198 | | + } |
| 6199 | | + } |
| 6200 | | + |
| 6201 | | + /* Swap port numbers. */ |
| 6202 | | + tmp16 = BUF->srcport; |
| 6203 | | + BUF->srcport = BUF->destport; |
| 6204 | | + BUF->destport = tmp16; |
| 6205 | | + |
| 6206 | | + /* Swap IP addresses. */ |
| 6207 | | + tmp16 = BUF->destipaddr[0]; |
| 6208 | | + BUF->destipaddr[0] = BUF->srcipaddr[0]; |
| 6209 | | + BUF->srcipaddr[0] = tmp16; |
| 6210 | | + tmp16 = BUF->destipaddr[1]; |
| 6211 | | + BUF->destipaddr[1] = BUF->srcipaddr[1]; |
| 6212 | | + BUF->srcipaddr[1] = tmp16; |
| 6069 | +/** |
| 6070 | + * Representation of a 48-bit Ethernet address. |
| 6071 | + */ |
| 6072 | +struct uip_eth_addr { |
| 6073 | + u8_t addr[6]; |
| 6074 | +}; |
| 6213 | 6075 | + |
| 6214 | | + |
| 6215 | | + /* And send out the RST packet! */ |
| 6216 | | + goto tcp_send_noconn; |
| 6076 | +extern struct uip_eth_addr uip_ethaddr; |
| 6217 | 6077 | + |
| 6218 | | + /* This label will be jumped to if we matched the incoming packet |
| 6219 | | + with a connection in LISTEN. In that case, we should create a new |
| 6220 | | + connection and send a SYNACK in return. */ |
| 6221 | | + found_listen: |
| 6222 | | + /* First we check if there are any connections avaliable. Unused |
| 6223 | | + connections are kept in the same table as used connections, but |
| 6224 | | + unused ones have the tcpstate set to CLOSED. Also, connections in |
| 6225 | | + TIME_WAIT are kept track of and we'll use the oldest one if no |
| 6226 | | + CLOSED connections are found. Thanks to Eddie C. Dost for a very |
| 6227 | | + nice algorithm for the TIME_WAIT search. */ |
| 6228 | | + uip_connr = 0; |
| 6229 | | + for(c = 0; c < UIP_CONNS; ++c) { |
| 6230 | | + if(uip_conns[c].tcpstateflags == CLOSED) { |
| 6231 | | + uip_connr = &uip_conns[c]; |
| 6232 | | + break; |
| 6233 | | + } |
| 6234 | | + if(uip_conns[c].tcpstateflags == TIME_WAIT) { |
| 6235 | | + if(uip_connr == 0 || |
| 6236 | | + uip_conns[c].timer > uip_connr->timer) { |
| 6237 | | + uip_connr = &uip_conns[c]; |
| 6238 | | + } |
| 6239 | | + } |
| 6240 | | + } |
| 6078 | +/** |
| 6079 | + * The Ethernet header. |
| 6080 | + */ |
| 6081 | +struct uip_eth_hdr { |
| 6082 | + struct uip_eth_addr dest; |
| 6083 | + struct uip_eth_addr src; |
| 6084 | + u16_t type; |
| 6085 | +}; |
| 6241 | 6086 | + |
| 6242 | | + if(uip_connr == 0) { |
| 6243 | | + /* All connections are used already, we drop packet and hope that |
| 6244 | | + the remote end will retransmit the packet at a time when we |
| 6245 | | + have more spare connections. */ |
| 6246 | | + UIP_STAT(++uip_stat.tcp.syndrop); |
| 6247 | | + UIP_LOG("tcp: found no unused connections."); |
| 6248 | | + goto drop; |
| 6249 | | + } |
| 6250 | | + uip_conn = uip_connr; |
| 6251 | | + |
| 6252 | | + /* Fill in the necessary fields for the new connection. */ |
| 6253 | | + uip_connr->rto = uip_connr->timer = UIP_RTO; |
| 6254 | | + uip_connr->sa = 0; |
| 6255 | | + uip_connr->sv = 4; |
| 6256 | | + uip_connr->nrtx = 0; |
| 6257 | | + uip_connr->lport = BUF->destport; |
| 6258 | | + uip_connr->rport = BUF->srcport; |
| 6259 | | + uip_connr->ripaddr[0] = BUF->srcipaddr[0]; |
| 6260 | | + uip_connr->ripaddr[1] = BUF->srcipaddr[1]; |
| 6261 | | + uip_connr->tcpstateflags = SYN_RCVD; |
| 6087 | +#define UIP_ETHTYPE_ARP 0x0806 |
| 6088 | +#define UIP_ETHTYPE_IP 0x0800 |
| 6089 | +#define UIP_ETHTYPE_IP6 0x86dd |
| 6262 | 6090 | + |
| 6263 | | + uip_connr->snd_nxt[0] = iss[0]; |
| 6264 | | + uip_connr->snd_nxt[1] = iss[1]; |
| 6265 | | + uip_connr->snd_nxt[2] = iss[2]; |
| 6266 | | + uip_connr->snd_nxt[3] = iss[3]; |
| 6267 | | + uip_connr->len = 1; |
| 6268 | 6091 | + |
| 6269 | | + /* rcv_nxt should be the seqno from the incoming packet + 1. */ |
| 6270 | | + uip_connr->rcv_nxt[3] = BUF->seqno[3]; |
| 6271 | | + uip_connr->rcv_nxt[2] = BUF->seqno[2]; |
| 6272 | | + uip_connr->rcv_nxt[1] = BUF->seqno[1]; |
| 6273 | | + uip_connr->rcv_nxt[0] = BUF->seqno[0]; |
| 6274 | | + uip_add_rcv_nxt(1); |
| 6092 | +/* The uip_arp_init() function must be called before any of the other |
| 6093 | + ARP functions. */ |
| 6094 | +void uip_arp_init(void); |
| 6275 | 6095 | + |
| 6276 | | + /* Parse the TCP MSS option, if present. */ |
| 6277 | | + if((BUF->tcpoffset & 0xf0) > 0x50) { |
| 6278 | | + for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { |
| 6279 | | + opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c]; |
| 6280 | | + if(opt == 0x00) { |
| 6281 | | + /* End of options. */ |
| 6282 | | + break; |
| 6283 | | + } else if(opt == 0x01) { |
| 6284 | | + ++c; |
| 6285 | | + /* NOP option. */ |
| 6286 | | + } else if(opt == 0x02 && |
| 6287 | | + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) { |
| 6288 | | + /* An MSS option with the right option length. */ |
| 6289 | | + tmp16 = ((unsigned short int)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | |
| 6290 | | + (unsigned short int)uip_buf[40 + UIP_LLH_LEN + 3 + c]; |
| 6291 | | + uip_connr->initialmss = uip_connr->mss = |
| 6292 | | + tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; |
| 6293 | | + |
| 6294 | | + /* And we are done processing options. */ |
| 6295 | | + break; |
| 6296 | | + } else { |
| 6297 | | + /* All other options have a length field, so that we easily |
| 6298 | | + can skip past them. */ |
| 6299 | | + if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { |
| 6300 | | + /* If the length field is zero, the options are malformed |
| 6301 | | + and we don't process them further. */ |
| 6302 | | + break; |
| 6303 | | + } |
| 6304 | | + c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; |
| 6305 | | + } |
| 6306 | | + } |
| 6307 | | + } |
| 6308 | | + |
| 6309 | | + /* Our response will be a SYNACK. */ |
| 6310 | | +#if UIP_ACTIVE_OPEN |
| 6311 | | + tcp_send_synack: |
| 6312 | | + BUF->flags = TCP_ACK; |
| 6313 | | + |
| 6314 | | + tcp_send_syn: |
| 6315 | | + BUF->flags |= TCP_SYN; |
| 6316 | | +#else /* UIP_ACTIVE_OPEN */ |
| 6317 | | + tcp_send_synack: |
| 6318 | | + BUF->flags = TCP_SYN | TCP_ACK; |
| 6319 | | +#endif /* UIP_ACTIVE_OPEN */ |
| 6320 | | + |
| 6321 | | + /* We send out the TCP Maximum Segment Size option with our |
| 6322 | | + SYNACK. */ |
| 6323 | | + BUF->optdata[0] = 2; |
| 6324 | | + BUF->optdata[1] = 4; |
| 6325 | | + BUF->optdata[2] = (UIP_TCP_MSS) / 256; |
| 6326 | | + BUF->optdata[3] = (UIP_TCP_MSS) & 255; |
| 6327 | | + uip_len = 44; |
| 6328 | | + BUF->tcpoffset = 6 << 4; |
| 6329 | | + goto tcp_send; |
| 6096 | +/* The uip_arp_ipin() function should be called whenever an IP packet |
| 6097 | + arrives from the Ethernet. This function refreshes the ARP table or |
| 6098 | + inserts a new mapping if none exists. The function assumes that an |
| 6099 | + IP packet with an Ethernet header is present in the uip_buf buffer |
| 6100 | + and that the length of the packet is in the uip_len variable. */ |
| 6101 | +void uip_arp_ipin(void); |
| 6330 | 6102 | + |
| 6331 | | + /* This label will be jumped to if we found an active connection. */ |
| 6332 | | + found: |
| 6333 | | + uip_conn = uip_connr; |
| 6334 | | + uip_flags = 0; |
| 6103 | +/* The uip_arp_arpin() should be called when an ARP packet is received |
| 6104 | + by the Ethernet driver. This function also assumes that the |
| 6105 | + Ethernet frame is present in the uip_buf buffer. When the |
| 6106 | + uip_arp_arpin() function returns, the contents of the uip_buf |
| 6107 | + buffer should be sent out on the Ethernet if the uip_len variable |
| 6108 | + is > 0. */ |
| 6109 | +void uip_arp_arpin(void); |
| 6335 | 6110 | + |
| 6336 | | + /* We do a very naive form of TCP reset processing; we just accept |
| 6337 | | + any RST and kill our connection. We should in fact check if the |
| 6338 | | + sequence number of this reset is wihtin our advertised window |
| 6339 | | + before we accept the reset. */ |
| 6340 | | + if(BUF->flags & TCP_RST) { |
| 6341 | | + uip_connr->tcpstateflags = CLOSED; |
| 6342 | | + UIP_LOG("tcp: got reset, aborting connection."); |
| 6343 | | + uip_flags = UIP_ABORT; |
| 6344 | | + UIP_APPCALL(); |
| 6345 | | + goto drop; |
| 6346 | | + } |
| 6347 | | + /* Calculated the length of the data, if the application has sent |
| 6348 | | + any data to us. */ |
| 6349 | | + c = (BUF->tcpoffset >> 4) << 2; |
| 6350 | | + /* uip_len will contain the length of the actual TCP data. This is |
| 6351 | | + calculated by subtracing the length of the TCP header (in |
| 6352 | | + c) and the length of the IP header (20 bytes). */ |
| 6353 | | + uip_len = uip_len - c - 20; |
| 6111 | +/* The uip_arp_out() function should be called when an IP packet |
| 6112 | + should be sent out on the Ethernet. This function creates an |
| 6113 | + Ethernet header before the IP header in the uip_buf buffer. The |
| 6114 | + Ethernet header will have the correct Ethernet MAC destination |
| 6115 | + address filled in if an ARP table entry for the destination IP |
| 6116 | + address (or the IP address of the default router) is present. If no |
| 6117 | + such table entry is found, the IP packet is overwritten with an ARP |
| 6118 | + request and we rely on TCP to retransmit the packet that was |
| 6119 | + overwritten. In any case, the uip_len variable holds the length of |
| 6120 | + the Ethernet frame that should be transmitted. */ |
| 6121 | +void uip_arp_out(void); |
| 6354 | 6122 | + |
| 6355 | | + /* First, check if the sequence number of the incoming packet is |
| 6356 | | + what we're expecting next. If not, we send out an ACK with the |
| 6357 | | + correct numbers in. */ |
| 6358 | | + if(uip_len > 0 && |
| 6359 | | + (BUF->seqno[0] != uip_connr->rcv_nxt[0] || |
| 6360 | | + BUF->seqno[1] != uip_connr->rcv_nxt[1] || |
| 6361 | | + BUF->seqno[2] != uip_connr->rcv_nxt[2] || |
| 6362 | | + BUF->seqno[3] != uip_connr->rcv_nxt[3])) { |
| 6363 | | + goto tcp_send_ack; |
| 6364 | | + } |
| 6123 | +/* The uip_arp_timer() function should be called every ten seconds. It |
| 6124 | + is responsible for flushing old entries in the ARP table. */ |
| 6125 | +void uip_arp_timer(void); |
| 6365 | 6126 | + |
| 6366 | | + /* Next, check if the incoming segment acknowledges any outstanding |
| 6367 | | + data. If so, we update the sequence number, reset the length of |
| 6368 | | + the outstanding data, calculate RTT estimations, and reset the |
| 6369 | | + retransmission timer. */ |
| 6370 | | + if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) { |
| 6371 | | + uip_add32(uip_connr->snd_nxt, uip_connr->len); |
| 6372 | | + if(BUF->ackno[0] == uip_acc32[0] && |
| 6373 | | + BUF->ackno[1] == uip_acc32[1] && |
| 6374 | | + BUF->ackno[2] == uip_acc32[2] && |
| 6375 | | + BUF->ackno[3] == uip_acc32[3]) { |
| 6376 | | + /* Update sequence number. */ |
| 6377 | | + uip_connr->snd_nxt[0] = uip_acc32[0]; |
| 6378 | | + uip_connr->snd_nxt[1] = uip_acc32[1]; |
| 6379 | | + uip_connr->snd_nxt[2] = uip_acc32[2]; |
| 6380 | | + uip_connr->snd_nxt[3] = uip_acc32[3]; |
| 6381 | | + |
| 6127 | +/** @} */ |
| 6382 | 6128 | + |
| 6383 | | + /* Do RTT estimation, unless we have done retransmissions. */ |
| 6384 | | + if(uip_connr->nrtx == 0) { |
| 6385 | | + signed char m; |
| 6386 | | + m = uip_connr->rto - uip_connr->timer; |
| 6387 | | + /* This is taken directly from VJs original code in his paper */ |
| 6388 | | + m = m - (uip_connr->sa >> 3); |
| 6389 | | + uip_connr->sa += m; |
| 6390 | | + if(m < 0) { |
| 6391 | | + m = -m; |
| 6392 | | + } |
| 6393 | | + m = m - (uip_connr->sv >> 2); |
| 6394 | | + uip_connr->sv += m; |
| 6395 | | + uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv; |
| 6129 | +/** |
| 6130 | + * \addtogroup uipconffunc |
| 6131 | + * @{ |
| 6132 | + */ |
| 6396 | 6133 | + |
| 6397 | | + } |
| 6398 | | + /* Set the acknowledged flag. */ |
| 6399 | | + uip_flags = UIP_ACKDATA; |
| 6400 | | + /* Reset the retransmission timer. */ |
| 6401 | | + uip_connr->timer = uip_connr->rto; |
| 6402 | | + } |
| 6403 | | + |
| 6404 | | + } |
| 6134 | +/** |
| 6135 | + * Set the default router's IP address. |
| 6136 | + * |
| 6137 | + * \param addr A pointer to a 4-byte array containing the IP address |
| 6138 | + * of the default router. |
| 6139 | + * |
| 6140 | + * \hideinitializer |
| 6141 | + */ |
| 6142 | +#define uip_setdraddr(addr) do { uip_arp_draddr[0] = addr[0]; \ |
| 6143 | + uip_arp_draddr[1] = addr[1]; } while(0) |
| 6405 | 6144 | + |
| 6406 | | + /* Do different things depending on in what state the connection is. */ |
| 6407 | | + switch(uip_connr->tcpstateflags & TS_MASK) { |
| 6408 | | + /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not |
| 6409 | | + implemented, since we force the application to close when the |
| 6410 | | + peer sends a FIN (hence the application goes directly from |
| 6411 | | + ESTABLISHED to LAST_ACK). */ |
| 6412 | | + case SYN_RCVD: |
| 6413 | | + /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and |
| 6414 | | + we are waiting for an ACK that acknowledges the data we sent |
| 6415 | | + out the last time. Therefore, we want to have the UIP_ACKDATA |
| 6416 | | + flag set. If so, we enter the ESTABLISHED state. */ |
| 6417 | | + if(uip_flags & UIP_ACKDATA) { |
| 6418 | | + uip_connr->tcpstateflags = ESTABLISHED; |
| 6419 | | + uip_flags = UIP_CONNECTED; |
| 6420 | | + uip_connr->len = 0; |
| 6421 | | + if(uip_len > 0) { |
| 6422 | | + uip_flags |= UIP_NEWDATA; |
| 6423 | | + uip_add_rcv_nxt(uip_len); |
| 6424 | | + } |
| 6425 | | + uip_slen = 0; |
| 6426 | | + UIP_APPCALL(); |
| 6427 | | + goto appsend; |
| 6428 | | + } |
| 6429 | | + goto drop; |
| 6430 | | +#if UIP_ACTIVE_OPEN |
| 6431 | | + case SYN_SENT: |
| 6432 | | + /* In SYN_SENT, we wait for a SYNACK that is sent in response to |
| 6433 | | + our SYN. The rcv_nxt is set to sequence number in the SYNACK |
| 6434 | | + plus one, and we send an ACK. We move into the ESTABLISHED |
| 6435 | | + state. */ |
| 6436 | | + if((uip_flags & UIP_ACKDATA) && |
| 6437 | | + BUF->flags == (TCP_SYN | TCP_ACK)) { |
| 6145 | +/** |
| 6146 | + * Set the netmask. |
| 6147 | + * |
| 6148 | + * \param addr A pointer to a 4-byte array containing the IP address |
| 6149 | + * of the netmask. |
| 6150 | + * |
| 6151 | + * \hideinitializer |
| 6152 | + */ |
| 6153 | +#define uip_setnetmask(addr) do { uip_arp_netmask[0] = addr[0]; \ |
| 6154 | + uip_arp_netmask[1] = addr[1]; } while(0) |
| 6438 | 6155 | + |
| 6439 | | + /* Parse the TCP MSS option, if present. */ |
| 6440 | | + if((BUF->tcpoffset & 0xf0) > 0x50) { |
| 6441 | | + for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { |
| 6442 | | + opt = uip_buf[40 + UIP_LLH_LEN + c]; |
| 6443 | | + if(opt == 0x00) { |
| 6444 | | + /* End of options. */ |
| 6445 | | + break; |
| 6446 | | + } else if(opt == 0x01) { |
| 6447 | | + ++c; |
| 6448 | | + /* NOP option. */ |
| 6449 | | + } else if(opt == 0x02 && |
| 6450 | | + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) { |
| 6451 | | + /* An MSS option with the right option length. */ |
| 6452 | | + tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | |
| 6453 | | + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c]; |
| 6454 | | + uip_connr->initialmss = |
| 6455 | | + uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; |
| 6456 | 6156 | + |
| 6457 | | + /* And we are done processing options. */ |
| 6458 | | + break; |
| 6459 | | + } else { |
| 6460 | | + /* All other options have a length field, so that we easily |
| 6461 | | + can skip past them. */ |
| 6462 | | + if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { |
| 6463 | | + /* If the length field is zero, the options are malformed |
| 6464 | | + and we don't process them further. */ |
| 6465 | | + break; |
| 6466 | | + } |
| 6467 | | + c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; |
| 6468 | | + } |
| 6469 | | + } |
| 6470 | | + } |
| 6471 | | + uip_connr->tcpstateflags = ESTABLISHED; |
| 6472 | | + uip_connr->rcv_nxt[0] = BUF->seqno[0]; |
| 6473 | | + uip_connr->rcv_nxt[1] = BUF->seqno[1]; |
| 6474 | | + uip_connr->rcv_nxt[2] = BUF->seqno[2]; |
| 6475 | | + uip_connr->rcv_nxt[3] = BUF->seqno[3]; |
| 6476 | | + uip_add_rcv_nxt(1); |
| 6477 | | + uip_flags = UIP_CONNECTED | UIP_NEWDATA; |
| 6478 | | + uip_connr->len = 0; |
| 6479 | | + uip_len = 0; |
| 6480 | | + uip_slen = 0; |
| 6481 | | + UIP_APPCALL(); |
| 6482 | | + goto appsend; |
| 6483 | | + } |
| 6484 | | + goto reset; |
| 6485 | | +#endif /* UIP_ACTIVE_OPEN */ |
| 6486 | | + |
| 6487 | | + case ESTABLISHED: |
| 6488 | | + /* In the ESTABLISHED state, we call upon the application to feed |
| 6489 | | + data into the uip_buf. If the UIP_ACKDATA flag is set, the |
| 6490 | | + application should put new data into the buffer, otherwise we are |
| 6491 | | + retransmitting an old segment, and the application should put that |
| 6492 | | + data into the buffer. |
| 6157 | +/** |
| 6158 | + * Get the default router's IP address. |
| 6159 | + * |
| 6160 | + * \param addr A pointer to a 4-byte array that will be filled in with |
| 6161 | + * the IP address of the default router. |
| 6162 | + * |
| 6163 | + * \hideinitializer |
| 6164 | + */ |
| 6165 | +#define uip_getdraddr(addr) do { addr[0] = uip_arp_draddr[0]; \ |
| 6166 | + addr[1] = uip_arp_draddr[1]; } while(0) |
| 6493 | 6167 | + |
| 6494 | | + If the incoming packet is a FIN, we should close the connection on |
| 6495 | | + this side as well, and we send out a FIN and enter the LAST_ACK |
| 6496 | | + state. We require that there is no outstanding data; otherwise the |
| 6497 | | + sequence numbers will be screwed up. */ |
| 6168 | +/** |
| 6169 | + * Get the netmask. |
| 6170 | + * |
| 6171 | + * \param addr A pointer to a 4-byte array that will be filled in with |
| 6172 | + * the value of the netmask. |
| 6173 | + * |
| 6174 | + * \hideinitializer |
| 6175 | + */ |
| 6176 | +#define uip_getnetmask(addr) do { addr[0] = uip_arp_netmask[0]; \ |
| 6177 | + addr[1] = uip_arp_netmask[1]; } while(0) |
| 6498 | 6178 | + |
| 6499 | | + if(BUF->flags & TCP_FIN) { |
| 6500 | | + if(uip_outstanding(uip_connr)) { |
| 6501 | | + goto drop; |
| 6502 | | + } |
| 6503 | | + uip_add_rcv_nxt(1 + uip_len); |
| 6504 | | + uip_flags = UIP_CLOSE; |
| 6505 | | + if(uip_len > 0) { |
| 6506 | | + uip_flags |= UIP_NEWDATA; |
| 6507 | | + } |
| 6508 | | + UIP_APPCALL(); |
| 6509 | | + uip_connr->len = 1; |
| 6510 | | + uip_connr->tcpstateflags = LAST_ACK; |
| 6511 | | + uip_connr->nrtx = 0; |
| 6512 | | + tcp_send_finack: |
| 6513 | | + BUF->flags = TCP_FIN | TCP_ACK; |
| 6514 | | + goto tcp_send_nodata; |
| 6515 | | + } |
| 6516 | 6179 | + |
| 6517 | | + /* Check the URG flag. If this is set, the segment carries urgent |
| 6518 | | + data that we must pass to the application. */ |
| 6519 | | + if(BUF->flags & TCP_URG) { |
| 6520 | | +#if UIP_URGDATA > 0 |
| 6521 | | + uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1]; |
| 6522 | | + if(uip_urglen > uip_len) { |
| 6523 | | + /* There is more urgent data in the next segment to come. */ |
| 6524 | | + uip_urglen = uip_len; |
| 6525 | | + } |
| 6526 | | + uip_add_rcv_nxt(uip_urglen); |
| 6527 | | + uip_len -= uip_urglen; |
| 6528 | | + uip_urgdata = uip_appdata; |
| 6529 | | + uip_appdata += uip_urglen; |
| 6530 | | + } else { |
| 6531 | | + uip_urglen = 0; |
| 6532 | | +#endif /* UIP_URGDATA > 0 */ |
| 6533 | | + uip_appdata += (BUF->urgp[0] << 8) | BUF->urgp[1]; |
| 6534 | | + uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1]; |
| 6535 | | + } |
| 6536 | | + |
| 6537 | | + |
| 6538 | | + /* If uip_len > 0 we have TCP data in the packet, and we flag this |
| 6539 | | + by setting the UIP_NEWDATA flag and update the sequence number |
| 6540 | | + we acknowledge. If the application has stopped the dataflow |
| 6541 | | + using uip_stop(), we must not accept any data packets from the |
| 6542 | | + remote host. */ |
| 6543 | | + if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) { |
| 6544 | | + uip_flags |= UIP_NEWDATA; |
| 6545 | | + uip_add_rcv_nxt(uip_len); |
| 6546 | | + } |
| 6180 | +/** |
| 6181 | + * Specifiy the Ethernet MAC address. |
| 6182 | + * |
| 6183 | + * The ARP code needs to know the MAC address of the Ethernet card in |
| 6184 | + * order to be able to respond to ARP queries and to generate working |
| 6185 | + * Ethernet headers. |
| 6186 | + * |
| 6187 | + * \note This macro only specifies the Ethernet MAC address to the ARP |
| 6188 | + * code. It cannot be used to change the MAC address of the Ethernet |
| 6189 | + * card. |
| 6190 | + * |
| 6191 | + * \param eaddr A pointer to a struct uip_eth_addr containing the |
| 6192 | + * Ethernet MAC address of the Ethernet card. |
| 6193 | + * |
| 6194 | + * \hideinitializer |
| 6195 | + */ |
| 6196 | +#define uip_setethaddr(eaddr) do {uip_ethaddr.addr[0] = eaddr.addr[0]; \ |
| 6197 | + uip_ethaddr.addr[1] = eaddr.addr[1];\ |
| 6198 | + uip_ethaddr.addr[2] = eaddr.addr[2];\ |
| 6199 | + uip_ethaddr.addr[3] = eaddr.addr[3];\ |
| 6200 | + uip_ethaddr.addr[4] = eaddr.addr[4];\ |
| 6201 | + uip_ethaddr.addr[5] = eaddr.addr[5];} while(0) |
| 6547 | 6202 | + |
| 6548 | | + /* Check if the available buffer space advertised by the other end |
| 6549 | | + is smaller than the initial MSS for this connection. If so, we |
| 6550 | | + set the current MSS to the window size to ensure that the |
| 6551 | | + application does not send more data than the other end can |
| 6552 | | + handle. |
| 6203 | +/** @} */ |
| 6553 | 6204 | + |
| 6554 | | + If the remote host advertises a zero window, we set the MSS to |
| 6555 | | + the initial MSS so that the application will send an entire MSS |
| 6556 | | + of data. This data will not be acknowledged by the receiver, |
| 6557 | | + and the application will retransmit it. This is called the |
| 6558 | | + "persistent timer" and uses the retransmission mechanim. |
| 6559 | | + */ |
| 6560 | | + tmp16 = ((unsigned short int)BUF->wnd[0] << 8) + (unsigned short int)BUF->wnd[1]; |
| 6561 | | + if(tmp16 > uip_connr->initialmss || |
| 6562 | | + tmp16 == 0) { |
| 6563 | | + tmp16 = uip_connr->initialmss; |
| 6564 | | + } |
| 6565 | | + uip_connr->mss = tmp16; |
| 6205 | +/** |
| 6206 | + * \internal Internal variables that are set using the macros |
| 6207 | + * uip_setdraddr and uip_setnetmask. |
| 6208 | + */ |
| 6209 | +extern u16_t uip_arp_draddr[2], uip_arp_netmask[2]; |
| 6210 | +#endif /* __UIP_ARP_H__ */ |
| 6566 | 6211 | + |
| 6567 | | + /* If this packet constitutes an ACK for outstanding data (flagged |
| 6568 | | + by the UIP_ACKDATA flag, we should call the application since it |
| 6569 | | + might want to send more data. If the incoming packet had data |
| 6570 | | + from the peer (as flagged by the UIP_NEWDATA flag), the |
| 6571 | | + application must also be notified. |
| 6572 | 6212 | + |
| 6573 | | + When the application is called, the global variable uip_len |
| 6574 | | + contains the length of the incoming data. The application can |
| 6575 | | + access the incoming data through the global pointer |
| 6576 | | + uip_appdata, which usually points 40 bytes into the uip_buf |
| 6577 | | + array. |
| 6213 | --- /dev/null |
| 6214 | @@ -0,0 +1,1503 @@ |
| 6215 | +/** |
| 6216 | + * \addtogroup uip |
| 6217 | + * @{ |
| 6218 | + */ |
| 6578 | 6219 | + |
| 6579 | | + If the application wishes to send any data, this data should be |
| 6580 | | + put into the uip_appdata and the length of the data should be |
| 6581 | | + put into uip_len. If the application don't have any data to |
| 6582 | | + send, uip_len must be set to 0. */ |
| 6583 | | + if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) { |
| 6584 | | + uip_slen = 0; |
| 6585 | | + UIP_APPCALL(); |
| 6220 | +/** |
| 6221 | + * \file |
| 6222 | + * The uIP TCP/IP stack code. |
| 6223 | + * \author Adam Dunkels <adam@dunkels.com> |
| 6224 | + */ |
| 6586 | 6225 | + |
| 6587 | | + appsend: |
| 6588 | | + |
| 6589 | | + if(uip_flags & UIP_ABORT) { |
| 6590 | | + uip_slen = 0; |
| 6591 | | + uip_connr->tcpstateflags = CLOSED; |
| 6592 | | + BUF->flags = TCP_RST | TCP_ACK; |
| 6593 | | + goto tcp_send_nodata; |
| 6594 | | + } |
| 6226 | +/* |
| 6227 | + * Copyright (c) 2001-2003, Adam Dunkels. |
| 6228 | + * All rights reserved. |
| 6229 | + * |
| 6230 | + * Redistribution and use in source and binary forms, with or without |
| 6231 | + * modification, are permitted provided that the following conditions |
| 6232 | + * are met: |
| 6233 | + * 1. Redistributions of source code must retain the above copyright |
| 6234 | + * notice, this list of conditions and the following disclaimer. |
| 6235 | + * 2. Redistributions in binary form must reproduce the above copyright |
| 6236 | + * notice, this list of conditions and the following disclaimer in the |
| 6237 | + * documentation and/or other materials provided with the distribution. |
| 6238 | + * 3. The name of the author may not be used to endorse or promote |
| 6239 | + * products derived from this software without specific prior |
| 6240 | + * written permission. |
| 6241 | + * |
| 6242 | + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS |
| 6243 | + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 6244 | + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 6245 | + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
| 6246 | + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 6247 | + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
| 6248 | + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 6249 | + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| 6250 | + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| 6251 | + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 6252 | + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 6253 | + * |
| 6254 | + * This file is part of the uIP TCP/IP stack. |
| 6255 | + * |
| 6256 | + * $Id: uip.c,v 1.62.2.10 2003/10/07 13:23:01 adam Exp $ |
| 6257 | + * |
| 6258 | + */ |
| 6595 | 6259 | + |
| 6596 | | + if(uip_flags & UIP_CLOSE) { |
| 6597 | | + uip_slen = 0; |
| 6598 | | + uip_connr->len = 1; |
| 6599 | | + uip_connr->tcpstateflags = FIN_WAIT_1; |
| 6600 | | + uip_connr->nrtx = 0; |
| 6601 | | + BUF->flags = TCP_FIN | TCP_ACK; |
| 6602 | | + goto tcp_send_nodata; |
| 6603 | | + } |
| 6260 | +/* |
| 6261 | +This is a small implementation of the IP and TCP protocols (as well as |
| 6262 | +some basic ICMP stuff). The implementation couples the IP, TCP and the |
| 6263 | +application layers very tightly. To keep the size of the compiled code |
| 6264 | +down, this code also features heavy usage of the goto statement. |
| 6604 | 6265 | + |
| 6605 | | + /* If uip_slen > 0, the application has data to be sent. */ |
| 6606 | | + if(uip_slen > 0) { |
| 6266 | +The principle is that we have a small buffer, called the uip_buf, in |
| 6267 | +which the device driver puts an incoming packet. The TCP/IP stack |
| 6268 | +parses the headers in the packet, and calls upon the application. If |
| 6269 | +the remote host has sent data to the application, this data is present |
| 6270 | +in the uip_buf and the application read the data from there. It is up |
| 6271 | +to the application to put this data into a byte stream if needed. The |
| 6272 | +application will not be fed with data that is out of sequence. |
| 6607 | 6273 | + |
| 6608 | | + /* If the connection has acknowledged data, the contents of |
| 6609 | | + the ->len variable should be discarded. */ |
| 6610 | | + if((uip_flags & UIP_ACKDATA) != 0) { |
| 6611 | | + uip_connr->len = 0; |
| 6612 | | + } |
| 6274 | +If the application whishes to send data to the peer, it should put its |
| 6275 | +data into the uip_buf, 40 bytes from the start of the buffer. The |
| 6276 | +TCP/IP stack will calculate the checksums, and fill in the necessary |
| 6277 | +header fields and finally send the packet back to the peer. |
| 6278 | +*/ |
| 6613 | 6279 | + |
| 6614 | | + /* If the ->len variable is non-zero the connection has |
| 6615 | | + already data in transit and cannot send anymore right |
| 6616 | | + now. */ |
| 6617 | | + if(uip_connr->len == 0) { |
| 6280 | +#include "uip.h" |
| 6281 | +#include "uipopt.h" |
| 6282 | +#include "uip_arch.h" |
| 6618 | 6283 | + |
| 6619 | | + /* The application cannot send more than what is allowed by |
| 6620 | | + the mss (the minumum of the MSS and the available |
| 6621 | | + window). */ |
| 6622 | | + if(uip_slen > uip_connr->mss) { |
| 6623 | | + uip_slen = uip_connr->mss; |
| 6624 | | + } |
| 6284 | +/*-----------------------------------------------------------------------------------*/ |
| 6285 | +/* Variable definitions. */ |
| 6625 | 6286 | + |
| 6626 | | + /* Remember how much data we send out now so that we know |
| 6627 | | + when everything has been acknowledged. */ |
| 6628 | | + uip_connr->len = uip_slen; |
| 6629 | | + } else { |
| 6630 | 6287 | + |
| 6631 | | + /* If the application already had unacknowledged data, we |
| 6632 | | + make sure that the application does not send (i.e., |
| 6633 | | + retransmit) out more than it previously sent out. */ |
| 6634 | | + uip_slen = uip_connr->len; |
| 6635 | | + } |
| 6636 | | + } else { |
| 6637 | | + uip_connr->len = 0; |
| 6638 | | + } |
| 6639 | | + uip_connr->nrtx = 0; |
| 6640 | | + apprexmit: |
| 6641 | | + uip_appdata = uip_sappdata; |
| 6288 | +/* 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 */ |
| 6289 | +#if UIP_FIXEDADDR > 0 |
| 6290 | +const unsigned short int uip_hostaddr[2] = |
| 6291 | + {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1), |
| 6292 | + HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)}; |
| 6293 | +const unsigned short int uip_arp_draddr[2] = |
| 6294 | + {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1), |
| 6295 | + HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)}; |
| 6296 | +const unsigned short int uip_arp_netmask[2] = |
| 6297 | + {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1), |
| 6298 | + HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)}; |
| 6299 | +#else |
| 6300 | +unsigned short int uip_hostaddr[2]; |
| 6301 | +unsigned short int uip_arp_draddr[2], uip_arp_netmask[2]; |
| 6302 | +#endif /* UIP_FIXEDADDR */ |
| 6642 | 6303 | + |
| 6643 | | + /* If the application has data to be sent, or if the incoming |
| 6644 | | + packet had new data in it, we must send out a packet. */ |
| 6645 | | + if(uip_slen > 0 && uip_connr->len > 0) { |
| 6646 | | + /* Add the length of the IP and TCP headers. */ |
| 6647 | | + uip_len = uip_connr->len + UIP_TCPIP_HLEN; |
| 6648 | | + /* We always set the ACK flag in response packets. */ |
| 6649 | | + BUF->flags = TCP_ACK | TCP_PSH; |
| 6650 | | + /* Send the packet. */ |
| 6651 | | + goto tcp_send_noopts; |
| 6652 | | + } |
| 6653 | | + /* If there is no data to send, just send out a pure ACK if |
| 6654 | | + there is newdata. */ |
| 6655 | | + if(uip_flags & UIP_NEWDATA) { |
| 6656 | | + uip_len = UIP_TCPIP_HLEN; |
| 6657 | | + BUF->flags = TCP_ACK; |
| 6658 | | + goto tcp_send_noopts; |
| 6659 | | + } |
| 6660 | | + } |
| 6661 | | + goto drop; |
| 6662 | | + case LAST_ACK: |
| 6663 | | + /* We can close this connection if the peer has acknowledged our |
| 6664 | | + FIN. This is indicated by the UIP_ACKDATA flag. */ |
| 6665 | | + if(uip_flags & UIP_ACKDATA) { |
| 6666 | | + uip_connr->tcpstateflags = CLOSED; |
| 6667 | | + uip_flags = UIP_CLOSE; |
| 6668 | | + UIP_APPCALL(); |
| 6669 | | + } |
| 6670 | | + break; |
| 6671 | | + |
| 6672 | | + case FIN_WAIT_1: |
| 6673 | | + /* The application has closed the connection, but the remote host |
| 6674 | | + hasn't closed its end yet. Thus we do nothing but wait for a |
| 6675 | | + FIN from the other side. */ |
| 6676 | | + if(uip_len > 0) { |
| 6677 | | + uip_add_rcv_nxt(uip_len); |
| 6678 | | + } |
| 6679 | | + if(BUF->flags & TCP_FIN) { |
| 6680 | | + if(uip_flags & UIP_ACKDATA) { |
| 6681 | | + uip_connr->tcpstateflags = TIME_WAIT; |
| 6682 | | + uip_connr->timer = 0; |
| 6683 | | + uip_connr->len = 0; |
| 6684 | | + } else { |
| 6685 | | + uip_connr->tcpstateflags = CLOSING; |
| 6686 | | + } |
| 6687 | | + uip_add_rcv_nxt(1); |
| 6688 | | + uip_flags = UIP_CLOSE; |
| 6689 | | + UIP_APPCALL(); |
| 6690 | | + goto tcp_send_ack; |
| 6691 | | + } else if(uip_flags & UIP_ACKDATA) { |
| 6692 | | + uip_connr->tcpstateflags = FIN_WAIT_2; |
| 6693 | | + uip_connr->len = 0; |
| 6694 | | + goto drop; |
| 6695 | | + } |
| 6696 | | + if(uip_len > 0) { |
| 6697 | | + goto tcp_send_ack; |
| 6698 | | + } |
| 6699 | | + goto drop; |
| 6700 | | + |
| 6701 | | + case FIN_WAIT_2: |
| 6702 | | + if(uip_len > 0) { |
| 6703 | | + uip_add_rcv_nxt(uip_len); |
| 6704 | | + } |
| 6705 | | + if(BUF->flags & TCP_FIN) { |
| 6706 | | + uip_connr->tcpstateflags = TIME_WAIT; |
| 6707 | | + uip_connr->timer = 0; |
| 6708 | | + uip_add_rcv_nxt(1); |
| 6709 | | + uip_flags = UIP_CLOSE; |
| 6710 | | + UIP_APPCALL(); |
| 6711 | | + goto tcp_send_ack; |
| 6712 | | + } |
| 6713 | | + if(uip_len > 0) { |
| 6714 | | + goto tcp_send_ack; |
| 6715 | | + } |
| 6716 | | + goto drop; |
| 6304 | +u8_t uip_buf[UIP_BUFSIZE+2]; /* The packet buffer that contains |
| 6305 | + incoming packets. */ |
| 6306 | +volatile u8_t *uip_appdata; /* The uip_appdata pointer points to |
| 6307 | + application data. */ |
| 6308 | +volatile u8_t *uip_sappdata; /* The uip_appdata pointer points to the |
| 6309 | + application data which is to be sent. */ |
| 6310 | +#if UIP_URGDATA > 0 |
| 6311 | +volatile u8_t *uip_urgdata; /* The uip_urgdata pointer points to |
| 6312 | + urgent data (out-of-band data), if |
| 6313 | + present. */ |
| 6314 | +volatile u8_t uip_urglen, uip_surglen; |
| 6315 | +#endif /* UIP_URGDATA > 0 */ |
| 6717 | 6316 | + |
| 6718 | | + case TIME_WAIT: |
| 6719 | | + goto tcp_send_ack; |
| 6720 | | + |
| 6721 | | + case CLOSING: |
| 6722 | | + if(uip_flags & UIP_ACKDATA) { |
| 6723 | | + uip_connr->tcpstateflags = TIME_WAIT; |
| 6724 | | + uip_connr->timer = 0; |
| 6725 | | + } |
| 6726 | | + } |
| 6727 | | + goto drop; |
| 6728 | | + |
| 6317 | +volatile unsigned short int uip_len, uip_slen; |
| 6318 | + /* The uip_len is either 8 or 16 bits, |
| 6319 | + depending on the maximum packet |
| 6320 | + size. */ |
| 6729 | 6321 | + |
| 6730 | | + /* We jump here when we are ready to send the packet, and just want |
| 6731 | | + to set the appropriate TCP sequence numbers in the TCP header. */ |
| 6732 | | + tcp_send_ack: |
| 6733 | | + BUF->flags = TCP_ACK; |
| 6734 | | + tcp_send_nodata: |
| 6735 | | + uip_len = 40; |
| 6736 | | + tcp_send_noopts: |
| 6737 | | + BUF->tcpoffset = 5 << 4; |
| 6738 | | + tcp_send: |
| 6739 | | + /* We're done with the input processing. We are now ready to send a |
| 6740 | | + reply. Our job is to fill in all the fields of the TCP and IP |
| 6741 | | + headers before calculating the checksum and finally send the |
| 6742 | | + packet. */ |
| 6743 | | + BUF->ackno[0] = uip_connr->rcv_nxt[0]; |
| 6744 | | + BUF->ackno[1] = uip_connr->rcv_nxt[1]; |
| 6745 | | + BUF->ackno[2] = uip_connr->rcv_nxt[2]; |
| 6746 | | + BUF->ackno[3] = uip_connr->rcv_nxt[3]; |
| 6747 | | + |
| 6748 | | + BUF->seqno[0] = uip_connr->snd_nxt[0]; |
| 6749 | | + BUF->seqno[1] = uip_connr->snd_nxt[1]; |
| 6750 | | + BUF->seqno[2] = uip_connr->snd_nxt[2]; |
| 6751 | | + BUF->seqno[3] = uip_connr->snd_nxt[3]; |
| 6322 | +volatile u8_t uip_flags; /* The uip_flags variable is used for |
| 6323 | + communication between the TCP/IP stack |
| 6324 | + and the application program. */ |
| 6325 | +struct uip_conn *uip_conn; /* uip_conn always points to the current |
| 6326 | + connection. */ |
| 6752 | 6327 | + |
| 6753 | | + BUF->proto = UIP_PROTO_TCP; |
| 6754 | | + |
| 6755 | | + BUF->srcport = uip_connr->lport; |
| 6756 | | + BUF->destport = uip_connr->rport; |
| 6328 | +struct uip_conn uip_conns[UIP_CONNS]; |
| 6329 | + /* The uip_conns array holds all TCP |
| 6330 | + connections. */ |
| 6331 | +unsigned short int uip_listenports[UIP_LISTENPORTS]; |
| 6332 | + /* The uip_listenports list all currently |
| 6333 | + listning ports. */ |
| 6334 | +#if UIP_UDP |
| 6335 | +struct uip_udp_conn *uip_udp_conn; |
| 6336 | +struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; |
| 6337 | +#endif /* UIP_UDP */ |
| 6757 | 6338 | + |
| 6758 | | + BUF->srcipaddr[0] = uip_hostaddr[0]; |
| 6759 | | + BUF->srcipaddr[1] = uip_hostaddr[1]; |
| 6760 | | + BUF->destipaddr[0] = uip_connr->ripaddr[0]; |
| 6761 | | + BUF->destipaddr[1] = uip_connr->ripaddr[1]; |
| 6762 | | + |
| 6763 | 6339 | + |
| 6764 | | + if(uip_connr->tcpstateflags & UIP_STOPPED) { |
| 6765 | | + /* If the connection has issued uip_stop(), we advertise a zero |
| 6766 | | + window so that the remote host will stop sending data. */ |
| 6767 | | + BUF->wnd[0] = BUF->wnd[1] = 0; |
| 6768 | | + } else { |
| 6769 | | + BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8); |
| 6770 | | + BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff); |
| 6771 | | + } |
| 6340 | +static unsigned short int ipid; /* Ths ipid variable is an increasing |
| 6341 | + number that is used for the IP ID |
| 6342 | + field. */ |
| 6772 | 6343 | + |
| 6773 | | + tcp_send_noconn: |
| 6344 | +static u8_t iss[4]; /* The iss variable is used for the TCP |
| 6345 | + initial sequence number. */ |
| 6774 | 6346 | + |
| 6775 | | + BUF->len[0] = (uip_len >> 8); |
| 6776 | | + BUF->len[1] = (uip_len & 0xff); |
| 6347 | +#if UIP_ACTIVE_OPEN |
| 6348 | +static unsigned short int lastport; /* Keeps track of the last port used for |
| 6349 | + a new connection. */ |
| 6350 | +#endif /* UIP_ACTIVE_OPEN */ |
| 6777 | 6351 | + |
| 6778 | | + /* Calculate TCP checksum. */ |
| 6779 | | + BUF->tcpchksum = 0; |
| 6780 | | + BUF->tcpchksum = ~(uip_tcpchksum()); |
| 6781 | | + |
| 6782 | | + //ip_send_nolen: |
| 6352 | +/* Temporary variables. */ |
| 6353 | +volatile u8_t uip_acc32[4]; |
| 6354 | +static u8_t c, opt; |
| 6355 | +static unsigned short int tmp16; |
| 6783 | 6356 | + |
| 6784 | | + BUF->vhl = 0x45; |
| 6785 | | + BUF->tos = 0; |
| 6786 | | + BUF->ipoffset[0] = BUF->ipoffset[1] = 0; |
| 6787 | | + BUF->ttl = UIP_TTL; |
| 6788 | | + ++ipid; |
| 6789 | | + BUF->ipid[0] = ipid >> 8; |
| 6790 | | + BUF->ipid[1] = ipid & 0xff; |
| 6357 | +/* Structures and definitions. */ |
| 6358 | +#define TCP_FIN 0x01 |
| 6359 | +#define TCP_SYN 0x02 |
| 6360 | +#define TCP_RST 0x04 |
| 6361 | +#define TCP_PSH 0x08 |
| 6362 | +#define TCP_ACK 0x10 |
| 6363 | +#define TCP_URG 0x20 |
| 6364 | +#define TCP_CTL 0x3f |
| 6365 | + |
| 6366 | +#define ICMP_ECHO_REPLY 0 |
| 6367 | +#define ICMP_ECHO 8 |
| 6368 | + |
| 6369 | +/* Macros. */ |
| 6370 | +#define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) |
| 6371 | +#define FBUF ((uip_tcpip_hdr *)&uip_reassbuf[0]) |
| 6372 | +#define ICMPBUF ((uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN]) |
| 6373 | +#define UDPBUF ((uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN]) |
| 6374 | + |
| 6375 | +#if UIP_STATISTICS == 1 |
| 6376 | +struct uip_stats uip_stat; |
| 6377 | +#define UIP_STAT(s) s |
| 6378 | +#else |
| 6379 | +#define UIP_STAT(s) |
| 6380 | +#endif /* UIP_STATISTICS == 1 */ |
| 6381 | + |
| 6382 | +#if UIP_LOGGING == 1 |
| 6383 | +extern void puts(const char *s); |
| 6384 | +#define UIP_LOG(m) puts(m) |
| 6385 | +#else |
| 6386 | +#define UIP_LOG(m) |
| 6387 | +#endif /* UIP_LOGGING == 1 */ |
| 6388 | + |
| 6389 | +/*-----------------------------------------------------------------------------------*/ |
| 6390 | +void |
| 6391 | +uip_init(void) |
| 6392 | +{ |
| 6393 | + for(c = 0; c < UIP_LISTENPORTS; ++c) { |
| 6394 | + uip_listenports[c] = 0; |
| 6395 | + } |
| 6396 | + for(c = 0; c < UIP_CONNS; ++c) { |
| 6397 | + uip_conns[c].tcpstateflags = CLOSED; |
| 6398 | + } |
| 6399 | +#if UIP_ACTIVE_OPEN |
| 6400 | + lastport = 1024; |
| 6401 | +#endif /* UIP_ACTIVE_OPEN */ |
| 6402 | + |
| 6403 | +#if UIP_UDP |
| 6404 | + for(c = 0; c < UIP_UDP_CONNS; ++c) { |
| 6405 | + uip_udp_conns[c].lport = 0; |
| 6406 | + } |
| 6407 | +#endif /* UIP_UDP */ |
| 6791 | 6408 | + |
| 6792 | | + /* Calculate IP checksum. */ |
| 6793 | | + BUF->ipchksum = 0; |
| 6794 | | + BUF->ipchksum = ~(uip_ipchksum()); |
| 6795 | 6409 | + |
| 6796 | | + UIP_STAT(++uip_stat.tcp.sent); |
| 6797 | | + send: |
| 6798 | | + UIP_STAT(++uip_stat.ip.sent); |
| 6799 | | + /* Return and let the caller do the actual transmission. */ |
| 6800 | | + return; |
| 6801 | | + drop: |
| 6802 | | + uip_len = 0; |
| 6803 | | + return; |
| 6410 | + /* IPv4 initialization. */ |
| 6411 | +#if UIP_FIXEDADDR == 0 |
| 6412 | + uip_hostaddr[0] = uip_hostaddr[1] = 0; |
| 6413 | +#endif /* UIP_FIXEDADDR */ |
| 6414 | + |
| 6804 | 6415 | +} |
| 6805 | 6416 | +/*-----------------------------------------------------------------------------------*/ |
| 6806 | | +/*unsigned short int |
| 6807 | | +htons(unsigned short int val) |
| 6417 | +#if UIP_ACTIVE_OPEN |
| 6418 | +struct uip_conn * |
| 6419 | +uip_connect(unsigned short int *ripaddr, unsigned short int rport) |
| 6808 | 6420 | +{ |
| 6809 | | + return HTONS(val); |
| 6810 | | +}*/ |
| 6811 | | +/*-----------------------------------------------------------------------------------*/ |
| 6812 | | +/** @} */ |
| 6813 | | +++ b/net/uip-0.9/uip.h |
| 6814 | | @@ -0,0 +1,1066 @@ |
| 6815 | | +/** |
| 6816 | | + * \addtogroup uip |
| 6817 | | + * @{ |
| 6818 | | + */ |
| 6421 | + register struct uip_conn *conn, *cconn; |
| 6422 | + |
| 6423 | + /* Find an unused local port. */ |
| 6424 | + again: |
| 6425 | + ++lastport; |
| 6819 | 6426 | + |
| 6820 | | +/** |
| 6821 | | + * \file |
| 6822 | | + * Header file for the uIP TCP/IP stack. |
| 6823 | | + * \author Adam Dunkels <adam@dunkels.com> |
| 6824 | | + * |
| 6825 | | + * The uIP TCP/IP stack header file contains definitions for a number |
| 6826 | | + * of C macros that are used by uIP programs as well as internal uIP |
| 6827 | | + * structures, TCP/IP header structures and function declarations. |
| 6828 | | + * |
| 6829 | | + */ |
| 6427 | + if(lastport >= 32000) { |
| 6428 | + lastport = 4096; |
| 6429 | + } |
| 6830 | 6430 | + |
| 6431 | + /* Check if this port is already in use, and if so try to find |
| 6432 | + another one. */ |
| 6433 | + for(c = 0; c < UIP_CONNS; ++c) { |
| 6434 | + conn = &uip_conns[c]; |
| 6435 | + if(conn->tcpstateflags != CLOSED && |
| 6436 | + conn->lport == htons(lastport)) { |
| 6437 | + goto again; |
| 6438 | + } |
| 6439 | + } |
| 6831 | 6440 | + |
| 6832 | | +/* |
| 6833 | | + * Copyright (c) 2001-2003, Adam Dunkels. |
| 6834 | | + * All rights reserved. |
| 6835 | | + * |
| 6836 | | + * Redistribution and use in source and binary forms, with or without |
| 6837 | | + * modification, are permitted provided that the following conditions |
| 6838 | | + * are met: |
| 6839 | | + * 1. Redistributions of source code must retain the above copyright |
| 6840 | | + * notice, this list of conditions and the following disclaimer. |
| 6841 | | + * 2. Redistributions in binary form must reproduce the above copyright |
| 6842 | | + * notice, this list of conditions and the following disclaimer in the |
| 6843 | | + * documentation and/or other materials provided with the distribution. |
| 6844 | | + * 3. The name of the author may not be used to endorse or promote |
| 6845 | | + * products derived from this software without specific prior |
| 6846 | | + * written permission. |
| 6847 | | + * |
| 6848 | | + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS |
| 6849 | | + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 6850 | | + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 6851 | | + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
| 6852 | | + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 6853 | | + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
| 6854 | | + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 6855 | | + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| 6856 | | + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| 6857 | | + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 6858 | | + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 6859 | | + * |
| 6860 | | + * This file is part of the uIP TCP/IP stack. |
| 6861 | | + * |
| 6862 | | + * $Id: uip.h,v 1.36.2.7 2003/10/07 13:47:51 adam Exp $ |
| 6863 | | + * |
| 6864 | | + */ |
| 6865 | 6441 | + |
| 6866 | | +#ifndef __UIP_H__ |
| 6867 | | +#define __UIP_H__ |
| 6868 | | +#include <linux/types.h> |
| 6869 | | +#include <linux/string.h> |
| 6870 | | +#include <linux/ctype.h> |
| 6871 | | +#include <malloc.h> |
| 6872 | | +#include <common.h> |
| 6442 | + conn = 0; |
| 6443 | + for(c = 0; c < UIP_CONNS; ++c) { |
| 6444 | + cconn = &uip_conns[c]; |
| 6445 | + if(cconn->tcpstateflags == CLOSED) { |
| 6446 | + conn = cconn; |
| 6447 | + break; |
| 6448 | + } |
| 6449 | + if(cconn->tcpstateflags == TIME_WAIT) { |
| 6450 | + if(conn == 0 || |
| 6451 | + cconn->timer > uip_conn->timer) { |
| 6452 | + conn = cconn; |
| 6453 | + } |
| 6454 | + } |
| 6455 | + } |
| 6873 | 6456 | + |
| 6457 | + if(conn == 0) { |
| 6458 | + return 0; |
| 6459 | + } |
| 6460 | + |
| 6461 | + conn->tcpstateflags = SYN_SENT; |
| 6874 | 6462 | + |
| 6875 | | +#include "uipopt.h" |
| 6463 | + conn->snd_nxt[0] = iss[0]; |
| 6464 | + conn->snd_nxt[1] = iss[1]; |
| 6465 | + conn->snd_nxt[2] = iss[2]; |
| 6466 | + conn->snd_nxt[3] = iss[3]; |
| 6876 | 6467 | + |
| 6468 | + conn->initialmss = conn->mss = UIP_TCP_MSS; |
| 6469 | + |
| 6470 | + conn->len = 1; /* TCP length of the SYN is one. */ |
| 6471 | + conn->nrtx = 0; |
| 6472 | + conn->timer = 1; /* Send the SYN next time around. */ |
| 6473 | + conn->rto = UIP_RTO; |
| 6474 | + conn->sa = 0; |
| 6475 | + conn->sv = 16; |
| 6476 | + conn->lport = htons(lastport); |
| 6477 | + conn->rport = rport; |
| 6478 | + conn->ripaddr[0] = ripaddr[0]; |
| 6479 | + conn->ripaddr[1] = ripaddr[1]; |
| 6480 | + |
| 6481 | + return conn; |
| 6482 | +} |
| 6483 | +#endif /* UIP_ACTIVE_OPEN */ |
| 6877 | 6484 | +/*-----------------------------------------------------------------------------------*/ |
| 6878 | | +/* First, the functions that should be called from the |
| 6879 | | + * system. Initialization, the periodic timer and incoming packets are |
| 6880 | | + * handled by the following three functions. |
| 6881 | | + */ |
| 6485 | +#if UIP_UDP |
| 6486 | +struct uip_udp_conn * |
| 6487 | +uip_udp_new(unsigned short int *ripaddr, unsigned short int rport) |
| 6488 | +{ |
| 6489 | + register struct uip_udp_conn *conn; |
| 6490 | + |
| 6491 | + /* Find an unused local port. */ |
| 6492 | + again: |
| 6493 | + ++lastport; |
| 6882 | 6494 | + |
| 6883 | | +/** |
| 6884 | | + * \defgroup uipconffunc uIP configuration functions |
| 6885 | | + * @{ |
| 6886 | | + * |
| 6887 | | + * The uIP configuration functions are used for setting run-time |
| 6888 | | + * parameters in uIP such as IP addresses. |
| 6889 | | + */ |
| 6495 | + if(lastport >= 32000) { |
| 6496 | + lastport = 4096; |
| 6497 | + } |
| 6498 | + |
| 6499 | + for(c = 0; c < UIP_UDP_CONNS; ++c) { |
| 6500 | + if(uip_udp_conns[c].lport == lastport) { |
| 6501 | + goto again; |
| 6502 | + } |
| 6503 | + } |
| 6890 | 6504 | + |
| 6891 | | +/** |
| 6892 | | + * Set the IP address of this host. |
| 6893 | | + * |
| 6894 | | + * The IP address is represented as a 4-byte array where the first |
| 6895 | | + * octet of the IP address is put in the first member of the 4-byte |
| 6896 | | + * array. |
| 6897 | | + * |
| 6898 | | + * \param addr A pointer to a 4-byte representation of the IP address. |
| 6899 | | + * |
| 6900 | | + * \hideinitializer |
| 6901 | | + */ |
| 6902 | | +#define uip_sethostaddr(addr) do { uip_hostaddr[0] = addr[0]; \ |
| 6903 | | + uip_hostaddr[1] = addr[1]; } while(0) |
| 6904 | 6505 | + |
| 6905 | | +/** |
| 6906 | | + * Get the IP address of this host. |
| 6907 | | + * |
| 6908 | | + * The IP address is represented as a 4-byte array where the first |
| 6909 | | + * octet of the IP address is put in the first member of the 4-byte |
| 6910 | | + * array. |
| 6911 | | + * |
| 6912 | | + * \param addr A pointer to a 4-byte array that will be filled in with |
| 6913 | | + * the currently configured IP address. |
| 6914 | | + * |
| 6915 | | + * \hideinitializer |
| 6916 | | + */ |
| 6917 | | +#define uip_gethostaddr(addr) do { addr[0] = uip_hostaddr[0]; \ |
| 6918 | | + addr[1] = uip_hostaddr[1]; } while(0) |
| 6506 | + conn = 0; |
| 6507 | + for(c = 0; c < UIP_UDP_CONNS; ++c) { |
| 6508 | + if(uip_udp_conns[c].lport == 0) { |
| 6509 | + conn = &uip_udp_conns[c]; |
| 6510 | + break; |
| 6511 | + } |
| 6512 | + } |
| 6919 | 6513 | + |
| 6920 | | +/** @} */ |
| 6514 | + if(conn == 0) { |
| 6515 | + return 0; |
| 6516 | + } |
| 6517 | + |
| 6518 | + conn->lport = HTONS(lastport); |
| 6519 | + conn->rport = HTONS(rport); |
| 6520 | + conn->ripaddr[0] = ripaddr[0]; |
| 6521 | + conn->ripaddr[1] = ripaddr[1]; |
| 6522 | + |
| 6523 | + return conn; |
| 6524 | +} |
| 6525 | +#endif /* UIP_UDP */ |
| 6526 | +/*-----------------------------------------------------------------------------------*/ |
| 6527 | +void |
| 6528 | +uip_unlisten(unsigned short int port) |
| 6529 | +{ |
| 6530 | + for(c = 0; c < UIP_LISTENPORTS; ++c) { |
| 6531 | + if(uip_listenports[c] == port) { |
| 6532 | + uip_listenports[c] = 0; |
| 6533 | + return; |
| 6534 | + } |
| 6535 | + } |
| 6536 | +} |
| 6537 | +/*-----------------------------------------------------------------------------------*/ |
| 6538 | +void |
| 6539 | +uip_listen(unsigned short int port) |
| 6540 | +{ |
| 6541 | + for(c = 0; c < UIP_LISTENPORTS; ++c) { |
| 6542 | + if(uip_listenports[c] == 0) { |
| 6543 | + uip_listenports[c] = port; |
| 6544 | + return; |
| 6545 | + } |
| 6546 | + } |
| 6547 | +} |
| 6548 | +/*-----------------------------------------------------------------------------------*/ |
| 6549 | +/* XXX: IP fragment reassembly: not well-tested. */ |
| 6921 | 6550 | + |
| 6922 | | +/** |
| 6923 | | + * \defgroup uipinit uIP initialization functions |
| 6924 | | + * @{ |
| 6925 | | + * |
| 6926 | | + * The uIP initialization functions are used for booting uIP. |
| 6927 | | + */ |
| 6551 | +#if UIP_REASSEMBLY |
| 6552 | +#define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN) |
| 6553 | +static u8_t uip_reassbuf[UIP_REASS_BUFSIZE]; |
| 6554 | +static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)]; |
| 6555 | +static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f, |
| 6556 | + 0x0f, 0x07, 0x03, 0x01}; |
| 6557 | +static unsigned short int uip_reasslen; |
| 6558 | +static u8_t uip_reassflags; |
| 6559 | +#define UIP_REASS_FLAG_LASTFRAG 0x01 |
| 6560 | +static u8_t uip_reasstmr; |
| 6928 | 6561 | + |
| 6929 | | +/** |
| 6930 | | + * uIP initialization function. |
| 6931 | | + * |
| 6932 | | + * This function should be called at boot up to initilize the uIP |
| 6933 | | + * TCP/IP stack. |
| 6934 | | + */ |
| 6935 | | +void uip_init(void); |
| 6562 | +#define IP_HLEN 20 |
| 6563 | +#define IP_MF 0x20 |
| 6936 | 6564 | + |
| 6937 | | +/** @} */ |
| 6565 | +static u8_t |
| 6566 | +uip_reass(void) |
| 6567 | +{ |
| 6568 | + unsigned short int offset, len; |
| 6569 | + unsigned short int i; |
| 6938 | 6570 | + |
| 6939 | | +/** |
| 6940 | | + * \defgroup uipdevfunc uIP device driver functions |
| 6941 | | + * @{ |
| 6942 | | + * |
| 6943 | | + * These functions are used by a network device driver for interacting |
| 6944 | | + * with uIP. |
| 6945 | | + */ |
| 6571 | + /* If ip_reasstmr is zero, no packet is present in the buffer, so we |
| 6572 | + write the IP header of the fragment into the reassembly |
| 6573 | + buffer. The timer is updated with the maximum age. */ |
| 6574 | + if(uip_reasstmr == 0) { |
| 6575 | + memcpy(uip_reassbuf, &BUF->vhl, IP_HLEN); |
| 6576 | + uip_reasstmr = UIP_REASS_MAXAGE; |
| 6577 | + uip_reassflags = 0; |
| 6578 | + /* Clear the bitmap. */ |
| 6579 | + memset(uip_reassbitmap, sizeof(uip_reassbitmap), 0); |
| 6580 | + } |
| 6946 | 6581 | + |
| 6947 | | +/** |
| 6948 | | + * Process an incoming packet. |
| 6949 | | + * |
| 6950 | | + * This function should be called when the device driver has received |
| 6951 | | + * a packet from the network. The packet from the device driver must |
| 6952 | | + * be present in the uip_buf buffer, and the length of the packet |
| 6953 | | + * should be placed in the uip_len variable. |
| 6954 | | + * |
| 6955 | | + * When the function returns, there may be an outbound packet placed |
| 6956 | | + * in the uip_buf packet buffer. If so, the uip_len variable is set to |
| 6957 | | + * the length of the packet. If no packet is to be sent out, the |
| 6958 | | + * uip_len variable is set to 0. |
| 6959 | | + * |
| 6960 | | + * The usual way of calling the function is presented by the source |
| 6961 | | + * code below. |
| 6962 | | + \code |
| 6963 | | + uip_len = devicedriver_poll(); |
| 6964 | | + if(uip_len > 0) { |
| 6965 | | + uip_input(); |
| 6966 | | + if(uip_len > 0) { |
| 6967 | | + devicedriver_send(); |
| 6582 | + /* Check if the incoming fragment matches the one currently present |
| 6583 | + in the reasembly buffer. If so, we proceed with copying the |
| 6584 | + fragment into the buffer. */ |
| 6585 | + if(BUF->srcipaddr[0] == FBUF->srcipaddr[0] && |
| 6586 | + BUF->srcipaddr[1] == FBUF->srcipaddr[1] && |
| 6587 | + BUF->destipaddr[0] == FBUF->destipaddr[0] && |
| 6588 | + BUF->destipaddr[1] == FBUF->destipaddr[1] && |
| 6589 | + BUF->ipid[0] == FBUF->ipid[0] && |
| 6590 | + BUF->ipid[1] == FBUF->ipid[1]) { |
| 6591 | + |
| 6592 | + len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4; |
| 6593 | + offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8; |
| 6594 | + |
| 6595 | + /* If the offset or the offset + fragment length overflows the |
| 6596 | + reassembly buffer, we discard the entire packet. */ |
| 6597 | + if(offset > UIP_REASS_BUFSIZE || |
| 6598 | + offset + len > UIP_REASS_BUFSIZE) { |
| 6599 | + uip_reasstmr = 0; |
| 6600 | + goto nullreturn; |
| 6968 | 6601 | + } |
| 6969 | | + } |
| 6970 | | + \endcode |
| 6971 | | + * |
| 6972 | | + * \note If you are writing a uIP device driver that needs ARP |
| 6973 | | + * (Address Resolution Protocol), e.g., when running uIP over |
| 6974 | | + * Ethernet, you will need to call the uIP ARP code before calling |
| 6975 | | + * this function: |
| 6976 | | + \code |
| 6977 | | + #define BUF ((struct uip_eth_hdr *)&uip_buf[0]) |
| 6978 | | + uip_len = ethernet_devicedrver_poll(); |
| 6979 | | + if(uip_len > 0) { |
| 6980 | | + if(BUF->type == HTONS(UIP_ETHTYPE_IP)) { |
| 6981 | | + uip_arp_ipin(); |
| 6982 | | + uip_input(); |
| 6983 | | + if(uip_len > 0) { |
| 6984 | | + uip_arp_out(); |
| 6985 | | + ethernet_devicedriver_send(); |
| 6986 | | + } |
| 6987 | | + } else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) { |
| 6988 | | + uip_arp_arpin(); |
| 6989 | | + if(uip_len > 0) { |
| 6990 | | + ethernet_devicedriver_send(); |
| 6991 | | + } |
| 6992 | | + } |
| 6993 | | + \endcode |
| 6994 | | + * |
| 6995 | | + * \hideinitializer |
| 6996 | | + */ |
| 6997 | | +#define uip_input() uip_process(UIP_DATA) |
| 6998 | 6602 | + |
| 6999 | | +/** |
| 7000 | | + * Periodic processing for a connection identified by its number. |
| 7001 | | + * |
| 7002 | | + * This function does the necessary periodic processing (timers, |
| 7003 | | + * polling) for a uIP TCP conneciton, and should be called when the |
| 7004 | | + * periodic uIP timer goes off. It should be called for every |
| 7005 | | + * connection, regardless of whether they are open of closed. |
| 7006 | | + * |
| 7007 | | + * When the function returns, it may have an outbound packet waiting |
| 7008 | | + * for service in the uIP packet buffer, and if so the uip_len |
| 7009 | | + * variable is set to a value larger than zero. The device driver |
| 7010 | | + * should be called to send out the packet. |
| 7011 | | + * |
| 7012 | | + * The ususal way of calling the function is through a for() loop like |
| 7013 | | + * this: |
| 7014 | | + \code |
| 7015 | | + for(i = 0; i < UIP_CONNS; ++i) { |
| 7016 | | + uip_periodic(i); |
| 7017 | | + if(uip_len > 0) { |
| 7018 | | + devicedriver_send(); |
| 7019 | | + } |
| 7020 | | + } |
| 7021 | | + \endcode |
| 7022 | | + * |
| 7023 | | + * \note If you are writing a uIP device driver that needs ARP |
| 7024 | | + * (Address Resolution Protocol), e.g., when running uIP over |
| 7025 | | + * Ethernet, you will need to call the uip_arp_out() function before |
| 7026 | | + * calling the device driver: |
| 7027 | | + \code |
| 7028 | | + for(i = 0; i < UIP_CONNS; ++i) { |
| 7029 | | + uip_periodic(i); |
| 7030 | | + if(uip_len > 0) { |
| 7031 | | + uip_arp_out(); |
| 7032 | | + ethernet_devicedriver_send(); |
| 6603 | + /* Copy the fragment into the reassembly buffer, at the right |
| 6604 | + offset. */ |
| 6605 | + memcpy(&uip_reassbuf[IP_HLEN + offset], |
| 6606 | + (char *)BUF + (int)((BUF->vhl & 0x0f) * 4), |
| 6607 | + len); |
| 6608 | + |
| 6609 | + /* Update the bitmap. */ |
| 6610 | + if(offset / (8 * 8) == (offset + len) / (8 * 8)) { |
| 6611 | + /* If the two endpoints are in the same byte, we only update |
| 6612 | + that byte. */ |
| 6613 | + |
| 6614 | + uip_reassbitmap[offset / (8 * 8)] |= |
| 6615 | + bitmap_bits[(offset / 8 ) & 7] & |
| 6616 | + ~bitmap_bits[((offset + len) / 8 ) & 7]; |
| 6617 | + } else { |
| 6618 | + /* If the two endpoints are in different bytes, we update the |
| 6619 | + bytes in the endpoints and fill the stuff inbetween with |
| 6620 | + 0xff. */ |
| 6621 | + uip_reassbitmap[offset / (8 * 8)] |= |
| 6622 | + bitmap_bits[(offset / 8 ) & 7]; |
| 6623 | + for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) { |
| 6624 | + uip_reassbitmap[i] = 0xff; |
| 6625 | + } |
| 6626 | + uip_reassbitmap[(offset + len) / (8 * 8)] |= |
| 6627 | + ~bitmap_bits[((offset + len) / 8 ) & 7]; |
| 7033 | 6628 | + } |
| 7034 | | + } |
| 7035 | | + \endcode |
| 7036 | | + * |
| 7037 | | + * \param conn The number of the connection which is to be periodically polled. |
| 7038 | | + * |
| 7039 | | + * \hideinitializer |
| 7040 | | + */ |
| 7041 | | +#define uip_periodic(conn) do { uip_conn = &uip_conns[conn]; \ |
| 7042 | | + uip_process(UIP_TIMER); } while (0) |
| 7043 | | + |
| 7044 | | +/** |
| 7045 | | + * Periodic processing for a connection identified by a pointer to its structure. |
| 7046 | | + * |
| 7047 | | + * Same as uip_periodic() but takes a pointer to the actual uip_conn |
| 7048 | | + * struct instead of an integer as its argument. This function can be |
| 7049 | | + * used to force periodic processing of a specific connection. |
| 7050 | | + * |
| 7051 | | + * \param conn A pointer to the uip_conn struct for the connection to |
| 7052 | | + * be processed. |
| 7053 | | + * |
| 7054 | | + * \hideinitializer |
| 7055 | | + */ |
| 7056 | | +#define uip_periodic_conn(conn) do { uip_conn = conn; \ |
| 7057 | | + uip_process(UIP_TIMER); } while (0) |
| 6629 | + |
| 6630 | + /* If this fragment has the More Fragments flag set to zero, we |
| 6631 | + know that this is the last fragment, so we can calculate the |
| 6632 | + size of the entire packet. We also set the |
| 6633 | + IP_REASS_FLAG_LASTFRAG flag to indicate that we have received |
| 6634 | + the final fragment. */ |
| 7058 | 6635 | + |
| 7059 | | +#if UIP_UDP |
| 7060 | | +/** |
| 7061 | | + * Periodic processing for a UDP connection identified by its number. |
| 7062 | | + * |
| 7063 | | + * This function is essentially the same as uip_prerioic(), but for |
| 7064 | | + * UDP connections. It is called in a similar fashion as the |
| 7065 | | + * uip_periodic() function: |
| 7066 | | + \code |
| 7067 | | + for(i = 0; i < UIP_UDP_CONNS; i++) { |
| 7068 | | + uip_udp_periodic(i); |
| 7069 | | + if(uip_len > 0) { |
| 7070 | | + devicedriver_send(); |
| 7071 | | + } |
| 7072 | | + } |
| 7073 | | + \endcode |
| 7074 | | + * |
| 7075 | | + * \note As for the uip_periodic() function, special care has to be |
| 7076 | | + * taken when using uIP together with ARP and Ethernet: |
| 7077 | | + \code |
| 7078 | | + for(i = 0; i < UIP_UDP_CONNS; i++) { |
| 7079 | | + uip_udp_periodic(i); |
| 7080 | | + if(uip_len > 0) { |
| 7081 | | + uip_arp_out(); |
| 7082 | | + ethernet_devicedriver_send(); |
| 6636 | + if((BUF->ipoffset[0] & IP_MF) == 0) { |
| 6637 | + uip_reassflags |= UIP_REASS_FLAG_LASTFRAG; |
| 6638 | + uip_reasslen = offset + len; |
| 7083 | 6639 | + } |
| 7084 | | + } |
| 7085 | | + \endcode |
| 7086 | | + * |
| 7087 | | + * \param conn The number of the UDP connection to be processed. |
| 7088 | | + * |
| 7089 | | + * \hideinitializer |
| 7090 | | + */ |
| 7091 | | +#define uip_udp_periodic(conn) do { uip_udp_conn = &uip_udp_conns[conn]; \ |
| 7092 | | + uip_process(UIP_UDP_TIMER); } while (0) |
| 7093 | | + |
| 7094 | | +/** |
| 7095 | | + * Periodic processing for a UDP connection identified by a pointer to |
| 7096 | | + * its structure. |
| 7097 | | + * |
| 7098 | | + * Same as uip_udp_periodic() but takes a pointer to the actual |
| 7099 | | + * uip_conn struct instead of an integer as its argument. This |
| 7100 | | + * function can be used to force periodic processing of a specific |
| 7101 | | + * connection. |
| 7102 | | + * |
| 7103 | | + * \param conn A pointer to the uip_udp_conn struct for the connection |
| 7104 | | + * to be processed. |
| 7105 | | + * |
| 7106 | | + * \hideinitializer |
| 7107 | | + */ |
| 7108 | | +#define uip_udp_periodic_conn(conn) do { uip_udp_conn = conn; \ |
| 7109 | | + uip_process(UIP_UDP_TIMER); } while (0) |
| 7110 | | + |
| 6640 | + |
| 6641 | + /* Finally, we check if we have a full packet in the buffer. We do |
| 6642 | + this by checking if we have the last fragment and if all bits |
| 6643 | + in the bitmap are set. */ |
| 6644 | + if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) { |
| 6645 | + /* Check all bytes up to and including all but the last byte in |
| 6646 | + the bitmap. */ |
| 6647 | + for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) { |
| 6648 | + if(uip_reassbitmap[i] != 0xff) { |
| 6649 | + goto nullreturn; |
| 6650 | + } |
| 6651 | + } |
| 6652 | + /* Check the last byte in the bitmap. It should contain just the |
| 6653 | + right amount of bits. */ |
| 6654 | + if(uip_reassbitmap[uip_reasslen / (8 * 8)] != |
| 6655 | + (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) { |
| 6656 | + goto nullreturn; |
| 6657 | + } |
| 7111 | 6658 | + |
| 7112 | | +#endif /* UIP_UDP */ |
| 6659 | + /* If we have come this far, we have a full packet in the |
| 6660 | + buffer, so we allocate a pbuf and copy the packet into it. We |
| 6661 | + also reset the timer. */ |
| 6662 | + uip_reasstmr = 0; |
| 6663 | + memcpy(BUF, FBUF, uip_reasslen); |
| 7113 | 6664 | + |
| 7114 | | +/** |
| 7115 | | + * The uIP packet buffer. |
| 7116 | | + * |
| 7117 | | + * The uip_buf array is used to hold incoming and outgoing |
| 7118 | | + * packets. The device driver should place incoming data into this |
| 7119 | | + * buffer. When sending data, the device driver should read the link |
| 7120 | | + * level headers and the TCP/IP headers from this buffer. The size of |
| 7121 | | + * the link level headers is configured by the UIP_LLH_LEN define. |
| 7122 | | + * |
| 7123 | | + * \note The application data need not be placed in this buffer, so |
| 7124 | | + * the device driver must read it from the place pointed to by the |
| 7125 | | + * uip_appdata pointer as illustrated by the following example: |
| 7126 | | + \code |
| 7127 | | + void |
| 7128 | | + devicedriver_send(void) |
| 7129 | | + { |
| 7130 | | + hwsend(&uip_buf[0], UIP_LLH_LEN); |
| 7131 | | + hwsend(&uip_buf[UIP_LLH_LEN], 40); |
| 7132 | | + hwsend(uip_appdata, uip_len - 40 - UIP_LLH_LEN); |
| 7133 | | + } |
| 7134 | | + \endcode |
| 7135 | | + */ |
| 7136 | | +extern u8_t uip_buf[UIP_BUFSIZE+2]; |
| 6665 | + /* Pretend to be a "normal" (i.e., not fragmented) IP packet |
| 6666 | + from now on. */ |
| 6667 | + BUF->ipoffset[0] = BUF->ipoffset[1] = 0; |
| 6668 | + BUF->len[0] = uip_reasslen >> 8; |
| 6669 | + BUF->len[1] = uip_reasslen & 0xff; |
| 6670 | + BUF->ipchksum = 0; |
| 6671 | + BUF->ipchksum = ~(uip_ipchksum()); |
| 7137 | 6672 | + |
| 7138 | | +/** @} */ |
| 6673 | + return uip_reasslen; |
| 6674 | + } |
| 6675 | + } |
| 7139 | 6676 | + |
| 6677 | + nullreturn: |
| 6678 | + return 0; |
| 6679 | +} |
| 6680 | +#endif /* UIP_REASSEMBL */ |
| 7140 | 6681 | +/*-----------------------------------------------------------------------------------*/ |
| 7141 | | +/* Functions that are used by the uIP application program. Opening and |
| 7142 | | + * closing connections, sending and receiving data, etc. is all |
| 7143 | | + * handled by the functions below. |
| 7144 | | +*/ |
| 7145 | | +/** |
| 7146 | | + * \defgroup uipappfunc uIP application functions |
| 7147 | | + * @{ |
| 7148 | | + * |
| 7149 | | + * Functions used by an application running of top of uIP. |
| 7150 | | + */ |
| 7151 | | + |
| 7152 | | +/** |
| 7153 | | + * Start listening to the specified port. |
| 7154 | | + * |
| 7155 | | + * \note Since this function expects the port number in network byte |
| 7156 | | + * order, a conversion using HTONS() or htons() is necessary. |
| 7157 | | + * |
| 7158 | | + \code |
| 7159 | | + uip_listen(HTONS(80)); |
| 7160 | | + \endcode |
| 7161 | | + * |
| 7162 | | + * \param port A 16-bit port number in network byte order. |
| 7163 | | + */ |
| 7164 | | +void uip_listen(u16_t port); |
| 7165 | | + |
| 7166 | | +/** |
| 7167 | | + * Stop listening to the specified port. |
| 7168 | | + * |
| 7169 | | + * \note Since this function expects the port number in network byte |
| 7170 | | + * order, a conversion using HTONS() or htons() is necessary. |
| 7171 | | + * |
| 7172 | | + \code |
| 7173 | | + uip_unlisten(HTONS(80)); |
| 7174 | | + \endcode |
| 7175 | | + * |
| 7176 | | + * \param port A 16-bit port number in network byte order. |
| 7177 | | + */ |
| 7178 | | +void uip_unlisten(u16_t port); |
| 7179 | | + |
| 7180 | | +/** |
| 7181 | | + * Connect to a remote host using TCP. |
| 7182 | | + * |
| 7183 | | + * This function is used to start a new connection to the specified |
| 7184 | | + * port on the specied host. It allocates a new connection identifier, |
| 7185 | | + * sets the connection to the SYN_SENT state and sets the |
| 7186 | | + * retransmission timer to 0. This will cause a TCP SYN segment to be |
| 7187 | | + * sent out the next time this connection is periodically processed, |
| 7188 | | + * which usually is done within 0.5 seconds after the call to |
| 7189 | | + * uip_connect(). |
| 7190 | | + * |
| 7191 | | + * \note This function is avaliable only if support for active open |
| 7192 | | + * has been configured by defining UIP_ACTIVE_OPEN to 1 in uipopt.h. |
| 7193 | | + * |
| 7194 | | + * \note Since this function requires the port number to be in network |
| 7195 | | + * byte order, a convertion using HTONS() or htons() is necessary. |
| 7196 | | + * |
| 7197 | | + \code |
| 7198 | | + u16_t ipaddr[2]; |
| 6682 | +static void |
| 6683 | +uip_add_rcv_nxt(unsigned short int n) |
| 6684 | +{ |
| 6685 | + uip_add32(uip_conn->rcv_nxt, n); |
| 6686 | + uip_conn->rcv_nxt[0] = uip_acc32[0]; |
| 6687 | + uip_conn->rcv_nxt[1] = uip_acc32[1]; |
| 6688 | + uip_conn->rcv_nxt[2] = uip_acc32[2]; |
| 6689 | + uip_conn->rcv_nxt[3] = uip_acc32[3]; |
| 6690 | +} |
| 6691 | +/*-----------------------------------------------------------------------------------*/ |
| 6692 | +void |
| 6693 | +uip_process(u8_t flag) |
| 6694 | +{ |
| 6695 | + register struct uip_conn *uip_connr = uip_conn; |
| 6696 | + |
| 6697 | + uip_appdata = &uip_buf[40 + UIP_LLH_LEN]; |
| 7199 | 6698 | + |
| 7200 | | + uip_ipaddr(ipaddr, 192,168,1,2); |
| 7201 | | + uip_connect(ipaddr, HTONS(80)); |
| 7202 | | + \endcode |
| 7203 | | + * |
| 7204 | | + * \param ripaddr A pointer to a 4-byte array representing the IP |
| 7205 | | + * address of the remote hot. |
| 7206 | | + * |
| 7207 | | + * \param port A 16-bit port number in network byte order. |
| 7208 | | + * |
| 7209 | | + * \return A pointer to the uIP connection identifier for the new connection, |
| 7210 | | + * or NULL if no connection could be allocated. |
| 7211 | | + * |
| 7212 | | + */ |
| 7213 | | +struct uip_conn *uip_connect(u16_t *ripaddr, u16_t port); |
| 6699 | + |
| 6700 | + /* Check if we were invoked because of the perodic timer fireing. */ |
| 6701 | + if(flag == UIP_TIMER) { |
| 6702 | +#if UIP_REASSEMBLY |
| 6703 | + if(uip_reasstmr != 0) { |
| 6704 | + --uip_reasstmr; |
| 6705 | + } |
| 6706 | +#endif /* UIP_REASSEMBLY */ |
| 6707 | + /* Increase the initial sequence number. */ |
| 6708 | + if(++iss[3] == 0) { |
| 6709 | + if(++iss[2] == 0) { |
| 6710 | + if(++iss[1] == 0) { |
| 6711 | + ++iss[0]; |
| 6712 | + } |
| 6713 | + } |
| 6714 | + } |
| 6715 | + uip_len = 0; |
| 6716 | + if(uip_connr->tcpstateflags == TIME_WAIT || |
| 6717 | + uip_connr->tcpstateflags == FIN_WAIT_2) { |
| 6718 | + ++(uip_connr->timer); |
| 6719 | + if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) { |
| 6720 | + uip_connr->tcpstateflags = CLOSED; |
| 6721 | + } |
| 6722 | + } else if(uip_connr->tcpstateflags != CLOSED) { |
| 6723 | + /* If the connection has outstanding data, we increase the |
| 6724 | + connection's timer and see if it has reached the RTO value |
| 6725 | + in which case we retransmit. */ |
| 6726 | + if(uip_outstanding(uip_connr)) { |
| 6727 | + if(uip_connr->timer-- == 0) { |
| 6728 | + if(uip_connr->nrtx == UIP_MAXRTX || |
| 6729 | + ((uip_connr->tcpstateflags == SYN_SENT || |
| 6730 | + uip_connr->tcpstateflags == SYN_RCVD) && |
| 6731 | + uip_connr->nrtx == UIP_MAXSYNRTX)) { |
| 6732 | + uip_connr->tcpstateflags = CLOSED; |
| 7214 | 6733 | + |
| 6734 | + /* We call UIP_APPCALL() with uip_flags set to |
| 6735 | + UIP_TIMEDOUT to inform the application that the |
| 6736 | + connection has timed out. */ |
| 6737 | + uip_flags = UIP_TIMEDOUT; |
| 6738 | + UIP_APPCALL(); |
| 7215 | 6739 | + |
| 6740 | + /* We also send a reset packet to the remote host. */ |
| 6741 | + BUF->flags = TCP_RST | TCP_ACK; |
| 6742 | + goto tcp_send_nodata; |
| 6743 | + } |
| 7216 | 6744 | + |
| 7217 | | +/** |
| 7218 | | + * \internal |
| 7219 | | + * |
| 7220 | | + * Check if a connection has outstanding (i.e., unacknowledged) data. |
| 7221 | | + * |
| 7222 | | + * \param conn A pointer to the uip_conn structure for the connection. |
| 7223 | | + * |
| 7224 | | + * \hideinitializer |
| 7225 | | + */ |
| 7226 | | +#define uip_outstanding(conn) ((conn)->len) |
| 6745 | + /* Exponential backoff. */ |
| 6746 | + uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4? |
| 6747 | + 4: |
| 6748 | + uip_connr->nrtx); |
| 6749 | + ++(uip_connr->nrtx); |
| 6750 | + |
| 6751 | + /* Ok, so we need to retransmit. We do this differently |
| 6752 | + depending on which state we are in. In ESTABLISHED, we |
| 6753 | + call upon the application so that it may prepare the |
| 6754 | + data for the retransmit. In SYN_RCVD, we resend the |
| 6755 | + SYNACK that we sent earlier and in LAST_ACK we have to |
| 6756 | + retransmit our FINACK. */ |
| 6757 | + UIP_STAT(++uip_stat.tcp.rexmit); |
| 6758 | + switch(uip_connr->tcpstateflags & TS_MASK) { |
| 6759 | + case SYN_RCVD: |
| 6760 | + /* In the SYN_RCVD state, we should retransmit our |
| 6761 | + SYNACK. */ |
| 6762 | + goto tcp_send_synack; |
| 6763 | + |
| 6764 | +#if UIP_ACTIVE_OPEN |
| 6765 | + case SYN_SENT: |
| 6766 | + /* In the SYN_SENT state, we retransmit out SYN. */ |
| 6767 | + BUF->flags = 0; |
| 6768 | + goto tcp_send_syn; |
| 6769 | +#endif /* UIP_ACTIVE_OPEN */ |
| 6770 | + |
| 6771 | + case ESTABLISHED: |
| 6772 | + /* In the ESTABLISHED state, we call upon the application |
| 6773 | + to do the actual retransmit after which we jump into |
| 6774 | + the code for sending out the packet (the apprexmit |
| 6775 | + label). */ |
| 6776 | + uip_len = 0; |
| 6777 | + uip_slen = 0; |
| 6778 | + uip_flags = UIP_REXMIT; |
| 6779 | + UIP_APPCALL(); |
| 6780 | + goto apprexmit; |
| 6781 | + |
| 6782 | + case FIN_WAIT_1: |
| 6783 | + case CLOSING: |
| 6784 | + case LAST_ACK: |
| 6785 | + /* In all these states we should retransmit a FINACK. */ |
| 6786 | + goto tcp_send_finack; |
| 6787 | + |
| 6788 | + } |
| 6789 | + } |
| 6790 | + } else if((uip_connr->tcpstateflags & TS_MASK) == ESTABLISHED) { |
| 6791 | + /* If there was no need for a retransmission, we poll the |
| 6792 | + application for new data. */ |
| 6793 | + uip_len = 0; |
| 6794 | + uip_slen = 0; |
| 6795 | + uip_flags = UIP_POLL; |
| 6796 | + UIP_APPCALL(); |
| 6797 | + goto appsend; |
| 6798 | + } |
| 6799 | + } |
| 6800 | + goto drop; |
| 6801 | + } |
| 6802 | +#if UIP_UDP |
| 6803 | + if(flag == UIP_UDP_TIMER) { |
| 6804 | + if(uip_udp_conn->lport != 0) { |
| 6805 | + uip_appdata = &uip_buf[UIP_LLH_LEN + 28]; |
| 6806 | + uip_len = uip_slen = 0; |
| 6807 | + uip_flags = UIP_POLL; |
| 6808 | + UIP_UDP_APPCALL(); |
| 6809 | + goto udp_send; |
| 6810 | + } else { |
| 6811 | + goto drop; |
| 6812 | + } |
| 6813 | + } |
| 6814 | +#endif |
| 7227 | 6815 | + |
| 7228 | | +/** |
| 7229 | | + * Send data on the current connection. |
| 7230 | | + * |
| 7231 | | + * This function is used to send out a single segment of TCP |
| 7232 | | + * data. Only applications that have been invoked by uIP for event |
| 7233 | | + * processing can send data. |
| 7234 | | + * |
| 7235 | | + * The amount of data that actually is sent out after a call to this |
| 7236 | | + * funcion is determined by the maximum amount of data TCP allows. uIP |
| 7237 | | + * will automatically crop the data so that only the appropriate |
| 7238 | | + * amount of data is sent. The function uip_mss() can be used to query |
| 7239 | | + * uIP for the amount of data that actually will be sent. |
| 7240 | | + * |
| 7241 | | + * \note This function does not guarantee that the sent data will |
| 7242 | | + * arrive at the destination. If the data is lost in the network, the |
| 7243 | | + * application will be invoked with the uip_rexmit() event being |
| 7244 | | + * set. The application will then have to resend the data using this |
| 7245 | | + * function. |
| 7246 | | + * |
| 7247 | | + * \param data A pointer to the data which is to be sent. |
| 7248 | | + * |
| 7249 | | + * \param len The maximum amount of data bytes to be sent. |
| 7250 | | + * |
| 7251 | | + * \hideinitializer |
| 7252 | | + */ |
| 7253 | | +#define uip_send(data, len) do { uip_sappdata = (data); uip_slen = (len);} while(0) |
| 6816 | + /* This is where the input processing starts. */ |
| 6817 | + UIP_STAT(++uip_stat.ip.recv); |
| 7254 | 6818 | + |
| 7255 | | +/** |
| 7256 | | + * The length of any incoming data that is currently avaliable (if avaliable) |
| 7257 | | + * in the uip_appdata buffer. |
| 7258 | | + * |
| 7259 | | + * The test function uip_data() must first be used to check if there |
| 7260 | | + * is any data available at all. |
| 7261 | | + * |
| 7262 | | + * \hideinitializer |
| 7263 | | + */ |
| 7264 | | +#define uip_datalen() uip_len |
| 7265 | 6819 | + |
| 7266 | | +/** |
| 7267 | | + * The length of any out-of-band data (urgent data) that has arrived |
| 7268 | | + * on the connection. |
| 7269 | | + * |
| 7270 | | + * \note The configuration parameter UIP_URGDATA must be set for this |
| 7271 | | + * function to be enabled. |
| 7272 | | + * |
| 7273 | | + * \hideinitializer |
| 7274 | | + */ |
| 7275 | | +#define uip_urgdatalen() uip_urglen |
| 6820 | + /* Start of IPv4 input header processing code. */ |
| 6821 | + |
| 6822 | + /* Check validity of the IP header. */ |
| 6823 | + if(BUF->vhl != 0x45) { /* IP version and header length. */ |
| 6824 | + UIP_STAT(++uip_stat.ip.drop); |
| 6825 | + UIP_STAT(++uip_stat.ip.vhlerr); |
| 6826 | + UIP_LOG("ip: invalid version or header length."); |
| 6827 | + goto drop; |
| 6828 | + } |
| 6829 | + |
| 6830 | + /* Check the size of the packet. If the size reported to us in |
| 6831 | + uip_len doesn't match the size reported in the IP header, there |
| 6832 | + has been a transmission error and we drop the packet. */ |
| 6833 | + |
| 6834 | + if(BUF->len[0] != (uip_len >> 8)) { /* IP length, high byte. */ |
| 6835 | + uip_len = (uip_len & 0xff) | (BUF->len[0] << 8); |
| 6836 | + } |
| 6837 | + if(BUF->len[1] != (uip_len & 0xff)) { /* IP length, low byte. */ |
| 6838 | + uip_len = (uip_len & 0xff00) | BUF->len[1]; |
| 6839 | + } |
| 7276 | 6840 | + |
| 7277 | | +/** |
| 7278 | | + * Close the current connection. |
| 7279 | | + * |
| 7280 | | + * This function will close the current connection in a nice way. |
| 7281 | | + * |
| 7282 | | + * \hideinitializer |
| 7283 | | + */ |
| 7284 | | +#define uip_close() (uip_flags = UIP_CLOSE) |
| 6841 | + /* Check the fragment flag. */ |
| 6842 | + if((BUF->ipoffset[0] & 0x3f) != 0 || |
| 6843 | + BUF->ipoffset[1] != 0) { |
| 6844 | +#if UIP_REASSEMBLY |
| 6845 | + uip_len = uip_reass(); |
| 6846 | + if(uip_len == 0) { |
| 6847 | + goto drop; |
| 6848 | + } |
| 6849 | +#else |
| 6850 | + UIP_STAT(++uip_stat.ip.drop); |
| 6851 | + UIP_STAT(++uip_stat.ip.fragerr); |
| 6852 | + UIP_LOG("ip: fragment dropped."); |
| 6853 | + goto drop; |
| 6854 | +#endif /* UIP_REASSEMBLY */ |
| 6855 | + } |
| 7285 | 6856 | + |
| 7286 | | +/** |
| 7287 | | + * Abort the current connection. |
| 7288 | | + * |
| 7289 | | + * This function will abort (reset) the current connection, and is |
| 7290 | | + * usually used when an error has occured that prevents using the |
| 7291 | | + * uip_close() function. |
| 7292 | | + * |
| 7293 | | + * \hideinitializer |
| 7294 | | + */ |
| 7295 | | +#define uip_abort() (uip_flags = UIP_ABORT) |
| 6857 | + /* If we are configured to use ping IP address configuration and |
| 6858 | + hasn't been assigned an IP address yet, we accept all ICMP |
| 6859 | + packets. */ |
| 6860 | +#if UIP_PINGADDRCONF |
| 6861 | + if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) { |
| 6862 | + if(BUF->proto == UIP_PROTO_ICMP) { |
| 6863 | + UIP_LOG("ip: possible ping config packet received."); |
| 6864 | + goto icmp_input; |
| 6865 | + } else { |
| 6866 | + UIP_LOG("ip: packet dropped since no address assigned."); |
| 6867 | + goto drop; |
| 6868 | + } |
| 6869 | + } |
| 6870 | +#endif /* UIP_PINGADDRCONF */ |
| 6871 | + |
| 6872 | + /* Check if the packet is destined for our IP address. */ |
| 6873 | + if(BUF->destipaddr[0] != uip_hostaddr[0]) { |
| 6874 | + UIP_STAT(++uip_stat.ip.drop); |
| 6875 | + UIP_LOG("ip: packet not for us."); |
| 6876 | + goto drop; |
| 6877 | + } |
| 6878 | + if(BUF->destipaddr[1] != uip_hostaddr[1]) { |
| 6879 | + UIP_STAT(++uip_stat.ip.drop); |
| 6880 | + UIP_LOG("ip: packet not for us."); |
| 6881 | + goto drop; |
| 6882 | + } |
| 7296 | 6883 | + |
| 7297 | | +/** |
| 7298 | | + * Tell the sending host to stop sending data. |
| 7299 | | + * |
| 7300 | | + * This function will close our receiver's window so that we stop |
| 7301 | | + * receiving data for the current connection. |
| 7302 | | + * |
| 7303 | | + * \hideinitializer |
| 7304 | | + */ |
| 7305 | | +#define uip_stop() (uip_conn->tcpstateflags |= UIP_STOPPED) |
| 6884 | + if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header |
| 6885 | + checksum. */ |
| 6886 | + UIP_STAT(++uip_stat.ip.drop); |
| 6887 | + UIP_STAT(++uip_stat.ip.chkerr); |
| 6888 | + UIP_LOG("ip: bad checksum."); |
| 6889 | + goto drop; |
| 6890 | + } |
| 7306 | 6891 | + |
| 7307 | | +/** |
| 7308 | | + * Find out if the current connection has been previously stopped with |
| 7309 | | + * uip_stop(). |
| 7310 | | + * |
| 7311 | | + * \hideinitializer |
| 7312 | | + */ |
| 7313 | | +#define uip_stopped(conn) ((conn)->tcpstateflags & UIP_STOPPED) |
| 6892 | + if(BUF->proto == UIP_PROTO_TCP) /* Check for TCP packet. If so, jump |
| 6893 | + to the tcp_input label. */ |
| 6894 | + goto tcp_input; |
| 7314 | 6895 | + |
| 7315 | | +/** |
| 7316 | | + * Restart the current connection, if is has previously been stopped |
| 7317 | | + * with uip_stop(). |
| 7318 | | + * |
| 7319 | | + * This function will open the receiver's window again so that we |
| 7320 | | + * start receiving data for the current connection. |
| 7321 | | + * |
| 7322 | | + * \hideinitializer |
| 7323 | | + */ |
| 7324 | | +#define uip_restart() do { uip_flags |= UIP_NEWDATA; \ |
| 7325 | | + uip_conn->tcpstateflags &= ~UIP_STOPPED; \ |
| 7326 | | + } while(0) |
| 6896 | +#if UIP_UDP |
| 6897 | + if(BUF->proto == UIP_PROTO_UDP) |
| 6898 | + goto udp_input; |
| 6899 | +#endif /* UIP_UDP */ |
| 7327 | 6900 | + |
| 6901 | + if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from |
| 6902 | + here. */ |
| 6903 | + UIP_STAT(++uip_stat.ip.drop); |
| 6904 | + UIP_STAT(++uip_stat.ip.protoerr); |
| 6905 | + UIP_LOG("ip: neither tcp nor icmp."); |
| 6906 | + goto drop; |
| 6907 | + } |
| 6908 | + |
| 6909 | + //icmp_input: |
| 6910 | + UIP_STAT(++uip_stat.icmp.recv); |
| 6911 | + |
| 6912 | + /* ICMP echo (i.e., ping) processing. This is simple, we only change |
| 6913 | + the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP |
| 6914 | + checksum before we return the packet. */ |
| 6915 | + if(ICMPBUF->type != ICMP_ECHO) { |
| 6916 | + UIP_STAT(++uip_stat.icmp.drop); |
| 6917 | + UIP_STAT(++uip_stat.icmp.typeerr); |
| 6918 | + UIP_LOG("icmp: not icmp echo."); |
| 6919 | + goto drop; |
| 6920 | + } |
| 7328 | 6921 | + |
| 7329 | | +/* uIP tests that can be made to determine in what state the current |
| 7330 | | + connection is, and what the application function should do. */ |
| 6922 | + /* If we are configured to use ping IP address assignment, we use |
| 6923 | + the destination IP address of this ping packet and assign it to |
| 6924 | + ourself. */ |
| 6925 | +#if UIP_PINGADDRCONF |
| 6926 | + if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) { |
| 6927 | + uip_hostaddr[0] = BUF->destipaddr[0]; |
| 6928 | + uip_hostaddr[1] = BUF->destipaddr[1]; |
| 6929 | + } |
| 6930 | +#endif /* UIP_PINGADDRCONF */ |
| 6931 | + |
| 6932 | + ICMPBUF->type = ICMP_ECHO_REPLY; |
| 6933 | + |
| 6934 | + if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) { |
| 6935 | + ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1; |
| 6936 | + } else { |
| 6937 | + ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8); |
| 6938 | + } |
| 6939 | + |
| 6940 | + /* Swap IP addresses. */ |
| 6941 | + tmp16 = BUF->destipaddr[0]; |
| 6942 | + BUF->destipaddr[0] = BUF->srcipaddr[0]; |
| 6943 | + BUF->srcipaddr[0] = tmp16; |
| 6944 | + tmp16 = BUF->destipaddr[1]; |
| 6945 | + BUF->destipaddr[1] = BUF->srcipaddr[1]; |
| 6946 | + BUF->srcipaddr[1] = tmp16; |
| 7331 | 6947 | + |
| 7332 | | +/** |
| 7333 | | + * Is new incoming data available? |
| 7334 | | + * |
| 7335 | | + * Will reduce to non-zero if there is new data for the application |
| 7336 | | + * present at the uip_appdata pointer. The size of the data is |
| 7337 | | + * avaliable through the uip_len variable. |
| 7338 | | + * |
| 7339 | | + * \hideinitializer |
| 7340 | | + */ |
| 7341 | | +#define uip_newdata() (uip_flags & UIP_NEWDATA) |
| 6948 | + UIP_STAT(++uip_stat.icmp.sent); |
| 6949 | + goto send; |
| 7342 | 6950 | + |
| 7343 | | +/** |
| 7344 | | + * Has previously sent data been acknowledged? |
| 7345 | | + * |
| 7346 | | + * Will reduce to non-zero if the previously sent data has been |
| 7347 | | + * acknowledged by the remote host. This means that the application |
| 7348 | | + * can send new data. |
| 7349 | | + * |
| 7350 | | + * \hideinitializer |
| 7351 | | + */ |
| 7352 | | +#define uip_acked() (uip_flags & UIP_ACKDATA) |
| 6951 | + /* End of IPv4 input header processing code. */ |
| 6952 | + |
| 7353 | 6953 | + |
| 7354 | | +/** |
| 7355 | | + * Has the connection just been connected? |
| 7356 | | + * |
| 7357 | | + * Reduces to non-zero if the current connection has been connected to |
| 7358 | | + * a remote host. This will happen both if the connection has been |
| 7359 | | + * actively opened (with uip_connect()) or passively opened (with |
| 7360 | | + * uip_listen()). |
| 7361 | | + * |
| 7362 | | + * \hideinitializer |
| 7363 | | + */ |
| 7364 | | +#define uip_connected() (uip_flags & UIP_CONNECTED) |
| 6954 | +#if UIP_UDP |
| 6955 | + /* UDP input processing. */ |
| 6956 | + udp_input: |
| 6957 | + /* UDP processing is really just a hack. We don't do anything to the |
| 6958 | + UDP/IP headers, but let the UDP application do all the hard |
| 6959 | + work. If the application sets uip_slen, it has a packet to |
| 6960 | + send. */ |
| 6961 | +#if UIP_UDP_CHECKSUMS |
| 6962 | + if(uip_udpchksum() != 0xffff) { |
| 6963 | + UIP_STAT(++uip_stat.udp.drop); |
| 6964 | + UIP_STAT(++uip_stat.udp.chkerr); |
| 6965 | + UIP_LOG("udp: bad checksum."); |
| 6966 | + goto drop; |
| 6967 | + } |
| 6968 | +#endif /* UIP_UDP_CHECKSUMS */ |
| 7365 | 6969 | + |
| 7366 | | +/** |
| 7367 | | + * Has the connection been closed by the other end? |
| 7368 | | + * |
| 7369 | | + * Is non-zero if the connection has been closed by the remote |
| 7370 | | + * host. The application may then do the necessary clean-ups. |
| 7371 | | + * |
| 7372 | | + * \hideinitializer |
| 7373 | | + */ |
| 7374 | | +#define uip_closed() (uip_flags & UIP_CLOSE) |
| 6970 | + /* Demultiplex this UDP packet between the UDP "connections". */ |
| 6971 | + for(uip_udp_conn = &uip_udp_conns[0]; |
| 6972 | + uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS]; |
| 6973 | + ++uip_udp_conn) { |
| 6974 | + if(uip_udp_conn->lport != 0 && |
| 6975 | + UDPBUF->destport == uip_udp_conn->lport && |
| 6976 | + (uip_udp_conn->rport == 0 || |
| 6977 | + UDPBUF->srcport == uip_udp_conn->rport) && |
| 6978 | + BUF->srcipaddr[0] == uip_udp_conn->ripaddr[0] && |
| 6979 | + BUF->srcipaddr[1] == uip_udp_conn->ripaddr[1]) { |
| 6980 | + goto udp_found; |
| 6981 | + } |
| 6982 | + } |
| 6983 | + goto drop; |
| 6984 | + |
| 6985 | + udp_found: |
| 6986 | + uip_len = uip_len - 28; |
| 6987 | + uip_appdata = &uip_buf[UIP_LLH_LEN + 28]; |
| 6988 | + uip_flags = UIP_NEWDATA; |
| 6989 | + uip_slen = 0; |
| 6990 | + UIP_UDP_APPCALL(); |
| 6991 | + udp_send: |
| 6992 | + if(uip_slen == 0) { |
| 6993 | + goto drop; |
| 6994 | + } |
| 6995 | + uip_len = uip_slen + 28; |
| 7375 | 6996 | + |
| 7376 | | +/** |
| 7377 | | + * Has the connection been aborted by the other end? |
| 7378 | | + * |
| 7379 | | + * Non-zero if the current connection has been aborted (reset) by the |
| 7380 | | + * remote host. |
| 7381 | | + * |
| 7382 | | + * \hideinitializer |
| 7383 | | + */ |
| 7384 | | +#define uip_aborted() (uip_flags & UIP_ABORT) |
| 6997 | + BUF->len[0] = (uip_len >> 8); |
| 6998 | + BUF->len[1] = (uip_len & 0xff); |
| 6999 | + |
| 7000 | + BUF->proto = UIP_PROTO_UDP; |
| 7385 | 7001 | + |
| 7386 | | +/** |
| 7387 | | + * Has the connection timed out? |
| 7388 | | + * |
| 7389 | | + * Non-zero if the current connection has been aborted due to too many |
| 7390 | | + * retransmissions. |
| 7391 | | + * |
| 7392 | | + * \hideinitializer |
| 7393 | | + */ |
| 7394 | | +#define uip_timedout() (uip_flags & UIP_TIMEDOUT) |
| 7002 | + UDPBUF->udplen = HTONS(uip_slen + 8); |
| 7003 | + UDPBUF->udpchksum = 0; |
| 7004 | +#if UIP_UDP_CHECKSUMS |
| 7005 | + /* Calculate UDP checksum. */ |
| 7006 | + UDPBUF->udpchksum = ~(uip_udpchksum()); |
| 7007 | + if(UDPBUF->udpchksum == 0) { |
| 7008 | + UDPBUF->udpchksum = 0xffff; |
| 7009 | + } |
| 7010 | +#endif /* UIP_UDP_CHECKSUMS */ |
| 7395 | 7011 | + |
| 7396 | | +/** |
| 7397 | | + * Do we need to retransmit previously data? |
| 7398 | | + * |
| 7399 | | + * Reduces to non-zero if the previously sent data has been lost in |
| 7400 | | + * the network, and the application should retransmit it. The |
| 7401 | | + * application should send the exact same data as it did the last |
| 7402 | | + * time, using the uip_send() function. |
| 7403 | | + * |
| 7404 | | + * \hideinitializer |
| 7405 | | + */ |
| 7406 | | +#define uip_rexmit() (uip_flags & UIP_REXMIT) |
| 7012 | + BUF->srcport = uip_udp_conn->lport; |
| 7013 | + BUF->destport = uip_udp_conn->rport; |
| 7407 | 7014 | + |
| 7408 | | +/** |
| 7409 | | + * Is the connection being polled by uIP? |
| 7410 | | + * |
| 7411 | | + * Is non-zero if the reason the application is invoked is that the |
| 7412 | | + * current connection has been idle for a while and should be |
| 7413 | | + * polled. |
| 7414 | | + * |
| 7415 | | + * The polling event can be used for sending data without having to |
| 7416 | | + * wait for the remote host to send data. |
| 7417 | | + * |
| 7418 | | + * \hideinitializer |
| 7419 | | + */ |
| 7420 | | +#define uip_poll() (uip_flags & UIP_POLL) |
| 7015 | + BUF->srcipaddr[0] = uip_hostaddr[0]; |
| 7016 | + BUF->srcipaddr[1] = uip_hostaddr[1]; |
| 7017 | + BUF->destipaddr[0] = uip_udp_conn->ripaddr[0]; |
| 7018 | + BUF->destipaddr[1] = uip_udp_conn->ripaddr[1]; |
| 7019 | + |
| 7020 | + uip_appdata = &uip_buf[UIP_LLH_LEN + 40]; |
| 7021 | + goto ip_send_nolen; |
| 7022 | +#endif /* UIP_UDP */ |
| 7023 | + |
| 7024 | + /* TCP input processing. */ |
| 7025 | + tcp_input: |
| 7026 | + UIP_STAT(++uip_stat.tcp.recv); |
| 7421 | 7027 | + |
| 7422 | | +/** |
| 7423 | | + * Get the initial maxium segment size (MSS) of the current |
| 7424 | | + * connection. |
| 7425 | | + * |
| 7426 | | + * \hideinitializer |
| 7427 | | + */ |
| 7428 | | +#define uip_initialmss() (uip_conn->initialmss) |
| 7028 | + /* Start of TCP input header processing code. */ |
| 7029 | + |
| 7030 | + if(uip_tcpchksum() != 0xffff) { /* Compute and check the TCP |
| 7031 | + checksum. */ |
| 7032 | + UIP_STAT(++uip_stat.tcp.drop); |
| 7033 | + UIP_STAT(++uip_stat.tcp.chkerr); |
| 7034 | + UIP_LOG("tcp: bad checksum."); |
| 7035 | + goto drop; |
| 7036 | + } |
| 7037 | + |
| 7038 | + /* Demultiplex this segment. */ |
| 7039 | + /* First check any active connections. */ |
| 7040 | + for(uip_connr = &uip_conns[0]; uip_connr < &uip_conns[UIP_CONNS]; ++uip_connr) { |
| 7041 | + if(uip_connr->tcpstateflags != CLOSED && |
| 7042 | + BUF->destport == uip_connr->lport && |
| 7043 | + BUF->srcport == uip_connr->rport && |
| 7044 | + BUF->srcipaddr[0] == uip_connr->ripaddr[0] && |
| 7045 | + BUF->srcipaddr[1] == uip_connr->ripaddr[1]) { |
| 7046 | + goto found; |
| 7047 | + } |
| 7048 | + } |
| 7429 | 7049 | + |
| 7430 | | +/** |
| 7431 | | + * Get the current maxium segment size that can be sent on the current |
| 7432 | | + * connection. |
| 7433 | | + * |
| 7434 | | + * The current maxiumum segment size that can be sent on the |
| 7435 | | + * connection is computed from the receiver's window and the MSS of |
| 7436 | | + * the connection (which also is available by calling |
| 7437 | | + * uip_initialmss()). |
| 7438 | | + * |
| 7439 | | + * \hideinitializer |
| 7440 | | + */ |
| 7441 | | +#define uip_mss() (uip_conn->mss) |
| 7050 | + /* If we didn't find and active connection that expected the packet, |
| 7051 | + either this packet is an old duplicate, or this is a SYN packet |
| 7052 | + destined for a connection in LISTEN. If the SYN flag isn't set, |
| 7053 | + it is an old packet and we send a RST. */ |
| 7054 | + if((BUF->flags & TCP_CTL) != TCP_SYN) |
| 7055 | + goto reset; |
| 7056 | + |
| 7057 | + tmp16 = BUF->destport; |
| 7058 | + /* Next, check listening connections. */ |
| 7059 | + for(c = 0; c < UIP_LISTENPORTS; ++c) { |
| 7060 | + if(tmp16 == uip_listenports[c]) |
| 7061 | + goto found_listen; |
| 7062 | + } |
| 7063 | + |
| 7064 | + /* No matching connection found, so we send a RST packet. */ |
| 7065 | + UIP_STAT(++uip_stat.tcp.synrst); |
| 7066 | + reset: |
| 7442 | 7067 | + |
| 7443 | | +/** |
| 7444 | | + * Set up a new UDP connection. |
| 7445 | | + * |
| 7446 | | + * \param ripaddr A pointer to a 4-byte structure representing the IP |
| 7447 | | + * address of the remote host. |
| 7448 | | + * |
| 7449 | | + * \param rport The remote port number in network byte order. |
| 7450 | | + * |
| 7451 | | + * \return The uip_udp_conn structure for the new connection or NULL |
| 7452 | | + * if no connection could be allocated. |
| 7453 | | + */ |
| 7454 | | +struct uip_udp_conn *uip_udp_new(u16_t *ripaddr, u16_t rport); |
| 7068 | + /* We do not send resets in response to resets. */ |
| 7069 | + if(BUF->flags & TCP_RST) |
| 7070 | + goto drop; |
| 7455 | 7071 | + |
| 7456 | | +/** |
| 7457 | | + * Removed a UDP connection. |
| 7458 | | + * |
| 7459 | | + * \param conn A pointer to the uip_udp_conn structure for the connection. |
| 7460 | | + * |
| 7461 | | + * \hideinitializer |
| 7462 | | + */ |
| 7463 | | +#define uip_udp_remove(conn) (conn)->lport = 0 |
| 7072 | + UIP_STAT(++uip_stat.tcp.rst); |
| 7073 | + |
| 7074 | + BUF->flags = TCP_RST | TCP_ACK; |
| 7075 | + uip_len = 40; |
| 7076 | + BUF->tcpoffset = 5 << 4; |
| 7464 | 7077 | + |
| 7465 | | +/** |
| 7466 | | + * Send a UDP datagram of length len on the current connection. |
| 7467 | | + * |
| 7468 | | + * This function can only be called in response to a UDP event (poll |
| 7469 | | + * or newdata). The data must be present in the uip_buf buffer, at the |
| 7470 | | + * place pointed to by the uip_appdata pointer. |
| 7471 | | + * |
| 7472 | | + * \param len The length of the data in the uip_buf buffer. |
| 7473 | | + * |
| 7474 | | + * \hideinitializer |
| 7475 | | + */ |
| 7476 | | +#define uip_udp_send(len) uip_slen = (len) |
| 7078 | + /* Flip the seqno and ackno fields in the TCP header. */ |
| 7079 | + c = BUF->seqno[3]; |
| 7080 | + BUF->seqno[3] = BUF->ackno[3]; |
| 7081 | + BUF->ackno[3] = c; |
| 7082 | + |
| 7083 | + c = BUF->seqno[2]; |
| 7084 | + BUF->seqno[2] = BUF->ackno[2]; |
| 7085 | + BUF->ackno[2] = c; |
| 7086 | + |
| 7087 | + c = BUF->seqno[1]; |
| 7088 | + BUF->seqno[1] = BUF->ackno[1]; |
| 7089 | + BUF->ackno[1] = c; |
| 7090 | + |
| 7091 | + c = BUF->seqno[0]; |
| 7092 | + BUF->seqno[0] = BUF->ackno[0]; |
| 7093 | + BUF->ackno[0] = c; |
| 7477 | 7094 | + |
| 7478 | | +/** @} */ |
| 7095 | + /* We also have to increase the sequence number we are |
| 7096 | + acknowledging. If the least significant byte overflowed, we need |
| 7097 | + to propagate the carry to the other bytes as well. */ |
| 7098 | + if(++BUF->ackno[3] == 0) { |
| 7099 | + if(++BUF->ackno[2] == 0) { |
| 7100 | + if(++BUF->ackno[1] == 0) { |
| 7101 | + ++BUF->ackno[0]; |
| 7102 | + } |
| 7103 | + } |
| 7104 | + } |
| 7105 | + |
| 7106 | + /* Swap port numbers. */ |
| 7107 | + tmp16 = BUF->srcport; |
| 7108 | + BUF->srcport = BUF->destport; |
| 7109 | + BUF->destport = tmp16; |
| 7110 | + |
| 7111 | + /* Swap IP addresses. */ |
| 7112 | + tmp16 = BUF->destipaddr[0]; |
| 7113 | + BUF->destipaddr[0] = BUF->srcipaddr[0]; |
| 7114 | + BUF->srcipaddr[0] = tmp16; |
| 7115 | + tmp16 = BUF->destipaddr[1]; |
| 7116 | + BUF->destipaddr[1] = BUF->srcipaddr[1]; |
| 7117 | + BUF->srcipaddr[1] = tmp16; |
| 7479 | 7118 | + |
| 7480 | | +/* uIP convenience and converting functions. */ |
| 7119 | + |
| 7120 | + /* And send out the RST packet! */ |
| 7121 | + goto tcp_send_noconn; |
| 7481 | 7122 | + |
| 7482 | | +/** |
| 7483 | | + * \defgroup uipconvfunc uIP conversion functions |
| 7484 | | + * @{ |
| 7485 | | + * |
| 7486 | | + * These functions can be used for converting between different data |
| 7487 | | + * formats used by uIP. |
| 7488 | | + */ |
| 7489 | | + |
| 7490 | | +/** |
| 7491 | | + * Pack an IP address into a 4-byte array which is used by uIP to |
| 7492 | | + * represent IP addresses. |
| 7493 | | + * |
| 7494 | | + * Example: |
| 7495 | | + \code |
| 7496 | | + u16_t ipaddr[2]; |
| 7123 | + /* This label will be jumped to if we matched the incoming packet |
| 7124 | + with a connection in LISTEN. In that case, we should create a new |
| 7125 | + connection and send a SYNACK in return. */ |
| 7126 | + found_listen: |
| 7127 | + /* First we check if there are any connections avaliable. Unused |
| 7128 | + connections are kept in the same table as used connections, but |
| 7129 | + unused ones have the tcpstate set to CLOSED. Also, connections in |
| 7130 | + TIME_WAIT are kept track of and we'll use the oldest one if no |
| 7131 | + CLOSED connections are found. Thanks to Eddie C. Dost for a very |
| 7132 | + nice algorithm for the TIME_WAIT search. */ |
| 7133 | + uip_connr = 0; |
| 7134 | + for(c = 0; c < UIP_CONNS; ++c) { |
| 7135 | + if(uip_conns[c].tcpstateflags == CLOSED) { |
| 7136 | + uip_connr = &uip_conns[c]; |
| 7137 | + break; |
| 7138 | + } |
| 7139 | + if(uip_conns[c].tcpstateflags == TIME_WAIT) { |
| 7140 | + if(uip_connr == 0 || |
| 7141 | + uip_conns[c].timer > uip_connr->timer) { |
| 7142 | + uip_connr = &uip_conns[c]; |
| 7143 | + } |
| 7144 | + } |
| 7145 | + } |
| 7497 | 7146 | + |
| 7498 | | + uip_ipaddr(&ipaddr, 192,168,1,2); |
| 7499 | | + \endcode |
| 7500 | | + * |
| 7501 | | + * \param addr A pointer to a 4-byte array that will be filled in with |
| 7502 | | + * the IP addres. |
| 7503 | | + * \param addr0 The first octet of the IP address. |
| 7504 | | + * \param addr1 The second octet of the IP address. |
| 7505 | | + * \param addr2 The third octet of the IP address. |
| 7506 | | + * \param addr3 The forth octet of the IP address. |
| 7507 | | + * |
| 7508 | | + * \hideinitializer |
| 7509 | | + */ |
| 7510 | | +#define uip_ipaddr(addr, addr0,addr1,addr2,addr3) do { \ |
| 7511 | | + (addr)[0] = HTONS(((addr0) << 8) | (addr1)); \ |
| 7512 | | + (addr)[1] = HTONS(((addr2) << 8) | (addr3)); \ |
| 7513 | | + } while(0) |
| 7147 | + if(uip_connr == 0) { |
| 7148 | + /* All connections are used already, we drop packet and hope that |
| 7149 | + the remote end will retransmit the packet at a time when we |
| 7150 | + have more spare connections. */ |
| 7151 | + UIP_STAT(++uip_stat.tcp.syndrop); |
| 7152 | + UIP_LOG("tcp: found no unused connections."); |
| 7153 | + goto drop; |
| 7154 | + } |
| 7155 | + uip_conn = uip_connr; |
| 7156 | + |
| 7157 | + /* Fill in the necessary fields for the new connection. */ |
| 7158 | + uip_connr->rto = uip_connr->timer = UIP_RTO; |
| 7159 | + uip_connr->sa = 0; |
| 7160 | + uip_connr->sv = 4; |
| 7161 | + uip_connr->nrtx = 0; |
| 7162 | + uip_connr->lport = BUF->destport; |
| 7163 | + uip_connr->rport = BUF->srcport; |
| 7164 | + uip_connr->ripaddr[0] = BUF->srcipaddr[0]; |
| 7165 | + uip_connr->ripaddr[1] = BUF->srcipaddr[1]; |
| 7166 | + uip_connr->tcpstateflags = SYN_RCVD; |
| 7514 | 7167 | + |
| 7515 | | +/** |
| 7516 | | + * Convert 16-bit quantity from host byte order to network byte order. |
| 7517 | | + * |
| 7518 | | + * This macro is primarily used for converting constants from host |
| 7519 | | + * byte order to network byte order. For converting variables to |
| 7520 | | + * network byte order, use the htons() function instead. |
| 7521 | | + * |
| 7522 | | + * \hideinitializer |
| 7523 | | + */ |
| 7524 | | +#ifndef HTONS |
| 7525 | | +# if BYTE_ORDER == BIG_ENDIAN |
| 7526 | | +# define HTONS(n) (n) |
| 7527 | | +# else /* BYTE_ORDER == BIG_ENDIAN */ |
| 7528 | | +# define HTONS(n) ((((u16_t)((n) & 0xff)) << 8) | (((n) & 0xff00) >> 8)) |
| 7529 | | +# endif /* BYTE_ORDER == BIG_ENDIAN */ |
| 7530 | | +#endif /* HTONS */ |
| 7168 | + uip_connr->snd_nxt[0] = iss[0]; |
| 7169 | + uip_connr->snd_nxt[1] = iss[1]; |
| 7170 | + uip_connr->snd_nxt[2] = iss[2]; |
| 7171 | + uip_connr->snd_nxt[3] = iss[3]; |
| 7172 | + uip_connr->len = 1; |
| 7531 | 7173 | + |
| 7532 | | +/** |
| 7533 | | + * Convert 16-bit quantity from host byte order to network byte order. |
| 7534 | | + * |
| 7535 | | + * This function is primarily used for converting variables from host |
| 7536 | | + * byte order to network byte order. For converting constants to |
| 7537 | | + * network byte order, use the HTONS() macro instead. |
| 7538 | | + */ |
| 7539 | | +#ifndef htons |
| 7540 | | +u16_t htons(u16_t val); |
| 7541 | | +#endif /* htons */ |
| 7174 | + /* rcv_nxt should be the seqno from the incoming packet + 1. */ |
| 7175 | + uip_connr->rcv_nxt[3] = BUF->seqno[3]; |
| 7176 | + uip_connr->rcv_nxt[2] = BUF->seqno[2]; |
| 7177 | + uip_connr->rcv_nxt[1] = BUF->seqno[1]; |
| 7178 | + uip_connr->rcv_nxt[0] = BUF->seqno[0]; |
| 7179 | + uip_add_rcv_nxt(1); |
| 7542 | 7180 | + |
| 7543 | | +/** @} */ |
| 7181 | + /* Parse the TCP MSS option, if present. */ |
| 7182 | + if((BUF->tcpoffset & 0xf0) > 0x50) { |
| 7183 | + for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { |
| 7184 | + opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c]; |
| 7185 | + if(opt == 0x00) { |
| 7186 | + /* End of options. */ |
| 7187 | + break; |
| 7188 | + } else if(opt == 0x01) { |
| 7189 | + ++c; |
| 7190 | + /* NOP option. */ |
| 7191 | + } else if(opt == 0x02 && |
| 7192 | + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) { |
| 7193 | + /* An MSS option with the right option length. */ |
| 7194 | + tmp16 = ((unsigned short int)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | |
| 7195 | + (unsigned short int)uip_buf[40 + UIP_LLH_LEN + 3 + c]; |
| 7196 | + uip_connr->initialmss = uip_connr->mss = |
| 7197 | + tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; |
| 7198 | + |
| 7199 | + /* And we are done processing options. */ |
| 7200 | + break; |
| 7201 | + } else { |
| 7202 | + /* All other options have a length field, so that we easily |
| 7203 | + can skip past them. */ |
| 7204 | + if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { |
| 7205 | + /* If the length field is zero, the options are malformed |
| 7206 | + and we don't process them further. */ |
| 7207 | + break; |
| 7208 | + } |
| 7209 | + c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; |
| 7210 | + } |
| 7211 | + } |
| 7212 | + } |
| 7213 | + |
| 7214 | + /* Our response will be a SYNACK. */ |
| 7215 | +#if UIP_ACTIVE_OPEN |
| 7216 | + tcp_send_synack: |
| 7217 | + BUF->flags = TCP_ACK; |
| 7218 | + |
| 7219 | + tcp_send_syn: |
| 7220 | + BUF->flags |= TCP_SYN; |
| 7221 | +#else /* UIP_ACTIVE_OPEN */ |
| 7222 | + tcp_send_synack: |
| 7223 | + BUF->flags = TCP_SYN | TCP_ACK; |
| 7224 | +#endif /* UIP_ACTIVE_OPEN */ |
| 7225 | + |
| 7226 | + /* We send out the TCP Maximum Segment Size option with our |
| 7227 | + SYNACK. */ |
| 7228 | + BUF->optdata[0] = 2; |
| 7229 | + BUF->optdata[1] = 4; |
| 7230 | + BUF->optdata[2] = (UIP_TCP_MSS) / 256; |
| 7231 | + BUF->optdata[3] = (UIP_TCP_MSS) & 255; |
| 7232 | + uip_len = 44; |
| 7233 | + BUF->tcpoffset = 6 << 4; |
| 7234 | + goto tcp_send; |
| 7544 | 7235 | + |
| 7545 | | +/** |
| 7546 | | + * Pointer to the application data in the packet buffer. |
| 7547 | | + * |
| 7548 | | + * This pointer points to the application data when the application is |
| 7549 | | + * called. If the application wishes to send data, the application may |
| 7550 | | + * use this space to write the data into before calling uip_send(). |
| 7551 | | + */ |
| 7552 | | +extern volatile u8_t *uip_appdata; |
| 7553 | | +extern volatile u8_t *uip_sappdata; |
| 7236 | + /* This label will be jumped to if we found an active connection. */ |
| 7237 | + found: |
| 7238 | + uip_conn = uip_connr; |
| 7239 | + uip_flags = 0; |
| 7554 | 7240 | + |
| 7555 | | +#if UIP_URGDATA > 0 |
| 7556 | | +/* u8_t *uip_urgdata: |
| 7557 | | + * |
| 7558 | | + * This pointer points to any urgent data that has been received. Only |
| 7559 | | + * present if compiled with support for urgent data (UIP_URGDATA). |
| 7560 | | + */ |
| 7561 | | +extern volatile u8_t *uip_urgdata; |
| 7562 | | +#endif /* UIP_URGDATA > 0 */ |
| 7241 | + /* We do a very naive form of TCP reset processing; we just accept |
| 7242 | + any RST and kill our connection. We should in fact check if the |
| 7243 | + sequence number of this reset is wihtin our advertised window |
| 7244 | + before we accept the reset. */ |
| 7245 | + if(BUF->flags & TCP_RST) { |
| 7246 | + uip_connr->tcpstateflags = CLOSED; |
| 7247 | + UIP_LOG("tcp: got reset, aborting connection."); |
| 7248 | + uip_flags = UIP_ABORT; |
| 7249 | + UIP_APPCALL(); |
| 7250 | + goto drop; |
| 7251 | + } |
| 7252 | + /* Calculated the length of the data, if the application has sent |
| 7253 | + any data to us. */ |
| 7254 | + c = (BUF->tcpoffset >> 4) << 2; |
| 7255 | + /* uip_len will contain the length of the actual TCP data. This is |
| 7256 | + calculated by subtracing the length of the TCP header (in |
| 7257 | + c) and the length of the IP header (20 bytes). */ |
| 7258 | + uip_len = uip_len - c - 20; |
| 7563 | 7259 | + |
| 7260 | + /* First, check if the sequence number of the incoming packet is |
| 7261 | + what we're expecting next. If not, we send out an ACK with the |
| 7262 | + correct numbers in. */ |
| 7263 | + if(uip_len > 0 && |
| 7264 | + (BUF->seqno[0] != uip_connr->rcv_nxt[0] || |
| 7265 | + BUF->seqno[1] != uip_connr->rcv_nxt[1] || |
| 7266 | + BUF->seqno[2] != uip_connr->rcv_nxt[2] || |
| 7267 | + BUF->seqno[3] != uip_connr->rcv_nxt[3])) { |
| 7268 | + goto tcp_send_ack; |
| 7269 | + } |
| 7564 | 7270 | + |
| 7565 | | +/* u[8|16]_t uip_len: |
| 7566 | | + * |
| 7567 | | + * When the application is called, uip_len contains the length of any |
| 7568 | | + * new data that has been received from the remote host. The |
| 7569 | | + * application should set this variable to the size of any data that |
| 7570 | | + * the application wishes to send. When the network device driver |
| 7571 | | + * output function is called, uip_len should contain the length of the |
| 7572 | | + * outgoing packet. |
| 7573 | | + */ |
| 7574 | | +extern volatile u16_t uip_len, uip_slen; |
| 7271 | + /* Next, check if the incoming segment acknowledges any outstanding |
| 7272 | + data. If so, we update the sequence number, reset the length of |
| 7273 | + the outstanding data, calculate RTT estimations, and reset the |
| 7274 | + retransmission timer. */ |
| 7275 | + if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) { |
| 7276 | + uip_add32(uip_connr->snd_nxt, uip_connr->len); |
| 7277 | + if(BUF->ackno[0] == uip_acc32[0] && |
| 7278 | + BUF->ackno[1] == uip_acc32[1] && |
| 7279 | + BUF->ackno[2] == uip_acc32[2] && |
| 7280 | + BUF->ackno[3] == uip_acc32[3]) { |
| 7281 | + /* Update sequence number. */ |
| 7282 | + uip_connr->snd_nxt[0] = uip_acc32[0]; |
| 7283 | + uip_connr->snd_nxt[1] = uip_acc32[1]; |
| 7284 | + uip_connr->snd_nxt[2] = uip_acc32[2]; |
| 7285 | + uip_connr->snd_nxt[3] = uip_acc32[3]; |
| 7286 | + |
| 7575 | 7287 | + |
| 7576 | | +#if UIP_URGDATA > 0 |
| 7577 | | +extern volatile u8_t uip_urglen, uip_surglen; |
| 7578 | | +#endif /* UIP_URGDATA > 0 */ |
| 7288 | + /* Do RTT estimation, unless we have done retransmissions. */ |
| 7289 | + if(uip_connr->nrtx == 0) { |
| 7290 | + signed char m; |
| 7291 | + m = uip_connr->rto - uip_connr->timer; |
| 7292 | + /* This is taken directly from VJs original code in his paper */ |
| 7293 | + m = m - (uip_connr->sa >> 3); |
| 7294 | + uip_connr->sa += m; |
| 7295 | + if(m < 0) { |
| 7296 | + m = -m; |
| 7297 | + } |
| 7298 | + m = m - (uip_connr->sv >> 2); |
| 7299 | + uip_connr->sv += m; |
| 7300 | + uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv; |
| 7579 | 7301 | + |
| 7302 | + } |
| 7303 | + /* Set the acknowledged flag. */ |
| 7304 | + uip_flags = UIP_ACKDATA; |
| 7305 | + /* Reset the retransmission timer. */ |
| 7306 | + uip_connr->timer = uip_connr->rto; |
| 7307 | + } |
| 7308 | + |
| 7309 | + } |
| 7580 | 7310 | + |
| 7581 | | +/** |
| 7582 | | + * Representation of a uIP TCP connection. |
| 7583 | | + * |
| 7584 | | + * The uip_conn structure is used for identifying a connection. All |
| 7585 | | + * but one field in the structure are to be considered read-only by an |
| 7586 | | + * application. The only exception is the appstate field whos purpose |
| 7587 | | + * is to let the application store application-specific state (e.g., |
| 7588 | | + * file pointers) for the connection. The size of this field is |
| 7589 | | + * configured in the "uipopt.h" header file. |
| 7590 | | + */ |
| 7591 | | +struct uip_conn { |
| 7592 | | + u16_t ripaddr[2]; /**< The IP address of the remote host. */ |
| 7593 | | + |
| 7594 | | + u16_t lport; /**< The local TCP port, in network byte order. */ |
| 7595 | | + u16_t rport; /**< The local remote TCP port, in network byte |
| 7596 | | + order. */ |
| 7597 | | + |
| 7598 | | + u8_t rcv_nxt[4]; /**< The sequence number that we expect to |
| 7599 | | + receive next. */ |
| 7600 | | + u8_t snd_nxt[4]; /**< The sequence number that was last sent by |
| 7601 | | + us. */ |
| 7602 | | + u16_t len; /**< Length of the data that was previously sent. */ |
| 7603 | | + u16_t mss; /**< Current maximum segment size for the |
| 7604 | | + connection. */ |
| 7605 | | + u16_t initialmss; /**< Initial maximum segment size for the |
| 7606 | | + connection. */ |
| 7607 | | + u8_t sa; /**< Retransmission time-out calculation state |
| 7608 | | + variable. */ |
| 7609 | | + u8_t sv; /**< Retransmission time-out calculation state |
| 7610 | | + variable. */ |
| 7611 | | + u8_t rto; /**< Retransmission time-out. */ |
| 7612 | | + u8_t tcpstateflags; /**< TCP state and flags. */ |
| 7613 | | + u8_t timer; /**< The retransmission timer. */ |
| 7614 | | + u8_t nrtx; /**< The number of retransmissions for the last |
| 7615 | | + segment sent. */ |
| 7311 | + /* Do different things depending on in what state the connection is. */ |
| 7312 | + switch(uip_connr->tcpstateflags & TS_MASK) { |
| 7313 | + /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not |
| 7314 | + implemented, since we force the application to close when the |
| 7315 | + peer sends a FIN (hence the application goes directly from |
| 7316 | + ESTABLISHED to LAST_ACK). */ |
| 7317 | + case SYN_RCVD: |
| 7318 | + /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and |
| 7319 | + we are waiting for an ACK that acknowledges the data we sent |
| 7320 | + out the last time. Therefore, we want to have the UIP_ACKDATA |
| 7321 | + flag set. If so, we enter the ESTABLISHED state. */ |
| 7322 | + if(uip_flags & UIP_ACKDATA) { |
| 7323 | + uip_connr->tcpstateflags = ESTABLISHED; |
| 7324 | + uip_flags = UIP_CONNECTED; |
| 7325 | + uip_connr->len = 0; |
| 7326 | + if(uip_len > 0) { |
| 7327 | + uip_flags |= UIP_NEWDATA; |
| 7328 | + uip_add_rcv_nxt(uip_len); |
| 7329 | + } |
| 7330 | + uip_slen = 0; |
| 7331 | + UIP_APPCALL(); |
| 7332 | + goto appsend; |
| 7333 | + } |
| 7334 | + goto drop; |
| 7335 | +#if UIP_ACTIVE_OPEN |
| 7336 | + case SYN_SENT: |
| 7337 | + /* In SYN_SENT, we wait for a SYNACK that is sent in response to |
| 7338 | + our SYN. The rcv_nxt is set to sequence number in the SYNACK |
| 7339 | + plus one, and we send an ACK. We move into the ESTABLISHED |
| 7340 | + state. */ |
| 7341 | + if((uip_flags & UIP_ACKDATA) && |
| 7342 | + BUF->flags == (TCP_SYN | TCP_ACK)) { |
| 7616 | 7343 | + |
| 7617 | | + /** The application state. */ |
| 7618 | | + u8_t appstate[UIP_APPSTATE_SIZE]; |
| 7619 | | +}; |
| 7344 | + /* Parse the TCP MSS option, if present. */ |
| 7345 | + if((BUF->tcpoffset & 0xf0) > 0x50) { |
| 7346 | + for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { |
| 7347 | + opt = uip_buf[40 + UIP_LLH_LEN + c]; |
| 7348 | + if(opt == 0x00) { |
| 7349 | + /* End of options. */ |
| 7350 | + break; |
| 7351 | + } else if(opt == 0x01) { |
| 7352 | + ++c; |
| 7353 | + /* NOP option. */ |
| 7354 | + } else if(opt == 0x02 && |
| 7355 | + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) { |
| 7356 | + /* An MSS option with the right option length. */ |
| 7357 | + tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | |
| 7358 | + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c]; |
| 7359 | + uip_connr->initialmss = |
| 7360 | + uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; |
| 7620 | 7361 | + |
| 7362 | + /* And we are done processing options. */ |
| 7363 | + break; |
| 7364 | + } else { |
| 7365 | + /* All other options have a length field, so that we easily |
| 7366 | + can skip past them. */ |
| 7367 | + if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { |
| 7368 | + /* If the length field is zero, the options are malformed |
| 7369 | + and we don't process them further. */ |
| 7370 | + break; |
| 7371 | + } |
| 7372 | + c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; |
| 7373 | + } |
| 7374 | + } |
| 7375 | + } |
| 7376 | + uip_connr->tcpstateflags = ESTABLISHED; |
| 7377 | + uip_connr->rcv_nxt[0] = BUF->seqno[0]; |
| 7378 | + uip_connr->rcv_nxt[1] = BUF->seqno[1]; |
| 7379 | + uip_connr->rcv_nxt[2] = BUF->seqno[2]; |
| 7380 | + uip_connr->rcv_nxt[3] = BUF->seqno[3]; |
| 7381 | + uip_add_rcv_nxt(1); |
| 7382 | + uip_flags = UIP_CONNECTED | UIP_NEWDATA; |
| 7383 | + uip_connr->len = 0; |
| 7384 | + uip_len = 0; |
| 7385 | + uip_slen = 0; |
| 7386 | + UIP_APPCALL(); |
| 7387 | + goto appsend; |
| 7388 | + } |
| 7389 | + goto reset; |
| 7390 | +#endif /* UIP_ACTIVE_OPEN */ |
| 7391 | + |
| 7392 | + case ESTABLISHED: |
| 7393 | + /* In the ESTABLISHED state, we call upon the application to feed |
| 7394 | + data into the uip_buf. If the UIP_ACKDATA flag is set, the |
| 7395 | + application should put new data into the buffer, otherwise we are |
| 7396 | + retransmitting an old segment, and the application should put that |
| 7397 | + data into the buffer. |
| 7621 | 7398 | + |
| 7622 | | +/* Pointer to the current connection. */ |
| 7623 | | +extern struct uip_conn *uip_conn; |
| 7624 | | +/* The array containing all uIP connections. */ |
| 7625 | | +extern struct uip_conn uip_conns[UIP_CONNS]; |
| 7626 | | +/** |
| 7627 | | + * \addtogroup uiparch |
| 7628 | | + * @{ |
| 7629 | | + */ |
| 7399 | + If the incoming packet is a FIN, we should close the connection on |
| 7400 | + this side as well, and we send out a FIN and enter the LAST_ACK |
| 7401 | + state. We require that there is no outstanding data; otherwise the |
| 7402 | + sequence numbers will be screwed up. */ |
| 7630 | 7403 | + |
| 7631 | | +/** |
| 7632 | | + * 4-byte array used for the 32-bit sequence number calculations. |
| 7633 | | + */ |
| 7634 | | +extern volatile u8_t uip_acc32[4]; |
| 7404 | + if(BUF->flags & TCP_FIN) { |
| 7405 | + if(uip_outstanding(uip_connr)) { |
| 7406 | + goto drop; |
| 7407 | + } |
| 7408 | + uip_add_rcv_nxt(1 + uip_len); |
| 7409 | + uip_flags = UIP_CLOSE; |
| 7410 | + if(uip_len > 0) { |
| 7411 | + uip_flags |= UIP_NEWDATA; |
| 7412 | + } |
| 7413 | + UIP_APPCALL(); |
| 7414 | + uip_connr->len = 1; |
| 7415 | + uip_connr->tcpstateflags = LAST_ACK; |
| 7416 | + uip_connr->nrtx = 0; |
| 7417 | + tcp_send_finack: |
| 7418 | + BUF->flags = TCP_FIN | TCP_ACK; |
| 7419 | + goto tcp_send_nodata; |
| 7420 | + } |
| 7635 | 7421 | + |
| 7636 | | +/** @} */ |
| 7422 | + /* Check the URG flag. If this is set, the segment carries urgent |
| 7423 | + data that we must pass to the application. */ |
| 7424 | + if(BUF->flags & TCP_URG) { |
| 7425 | +#if UIP_URGDATA > 0 |
| 7426 | + uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1]; |
| 7427 | + if(uip_urglen > uip_len) { |
| 7428 | + /* There is more urgent data in the next segment to come. */ |
| 7429 | + uip_urglen = uip_len; |
| 7430 | + } |
| 7431 | + uip_add_rcv_nxt(uip_urglen); |
| 7432 | + uip_len -= uip_urglen; |
| 7433 | + uip_urgdata = uip_appdata; |
| 7434 | + uip_appdata += uip_urglen; |
| 7435 | + } else { |
| 7436 | + uip_urglen = 0; |
| 7437 | +#endif /* UIP_URGDATA > 0 */ |
| 7438 | + uip_appdata += (BUF->urgp[0] << 8) | BUF->urgp[1]; |
| 7439 | + uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1]; |
| 7440 | + } |
| 7441 | + |
| 7442 | + |
| 7443 | + /* If uip_len > 0 we have TCP data in the packet, and we flag this |
| 7444 | + by setting the UIP_NEWDATA flag and update the sequence number |
| 7445 | + we acknowledge. If the application has stopped the dataflow |
| 7446 | + using uip_stop(), we must not accept any data packets from the |
| 7447 | + remote host. */ |
| 7448 | + if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) { |
| 7449 | + uip_flags |= UIP_NEWDATA; |
| 7450 | + uip_add_rcv_nxt(uip_len); |
| 7451 | + } |
| 7637 | 7452 | + |
| 7453 | + /* Check if the available buffer space advertised by the other end |
| 7454 | + is smaller than the initial MSS for this connection. If so, we |
| 7455 | + set the current MSS to the window size to ensure that the |
| 7456 | + application does not send more data than the other end can |
| 7457 | + handle. |
| 7638 | 7458 | + |
| 7639 | | +#if UIP_UDP |
| 7640 | | +/** |
| 7641 | | + * Representation of a uIP UDP connection. |
| 7642 | | + */ |
| 7643 | | +struct uip_udp_conn { |
| 7644 | | + u16_t ripaddr[2]; /**< The IP address of the remote peer. */ |
| 7645 | | + u16_t lport; /**< The local port number in network byte order. */ |
| 7646 | | + u16_t rport; /**< The remote port number in network byte order. */ |
| 7647 | | +}; |
| 7459 | + If the remote host advertises a zero window, we set the MSS to |
| 7460 | + the initial MSS so that the application will send an entire MSS |
| 7461 | + of data. This data will not be acknowledged by the receiver, |
| 7462 | + and the application will retransmit it. This is called the |
| 7463 | + "persistent timer" and uses the retransmission mechanim. |
| 7464 | + */ |
| 7465 | + tmp16 = ((unsigned short int)BUF->wnd[0] << 8) + (unsigned short int)BUF->wnd[1]; |
| 7466 | + if(tmp16 > uip_connr->initialmss || |
| 7467 | + tmp16 == 0) { |
| 7468 | + tmp16 = uip_connr->initialmss; |
| 7469 | + } |
| 7470 | + uip_connr->mss = tmp16; |
| 7648 | 7471 | + |
| 7649 | | +extern struct uip_udp_conn *uip_udp_conn; |
| 7650 | | +extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; |
| 7651 | | +#endif /* UIP_UDP */ |
| 7472 | + /* If this packet constitutes an ACK for outstanding data (flagged |
| 7473 | + by the UIP_ACKDATA flag, we should call the application since it |
| 7474 | + might want to send more data. If the incoming packet had data |
| 7475 | + from the peer (as flagged by the UIP_NEWDATA flag), the |
| 7476 | + application must also be notified. |
| 7652 | 7477 | + |
| 7653 | | +/** |
| 7654 | | + * The structure holding the TCP/IP statistics that are gathered if |
| 7655 | | + * UIP_STATISTICS is set to 1. |
| 7656 | | + * |
| 7657 | | + */ |
| 7658 | | +struct uip_stats { |
| 7659 | | + struct { |
| 7660 | | + uip_stats_t drop; /**< Number of dropped packets at the IP |
| 7661 | | + layer. */ |
| 7662 | | + uip_stats_t recv; /**< Number of received packets at the IP |
| 7663 | | + layer. */ |
| 7664 | | + uip_stats_t sent; /**< Number of sent packets at the IP |
| 7665 | | + layer. */ |
| 7666 | | + uip_stats_t vhlerr; /**< Number of packets dropped due to wrong |
| 7667 | | + IP version or header length. */ |
| 7668 | | + uip_stats_t hblenerr; /**< Number of packets dropped due to wrong |
| 7669 | | + IP length, high byte. */ |
| 7670 | | + uip_stats_t lblenerr; /**< Number of packets dropped due to wrong |
| 7671 | | + IP length, low byte. */ |
| 7672 | | + uip_stats_t fragerr; /**< Number of packets dropped since they |
| 7673 | | + were IP fragments. */ |
| 7674 | | + uip_stats_t chkerr; /**< Number of packets dropped due to IP |
| 7675 | | + checksum errors. */ |
| 7676 | | + uip_stats_t protoerr; /**< Number of packets dropped since they |
| 7677 | | + were neither ICMP, UDP nor TCP. */ |
| 7678 | | + } ip; /**< IP statistics. */ |
| 7679 | | + struct { |
| 7680 | | + uip_stats_t drop; /**< Number of dropped ICMP packets. */ |
| 7681 | | + uip_stats_t recv; /**< Number of received ICMP packets. */ |
| 7682 | | + uip_stats_t sent; /**< Number of sent ICMP packets. */ |
| 7683 | | + uip_stats_t typeerr; /**< Number of ICMP packets with a wrong |
| 7684 | | + type. */ |
| 7685 | | + } icmp; /**< ICMP statistics. */ |
| 7686 | | + struct { |
| 7687 | | + uip_stats_t drop; /**< Number of dropped TCP segments. */ |
| 7688 | | + uip_stats_t recv; /**< Number of recived TCP segments. */ |
| 7689 | | + uip_stats_t sent; /**< Number of sent TCP segments. */ |
| 7690 | | + uip_stats_t chkerr; /**< Number of TCP segments with a bad |
| 7691 | | + checksum. */ |
| 7692 | | + uip_stats_t ackerr; /**< Number of TCP segments with a bad ACK |
| 7693 | | + number. */ |
| 7694 | | + uip_stats_t rst; /**< Number of recevied TCP RST (reset) segments. */ |
| 7695 | | + uip_stats_t rexmit; /**< Number of retransmitted TCP segments. */ |
| 7696 | | + uip_stats_t syndrop; /**< Number of dropped SYNs due to too few |
| 7697 | | + connections was avaliable. */ |
| 7698 | | + uip_stats_t synrst; /**< Number of SYNs for closed ports, |
| 7699 | | + triggering a RST. */ |
| 7700 | | + } tcp; /**< TCP statistics. */ |
| 7701 | | +}; |
| 7478 | + When the application is called, the global variable uip_len |
| 7479 | + contains the length of the incoming data. The application can |
| 7480 | + access the incoming data through the global pointer |
| 7481 | + uip_appdata, which usually points 40 bytes into the uip_buf |
| 7482 | + array. |
| 7702 | 7483 | + |
| 7703 | | +/** |
| 7704 | | + * The uIP TCP/IP statistics. |
| 7705 | | + * |
| 7706 | | + * This is the variable in which the uIP TCP/IP statistics are gathered. |
| 7707 | | + */ |
| 7708 | | +extern struct uip_stats uip_stat; |
| 7484 | + If the application wishes to send any data, this data should be |
| 7485 | + put into the uip_appdata and the length of the data should be |
| 7486 | + put into uip_len. If the application don't have any data to |
| 7487 | + send, uip_len must be set to 0. */ |
| 7488 | + if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) { |
| 7489 | + uip_slen = 0; |
| 7490 | + UIP_APPCALL(); |
| 7709 | 7491 | + |
| 7492 | + appsend: |
| 7493 | + |
| 7494 | + if(uip_flags & UIP_ABORT) { |
| 7495 | + uip_slen = 0; |
| 7496 | + uip_connr->tcpstateflags = CLOSED; |
| 7497 | + BUF->flags = TCP_RST | TCP_ACK; |
| 7498 | + goto tcp_send_nodata; |
| 7499 | + } |
| 7710 | 7500 | + |
| 7711 | | +/*-----------------------------------------------------------------------------------*/ |
| 7712 | | +/* All the stuff below this point is internal to uIP and should not be |
| 7713 | | + * used directly by an application or by a device driver. |
| 7714 | | + */ |
| 7715 | | +/*-----------------------------------------------------------------------------------*/ |
| 7716 | | +/* u8_t uip_flags: |
| 7717 | | + * |
| 7718 | | + * When the application is called, uip_flags will contain the flags |
| 7719 | | + * that are defined in this file. Please read below for more |
| 7720 | | + * infomation. |
| 7721 | | + */ |
| 7722 | | +extern volatile u8_t uip_flags; |
| 7501 | + if(uip_flags & UIP_CLOSE) { |
| 7502 | + uip_slen = 0; |
| 7503 | + uip_connr->len = 1; |
| 7504 | + uip_connr->tcpstateflags = FIN_WAIT_1; |
| 7505 | + uip_connr->nrtx = 0; |
| 7506 | + BUF->flags = TCP_FIN | TCP_ACK; |
| 7507 | + goto tcp_send_nodata; |
| 7508 | + } |
| 7723 | 7509 | + |
| 7724 | | +/* The following flags may be set in the global variable uip_flags |
| 7725 | | + before calling the application callback. The UIP_ACKDATA and |
| 7726 | | + UIP_NEWDATA flags may both be set at the same time, whereas the |
| 7727 | | + others are mutualy exclusive. Note that these flags should *NOT* be |
| 7728 | | + accessed directly, but through the uIP functions/macros. */ |
| 7510 | + /* If uip_slen > 0, the application has data to be sent. */ |
| 7511 | + if(uip_slen > 0) { |
| 7729 | 7512 | + |
| 7730 | | +#define UIP_ACKDATA 1 /* Signifies that the outstanding data was |
| 7731 | | + acked and the application should send |
| 7732 | | + out new data instead of retransmitting |
| 7733 | | + the last data. */ |
| 7734 | | +#define UIP_NEWDATA 2 /* Flags the fact that the peer has sent |
| 7735 | | + us new data. */ |
| 7736 | | +#define UIP_REXMIT 4 /* Tells the application to retransmit the |
| 7737 | | + data that was last sent. */ |
| 7738 | | +#define UIP_POLL 8 /* Used for polling the application, to |
| 7739 | | + check if the application has data that |
| 7740 | | + it wants to send. */ |
| 7741 | | +#define UIP_CLOSE 16 /* The remote host has closed the |
| 7742 | | + connection, thus the connection has |
| 7743 | | + gone away. Or the application signals |
| 7744 | | + that it wants to close the |
| 7745 | | + connection. */ |
| 7746 | | +#define UIP_ABORT 32 /* The remote host has aborted the |
| 7747 | | + connection, thus the connection has |
| 7748 | | + gone away. Or the application signals |
| 7749 | | + that it wants to abort the |
| 7750 | | + connection. */ |
| 7751 | | +#define UIP_CONNECTED 64 /* We have got a connection from a remote |
| 7752 | | + host and have set up a new connection |
| 7753 | | + for it, or an active connection has |
| 7754 | | + been successfully established. */ |
| 7513 | + /* If the connection has acknowledged data, the contents of |
| 7514 | + the ->len variable should be discarded. */ |
| 7515 | + if((uip_flags & UIP_ACKDATA) != 0) { |
| 7516 | + uip_connr->len = 0; |
| 7517 | + } |
| 7755 | 7518 | + |
| 7756 | | +#define UIP_TIMEDOUT 128 /* The connection has been aborted due to |
| 7757 | | + too many retransmissions. */ |
| 7519 | + /* If the ->len variable is non-zero the connection has |
| 7520 | + already data in transit and cannot send anymore right |
| 7521 | + now. */ |
| 7522 | + if(uip_connr->len == 0) { |
| 7758 | 7523 | + |
| 7524 | + /* The application cannot send more than what is allowed by |
| 7525 | + the mss (the minumum of the MSS and the available |
| 7526 | + window). */ |
| 7527 | + if(uip_slen > uip_connr->mss) { |
| 7528 | + uip_slen = uip_connr->mss; |
| 7529 | + } |
| 7759 | 7530 | + |
| 7760 | | +/* uip_process(flag): |
| 7761 | | + * |
| 7762 | | + * The actual uIP function which does all the work. |
| 7763 | | + */ |
| 7764 | | +void uip_process(u8_t flag); |
| 7531 | + /* Remember how much data we send out now so that we know |
| 7532 | + when everything has been acknowledged. */ |
| 7533 | + uip_connr->len = uip_slen; |
| 7534 | + } else { |
| 7765 | 7535 | + |
| 7766 | | +/* The following flags are passed as an argument to the uip_process() |
| 7767 | | + function. They are used to distinguish between the two cases where |
| 7768 | | + uip_process() is called. It can be called either because we have |
| 7769 | | + incoming data that should be processed, or because the periodic |
| 7770 | | + timer has fired. */ |
| 7536 | + /* If the application already had unacknowledged data, we |
| 7537 | + make sure that the application does not send (i.e., |
| 7538 | + retransmit) out more than it previously sent out. */ |
| 7539 | + uip_slen = uip_connr->len; |
| 7540 | + } |
| 7541 | + } else { |
| 7542 | + uip_connr->len = 0; |
| 7543 | + } |
| 7544 | + uip_connr->nrtx = 0; |
| 7545 | + apprexmit: |
| 7546 | + uip_appdata = uip_sappdata; |
| 7771 | 7547 | + |
| 7772 | | +#define UIP_DATA 1 /* Tells uIP that there is incoming data in |
| 7773 | | + the uip_buf buffer. The length of the |
| 7774 | | + data is stored in the global variable |
| 7775 | | + uip_len. */ |
| 7776 | | +#define UIP_TIMER 2 /* Tells uIP that the periodic timer has |
| 7777 | | + fired. */ |
| 7778 | | +#if UIP_UDP |
| 7779 | | +#define UIP_UDP_TIMER 3 |
| 7780 | | +#endif /* UIP_UDP */ |
| 7548 | + /* If the application has data to be sent, or if the incoming |
| 7549 | + packet had new data in it, we must send out a packet. */ |
| 7550 | + if(uip_slen > 0 && uip_connr->len > 0) { |
| 7551 | + /* Add the length of the IP and TCP headers. */ |
| 7552 | + uip_len = uip_connr->len + UIP_TCPIP_HLEN; |
| 7553 | + /* We always set the ACK flag in response packets. */ |
| 7554 | + BUF->flags = TCP_ACK | TCP_PSH; |
| 7555 | + /* Send the packet. */ |
| 7556 | + goto tcp_send_noopts; |
| 7557 | + } |
| 7558 | + /* If there is no data to send, just send out a pure ACK if |
| 7559 | + there is newdata. */ |
| 7560 | + if(uip_flags & UIP_NEWDATA) { |
| 7561 | + uip_len = UIP_TCPIP_HLEN; |
| 7562 | + BUF->flags = TCP_ACK; |
| 7563 | + goto tcp_send_noopts; |
| 7564 | + } |
| 7565 | + } |
| 7566 | + goto drop; |
| 7567 | + case LAST_ACK: |
| 7568 | + /* We can close this connection if the peer has acknowledged our |
| 7569 | + FIN. This is indicated by the UIP_ACKDATA flag. */ |
| 7570 | + if(uip_flags & UIP_ACKDATA) { |
| 7571 | + uip_connr->tcpstateflags = CLOSED; |
| 7572 | + uip_flags = UIP_CLOSE; |
| 7573 | + UIP_APPCALL(); |
| 7574 | + } |
| 7575 | + break; |
| 7576 | + |
| 7577 | + case FIN_WAIT_1: |
| 7578 | + /* The application has closed the connection, but the remote host |
| 7579 | + hasn't closed its end yet. Thus we do nothing but wait for a |
| 7580 | + FIN from the other side. */ |
| 7581 | + if(uip_len > 0) { |
| 7582 | + uip_add_rcv_nxt(uip_len); |
| 7583 | + } |
| 7584 | + if(BUF->flags & TCP_FIN) { |
| 7585 | + if(uip_flags & UIP_ACKDATA) { |
| 7586 | + uip_connr->tcpstateflags = TIME_WAIT; |
| 7587 | + uip_connr->timer = 0; |
| 7588 | + uip_connr->len = 0; |
| 7589 | + } else { |
| 7590 | + uip_connr->tcpstateflags = CLOSING; |
| 7591 | + } |
| 7592 | + uip_add_rcv_nxt(1); |
| 7593 | + uip_flags = UIP_CLOSE; |
| 7594 | + UIP_APPCALL(); |
| 7595 | + goto tcp_send_ack; |
| 7596 | + } else if(uip_flags & UIP_ACKDATA) { |
| 7597 | + uip_connr->tcpstateflags = FIN_WAIT_2; |
| 7598 | + uip_connr->len = 0; |
| 7599 | + goto drop; |
| 7600 | + } |
| 7601 | + if(uip_len > 0) { |
| 7602 | + goto tcp_send_ack; |
| 7603 | + } |
| 7604 | + goto drop; |
| 7605 | + |
| 7606 | + case FIN_WAIT_2: |
| 7607 | + if(uip_len > 0) { |
| 7608 | + uip_add_rcv_nxt(uip_len); |
| 7609 | + } |
| 7610 | + if(BUF->flags & TCP_FIN) { |
| 7611 | + uip_connr->tcpstateflags = TIME_WAIT; |
| 7612 | + uip_connr->timer = 0; |
| 7613 | + uip_add_rcv_nxt(1); |
| 7614 | + uip_flags = UIP_CLOSE; |
| 7615 | + UIP_APPCALL(); |
| 7616 | + goto tcp_send_ack; |
| 7617 | + } |
| 7618 | + if(uip_len > 0) { |
| 7619 | + goto tcp_send_ack; |
| 7620 | + } |
| 7621 | + goto drop; |
| 7781 | 7622 | + |
| 7782 | | +/* The TCP states used in the uip_conn->tcpstateflags. */ |
| 7783 | | +#define CLOSED 0 |
| 7784 | | +#define SYN_RCVD 1 |
| 7785 | | +#define SYN_SENT 2 |
| 7786 | | +#define ESTABLISHED 3 |
| 7787 | | +#define FIN_WAIT_1 4 |
| 7788 | | +#define FIN_WAIT_2 5 |
| 7789 | | +#define CLOSING 6 |
| 7790 | | +#define TIME_WAIT 7 |
| 7791 | | +#define LAST_ACK 8 |
| 7792 | | +#define TS_MASK 15 |
| 7623 | + case TIME_WAIT: |
| 7624 | + goto tcp_send_ack; |
| 7625 | + |
| 7626 | + case CLOSING: |
| 7627 | + if(uip_flags & UIP_ACKDATA) { |
| 7628 | + uip_connr->tcpstateflags = TIME_WAIT; |
| 7629 | + uip_connr->timer = 0; |
| 7630 | + } |
| 7631 | + } |
| 7632 | + goto drop; |
| 7793 | 7633 | + |
| 7794 | | +#define UIP_STOPPED 16 |
| 7795 | | + |
| 7796 | | +#define UIP_TCPIP_HLEN 40 |
| 7797 | 7634 | + |
| 7798 | | +/* The TCP and IP headers. */ |
| 7799 | | +typedef struct { |
| 7800 | | + /* IP header. */ |
| 7801 | | + u8_t vhl, |
| 7802 | | + tos, |
| 7803 | | + len[2], |
| 7804 | | + ipid[2], |
| 7805 | | + ipoffset[2], |
| 7806 | | + ttl, |
| 7807 | | + proto; |
| 7808 | | + u16_t ipchksum; |
| 7809 | | + u16_t srcipaddr[2], |
| 7810 | | + destipaddr[2]; |
| 7635 | + /* We jump here when we are ready to send the packet, and just want |
| 7636 | + to set the appropriate TCP sequence numbers in the TCP header. */ |
| 7637 | + tcp_send_ack: |
| 7638 | + BUF->flags = TCP_ACK; |
| 7639 | + tcp_send_nodata: |
| 7640 | + uip_len = 40; |
| 7641 | + tcp_send_noopts: |
| 7642 | + BUF->tcpoffset = 5 << 4; |
| 7643 | + tcp_send: |
| 7644 | + /* We're done with the input processing. We are now ready to send a |
| 7645 | + reply. Our job is to fill in all the fields of the TCP and IP |
| 7646 | + headers before calculating the checksum and finally send the |
| 7647 | + packet. */ |
| 7648 | + BUF->ackno[0] = uip_connr->rcv_nxt[0]; |
| 7649 | + BUF->ackno[1] = uip_connr->rcv_nxt[1]; |
| 7650 | + BUF->ackno[2] = uip_connr->rcv_nxt[2]; |
| 7651 | + BUF->ackno[3] = uip_connr->rcv_nxt[3]; |
| 7811 | 7652 | + |
| 7812 | | + /* TCP header. */ |
| 7813 | | + u16_t srcport, |
| 7814 | | + destport; |
| 7815 | | + u8_t seqno[4], |
| 7816 | | + ackno[4], |
| 7817 | | + tcpoffset, |
| 7818 | | + flags, |
| 7819 | | + wnd[2]; |
| 7820 | | + u16_t tcpchksum; |
| 7821 | | + u8_t urgp[2]; |
| 7822 | | + u8_t optdata[4]; |
| 7823 | | +} uip_tcpip_hdr; |
| 7653 | + BUF->seqno[0] = uip_connr->snd_nxt[0]; |
| 7654 | + BUF->seqno[1] = uip_connr->snd_nxt[1]; |
| 7655 | + BUF->seqno[2] = uip_connr->snd_nxt[2]; |
| 7656 | + BUF->seqno[3] = uip_connr->snd_nxt[3]; |
| 7824 | 7657 | + |
| 7825 | | +/* The ICMP and IP headers. */ |
| 7826 | | +typedef struct { |
| 7827 | | + /* IP header. */ |
| 7828 | | + u8_t vhl, |
| 7829 | | + tos, |
| 7830 | | + len[2], |
| 7831 | | + ipid[2], |
| 7832 | | + ipoffset[2], |
| 7833 | | + ttl, |
| 7834 | | + proto; |
| 7835 | | + u16_t ipchksum; |
| 7836 | | + u16_t srcipaddr[2], |
| 7837 | | + destipaddr[2]; |
| 7838 | | + /* ICMP (echo) header. */ |
| 7839 | | + u8_t type, icode; |
| 7840 | | + u16_t icmpchksum; |
| 7841 | | + u16_t id, seqno; |
| 7842 | | +} uip_icmpip_hdr; |
| 7658 | + BUF->proto = UIP_PROTO_TCP; |
| 7659 | + |
| 7660 | + BUF->srcport = uip_connr->lport; |
| 7661 | + BUF->destport = uip_connr->rport; |
| 7843 | 7662 | + |
| 7663 | + BUF->srcipaddr[0] = uip_hostaddr[0]; |
| 7664 | + BUF->srcipaddr[1] = uip_hostaddr[1]; |
| 7665 | + BUF->destipaddr[0] = uip_connr->ripaddr[0]; |
| 7666 | + BUF->destipaddr[1] = uip_connr->ripaddr[1]; |
| 7667 | + |
| 7844 | 7668 | + |
| 7845 | | +/* The UDP and IP headers. */ |
| 7846 | | +typedef struct { |
| 7847 | | + /* IP header. */ |
| 7848 | | + u8_t vhl, |
| 7849 | | + tos, |
| 7850 | | + len[2], |
| 7851 | | + ipid[2], |
| 7852 | | + ipoffset[2], |
| 7853 | | + ttl, |
| 7854 | | + proto; |
| 7855 | | + u16_t ipchksum; |
| 7856 | | + u16_t srcipaddr[2], |
| 7857 | | + destipaddr[2]; |
| 7858 | | + |
| 7859 | | + /* UDP header. */ |
| 7860 | | + u16_t srcport, |
| 7861 | | + destport; |
| 7862 | | + u16_t udplen; |
| 7863 | | + u16_t udpchksum; |
| 7864 | | +} uip_udpip_hdr; |
| 7669 | + if(uip_connr->tcpstateflags & UIP_STOPPED) { |
| 7670 | + /* If the connection has issued uip_stop(), we advertise a zero |
| 7671 | + window so that the remote host will stop sending data. */ |
| 7672 | + BUF->wnd[0] = BUF->wnd[1] = 0; |
| 7673 | + } else { |
| 7674 | + BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8); |
| 7675 | + BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff); |
| 7676 | + } |
| 7865 | 7677 | + |
| 7866 | | +#define UIP_PROTO_ICMP 1 |
| 7867 | | +#define UIP_PROTO_TCP 6 |
| 7868 | | +#define UIP_PROTO_UDP 17 |
| 7678 | + tcp_send_noconn: |
| 7869 | 7679 | + |
| 7870 | | +#if UIP_FIXEDADDR |
| 7871 | | +extern const u16_t uip_hostaddr[2]; |
| 7872 | | +#else /* UIP_FIXEDADDR */ |
| 7873 | | +extern u16_t uip_hostaddr[2]; |
| 7874 | | +#endif /* UIP_FIXEDADDR */ |
| 7680 | + BUF->len[0] = (uip_len >> 8); |
| 7681 | + BUF->len[1] = (uip_len & 0xff); |
| 7875 | 7682 | + |
| 7876 | | +#endif /* __UIP_H__ */ |
| 7683 | + /* Calculate TCP checksum. */ |
| 7684 | + BUF->tcpchksum = 0; |
| 7685 | + BUF->tcpchksum = ~(uip_tcpchksum()); |
| 7686 | + |
| 7687 | + //ip_send_nolen: |
| 7877 | 7688 | + |
| 7689 | + BUF->vhl = 0x45; |
| 7690 | + BUF->tos = 0; |
| 7691 | + BUF->ipoffset[0] = BUF->ipoffset[1] = 0; |
| 7692 | + BUF->ttl = UIP_TTL; |
| 7693 | + ++ipid; |
| 7694 | + BUF->ipid[0] = ipid >> 8; |
| 7695 | + BUF->ipid[1] = ipid & 0xff; |
| 7696 | + |
| 7697 | + /* Calculate IP checksum. */ |
| 7698 | + BUF->ipchksum = 0; |
| 7699 | + BUF->ipchksum = ~(uip_ipchksum()); |
| 7878 | 7700 | + |
| 7701 | + UIP_STAT(++uip_stat.tcp.sent); |
| 7702 | + send: |
| 7703 | + UIP_STAT(++uip_stat.ip.sent); |
| 7704 | + /* Return and let the caller do the actual transmission. */ |
| 7705 | + return; |
| 7706 | + drop: |
| 7707 | + uip_len = 0; |
| 7708 | + return; |
| 7709 | +} |
| 7710 | +/*-----------------------------------------------------------------------------------*/ |
| 7711 | +/*unsigned short int |
| 7712 | +htons(unsigned short int val) |
| 7713 | +{ |
| 7714 | + return HTONS(val); |
| 7715 | +}*/ |
| 7716 | +/*-----------------------------------------------------------------------------------*/ |
| 7879 | 7717 | +/** @} */ |
| 7880 | | + |
| 7881 | 7718 | --- /dev/null |
| 7882 | | +++ b/net/uip-0.9/uip_arch.c |
| 7883 | | @@ -0,0 +1,145 @@ |
| 7719 | @@ -0,0 +1,1066 @@ |
| 7720 | +/** |
| 7721 | + * \addtogroup uip |
| 7722 | + * @{ |
| 7723 | + */ |
| 7724 | + |
| 7725 | +/** |
| 7726 | + * \file |
| 7727 | + * Header file for the uIP TCP/IP stack. |
| 7728 | + * \author Adam Dunkels <adam@dunkels.com> |
| 7729 | + * |
| 7730 | + * The uIP TCP/IP stack header file contains definitions for a number |
| 7731 | + * of C macros that are used by uIP programs as well as internal uIP |
| 7732 | + * structures, TCP/IP header structures and function declarations. |
| 7733 | + * |
| 7734 | + */ |
| 7735 | + |
| 7736 | + |
| 7884 | 7737 | +/* |
| 7885 | | + * Copyright (c) 2001, Adam Dunkels. |
| 7738 | + * Copyright (c) 2001-2003, Adam Dunkels. |
| 7886 | 7739 | + * All rights reserved. |
| 7887 | 7740 | + * |
| 7888 | 7741 | + * Redistribution and use in source and binary forms, with or without |
| ... | ... | |
| 7910 | 7767 | + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 7911 | 7768 | + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 7912 | 7769 | + * |
| 7913 | | + * This file is part of the uIP TCP/IP stack. |
| 7770 | + * This file is part of the uIP TCP/IP stack. |
| 7771 | + * |
| 7772 | + * $Id: uip.h,v 1.36.2.7 2003/10/07 13:47:51 adam Exp $ |
| 7773 | + * |
| 7774 | + */ |
| 7775 | + |
| 7776 | +#ifndef __UIP_H__ |
| 7777 | +#define __UIP_H__ |
| 7778 | +#include <linux/types.h> |
| 7779 | +#include <linux/string.h> |
| 7780 | +#include <linux/ctype.h> |
| 7781 | +#include <malloc.h> |
| 7782 | +#include <common.h> |
| 7783 | + |
| 7784 | + |
| 7785 | +#include "uipopt.h" |
| 7786 | + |
| 7787 | +/*-----------------------------------------------------------------------------------*/ |
| 7788 | +/* First, the functions that should be called from the |
| 7789 | + * system. Initialization, the periodic timer and incoming packets are |
| 7790 | + * handled by the following three functions. |
| 7791 | + */ |
| 7792 | + |
| 7793 | +/** |
| 7794 | + * \defgroup uipconffunc uIP configuration functions |
| 7795 | + * @{ |
| 7796 | + * |
| 7797 | + * The uIP configuration functions are used for setting run-time |
| 7798 | + * parameters in uIP such as IP addresses. |
| 7799 | + */ |
| 7800 | + |
| 7801 | +/** |
| 7802 | + * Set the IP address of this host. |
| 7803 | + * |
| 7804 | + * The IP address is represented as a 4-byte array where the first |
| 7805 | + * octet of the IP address is put in the first member of the 4-byte |
| 7806 | + * array. |
| 7807 | + * |
| 7808 | + * \param addr A pointer to a 4-byte representation of the IP address. |
| 7809 | + * |
| 7810 | + * \hideinitializer |
| 7811 | + */ |
| 7812 | +#define uip_sethostaddr(addr) do { uip_hostaddr[0] = addr[0]; \ |
| 7813 | + uip_hostaddr[1] = addr[1]; } while(0) |
| 7814 | + |
| 7815 | +/** |
| 7816 | + * Get the IP address of this host. |
| 7817 | + * |
| 7818 | + * The IP address is represented as a 4-byte array where the first |
| 7819 | + * octet of the IP address is put in the first member of the 4-byte |
| 7820 | + * array. |
| 7821 | + * |
| 7822 | + * \param addr A pointer to a 4-byte array that will be filled in with |
| 7823 | + * the currently configured IP address. |
| 7914 | 7824 | + * |
| 7915 | | + * $Id: uip_arch.c,v 1.2.2.1 2003/10/04 22:54:17 adam Exp $ |
| 7825 | + * \hideinitializer |
| 7826 | + */ |
| 7827 | +#define uip_gethostaddr(addr) do { addr[0] = uip_hostaddr[0]; \ |
| 7828 | + addr[1] = uip_hostaddr[1]; } while(0) |
| 7829 | + |
| 7830 | +/** @} */ |
| 7831 | + |
| 7832 | +/** |
| 7833 | + * \defgroup uipinit uIP initialization functions |
| 7834 | + * @{ |
| 7916 | 7835 | + * |
| 7836 | + * The uIP initialization functions are used for booting uIP. |
| 7917 | 7837 | + */ |
| 7918 | 7838 | + |
| 7839 | +/** |
| 7840 | + * uIP initialization function. |
| 7841 | + * |
| 7842 | + * This function should be called at boot up to initilize the uIP |
| 7843 | + * TCP/IP stack. |
| 7844 | + */ |
| 7845 | +void uip_init(void); |
| 7919 | 7846 | + |
| 7920 | | +#include "uip.h" |
| 7921 | | +#include "uip_arch.h" |
| 7847 | +/** @} */ |
| 7922 | 7848 | + |
| 7923 | | +#define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) |
| 7924 | | +#define IP_PROTO_TCP 6 |
| 7849 | +/** |
| 7850 | + * \defgroup uipdevfunc uIP device driver functions |
| 7851 | + * @{ |
| 7852 | + * |
| 7853 | + * These functions are used by a network device driver for interacting |
| 7854 | + * with uIP. |
| 7855 | + */ |
| 7925 | 7856 | + |
| 7926 | | +/*-----------------------------------------------------------------------------------*/ |
| 7927 | | +void |
| 7928 | | +uip_add32(u8_t *op32, u16_t op16) |
| 7929 | | +{ |
| 7930 | | + |
| 7931 | | + uip_acc32[3] = op32[3] + (op16 & 0xff); |
| 7932 | | + uip_acc32[2] = op32[2] + (op16 >> 8); |
| 7933 | | + uip_acc32[1] = op32[1]; |
| 7934 | | + uip_acc32[0] = op32[0]; |
| 7935 | | + |
| 7936 | | + if(uip_acc32[2] < (op16 >> 8)) { |
| 7937 | | + ++uip_acc32[1]; |
| 7938 | | + if(uip_acc32[1] == 0) { |
| 7939 | | + ++uip_acc32[0]; |
| 7857 | +/** |
| 7858 | + * Process an incoming packet. |
| 7859 | + * |
| 7860 | + * This function should be called when the device driver has received |
| 7861 | + * a packet from the network. The packet from the device driver must |
| 7862 | + * be present in the uip_buf buffer, and the length of the packet |
| 7863 | + * should be placed in the uip_len variable. |
| 7864 | + * |
| 7865 | + * When the function returns, there may be an outbound packet placed |
| 7866 | + * in the uip_buf packet buffer. If so, the uip_len variable is set to |
| 7867 | + * the length of the packet. If no packet is to be sent out, the |
| 7868 | + * uip_len variable is set to 0. |
| 7869 | + * |
| 7870 | + * The usual way of calling the function is presented by the source |
| 7871 | + * code below. |
| 7872 | + \code |
| 7873 | + uip_len = devicedriver_poll(); |
| 7874 | + if(uip_len > 0) { |
| 7875 | + uip_input(); |
| 7876 | + if(uip_len > 0) { |
| 7877 | + devicedriver_send(); |
| 7940 | 7878 | + } |
| 7941 | 7879 | + } |
| 7942 | | + |
| 7943 | | + |
| 7944 | | + if(uip_acc32[3] < (op16 & 0xff)) { |
| 7945 | | + ++uip_acc32[2]; |
| 7946 | | + if(uip_acc32[2] == 0) { |
| 7947 | | + ++uip_acc32[1]; |
| 7948 | | + if(uip_acc32[1] == 0) { |
| 7949 | | + ++uip_acc32[0]; |
| 7880 | + \endcode |
| 7881 | + * |
| 7882 | + * \note If you are writing a uIP device driver that needs ARP |
| 7883 | + * (Address Resolution Protocol), e.g., when running uIP over |
| 7884 | + * Ethernet, you will need to call the uIP ARP code before calling |
| 7885 | + * this function: |
| 7886 | + \code |
| 7887 | + #define BUF ((struct uip_eth_hdr *)&uip_buf[0]) |
| 7888 | + uip_len = ethernet_devicedrver_poll(); |
| 7889 | + if(uip_len > 0) { |
| 7890 | + if(BUF->type == HTONS(UIP_ETHTYPE_IP)) { |
| 7891 | + uip_arp_ipin(); |
| 7892 | + uip_input(); |
| 7893 | + if(uip_len > 0) { |
| 7894 | + uip_arp_out(); |
| 7895 | + ethernet_devicedriver_send(); |
| 7896 | + } |
| 7897 | + } else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) { |
| 7898 | + uip_arp_arpin(); |
| 7899 | + if(uip_len > 0) { |
| 7900 | + ethernet_devicedriver_send(); |
| 7950 | 7901 | + } |
| 7951 | 7902 | + } |
| 7903 | + \endcode |
| 7904 | + * |
| 7905 | + * \hideinitializer |
| 7906 | + */ |
| 7907 | +#define uip_input() uip_process(UIP_DATA) |
| 7908 | + |
| 7909 | +/** |
| 7910 | + * Periodic processing for a connection identified by its number. |
| 7911 | + * |
| 7912 | + * This function does the necessary periodic processing (timers, |
| 7913 | + * polling) for a uIP TCP conneciton, and should be called when the |
| 7914 | + * periodic uIP timer goes off. It should be called for every |
| 7915 | + * connection, regardless of whether they are open of closed. |
| 7916 | + * |
| 7917 | + * When the function returns, it may have an outbound packet waiting |
| 7918 | + * for service in the uIP packet buffer, and if so the uip_len |
| 7919 | + * variable is set to a value larger than zero. The device driver |
| 7920 | + * should be called to send out the packet. |
| 7921 | + * |
| 7922 | + * The ususal way of calling the function is through a for() loop like |
| 7923 | + * this: |
| 7924 | + \code |
| 7925 | + for(i = 0; i < UIP_CONNS; ++i) { |
| 7926 | + uip_periodic(i); |
| 7927 | + if(uip_len > 0) { |
| 7928 | + devicedriver_send(); |
| 7929 | + } |
| 7952 | 7930 | + } |
| 7953 | | +} |
| 7954 | | +/*-----------------------------------------------------------------------------------*/ |
| 7955 | | +u16_t |
| 7956 | | +uip_chksum(u16_t *sdata, u16_t len) |
| 7957 | | +{ |
| 7958 | | + u16_t acc; |
| 7959 | | + |
| 7960 | | + for(acc = 0; len > 1; len -= 2) { |
| 7961 | | + acc += *sdata; |
| 7962 | | + if(acc < *sdata) { |
| 7963 | | + /* Overflow, so we add the carry to acc (i.e., increase by |
| 7964 | | + one). */ |
| 7965 | | + ++acc; |
| 7931 | + \endcode |
| 7932 | + * |
| 7933 | + * \note If you are writing a uIP device driver that needs ARP |
| 7934 | + * (Address Resolution Protocol), e.g., when running uIP over |
| 7935 | + * Ethernet, you will need to call the uip_arp_out() function before |
| 7936 | + * calling the device driver: |
| 7937 | + \code |
| 7938 | + for(i = 0; i < UIP_CONNS; ++i) { |
| 7939 | + uip_periodic(i); |
| 7940 | + if(uip_len > 0) { |
| 7941 | + uip_arp_out(); |
| 7942 | + ethernet_devicedriver_send(); |
| 7966 | 7943 | + } |
| 7967 | | + ++sdata; |
| 7968 | 7944 | + } |
| 7945 | + \endcode |
| 7946 | + * |
| 7947 | + * \param conn The number of the connection which is to be periodically polled. |
| 7948 | + * |
| 7949 | + * \hideinitializer |
| 7950 | + */ |
| 7951 | +#define uip_periodic(conn) do { uip_conn = &uip_conns[conn]; \ |
| 7952 | + uip_process(UIP_TIMER); } while (0) |
| 7969 | 7953 | + |
| 7970 | | + /* add up any odd byte */ |
| 7971 | | + if(len == 1) { |
| 7972 | | + acc += htons(((u16_t)(*(u8_t *)sdata)) << 8); |
| 7973 | | + if(acc < htons(((u16_t)(*(u8_t *)sdata)) << 8)) { |
| 7974 | | + ++acc; |
| 7954 | +/** |
| 7955 | + * Periodic processing for a connection identified by a pointer to its structure. |
| 7956 | + * |
| 7957 | + * Same as uip_periodic() but takes a pointer to the actual uip_conn |
| 7958 | + * struct instead of an integer as its argument. This function can be |
| 7959 | + * used to force periodic processing of a specific connection. |
| 7960 | + * |
| 7961 | + * \param conn A pointer to the uip_conn struct for the connection to |
| 7962 | + * be processed. |
| 7963 | + * |
| 7964 | + * \hideinitializer |
| 7965 | + */ |
| 7966 | +#define uip_periodic_conn(conn) do { uip_conn = conn; \ |
| 7967 | + uip_process(UIP_TIMER); } while (0) |
| 7968 | + |
| 7969 | +#if UIP_UDP |
| 7970 | +/** |
| 7971 | + * Periodic processing for a UDP connection identified by its number. |
| 7972 | + * |
| 7973 | + * This function is essentially the same as uip_prerioic(), but for |
| 7974 | + * UDP connections. It is called in a similar fashion as the |
| 7975 | + * uip_periodic() function: |
| 7976 | + \code |
| 7977 | + for(i = 0; i < UIP_UDP_CONNS; i++) { |
| 7978 | + uip_udp_periodic(i); |
| 7979 | + if(uip_len > 0) { |
| 7980 | + devicedriver_send(); |
| 7975 | 7981 | + } |
| 7976 | | + } |
| 7982 | + } |
| 7983 | + \endcode |
| 7984 | + * |
| 7985 | + * \note As for the uip_periodic() function, special care has to be |
| 7986 | + * taken when using uIP together with ARP and Ethernet: |
| 7987 | + \code |
| 7988 | + for(i = 0; i < UIP_UDP_CONNS; i++) { |
| 7989 | + uip_udp_periodic(i); |
| 7990 | + if(uip_len > 0) { |
| 7991 | + uip_arp_out(); |
| 7992 | + ethernet_devicedriver_send(); |
| 7993 | + } |
| 7994 | + } |
| 7995 | + \endcode |
| 7996 | + * |
| 7997 | + * \param conn The number of the UDP connection to be processed. |
| 7998 | + * |
| 7999 | + * \hideinitializer |
| 8000 | + */ |
| 8001 | +#define uip_udp_periodic(conn) do { uip_udp_conn = &uip_udp_conns[conn]; \ |
| 8002 | + uip_process(UIP_UDP_TIMER); } while (0) |
| 7977 | 8003 | + |
| 7978 | | + return acc; |
| 7979 | | +} |
| 7980 | | +/*-----------------------------------------------------------------------------------*/ |
| 7981 | | +u16_t |
| 7982 | | +uip_ipchksum(void) |
| 7983 | | +{ |
| 7984 | | + return uip_chksum((u16_t *)&uip_buf[UIP_LLH_LEN], 20); |
| 7985 | | +} |
| 7986 | | +/*-----------------------------------------------------------------------------------*/ |
| 7987 | | +u16_t |
| 7988 | | +uip_tcpchksum(void) |
| 7989 | | +{ |
| 7990 | | + u16_t hsum, sum; |
| 8004 | +/** |
| 8005 | + * Periodic processing for a UDP connection identified by a pointer to |
| 8006 | + * its structure. |
| 8007 | + * |
| 8008 | + * Same as uip_udp_periodic() but takes a pointer to the actual |
| 8009 | + * uip_conn struct instead of an integer as its argument. This |
| 8010 | + * function can be used to force periodic processing of a specific |
| 8011 | + * connection. |
| 8012 | + * |
| 8013 | + * \param conn A pointer to the uip_udp_conn struct for the connection |
| 8014 | + * to be processed. |
| 8015 | + * |
| 8016 | + * \hideinitializer |
| 8017 | + */ |
| 8018 | +#define uip_udp_periodic_conn(conn) do { uip_udp_conn = conn; \ |
| 8019 | + uip_process(UIP_UDP_TIMER); } while (0) |
| 7991 | 8020 | + |
| 7992 | | + |
| 7993 | | + /* Compute the checksum of the TCP header. */ |
| 7994 | | + hsum = uip_chksum((u16_t *)&uip_buf[20 + UIP_LLH_LEN], 20); |
| 7995 | 8021 | + |
| 7996 | | + /* Compute the checksum of the data in the TCP packet and add it to |
| 7997 | | + the TCP header checksum. */ |
| 7998 | | + sum = uip_chksum((u16_t *)uip_appdata, |
| 7999 | | + (u16_t)(((((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - 40))); |
| 8022 | +#endif /* UIP_UDP */ |
| 8023 | + |
| 8024 | +/** |
| 8025 | + * The uIP packet buffer. |
| 8026 | + * |
| 8027 | + * The uip_buf array is used to hold incoming and outgoing |
| 8028 | + * packets. The device driver should place incoming data into this |
| 8029 | + * buffer. When sending data, the device driver should read the link |
| 8030 | + * level headers and the TCP/IP headers from this buffer. The size of |
| 8031 | + * the link level headers is configured by the UIP_LLH_LEN define. |
| 8032 | + * |
| 8033 | + * \note The application data need not be placed in this buffer, so |
| 8034 | + * the device driver must read it from the place pointed to by the |
| 8035 | + * uip_appdata pointer as illustrated by the following example: |
| 8036 | + \code |
| 8037 | + void |
| 8038 | + devicedriver_send(void) |
| 8039 | + { |
| 8040 | + hwsend(&uip_buf[0], UIP_LLH_LEN); |
| 8041 | + hwsend(&uip_buf[UIP_LLH_LEN], 40); |
| 8042 | + hwsend(uip_appdata, uip_len - 40 - UIP_LLH_LEN); |
| 8043 | + } |
| 8044 | + \endcode |
| 8045 | + */ |
| 8046 | +extern u8_t uip_buf[UIP_BUFSIZE+2]; |
| 8000 | 8047 | + |
| 8001 | | + if((sum += hsum) < hsum) { |
| 8002 | | + ++sum; |
| 8003 | | + } |
| 8004 | | + |
| 8005 | | + if((sum += BUF->srcipaddr[0]) < BUF->srcipaddr[0]) { |
| 8006 | | + ++sum; |
| 8007 | | + } |
| 8008 | | + if((sum += BUF->srcipaddr[1]) < BUF->srcipaddr[1]) { |
| 8009 | | + ++sum; |
| 8010 | | + } |
| 8011 | | + if((sum += BUF->destipaddr[0]) < BUF->destipaddr[0]) { |
| 8012 | | + ++sum; |
| 8013 | | + } |
| 8014 | | + if((sum += BUF->destipaddr[1]) < BUF->destipaddr[1]) { |
| 8015 | | + ++sum; |
| 8016 | | + } |
| 8017 | | + if((sum += (u16_t)htons((u16_t)IP_PROTO_TCP)) < (u16_t)htons((u16_t)IP_PROTO_TCP)) { |
| 8018 | | + ++sum; |
| 8019 | | + } |
| 8048 | +/** @} */ |
| 8020 | 8049 | + |
| 8021 | | + hsum = (u16_t)htons((((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - 20); |
| 8022 | | + |
| 8023 | | + if((sum += hsum) < hsum) { |
| 8024 | | + ++sum; |
| 8025 | | + } |
| 8026 | | + |
| 8027 | | + return sum; |
| 8028 | | +} |
| 8029 | 8050 | +/*-----------------------------------------------------------------------------------*/ |
| 8030 | | +++ b/net/uip-0.9/uip_arch.h |
| 8031 | | @@ -0,0 +1,130 @@ |
| 8051 | +/* Functions that are used by the uIP application program. Opening and |
| 8052 | + * closing connections, sending and receiving data, etc. is all |
| 8053 | + * handled by the functions below. |
| 8054 | +*/ |
| 8032 | 8055 | +/** |
| 8033 | | + * \defgroup uiparch Architecture specific uIP functions |
| 8056 | + * \defgroup uipappfunc uIP application functions |
| 8034 | 8057 | + * @{ |
| 8035 | 8058 | + * |
| 8036 | | + * The functions in the architecture specific module implement the IP |
| 8037 | | + * check sum and 32-bit additions. |
| 8059 | + * Functions used by an application running of top of uIP. |
| 8060 | + */ |
| 8061 | + |
| 8062 | +/** |
| 8063 | + * Start listening to the specified port. |
| 8038 | 8064 | + * |
| 8039 | | + * The IP checksum calculation is the most computationally expensive |
| 8040 | | + * operation in the TCP/IP stack and it therefore pays off to |
| 8041 | | + * implement this in efficient assembler. The purpose of the uip-arch |
| 8042 | | + * module is to let the checksum functions to be implemented in |
| 8043 | | + * architecture specific assembler. |
| 8065 | + * \note Since this function expects the port number in network byte |
| 8066 | + * order, a conversion using HTONS() or htons() is necessary. |
| 8067 | + * |
| 8068 | + \code |
| 8069 | + uip_listen(HTONS(80)); |
| 8070 | + \endcode |
| 8044 | 8071 | + * |
| 8072 | + * \param port A 16-bit port number in network byte order. |
| 8045 | 8073 | + */ |
| 8074 | +void uip_listen(u16_t port); |
| 8046 | 8075 | + |
| 8047 | 8076 | +/** |
| 8048 | | + * \file |
| 8049 | | + * Declarations of architecture specific functions. |
| 8050 | | + * \author Adam Dunkels <adam@dunkels.com> |
| 8077 | + * Stop listening to the specified port. |
| 8078 | + * |
| 8079 | + * \note Since this function expects the port number in network byte |
| 8080 | + * order, a conversion using HTONS() or htons() is necessary. |
| 8081 | + * |
| 8082 | + \code |
| 8083 | + uip_unlisten(HTONS(80)); |
| 8084 | + \endcode |
| 8085 | + * |
| 8086 | + * \param port A 16-bit port number in network byte order. |
| 8051 | 8087 | + */ |
| 8088 | +void uip_unlisten(u16_t port); |
| 8052 | 8089 | + |
| 8053 | | +/* |
| 8054 | | + * Copyright (c) 2001, Adam Dunkels. |
| 8055 | | + * All rights reserved. |
| 8090 | +/** |
| 8091 | + * Connect to a remote host using TCP. |
| 8056 | 8092 | + * |
| 8057 | | + * Redistribution and use in source and binary forms, with or without |
| 8058 | | + * modification, are permitted provided that the following conditions |
| 8059 | | + * are met: |
| 8060 | | + * 1. Redistributions of source code must retain the above copyright |
| 8061 | | + * notice, this list of conditions and the following disclaimer. |
| 8062 | | + * 2. Redistributions in binary form must reproduce the above copyright |
| 8063 | | + * notice, this list of conditions and the following disclaimer in the |
| 8064 | | + * documentation and/or other materials provided with the distribution. |
| 8065 | | + * 3. The name of the author may not be used to endorse or promote |
| 8066 | | + * products derived from this software without specific prior |
| 8067 | | + * written permission. |
| 8093 | + * This function is used to start a new connection to the specified |
| 8094 | + * port on the specied host. It allocates a new connection identifier, |
| 8095 | + * sets the connection to the SYN_SENT state and sets the |
| 8096 | + * retransmission timer to 0. This will cause a TCP SYN segment to be |
| 8097 | + * sent out the next time this connection is periodically processed, |
| 8098 | + * which usually is done within 0.5 seconds after the call to |
| 8099 | + * uip_connect(). |
| 8068 | 8100 | + * |
| 8069 | | + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS |
| 8070 | | + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 8071 | | + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 8072 | | + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
| 8073 | | + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 8074 | | + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
| 8075 | | + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 8076 | | + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| 8077 | | + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| 8078 | | + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 8079 | | + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 8101 | + * \note This function is avaliable only if support for active open |
| 8102 | + * has been configured by defining UIP_ACTIVE_OPEN to 1 in uipopt.h. |
| 8080 | 8103 | + * |
| 8081 | | + * This file is part of the uIP TCP/IP stack. |
| 8104 | + * \note Since this function requires the port number to be in network |
| 8105 | + * byte order, a convertion using HTONS() or htons() is necessary. |
| 8082 | 8106 | + * |
| 8083 | | + * $Id: uip_arch.h,v 1.1.2.2 2003/10/06 15:10:22 adam Exp $ |
| 8107 | + \code |
| 8108 | + u16_t ipaddr[2]; |
| 8109 | + |
| 8110 | + uip_ipaddr(ipaddr, 192,168,1,2); |
| 8111 | + uip_connect(ipaddr, HTONS(80)); |
| 8112 | + \endcode |
| 8113 | + * |
| 8114 | + * \param ripaddr A pointer to a 4-byte array representing the IP |
| 8115 | + * address of the remote hot. |
| 8116 | + * |
| 8117 | + * \param port A 16-bit port number in network byte order. |
| 8118 | + * |
| 8119 | + * \return A pointer to the uIP connection identifier for the new connection, |
| 8120 | + * or NULL if no connection could be allocated. |
| 8084 | 8121 | + * |
| 8085 | 8122 | + */ |
| 8123 | +struct uip_conn *uip_connect(u16_t *ripaddr, u16_t port); |
| 8086 | 8124 | + |
| 8087 | | +#ifndef __UIP_ARCH_H__ |
| 8088 | | +#define __UIP_ARCH_H__ |
| 8089 | 8125 | + |
| 8090 | | +#include "uip.h" |
| 8091 | 8126 | + |
| 8092 | 8127 | +/** |
| 8093 | | + * Carry out a 32-bit addition. |
| 8128 | + * \internal |
| 8094 | 8129 | + * |
| 8095 | | + * Because not all architectures for which uIP is intended has native |
| 8096 | | + * 32-bit arithmetic, uIP uses an external C function for doing the |
| 8097 | | + * required 32-bit additions in the TCP protocol processing. This |
| 8098 | | + * function should add the two arguments and place the result in the |
| 8099 | | + * global variable uip_acc32. |
| 8130 | + * Check if a connection has outstanding (i.e., unacknowledged) data. |
| 8100 | 8131 | + * |
| 8101 | | + * \note The 32-bit integer pointed to by the op32 parameter and the |
| 8102 | | + * result in the uip_acc32 variable are in network byte order (big |
| 8103 | | + * endian). |
| 8132 | + * \param conn A pointer to the uip_conn structure for the connection. |
| 8104 | 8133 | + * |
| 8105 | | + * \param op32 A pointer to a 4-byte array representing a 32-bit |
| 8106 | | + * integer in network byte order (big endian). |
| 8134 | + * \hideinitializer |
| 8135 | + */ |
| 8136 | +#define uip_outstanding(conn) ((conn)->len) |
| 8137 | + |
| 8138 | +/** |
| 8139 | + * Send data on the current connection. |
| 8107 | 8140 | + * |
| 8108 | | + * \param op16 A 16-bit integer in host byte order. |
| 8141 | + * This function is used to send out a single segment of TCP |
| 8142 | + * data. Only applications that have been invoked by uIP for event |
| 8143 | + * processing can send data. |
| 8144 | + * |
| 8145 | + * The amount of data that actually is sent out after a call to this |
| 8146 | + * funcion is determined by the maximum amount of data TCP allows. uIP |
| 8147 | + * will automatically crop the data so that only the appropriate |
| 8148 | + * amount of data is sent. The function uip_mss() can be used to query |
| 8149 | + * uIP for the amount of data that actually will be sent. |
| 8150 | + * |
| 8151 | + * \note This function does not guarantee that the sent data will |
| 8152 | + * arrive at the destination. If the data is lost in the network, the |
| 8153 | + * application will be invoked with the uip_rexmit() event being |
| 8154 | + * set. The application will then have to resend the data using this |
| 8155 | + * function. |
| 8156 | + * |
| 8157 | + * \param data A pointer to the data which is to be sent. |
| 8158 | + * |
| 8159 | + * \param len The maximum amount of data bytes to be sent. |
| 8160 | + * |
| 8161 | + * \hideinitializer |
| 8109 | 8162 | + */ |
| 8110 | | +void uip_add32(u8_t *op32, u16_t op16); |
| 8163 | +#define uip_send(data, len) do { uip_sappdata = (data); uip_slen = (len);} while(0) |
| 8111 | 8164 | + |
| 8112 | 8165 | +/** |
| 8113 | | + * Calculate the Internet checksum over a buffer. |
| 8166 | + * The length of any incoming data that is currently avaliable (if avaliable) |
| 8167 | + * in the uip_appdata buffer. |
| 8114 | 8168 | + * |
| 8115 | | + * The Internet checksum is the one's complement of the one's |
| 8116 | | + * complement sum of all 16-bit words in the buffer. |
| 8169 | + * The test function uip_data() must first be used to check if there |
| 8170 | + * is any data available at all. |
| 8117 | 8171 | + * |
| 8118 | | + * See RFC1071. |
| 8172 | + * \hideinitializer |
| 8173 | + */ |
| 8174 | +#define uip_datalen() uip_len |
| 8175 | + |
| 8176 | +/** |
| 8177 | + * The length of any out-of-band data (urgent data) that has arrived |
| 8178 | + * on the connection. |
| 8119 | 8179 | + * |
| 8120 | | + * \note This function is not called in the current version of uIP, |
| 8121 | | + * but future versions might make use of it. |
| 8180 | + * \note The configuration parameter UIP_URGDATA must be set for this |
| 8181 | + * function to be enabled. |
| 8122 | 8182 | + * |
| 8123 | | + * \param buf A pointer to the buffer over which the checksum is to be |
| 8124 | | + * computed. |
| 8183 | + * \hideinitializer |
| 8184 | + */ |
| 8185 | +#define uip_urgdatalen() uip_urglen |
| 8186 | + |
| 8187 | +/** |
| 8188 | + * Close the current connection. |
| 8125 | 8189 | + * |
| 8126 | | + * \param len The length of the buffer over which the checksum is to |
| 8127 | | + * be computed. |
| 8190 | + * This function will close the current connection in a nice way. |
| 8128 | 8191 | + * |
| 8129 | | + * \return The Internet checksum of the buffer. |
| 8192 | + * \hideinitializer |
| 8130 | 8193 | + */ |
| 8131 | | +u16_t uip_chksum(u16_t *buf, u16_t len); |
| 8194 | +#define uip_close() (uip_flags = UIP_CLOSE) |
| 8132 | 8195 | + |
| 8133 | 8196 | +/** |
| 8134 | | + * Calculate the IP header checksum of the packet header in uip_buf. |
| 8197 | + * Abort the current connection. |
| 8135 | 8198 | + * |
| 8136 | | + * The IP header checksum is the Internet checksum of the 20 bytes of |
| 8137 | | + * the IP header. |
| 8199 | + * This function will abort (reset) the current connection, and is |
| 8200 | + * usually used when an error has occured that prevents using the |
| 8201 | + * uip_close() function. |
| 8138 | 8202 | + * |
| 8139 | | + * \return The IP header checksum of the IP header in the uip_buf |
| 8140 | | + * buffer. |
| 8203 | + * \hideinitializer |
| 8141 | 8204 | + */ |
| 8142 | | +u16_t uip_ipchksum(void); |
| 8205 | +#define uip_abort() (uip_flags = UIP_ABORT) |
| 8206 | + |
| 8207 | +/** |
| 8208 | + * Tell the sending host to stop sending data. |
| 8209 | + * |
| 8210 | + * This function will close our receiver's window so that we stop |
| 8211 | + * receiving data for the current connection. |
| 8212 | + * |
| 8213 | + * \hideinitializer |
| 8214 | + */ |
| 8215 | +#define uip_stop() (uip_conn->tcpstateflags |= UIP_STOPPED) |
| 8216 | + |
| 8217 | +/** |
| 8218 | + * Find out if the current connection has been previously stopped with |
| 8219 | + * uip_stop(). |
| 8220 | + * |
| 8221 | + * \hideinitializer |
| 8222 | + */ |
| 8223 | +#define uip_stopped(conn) ((conn)->tcpstateflags & UIP_STOPPED) |
| 8143 | 8224 | + |
| 8144 | 8225 | +/** |
| 8145 | | + * Calculate the TCP checksum of the packet in uip_buf and uip_appdata. |
| 8146 | | + * |
| 8147 | | + * The TCP checksum is the Internet checksum of data contents of the |
| 8148 | | + * TCP segment, and a pseudo-header as defined in RFC793. |
| 8226 | + * Restart the current connection, if is has previously been stopped |
| 8227 | + * with uip_stop(). |
| 8149 | 8228 | + * |
| 8150 | | + * \note The uip_appdata pointer that points to the packet data may |
| 8151 | | + * point anywhere in memory, so it is not possible to simply calculate |
| 8152 | | + * the Internet checksum of the contents of the uip_buf buffer. |
| 8229 | + * This function will open the receiver's window again so that we |
| 8230 | + * start receiving data for the current connection. |
| 8153 | 8231 | + * |
| 8154 | | + * \return The TCP checksum of the TCP segment in uip_buf and pointed |
| 8155 | | + * to by uip_appdata. |
| 8232 | + * \hideinitializer |
| 8156 | 8233 | + */ |
| 8157 | | +u16_t uip_tcpchksum(void); |
| 8234 | +#define uip_restart() do { uip_flags |= UIP_NEWDATA; \ |
| 8235 | + uip_conn->tcpstateflags &= ~UIP_STOPPED; \ |
| 8236 | + } while(0) |
| 8158 | 8237 | + |
| 8159 | | +/** @} */ |
| 8160 | 8238 | + |
| 8161 | | +#endif /* __UIP_ARCH_H__ */ |
| 8162 | | +++ b/net/uip-0.9/uip_arp.c |
| 8163 | | @@ -0,0 +1,421 @@ |
| 8164 | | +/** |
| 8165 | | + * \addtogroup uip |
| 8166 | | + * @{ |
| 8167 | | + */ |
| 8239 | +/* uIP tests that can be made to determine in what state the current |
| 8240 | + connection is, and what the application function should do. */ |
| 8168 | 8241 | + |
| 8169 | 8242 | +/** |
| 8170 | | + * \defgroup uiparp uIP Address Resolution Protocol |
| 8171 | | + * @{ |
| 8172 | | + * |
| 8173 | | + * The Address Resolution Protocol ARP is used for mapping between IP |
| 8174 | | + * addresses and link level addresses such as the Ethernet MAC |
| 8175 | | + * addresses. ARP uses broadcast queries to ask for the link level |
| 8176 | | + * address of a known IP address and the host which is configured with |
| 8177 | | + * the IP address for which the query was meant, will respond with its |
| 8178 | | + * link level address. |
| 8243 | + * Is new incoming data available? |
| 8179 | 8244 | + * |
| 8180 | | + * \note This ARP implementation only supports Ethernet. |
| 8181 | | + */ |
| 8182 | | + |
| 8183 | | +/** |
| 8184 | | + * \file |
| 8185 | | + * Implementation of the ARP Address Resolution Protocol. |
| 8186 | | + * \author Adam Dunkels <adam@dunkels.com> |
| 8245 | + * Will reduce to non-zero if there is new data for the application |
| 8246 | + * present at the uip_appdata pointer. The size of the data is |
| 8247 | + * avaliable through the uip_len variable. |
| 8187 | 8248 | + * |
| 8249 | + * \hideinitializer |
| 8188 | 8250 | + */ |
| 8251 | +#define uip_newdata() (uip_flags & UIP_NEWDATA) |
| 8189 | 8252 | + |
| 8190 | | +/* |
| 8191 | | + * Copyright (c) 2001-2003, Adam Dunkels. |
| 8192 | | + * All rights reserved. |
| 8193 | | + * |
| 8194 | | + * Redistribution and use in source and binary forms, with or without |
| 8195 | | + * modification, are permitted provided that the following conditions |
| 8196 | | + * are met: |
| 8197 | | + * 1. Redistributions of source code must retain the above copyright |
| 8198 | | + * notice, this list of conditions and the following disclaimer. |
| 8199 | | + * 2. Redistributions in binary form must reproduce the above copyright |
| 8200 | | + * notice, this list of conditions and the following disclaimer in the |
| 8201 | | + * documentation and/or other materials provided with the distribution. |
| 8202 | | + * 3. The name of the author may not be used to endorse or promote |
| 8203 | | + * products derived from this software without specific prior |
| 8204 | | + * written permission. |
| 8253 | +/** |
| 8254 | + * Has previously sent data been acknowledged? |
| 8205 | 8255 | + * |
| 8206 | | + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS |
| 8207 | | + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 8208 | | + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 8209 | | + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
| 8210 | | + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 8211 | | + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
| 8212 | | + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 8213 | | + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| 8214 | | + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| 8215 | | + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 8216 | | + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 8256 | + * Will reduce to non-zero if the previously sent data has been |
| 8257 | + * acknowledged by the remote host. This means that the application |
| 8258 | + * can send new data. |
| 8217 | 8259 | + * |
| 8218 | | + * This file is part of the uIP TCP/IP stack. |
| 8260 | + * \hideinitializer |
| 8261 | + */ |
| 8262 | +#define uip_acked() (uip_flags & UIP_ACKDATA) |
| 8263 | + |
| 8264 | +/** |
| 8265 | + * Has the connection just been connected? |
| 8219 | 8266 | + * |
| 8220 | | + * $Id: uip_arp.c,v 1.7.2.3 2003/10/06 22:42:30 adam Exp $ |
| 8267 | + * Reduces to non-zero if the current connection has been connected to |
| 8268 | + * a remote host. This will happen both if the connection has been |
| 8269 | + * actively opened (with uip_connect()) or passively opened (with |
| 8270 | + * uip_listen()). |
| 8221 | 8271 | + * |
| 8272 | + * \hideinitializer |
| 8222 | 8273 | + */ |
| 8274 | +#define uip_connected() (uip_flags & UIP_CONNECTED) |
| 8223 | 8275 | + |
| 8224 | | + |
| 8225 | | +#include "uip_arp.h" |
| 8226 | | + |
| 8227 | | +struct arp_hdr { |
| 8228 | | + struct uip_eth_hdr ethhdr; |
| 8229 | | + u16_t hwtype; |
| 8230 | | + u16_t protocol; |
| 8231 | | + u8_t hwlen; |
| 8232 | | + u8_t protolen; |
| 8233 | | + u16_t opcode; |
| 8234 | | + struct uip_eth_addr shwaddr; |
| 8235 | | + u16_t sipaddr[2]; |
| 8236 | | + struct uip_eth_addr dhwaddr; |
| 8237 | | + u16_t dipaddr[2]; |
| 8238 | | +}; |
| 8239 | | + |
| 8240 | | +struct ethip_hdr { |
| 8241 | | + struct uip_eth_hdr ethhdr; |
| 8242 | | + /* IP header. */ |
| 8243 | | + u8_t vhl, |
| 8244 | | + tos, |
| 8245 | | + len[2], |
| 8246 | | + ipid[2], |
| 8247 | | + ipoffset[2], |
| 8248 | | + ttl, |
| 8249 | | + proto; |
| 8250 | | + u16_t ipchksum; |
| 8251 | | + u16_t srcipaddr[2], |
| 8252 | | + destipaddr[2]; |
| 8253 | | +}; |
| 8254 | | + |
| 8255 | | +#define ARP_REQUEST 1 |
| 8256 | | +#define ARP_REPLY 2 |
| 8257 | | + |
| 8258 | | +#define ARP_HWTYPE_ETH 1 |
| 8259 | | + |
| 8260 | | +struct arp_entry { |
| 8261 | | + u16_t ipaddr[2]; |
| 8262 | | + struct uip_eth_addr ethaddr; |
| 8263 | | + u8_t time; |
| 8264 | | +}; |
| 8265 | | + |
| 8266 | | +struct uip_eth_addr uip_ethaddr = {{UIP_ETHADDR0, |
| 8267 | | + UIP_ETHADDR1, |
| 8268 | | + UIP_ETHADDR2, |
| 8269 | | + UIP_ETHADDR3, |
| 8270 | | + UIP_ETHADDR4, |
| 8271 | | + UIP_ETHADDR5}}; |
| 8272 | | + |
| 8273 | | +static struct arp_entry arp_table[UIP_ARPTAB_SIZE]; |
| 8274 | | +static u16_t ipaddr[2]; |
| 8275 | | +static u8_t i, c; |
| 8276 | | + |
| 8277 | | +static u8_t arptime; |
| 8278 | | +static u8_t tmpage; |
| 8279 | | + |
| 8280 | | +#define BUF ((struct arp_hdr *)&uip_buf[0]) |
| 8281 | | +#define IPBUF ((struct ethip_hdr *)&uip_buf[0]) |
| 8282 | | +/*-----------------------------------------------------------------------------------*/ |
| 8283 | 8276 | +/** |
| 8284 | | + * Initialize the ARP module. |
| 8277 | + * Has the connection been closed by the other end? |
| 8278 | + * |
| 8279 | + * Is non-zero if the connection has been closed by the remote |
| 8280 | + * host. The application may then do the necessary clean-ups. |
| 8285 | 8281 | + * |
| 8282 | + * \hideinitializer |
| 8286 | 8283 | + */ |
| 8287 | | +/*-----------------------------------------------------------------------------------*/ |
| 8288 | | +void |
| 8289 | | +uip_arp_init(void) |
| 8290 | | +{ |
| 8291 | | + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { |
| 8292 | | + memset(arp_table[i].ipaddr, 0, 4); |
| 8293 | | + } |
| 8294 | | +} |
| 8295 | | +/*-----------------------------------------------------------------------------------*/ |
| 8284 | +#define uip_closed() (uip_flags & UIP_CLOSE) |
| 8285 | + |
| 8296 | 8286 | +/** |
| 8297 | | + * Periodic ARP processing function. |
| 8287 | + * Has the connection been aborted by the other end? |
| 8298 | 8288 | + * |
| 8299 | | + * This function performs periodic timer processing in the ARP module |
| 8300 | | + * and should be called at regular intervals. The recommended interval |
| 8301 | | + * is 10 seconds between the calls. |
| 8289 | + * Non-zero if the current connection has been aborted (reset) by the |
| 8290 | + * remote host. |
| 8302 | 8291 | + * |
| 8292 | + * \hideinitializer |
| 8303 | 8293 | + */ |
| 8304 | | +/*-----------------------------------------------------------------------------------*/ |
| 8305 | | +void |
| 8306 | | +uip_arp_timer(void) |
| 8307 | | +{ |
| 8308 | | + struct arp_entry *tabptr; |
| 8309 | | + |
| 8310 | | + ++arptime; |
| 8311 | | + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { |
| 8312 | | + tabptr = &arp_table[i]; |
| 8313 | | + if((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 && |
| 8314 | | + arptime - tabptr->time >= UIP_ARP_MAXAGE) { |
| 8315 | | + memset(tabptr->ipaddr, 0, 4); |
| 8316 | | + } |
| 8317 | | + } |
| 8318 | | + |
| 8319 | | +} |
| 8320 | | +/*-----------------------------------------------------------------------------------*/ |
| 8321 | | +static void |
| 8322 | | +uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr) |
| 8323 | | +{ |
| 8324 | | + register struct arp_entry *tabptr; |
| 8325 | | + /* Walk through the ARP mapping table and try to find an entry to |
| 8326 | | + update. If none is found, the IP -> MAC address mapping is |
| 8327 | | + inserted in the ARP table. */ |
| 8328 | | + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { |
| 8329 | | + |
| 8330 | | + tabptr = &arp_table[i]; |
| 8331 | | + /* Only check those entries that are actually in use. */ |
| 8332 | | + if(tabptr->ipaddr[0] != 0 && |
| 8333 | | + tabptr->ipaddr[1] != 0) { |
| 8334 | | + |
| 8335 | | + /* Check if the source IP address of the incoming packet matches |
| 8336 | | + the IP address in this ARP table entry. */ |
| 8337 | | + if(ipaddr[0] == tabptr->ipaddr[0] && |
| 8338 | | + ipaddr[1] == tabptr->ipaddr[1]) { |
| 8339 | | + |
| 8340 | | + /* An old entry found, update this and return. */ |
| 8341 | | + memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); |
| 8342 | | + tabptr->time = arptime; |
| 8343 | | + |
| 8344 | | + return; |
| 8345 | | + } |
| 8346 | | + } |
| 8347 | | + } |
| 8348 | | + |
| 8349 | | + /* If we get here, no existing ARP table entry was found, so we |
| 8350 | | + create one. */ |
| 8351 | | + |
| 8352 | | + /* First, we try to find an unused entry in the ARP table. */ |
| 8353 | | + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { |
| 8354 | | + tabptr = &arp_table[i]; |
| 8355 | | + if(tabptr->ipaddr[0] == 0 && |
| 8356 | | + tabptr->ipaddr[1] == 0) { |
| 8357 | | + break; |
| 8358 | | + } |
| 8359 | | + } |
| 8294 | +#define uip_aborted() (uip_flags & UIP_ABORT) |
| 8360 | 8295 | + |
| 8361 | | + /* If no unused entry is found, we try to find the oldest entry and |
| 8362 | | + throw it away. */ |
| 8363 | | + if(i == UIP_ARPTAB_SIZE) { |
| 8364 | | + tmpage = 0; |
| 8365 | | + c = 0; |
| 8366 | | + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { |
| 8367 | | + tabptr = &arp_table[i]; |
| 8368 | | + if(arptime - tabptr->time > tmpage) { |
| 8369 | | + tmpage = arptime - tabptr->time; |
| 8370 | | + c = i; |
| 8371 | | + } |
| 8372 | | + } |
| 8373 | | + i = c; |
| 8374 | | + } |
| 8296 | +/** |
| 8297 | + * Has the connection timed out? |
| 8298 | + * |
| 8299 | + * Non-zero if the current connection has been aborted due to too many |
| 8300 | + * retransmissions. |
| 8301 | + * |
| 8302 | + * \hideinitializer |
| 8303 | + */ |
| 8304 | +#define uip_timedout() (uip_flags & UIP_TIMEDOUT) |
| 8375 | 8305 | + |
| 8376 | | + /* Now, i is the ARP table entry which we will fill with the new |
| 8377 | | + information. */ |
| 8378 | | + memcpy(tabptr->ipaddr, ipaddr, 4); |
| 8379 | | + memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); |
| 8380 | | + tabptr->time = arptime; |
| 8381 | | +} |
| 8382 | | +/*-----------------------------------------------------------------------------------*/ |
| 8383 | 8306 | +/** |
| 8384 | | + * ARP processing for incoming IP packets |
| 8307 | + * Do we need to retransmit previously data? |
| 8385 | 8308 | + * |
| 8386 | | + * This function should be called by the device driver when an IP |
| 8387 | | + * packet has been received. The function will check if the address is |
| 8388 | | + * in the ARP cache, and if so the ARP cache entry will be |
| 8389 | | + * refreshed. If no ARP cache entry was found, a new one is created. |
| 8309 | + * Reduces to non-zero if the previously sent data has been lost in |
| 8310 | + * the network, and the application should retransmit it. The |
| 8311 | + * application should send the exact same data as it did the last |
| 8312 | + * time, using the uip_send() function. |
| 8390 | 8313 | + * |
| 8391 | | + * This function expects an IP packet with a prepended Ethernet header |
| 8392 | | + * in the uip_buf[] buffer, and the length of the packet in the global |
| 8393 | | + * variable uip_len. |
| 8314 | + * \hideinitializer |
| 8394 | 8315 | + */ |
| 8395 | | +/*-----------------------------------------------------------------------------------*/ |
| 8396 | | +void |
| 8397 | | +uip_arp_ipin(void) |
| 8398 | | +{ |
| 8399 | | + uip_len -= sizeof(struct uip_eth_hdr); |
| 8400 | | + |
| 8401 | | + /* Only insert/update an entry if the source IP address of the |
| 8402 | | + incoming IP packet comes from a host on the local network. */ |
| 8403 | | + if((IPBUF->srcipaddr[0] & uip_arp_netmask[0]) != |
| 8404 | | + (uip_hostaddr[0] & uip_arp_netmask[0])) { |
| 8405 | | + return; |
| 8406 | | + } |
| 8407 | | + if((IPBUF->srcipaddr[1] & uip_arp_netmask[1]) != |
| 8408 | | + (uip_hostaddr[1] & uip_arp_netmask[1])) { |
| 8409 | | + return; |
| 8410 | | + } |
| 8411 | | + uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src)); |
| 8412 | | + |
| 8413 | | + return; |
| 8414 | | +} |
| 8415 | | +/*-----------------------------------------------------------------------------------*/ |
| 8316 | +#define uip_rexmit() (uip_flags & UIP_REXMIT) |
| 8317 | + |
| 8416 | 8318 | +/** |
| 8417 | | + * ARP processing for incoming ARP packets. |
| 8319 | + * Is the connection being polled by uIP? |
| 8418 | 8320 | + * |
| 8419 | | + * This function should be called by the device driver when an ARP |
| 8420 | | + * packet has been received. The function will act differently |
| 8421 | | + * depending on the ARP packet type: if it is a reply for a request |
| 8422 | | + * that we previously sent out, the ARP cache will be filled in with |
| 8423 | | + * the values from the ARP reply. If the incoming ARP packet is an ARP |
| 8424 | | + * request for our IP address, an ARP reply packet is created and put |
| 8425 | | + * into the uip_buf[] buffer. |
| 8321 | + * Is non-zero if the reason the application is invoked is that the |
| 8322 | + * current connection has been idle for a while and should be |
| 8323 | + * polled. |
| 8426 | 8324 | + * |
| 8427 | | + * When the function returns, the value of the global variable uip_len |
| 8428 | | + * indicates whether the device driver should send out a packet or |
| 8429 | | + * not. If uip_len is zero, no packet should be sent. If uip_len is |
| 8430 | | + * non-zero, it contains the length of the outbound packet that is |
| 8431 | | + * present in the uip_buf[] buffer. |
| 8325 | + * The polling event can be used for sending data without having to |
| 8326 | + * wait for the remote host to send data. |
| 8432 | 8327 | + * |
| 8433 | | + * This function expects an ARP packet with a prepended Ethernet |
| 8434 | | + * header in the uip_buf[] buffer, and the length of the packet in the |
| 8435 | | + * global variable uip_len. |
| 8328 | + * \hideinitializer |
| 8329 | + */ |
| 8330 | +#define uip_poll() (uip_flags & UIP_POLL) |
| 8331 | + |
| 8332 | +/** |
| 8333 | + * Get the initial maxium segment size (MSS) of the current |
| 8334 | + * connection. |
| 8335 | + * |
| 8336 | + * \hideinitializer |
| 8436 | 8337 | + */ |
| 8437 | | +/*-----------------------------------------------------------------------------------*/ |
| 8438 | | +void |
| 8439 | | +uip_arp_arpin(void) |
| 8440 | | +{ |
| 8338 | +#define uip_initialmss() (uip_conn->initialmss) |
| 8441 | 8339 | + |
| 8442 | | + if(uip_len < sizeof(struct arp_hdr)) { |
| 8443 | | + uip_len = 0; |
| 8444 | | + return; |
| 8445 | | + } |
| 8340 | +/** |
| 8341 | + * Get the current maxium segment size that can be sent on the current |
| 8342 | + * connection. |
| 8343 | + * |
| 8344 | + * The current maxiumum segment size that can be sent on the |
| 8345 | + * connection is computed from the receiver's window and the MSS of |
| 8346 | + * the connection (which also is available by calling |
| 8347 | + * uip_initialmss()). |
| 8348 | + * |
| 8349 | + * \hideinitializer |
| 8350 | + */ |
| 8351 | +#define uip_mss() (uip_conn->mss) |
| 8446 | 8352 | + |
| 8447 | | + uip_len = 0; |
| 8353 | +/** |
| 8354 | + * Set up a new UDP connection. |
| 8355 | + * |
| 8356 | + * \param ripaddr A pointer to a 4-byte structure representing the IP |
| 8357 | + * address of the remote host. |
| 8358 | + * |
| 8359 | + * \param rport The remote port number in network byte order. |
| 8360 | + * |
| 8361 | + * \return The uip_udp_conn structure for the new connection or NULL |
| 8362 | + * if no connection could be allocated. |
| 8363 | + */ |
| 8364 | +struct uip_udp_conn *uip_udp_new(u16_t *ripaddr, u16_t rport); |
| 8448 | 8365 | + |
| 8449 | | + switch(BUF->opcode) { |
| 8450 | | + case HTONS(ARP_REQUEST): |
| 8451 | | + /* ARP request. If it asked for our address, we send out a |
| 8452 | | + reply. */ |
| 8453 | | + if(BUF->dipaddr[0] == uip_hostaddr[0] && |
| 8454 | | + BUF->dipaddr[1] == uip_hostaddr[1]) { |
| 8455 | | + /* The reply opcode is 2. */ |
| 8456 | | + BUF->opcode = HTONS(2); |
| 8366 | +/** |
| 8367 | + * Removed a UDP connection. |
| 8368 | + * |
| 8369 | + * \param conn A pointer to the uip_udp_conn structure for the connection. |
| 8370 | + * |
| 8371 | + * \hideinitializer |
| 8372 | + */ |
| 8373 | +#define uip_udp_remove(conn) (conn)->lport = 0 |
| 8457 | 8374 | + |
| 8458 | | + memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6); |
| 8459 | | + memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); |
| 8460 | | + memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); |
| 8461 | | + memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6); |
| 8462 | | + |
| 8463 | | + BUF->dipaddr[0] = BUF->sipaddr[0]; |
| 8464 | | + BUF->dipaddr[1] = BUF->sipaddr[1]; |
| 8465 | | + BUF->sipaddr[0] = uip_hostaddr[0]; |
| 8466 | | + BUF->sipaddr[1] = uip_hostaddr[1]; |
| 8375 | +/** |
| 8376 | + * Send a UDP datagram of length len on the current connection. |
| 8377 | + * |
| 8378 | + * This function can only be called in response to a UDP event (poll |
| 8379 | + * or newdata). The data must be present in the uip_buf buffer, at the |
| 8380 | + * place pointed to by the uip_appdata pointer. |
| 8381 | + * |
| 8382 | + * \param len The length of the data in the uip_buf buffer. |
| 8383 | + * |
| 8384 | + * \hideinitializer |
| 8385 | + */ |
| 8386 | +#define uip_udp_send(len) uip_slen = (len) |
| 8467 | 8387 | + |
| 8468 | | + BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); |
| 8469 | | + uip_len = sizeof(struct arp_hdr); |
| 8470 | | + } |
| 8471 | | + break; |
| 8472 | | + case HTONS(ARP_REPLY): |
| 8473 | | + /* ARP reply. We insert or update the ARP table if it was meant |
| 8474 | | + for us. */ |
| 8475 | | + if(BUF->dipaddr[0] == uip_hostaddr[0] && |
| 8476 | | + BUF->dipaddr[1] == uip_hostaddr[1]) { |
| 8388 | +/** @} */ |
| 8477 | 8389 | + |
| 8478 | | + uip_arp_update(BUF->sipaddr, &BUF->shwaddr); |
| 8479 | | + } |
| 8480 | | + break; |
| 8481 | | + } |
| 8390 | +/* uIP convenience and converting functions. */ |
| 8482 | 8391 | + |
| 8483 | | + return; |
| 8484 | | +} |
| 8485 | | +/*-----------------------------------------------------------------------------------*/ |
| 8486 | 8392 | +/** |
| 8487 | | + * Prepend Ethernet header to an outbound IP packet and see if we need |
| 8488 | | + * to send out an ARP request. |
| 8393 | + * \defgroup uipconvfunc uIP conversion functions |
| 8394 | + * @{ |
| 8489 | 8395 | + * |
| 8490 | | + * This function should be called before sending out an IP packet. The |
| 8491 | | + * function checks the destination IP address of the IP packet to see |
| 8492 | | + * what Ethernet MAC address that should be used as a destination MAC |
| 8493 | | + * address on the Ethernet. |
| 8396 | + * These functions can be used for converting between different data |
| 8397 | + * formats used by uIP. |
| 8398 | + */ |
| 8399 | + |
| 8400 | +/** |
| 8401 | + * Pack an IP address into a 4-byte array which is used by uIP to |
| 8402 | + * represent IP addresses. |
| 8494 | 8403 | + * |
| 8495 | | + * If the destination IP address is in the local network (determined |
| 8496 | | + * by logical ANDing of netmask and our IP address), the function |
| 8497 | | + * checks the ARP cache to see if an entry for the destination IP |
| 8498 | | + * address is found. If so, an Ethernet header is prepended and the |
| 8499 | | + * function returns. If no ARP cache entry is found for the |
| 8500 | | + * destination IP address, the packet in the uip_buf[] is replaced by |
| 8501 | | + * an ARP request packet for the IP address. The IP packet is dropped |
| 8502 | | + * and it is assumed that they higher level protocols (e.g., TCP) |
| 8503 | | + * eventually will retransmit the dropped packet. |
| 8404 | + * Example: |
| 8405 | + \code |
| 8406 | + u16_t ipaddr[2]; |
| 8407 | + |
| 8408 | + uip_ipaddr(&ipaddr, 192,168,1,2); |
| 8409 | + \endcode |
| 8504 | 8410 | + * |
| 8505 | | + * If the destination IP address is not on the local network, the IP |
| 8506 | | + * address of the default router is used instead. |
| 8411 | + * \param addr A pointer to a 4-byte array that will be filled in with |
| 8412 | + * the IP addres. |
| 8413 | + * \param addr0 The first octet of the IP address. |
| 8414 | + * \param addr1 The second octet of the IP address. |
| 8415 | + * \param addr2 The third octet of the IP address. |
| 8416 | + * \param addr3 The forth octet of the IP address. |
| 8507 | 8417 | + * |
| 8508 | | + * When the function returns, a packet is present in the uip_buf[] |
| 8509 | | + * buffer, and the length of the packet is in the global variable |
| 8510 | | + * uip_len. |
| 8418 | + * \hideinitializer |
| 8511 | 8419 | + */ |
| 8512 | | +/*-----------------------------------------------------------------------------------*/ |
| 8513 | | +void |
| 8514 | | +uip_arp_out(void) |
| 8515 | | +{ |
| 8516 | | + struct arp_entry *tabptr; |
| 8517 | | + /* Find the destination IP address in the ARP table and construct |
| 8518 | | + the Ethernet header. If the destination IP addres isn't on the |
| 8519 | | + local network, we use the default router's IP address instead. |
| 8420 | +#define uip_ipaddr(addr, addr0,addr1,addr2,addr3) do { \ |
| 8421 | + (addr)[0] = HTONS(((addr0) << 8) | (addr1)); \ |
| 8422 | + (addr)[1] = HTONS(((addr2) << 8) | (addr3)); \ |
| 8423 | + } while(0) |
| 8424 | + |
| 8425 | +/** |
| 8426 | + * Convert 16-bit quantity from host byte order to network byte order. |
| 8427 | + * |
| 8428 | + * This macro is primarily used for converting constants from host |
| 8429 | + * byte order to network byte order. For converting variables to |
| 8430 | + * network byte order, use the htons() function instead. |
| 8431 | + * |
| 8432 | + * \hideinitializer |
| 8433 | + */ |
| 8434 | +#ifndef HTONS |
| 8435 | +# if BYTE_ORDER == BIG_ENDIAN |
| 8436 | +# define HTONS(n) (n) |
| 8437 | +# else /* BYTE_ORDER == BIG_ENDIAN */ |
| 8438 | +# define HTONS(n) ((((u16_t)((n) & 0xff)) << 8) | (((n) & 0xff00) >> 8)) |
| 8439 | +# endif /* BYTE_ORDER == BIG_ENDIAN */ |
| 8440 | +#endif /* HTONS */ |
| 8441 | + |
| 8442 | +/** |
| 8443 | + * Convert 16-bit quantity from host byte order to network byte order. |
| 8444 | + * |
| 8445 | + * This function is primarily used for converting variables from host |
| 8446 | + * byte order to network byte order. For converting constants to |
| 8447 | + * network byte order, use the HTONS() macro instead. |
| 8448 | + */ |
| 8449 | +#ifndef htons |
| 8450 | +u16_t htons(u16_t val); |
| 8451 | +#endif /* htons */ |
| 8452 | + |
| 8453 | +/** @} */ |
| 8454 | + |
| 8455 | +/** |
| 8456 | + * Pointer to the application data in the packet buffer. |
| 8457 | + * |
| 8458 | + * This pointer points to the application data when the application is |
| 8459 | + * called. If the application wishes to send data, the application may |
| 8460 | + * use this space to write the data into before calling uip_send(). |
| 8461 | + */ |
| 8462 | +extern volatile u8_t *uip_appdata; |
| 8463 | +extern volatile u8_t *uip_sappdata; |
| 8520 | 8464 | + |
| 8521 | | + If not ARP table entry is found, we overwrite the original IP |
| 8522 | | + packet with an ARP request for the IP address. */ |
| 8465 | +#if UIP_URGDATA > 0 |
| 8466 | +/* u8_t *uip_urgdata: |
| 8467 | + * |
| 8468 | + * This pointer points to any urgent data that has been received. Only |
| 8469 | + * present if compiled with support for urgent data (UIP_URGDATA). |
| 8470 | + */ |
| 8471 | +extern volatile u8_t *uip_urgdata; |
| 8472 | +#endif /* UIP_URGDATA > 0 */ |
| 8523 | 8473 | + |
| 8524 | | + /* Check if the destination address is on the local network. */ |
| 8525 | | + if((IPBUF->destipaddr[0] & uip_arp_netmask[0]) != |
| 8526 | | + (uip_hostaddr[0] & uip_arp_netmask[0]) || |
| 8527 | | + (IPBUF->destipaddr[1] & uip_arp_netmask[1]) != |
| 8528 | | + (uip_hostaddr[1] & uip_arp_netmask[1])) { |
| 8529 | | + /* Destination address was not on the local network, so we need to |
| 8530 | | + use the default router's IP address instead of the destination |
| 8531 | | + address when determining the MAC address. */ |
| 8532 | | + ipaddr[0] = uip_arp_draddr[0]; |
| 8533 | | + ipaddr[1] = uip_arp_draddr[1]; |
| 8534 | | + } else { |
| 8535 | | + /* Else, we use the destination IP address. */ |
| 8536 | | + ipaddr[0] = IPBUF->destipaddr[0]; |
| 8537 | | + ipaddr[1] = IPBUF->destipaddr[1]; |
| 8538 | | + } |
| 8539 | | + |
| 8540 | | + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { |
| 8541 | | + tabptr = &arp_table[i]; |
| 8542 | | + if(ipaddr[0] == tabptr->ipaddr[0] && |
| 8543 | | + ipaddr[1] == tabptr->ipaddr[1]) |
| 8544 | | + break; |
| 8545 | | + } |
| 8546 | 8474 | + |
| 8547 | | + if(i == UIP_ARPTAB_SIZE) { |
| 8548 | | + /* The destination address was not in our ARP table, so we |
| 8549 | | + overwrite the IP packet with an ARP request. */ |
| 8475 | +/* u[8|16]_t uip_len: |
| 8476 | + * |
| 8477 | + * When the application is called, uip_len contains the length of any |
| 8478 | + * new data that has been received from the remote host. The |
| 8479 | + * application should set this variable to the size of any data that |
| 8480 | + * the application wishes to send. When the network device driver |
| 8481 | + * output function is called, uip_len should contain the length of the |
| 8482 | + * outgoing packet. |
| 8483 | + */ |
| 8484 | +extern volatile u16_t uip_len, uip_slen; |
| 8550 | 8485 | + |
| 8551 | | + memset(BUF->ethhdr.dest.addr, 0xff, 6); |
| 8552 | | + memset(BUF->dhwaddr.addr, 0x00, 6); |
| 8553 | | + memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); |
| 8554 | | + memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); |
| 8555 | | + |
| 8556 | | + BUF->dipaddr[0] = ipaddr[0]; |
| 8557 | | + BUF->dipaddr[1] = ipaddr[1]; |
| 8558 | | + BUF->sipaddr[0] = uip_hostaddr[0]; |
| 8559 | | + BUF->sipaddr[1] = uip_hostaddr[1]; |
| 8560 | | + BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */ |
| 8561 | | + BUF->hwtype = HTONS(ARP_HWTYPE_ETH); |
| 8562 | | + BUF->protocol = HTONS(UIP_ETHTYPE_IP); |
| 8563 | | + BUF->hwlen = 6; |
| 8564 | | + BUF->protolen = 4; |
| 8565 | | + BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); |
| 8486 | +#if UIP_URGDATA > 0 |
| 8487 | +extern volatile u8_t uip_urglen, uip_surglen; |
| 8488 | +#endif /* UIP_URGDATA > 0 */ |
| 8566 | 8489 | + |
| 8567 | | + uip_appdata = &uip_buf[40 + UIP_LLH_LEN]; |
| 8568 | | + |
| 8569 | | + uip_len = sizeof(struct arp_hdr); |
| 8570 | | + return; |
| 8571 | | + } |
| 8572 | 8490 | + |
| 8573 | | + /* Build an ethernet header. */ |
| 8574 | | + memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6); |
| 8575 | | + memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6); |
| 8491 | +/** |
| 8492 | + * Representation of a uIP TCP connection. |
| 8493 | + * |
| 8494 | + * The uip_conn structure is used for identifying a connection. All |
| 8495 | + * but one field in the structure are to be considered read-only by an |
| 8496 | + * application. The only exception is the appstate field whos purpose |
| 8497 | + * is to let the application store application-specific state (e.g., |
| 8498 | + * file pointers) for the connection. The size of this field is |
| 8499 | + * configured in the "uipopt.h" header file. |
| 8500 | + */ |
| 8501 | +struct uip_conn { |
| 8502 | + u16_t ripaddr[2]; /**< The IP address of the remote host. */ |
| 8576 | 8503 | + |
| 8577 | | + IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP); |
| 8504 | + u16_t lport; /**< The local TCP port, in network byte order. */ |
| 8505 | + u16_t rport; /**< The local remote TCP port, in network byte |
| 8506 | + order. */ |
| 8507 | + |
| 8508 | + u8_t rcv_nxt[4]; /**< The sequence number that we expect to |
| 8509 | + receive next. */ |
| 8510 | + u8_t snd_nxt[4]; /**< The sequence number that was last sent by |
| 8511 | + us. */ |
| 8512 | + u16_t len; /**< Length of the data that was previously sent. */ |
| 8513 | + u16_t mss; /**< Current maximum segment size for the |
| 8514 | + connection. */ |
| 8515 | + u16_t initialmss; /**< Initial maximum segment size for the |
| 8516 | + connection. */ |
| 8517 | + u8_t sa; /**< Retransmission time-out calculation state |
| 8518 | + variable. */ |
| 8519 | + u8_t sv; /**< Retransmission time-out calculation state |
| 8520 | + variable. */ |
| 8521 | + u8_t rto; /**< Retransmission time-out. */ |
| 8522 | + u8_t tcpstateflags; /**< TCP state and flags. */ |
| 8523 | + u8_t timer; /**< The retransmission timer. */ |
| 8524 | + u8_t nrtx; /**< The number of retransmissions for the last |
| 8525 | + segment sent. */ |
| 8578 | 8526 | + |
| 8579 | | + uip_len += sizeof(struct uip_eth_hdr); |
| 8580 | | +} |
| 8581 | | +/*-----------------------------------------------------------------------------------*/ |
| 8527 | + /** The application state. */ |
| 8528 | + u8_t appstate[UIP_APPSTATE_SIZE]; |
| 8529 | +}; |
| 8582 | 8530 | + |
| 8583 | | +/** @} */ |
| 8584 | | +/** @} */ |
| 8585 | | +++ b/net/uip-0.9/uip_arp.h |
| 8586 | | @@ -0,0 +1,201 @@ |
| 8587 | | +/** |
| 8588 | | + * \addtogroup uip |
| 8589 | | + * @{ |
| 8590 | | + */ |
| 8591 | 8531 | + |
| 8532 | +/* Pointer to the current connection. */ |
| 8533 | +extern struct uip_conn *uip_conn; |
| 8534 | +/* The array containing all uIP connections. */ |
| 8535 | +extern struct uip_conn uip_conns[UIP_CONNS]; |
| 8592 | 8536 | +/** |
| 8593 | | + * \addtogroup uiparp |
| 8537 | + * \addtogroup uiparch |
| 8594 | 8538 | + * @{ |
| 8595 | 8539 | + */ |
| 8596 | | + |
| 8540 | + |
| 8597 | 8541 | +/** |
| 8598 | | + * \file |
| 8599 | | + * Macros and definitions for the ARP module. |
| 8600 | | + * \author Adam Dunkels <adam@dunkels.com> |
| 8542 | + * 4-byte array used for the 32-bit sequence number calculations. |
| 8601 | 8543 | + */ |
| 8602 | | + |
| 8544 | +extern volatile u8_t uip_acc32[4]; |
| 8603 | 8545 | + |
| 8604 | | +/* |
| 8605 | | + * Copyright (c) 2001-2003, Adam Dunkels. |
| 8606 | | + * All rights reserved. |
| 8607 | | + * |
| 8608 | | + * Redistribution and use in source and binary forms, with or without |
| 8609 | | + * modification, are permitted provided that the following conditions |
| 8610 | | + * are met: |
| 8611 | | + * 1. Redistributions of source code must retain the above copyright |
| 8612 | | + * notice, this list of conditions and the following disclaimer. |
| 8613 | | + * 2. Redistributions in binary form must reproduce the above copyright |
| 8614 | | + * notice, this list of conditions and the following disclaimer in the |
| 8615 | | + * documentation and/or other materials provided with the distribution. |
| 8616 | | + * 3. The name of the author may not be used to endorse or promote |
| 8617 | | + * products derived from this software without specific prior |
| 8618 | | + * written permission. |
| 8619 | | + * |
| 8620 | | + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS |
| 8621 | | + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 8622 | | + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 8623 | | + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
| 8624 | | + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 8625 | | + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
| 8626 | | + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 8627 | | + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| 8628 | | + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| 8629 | | + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 8630 | | + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 8631 | | + * |
| 8632 | | + * This file is part of the uIP TCP/IP stack. |
| 8633 | | + * |
| 8634 | | + * $Id: uip_arp.h,v 1.3.2.2 2003/10/06 15:10:22 adam Exp $ |
| 8635 | | + * |
| 8636 | | + */ |
| 8546 | +/** @} */ |
| 8637 | 8547 | + |
| 8638 | | +#ifndef __UIP_ARP_H__ |
| 8639 | | +#define __UIP_ARP_H__ |
| 8640 | 8548 | + |
| 8641 | | +#include "uip.h" |
| 8549 | +#if UIP_UDP |
| 8550 | +/** |
| 8551 | + * Representation of a uIP UDP connection. |
| 8552 | + */ |
| 8553 | +struct uip_udp_conn { |
| 8554 | + u16_t ripaddr[2]; /**< The IP address of the remote peer. */ |
| 8555 | + u16_t lport; /**< The local port number in network byte order. */ |
| 8556 | + u16_t rport; /**< The remote port number in network byte order. */ |
| 8557 | +}; |
| 8642 | 8558 | + |
| 8559 | +extern struct uip_udp_conn *uip_udp_conn; |
| 8560 | +extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; |
| 8561 | +#endif /* UIP_UDP */ |
| 8643 | 8562 | + |
| 8644 | 8563 | +/** |
| 8645 | | + * Representation of a 48-bit Ethernet address. |
| 8564 | + * The structure holding the TCP/IP statistics that are gathered if |
| 8565 | + * UIP_STATISTICS is set to 1. |
| 8566 | + * |
| 8646 | 8567 | + */ |
| 8647 | | +struct uip_eth_addr { |
| 8648 | | + u8_t addr[6]; |
| 8568 | +struct uip_stats { |
| 8569 | + struct { |
| 8570 | + uip_stats_t drop; /**< Number of dropped packets at the IP |
| 8571 | + layer. */ |
| 8572 | + uip_stats_t recv; /**< Number of received packets at the IP |
| 8573 | + layer. */ |
| 8574 | + uip_stats_t sent; /**< Number of sent packets at the IP |
| 8575 | + layer. */ |
| 8576 | + uip_stats_t vhlerr; /**< Number of packets dropped due to wrong |
| 8577 | + IP version or header length. */ |
| 8578 | + uip_stats_t hblenerr; /**< Number of packets dropped due to wrong |
| 8579 | + IP length, high byte. */ |
| 8580 | + uip_stats_t lblenerr; /**< Number of packets dropped due to wrong |
| 8581 | + IP length, low byte. */ |
| 8582 | + uip_stats_t fragerr; /**< Number of packets dropped since they |
| 8583 | + were IP fragments. */ |
| 8584 | + uip_stats_t chkerr; /**< Number of packets dropped due to IP |
| 8585 | + checksum errors. */ |
| 8586 | + uip_stats_t protoerr; /**< Number of packets dropped since they |
| 8587 | + were neither ICMP, UDP nor TCP. */ |
| 8588 | + } ip; /**< IP statistics. */ |
| 8589 | + struct { |
| 8590 | + uip_stats_t drop; /**< Number of dropped ICMP packets. */ |
| 8591 | + uip_stats_t recv; /**< Number of received ICMP packets. */ |
| 8592 | + uip_stats_t sent; /**< Number of sent ICMP packets. */ |
| 8593 | + uip_stats_t typeerr; /**< Number of ICMP packets with a wrong |
| 8594 | + type. */ |
| 8595 | + } icmp; /**< ICMP statistics. */ |
| 8596 | + struct { |
| 8597 | + uip_stats_t drop; /**< Number of dropped TCP segments. */ |
| 8598 | + uip_stats_t recv; /**< Number of recived TCP segments. */ |
| 8599 | + uip_stats_t sent; /**< Number of sent TCP segments. */ |
| 8600 | + uip_stats_t chkerr; /**< Number of TCP segments with a bad |
| 8601 | + checksum. */ |
| 8602 | + uip_stats_t ackerr; /**< Number of TCP segments with a bad ACK |
| 8603 | + number. */ |
| 8604 | + uip_stats_t rst; /**< Number of recevied TCP RST (reset) segments. */ |
| 8605 | + uip_stats_t rexmit; /**< Number of retransmitted TCP segments. */ |
| 8606 | + uip_stats_t syndrop; /**< Number of dropped SYNs due to too few |
| 8607 | + connections was avaliable. */ |
| 8608 | + uip_stats_t synrst; /**< Number of SYNs for closed ports, |
| 8609 | + triggering a RST. */ |
| 8610 | + } tcp; /**< TCP statistics. */ |
| 8649 | 8611 | +}; |
| 8650 | 8612 | + |
| 8651 | | +extern struct uip_eth_addr uip_ethaddr; |
| 8652 | | + |
| 8653 | 8613 | +/** |
| 8654 | | + * The Ethernet header. |
| 8614 | + * The uIP TCP/IP statistics. |
| 8615 | + * |
| 8616 | + * This is the variable in which the uIP TCP/IP statistics are gathered. |
| 8617 | + */ |
| 8618 | +extern struct uip_stats uip_stat; |
| 8619 | + |
| 8620 | + |
| 8621 | +/*-----------------------------------------------------------------------------------*/ |
| 8622 | +/* All the stuff below this point is internal to uIP and should not be |
| 8623 | + * used directly by an application or by a device driver. |
| 8624 | + */ |
| 8625 | +/*-----------------------------------------------------------------------------------*/ |
| 8626 | +/* u8_t uip_flags: |
| 8627 | + * |
| 8628 | + * When the application is called, uip_flags will contain the flags |
| 8629 | + * that are defined in this file. Please read below for more |
| 8630 | + * infomation. |
| 8655 | 8631 | + */ |
| 8656 | | +struct uip_eth_hdr { |
| 8657 | | + struct uip_eth_addr dest; |
| 8658 | | + struct uip_eth_addr src; |
| 8659 | | + u16_t type; |
| 8660 | | +}; |
| 8661 | | + |
| 8662 | | +#define UIP_ETHTYPE_ARP 0x0806 |
| 8663 | | +#define UIP_ETHTYPE_IP 0x0800 |
| 8664 | | +#define UIP_ETHTYPE_IP6 0x86dd |
| 8632 | +extern volatile u8_t uip_flags; |
| 8665 | 8633 | + |
| 8634 | +/* The following flags may be set in the global variable uip_flags |
| 8635 | + before calling the application callback. The UIP_ACKDATA and |
| 8636 | + UIP_NEWDATA flags may both be set at the same time, whereas the |
| 8637 | + others are mutualy exclusive. Note that these flags should *NOT* be |
| 8638 | + accessed directly, but through the uIP functions/macros. */ |
| 8666 | 8639 | + |
| 8667 | | +/* The uip_arp_init() function must be called before any of the other |
| 8668 | | + ARP functions. */ |
| 8669 | | +void uip_arp_init(void); |
| 8640 | +#define UIP_ACKDATA 1 /* Signifies that the outstanding data was |
| 8641 | + acked and the application should send |
| 8642 | + out new data instead of retransmitting |
| 8643 | + the last data. */ |
| 8644 | +#define UIP_NEWDATA 2 /* Flags the fact that the peer has sent |
| 8645 | + us new data. */ |
| 8646 | +#define UIP_REXMIT 4 /* Tells the application to retransmit the |
| 8647 | + data that was last sent. */ |
| 8648 | +#define UIP_POLL 8 /* Used for polling the application, to |
| 8649 | + check if the application has data that |
| 8650 | + it wants to send. */ |
| 8651 | +#define UIP_CLOSE 16 /* The remote host has closed the |
| 8652 | + connection, thus the connection has |
| 8653 | + gone away. Or the application signals |
| 8654 | + that it wants to close the |
| 8655 | + connection. */ |
| 8656 | +#define UIP_ABORT 32 /* The remote host has aborted the |
| 8657 | + connection, thus the connection has |
| 8658 | + gone away. Or the application signals |
| 8659 | + that it wants to abort the |
| 8660 | + connection. */ |
| 8661 | +#define UIP_CONNECTED 64 /* We have got a connection from a remote |
| 8662 | + host and have set up a new connection |
| 8663 | + for it, or an active connection has |
| 8664 | + been successfully established. */ |
| 8670 | 8665 | + |
| 8671 | | +/* The uip_arp_ipin() function should be called whenever an IP packet |
| 8672 | | + arrives from the Ethernet. This function refreshes the ARP table or |
| 8673 | | + inserts a new mapping if none exists. The function assumes that an |
| 8674 | | + IP packet with an Ethernet header is present in the uip_buf buffer |
| 8675 | | + and that the length of the packet is in the uip_len variable. */ |
| 8676 | | +void uip_arp_ipin(void); |
| 8666 | +#define UIP_TIMEDOUT 128 /* The connection has been aborted due to |
| 8667 | + too many retransmissions. */ |
| 8677 | 8668 | + |
| 8678 | | +/* The uip_arp_arpin() should be called when an ARP packet is received |
| 8679 | | + by the Ethernet driver. This function also assumes that the |
| 8680 | | + Ethernet frame is present in the uip_buf buffer. When the |
| 8681 | | + uip_arp_arpin() function returns, the contents of the uip_buf |
| 8682 | | + buffer should be sent out on the Ethernet if the uip_len variable |
| 8683 | | + is > 0. */ |
| 8684 | | +void uip_arp_arpin(void); |
| 8685 | 8669 | + |
| 8686 | | +/* The uip_arp_out() function should be called when an IP packet |
| 8687 | | + should be sent out on the Ethernet. This function creates an |
| 8688 | | + Ethernet header before the IP header in the uip_buf buffer. The |
| 8689 | | + Ethernet header will have the correct Ethernet MAC destination |
| 8690 | | + address filled in if an ARP table entry for the destination IP |
| 8691 | | + address (or the IP address of the default router) is present. If no |
| 8692 | | + such table entry is found, the IP packet is overwritten with an ARP |
| 8693 | | + request and we rely on TCP to retransmit the packet that was |
| 8694 | | + overwritten. In any case, the uip_len variable holds the length of |
| 8695 | | + the Ethernet frame that should be transmitted. */ |
| 8696 | | +void uip_arp_out(void); |
| 8670 | +/* uip_process(flag): |
| 8671 | + * |
| 8672 | + * The actual uIP function which does all the work. |
| 8673 | + */ |
| 8674 | +void uip_process(u8_t flag); |
| 8697 | 8675 | + |
| 8698 | | +/* The uip_arp_timer() function should be called every ten seconds. It |
| 8699 | | + is responsible for flushing old entries in the ARP table. */ |
| 8700 | | +void uip_arp_timer(void); |
| 8676 | +/* The following flags are passed as an argument to the uip_process() |
| 8677 | + function. They are used to distinguish between the two cases where |
| 8678 | + uip_process() is called. It can be called either because we have |
| 8679 | + incoming data that should be processed, or because the periodic |
| 8680 | + timer has fired. */ |
| 8701 | 8681 | + |
| 8702 | | +/** @} */ |
| 8682 | +#define UIP_DATA 1 /* Tells uIP that there is incoming data in |
| 8683 | + the uip_buf buffer. The length of the |
| 8684 | + data is stored in the global variable |
| 8685 | + uip_len. */ |
| 8686 | +#define UIP_TIMER 2 /* Tells uIP that the periodic timer has |
| 8687 | + fired. */ |
| 8688 | +#if UIP_UDP |
| 8689 | +#define UIP_UDP_TIMER 3 |
| 8690 | +#endif /* UIP_UDP */ |
| 8703 | 8691 | + |
| 8704 | | +/** |
| 8705 | | + * \addtogroup uipconffunc |
| 8706 | | + * @{ |
| 8707 | | + */ |
| 8692 | +/* The TCP states used in the uip_conn->tcpstateflags. */ |
| 8693 | +#define CLOSED 0 |
| 8694 | +#define SYN_RCVD 1 |
| 8695 | +#define SYN_SENT 2 |
| 8696 | +#define ESTABLISHED 3 |
| 8697 | +#define FIN_WAIT_1 4 |
| 8698 | +#define FIN_WAIT_2 5 |
| 8699 | +#define CLOSING 6 |
| 8700 | +#define TIME_WAIT 7 |
| 8701 | +#define LAST_ACK 8 |
| 8702 | +#define TS_MASK 15 |
| 8703 | + |
| 8704 | +#define UIP_STOPPED 16 |
| 8708 | 8705 | + |
| 8709 | | +/** |
| 8710 | | + * Set the default router's IP address. |
| 8711 | | + * |
| 8712 | | + * \param addr A pointer to a 4-byte array containing the IP address |
| 8713 | | + * of the default router. |
| 8714 | | + * |
| 8715 | | + * \hideinitializer |
| 8716 | | + */ |
| 8717 | | +#define uip_setdraddr(addr) do { uip_arp_draddr[0] = addr[0]; \ |
| 8718 | | + uip_arp_draddr[1] = addr[1]; } while(0) |
| 8706 | +#define UIP_TCPIP_HLEN 40 |
| 8719 | 8707 | + |
| 8720 | | +/** |
| 8721 | | + * Set the netmask. |
| 8722 | | + * |
| 8723 | | + * \param addr A pointer to a 4-byte array containing the IP address |
| 8724 | | + * of the netmask. |
| 8725 | | + * |
| 8726 | | + * \hideinitializer |
| 8727 | | + */ |
| 8728 | | +#define uip_setnetmask(addr) do { uip_arp_netmask[0] = addr[0]; \ |
| 8729 | | + uip_arp_netmask[1] = addr[1]; } while(0) |
| 8708 | +/* The TCP and IP headers. */ |
| 8709 | +typedef struct { |
| 8710 | + /* IP header. */ |
| 8711 | + u8_t vhl, |
| 8712 | + tos, |
| 8713 | + len[2], |
| 8714 | + ipid[2], |
| 8715 | + ipoffset[2], |
| 8716 | + ttl, |
| 8717 | + proto; |
| 8718 | + u16_t ipchksum; |
| 8719 | + u16_t srcipaddr[2], |
| 8720 | + destipaddr[2]; |
| 8721 | + |
| 8722 | + /* TCP header. */ |
| 8723 | + u16_t srcport, |
| 8724 | + destport; |
| 8725 | + u8_t seqno[4], |
| 8726 | + ackno[4], |
| 8727 | + tcpoffset, |
| 8728 | + flags, |
| 8729 | + wnd[2]; |
| 8730 | + u16_t tcpchksum; |
| 8731 | + u8_t urgp[2]; |
| 8732 | + u8_t optdata[4]; |
| 8733 | +} uip_tcpip_hdr; |
| 8730 | 8734 | + |
| 8735 | +/* The ICMP and IP headers. */ |
| 8736 | +typedef struct { |
| 8737 | + /* IP header. */ |
| 8738 | + u8_t vhl, |
| 8739 | + tos, |
| 8740 | + len[2], |
| 8741 | + ipid[2], |
| 8742 | + ipoffset[2], |
| 8743 | + ttl, |
| 8744 | + proto; |
| 8745 | + u16_t ipchksum; |
| 8746 | + u16_t srcipaddr[2], |
| 8747 | + destipaddr[2]; |
| 8748 | + /* ICMP (echo) header. */ |
| 8749 | + u8_t type, icode; |
| 8750 | + u16_t icmpchksum; |
| 8751 | + u16_t id, seqno; |
| 8752 | +} uip_icmpip_hdr; |
| 8731 | 8753 | + |
| 8732 | | +/** |
| 8733 | | + * Get the default router's IP address. |
| 8734 | | + * |
| 8735 | | + * \param addr A pointer to a 4-byte array that will be filled in with |
| 8736 | | + * the IP address of the default router. |
| 8737 | | + * |
| 8738 | | + * \hideinitializer |
| 8739 | | + */ |
| 8740 | | +#define uip_getdraddr(addr) do { addr[0] = uip_arp_draddr[0]; \ |
| 8741 | | + addr[1] = uip_arp_draddr[1]; } while(0) |
| 8742 | 8754 | + |
| 8743 | | +/** |
| 8744 | | + * Get the netmask. |
| 8745 | | + * |
| 8746 | | + * \param addr A pointer to a 4-byte array that will be filled in with |
| 8747 | | + * the value of the netmask. |
| 8748 | | + * |
| 8749 | | + * \hideinitializer |
| 8750 | | + */ |
| 8751 | | +#define uip_getnetmask(addr) do { addr[0] = uip_arp_netmask[0]; \ |
| 8752 | | + addr[1] = uip_arp_netmask[1]; } while(0) |
| 8755 | +/* The UDP and IP headers. */ |
| 8756 | +typedef struct { |
| 8757 | + /* IP header. */ |
| 8758 | + u8_t vhl, |
| 8759 | + tos, |
| 8760 | + len[2], |
| 8761 | + ipid[2], |
| 8762 | + ipoffset[2], |
| 8763 | + ttl, |
| 8764 | + proto; |
| 8765 | + u16_t ipchksum; |
| 8766 | + u16_t srcipaddr[2], |
| 8767 | + destipaddr[2]; |
| 8768 | + |
| 8769 | + /* UDP header. */ |
| 8770 | + u16_t srcport, |
| 8771 | + destport; |
| 8772 | + u16_t udplen; |
| 8773 | + u16_t udpchksum; |
| 8774 | +} uip_udpip_hdr; |
| 8753 | 8775 | + |
| 8776 | +#define UIP_PROTO_ICMP 1 |
| 8777 | +#define UIP_PROTO_TCP 6 |
| 8778 | +#define UIP_PROTO_UDP 17 |
| 8754 | 8779 | + |
| 8755 | | +/** |
| 8756 | | + * Specifiy the Ethernet MAC address. |
| 8757 | | + * |
| 8758 | | + * The ARP code needs to know the MAC address of the Ethernet card in |
| 8759 | | + * order to be able to respond to ARP queries and to generate working |
| 8760 | | + * Ethernet headers. |
| 8761 | | + * |
| 8762 | | + * \note This macro only specifies the Ethernet MAC address to the ARP |
| 8763 | | + * code. It cannot be used to change the MAC address of the Ethernet |
| 8764 | | + * card. |
| 8765 | | + * |
| 8766 | | + * \param eaddr A pointer to a struct uip_eth_addr containing the |
| 8767 | | + * Ethernet MAC address of the Ethernet card. |
| 8768 | | + * |
| 8769 | | + * \hideinitializer |
| 8770 | | + */ |
| 8771 | | +#define uip_setethaddr(eaddr) do {uip_ethaddr.addr[0] = eaddr.addr[0]; \ |
| 8772 | | + uip_ethaddr.addr[1] = eaddr.addr[1];\ |
| 8773 | | + uip_ethaddr.addr[2] = eaddr.addr[2];\ |
| 8774 | | + uip_ethaddr.addr[3] = eaddr.addr[3];\ |
| 8775 | | + uip_ethaddr.addr[4] = eaddr.addr[4];\ |
| 8776 | | + uip_ethaddr.addr[5] = eaddr.addr[5];} while(0) |
| 8780 | +#if UIP_FIXEDADDR |
| 8781 | +extern const u16_t uip_hostaddr[2]; |
| 8782 | +#else /* UIP_FIXEDADDR */ |
| 8783 | +extern u16_t uip_hostaddr[2]; |
| 8784 | +#endif /* UIP_FIXEDADDR */ |
| 8777 | 8785 | + |
| 8778 | | +/** @} */ |
| 8786 | +#endif /* __UIP_H__ */ |
| 8779 | 8787 | + |
| 8780 | | +/** |
| 8781 | | + * \internal Internal variables that are set using the macros |
| 8782 | | + * uip_setdraddr and uip_setnetmask. |
| 8783 | | + */ |
| 8784 | | +extern u16_t uip_arp_draddr[2], uip_arp_netmask[2]; |
| 8785 | | +#endif /* __UIP_ARP_H__ */ |
| 8786 | 8788 | + |
| 8789 | +/** @} */ |
| 8787 | 8790 | + |
| 8788 | 8791 | --- /dev/null |
| 8789 | 8792 | +++ b/net/uip-0.9/uipopt.h |