o: ActiveSupport::Cache::Entry :@compressedF: @value"ģ"½£
Modules/CommSerial/ETH01A/SW/STM32F107_ETH_uIP/Utilities/uip/httpd.d
1
Utilities/uip/httpd.o: Utilities/uip/httpd.c \
2
 Libraries/CMSIS/Core/CM3/stm32f10x.h Libraries/CMSIS/Core/CM3/core_cm3.h \
3
 /usr/bin/../lib/gcc/arm-none-eabi/4.7.4/include/stdint.h \
4
 /usr/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/include/stdint.h \
5
 /usr/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/include/_ansi.h \
6
 /usr/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/include/newlib.h \
7
 /usr/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/include/sys/config.h \
8
 /usr/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/include/machine/ieeefp.h \
9
 /usr/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/include/sys/features.h \
10
 Libraries/CMSIS/Core/CM3/system_stm32f10x.h \
11
 Project/Webserver_Demo_uIP/stm32f10x_conf.h \
12
 Libraries/STM32F10x_StdPeriph_Driver/inc/stm32f10x_adc.h \
13
 Libraries/STM32F10x_StdPeriph_Driver/inc/stm32f10x_exti.h \
14
 Libraries/STM32F10x_StdPeriph_Driver/inc/stm32f10x_flash.h \
15
 Libraries/STM32F10x_StdPeriph_Driver/inc/stm32f10x_gpio.h \
16
 Libraries/STM32F10x_StdPeriph_Driver/inc/stm32f10x_rcc.h \
17
 Libraries/STM32F10x_StdPeriph_Driver/inc/stm32f10x_spi.h \
18
 Libraries/STM32F10x_StdPeriph_Driver/inc/stm32f10x_usart.h \
19
 Libraries/STM32F10x_StdPeriph_Driver/inc/misc.h \
20
 Utilities/STM32_EVAL/stm32_eval.h Utilities/uip/uip.h \
21
 Utilities/uip/uipopt.h Utilities/uip/httpd.h Utilities/uip/fs.h \
22
 Utilities/uip/fsdata.h Utilities/uip/cgi.h
Modules/CommSerial/ETH01A/SW/STM32F107_ETH_uIP/Utilities/uip/memb.h
1
/**
2
 * \addtogroup exampleapps
3
 * @{
4
 */
5

  
6
/**
7
 * \file
8
 * Memory block allocation routines.
9
 * \author Adam Dunkels <adam@sics.se>
10
 *
11
 */
12

  
13
#ifndef __MEMB_H__
14
#define __MEMB_H__
15

  
16
/**
17
 * Declare a memory block.
18
 *
19
 * \param name The name of the memory block (later used with
20
 * memb_init(), memb_alloc() and memb_free()).
21
 *
22
 * \param size The size of each memory chunk, in bytes.
23
 *
24
 * \param num The total number of memory chunks in the block.
25
 *
26
 */
27
#define MEMB(name, size, num) \
28
        static char memb_mem[(size + 1) * num]; \
29
        static struct memb_blocks name = {size, num, memb_mem}
30

  
31
struct memb_blocks {
32
  unsigned short size;
33
  unsigned short num;
34
  char *mem;
35
};
36

  
37
void  memb_init(struct memb_blocks *m);
38
char *memb_alloc(struct memb_blocks *m);
39
char  memb_ref(struct memb_blocks *m, char *ptr);
40
char  memb_free(struct memb_blocks *m, char *ptr);
41

  
42

  
43
#endif /* __MEMB_H__ */
Modules/CommSerial/ETH01A/SW/STM32F107_ETH_uIP/Utilities/uip/httpd.h
1
/**
2
 * \addtogroup httpd
3
 * @{
4
 */
5

  
6
/**
7
 * \file
8
 * HTTP server header file.
9
 * \author Adam Dunkels <adam@dunkels.com>
10
 */
11

  
12
/*
13
 * Copyright (c) 2001, Adam Dunkels.
14
 * All rights reserved. 
15
 *
16
 * Redistribution and use in source and binary forms, with or without 
17
 * modification, are permitted provided that the following conditions 
18
 * are met: 
19
 * 1. Redistributions of source code must retain the above copyright 
20
 *    notice, this list of conditions and the following disclaimer. 
21
 * 2. Redistributions in binary form must reproduce the above copyright 
22
 *    notice, this list of conditions and the following disclaimer in the 
23
 *    documentation and/or other materials provided with the distribution. 
24
 * 3. The name of the author may not be used to endorse or promote
25
 *    products derived from this software without specific prior
26
 *    written permission.  
27
 *
28
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
29
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
30
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
32
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
34
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
36
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
37
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
38
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
39
 *
40
 * This file is part of the uIP TCP/IP stack.
41
 *
42
 * $Id: httpd.h,v 1.4.2.3 2003/10/06 22:56:44 adam Exp $
43
 *
44
 */
45

  
46
#ifndef __HTTPD_H__
47
#define __HTTPD_H__
48

  
49
void httpd_init(void);
50
void httpd_appcall(void);
51

  
52
/* UIP_APPCALL: the name of the application function. This function
53
   must return void and take no arguments (i.e., C type "void
54
   appfunc(void)"). */
55
#ifndef UIP_APPCALL
56
#define UIP_APPCALL     httpd_appcall
57
#endif
58

  
59
struct httpd_state {
60
  u8_t state; 
61
  u16_t count;
62
  char *dataptr;
63
  char *script;
64
};
65

  
66

  
67
/* UIP_APPSTATE_SIZE: The size of the application-specific state
68
   stored in the uip_conn structure. */
69
#ifndef UIP_APPSTATE_SIZE
70
#define UIP_APPSTATE_SIZE (sizeof(struct httpd_state))
71
#endif
72

  
73
#define FS_STATISTICS 1
74

  
75
extern struct httpd_state *hs;
76

  
77
#endif /* __HTTPD_H__ */
Modules/CommSerial/ETH01A/SW/STM32F107_ETH_uIP/Utilities/uip/tapdev.h
1
/*
2
 * Copyright (c) 2001, Adam Dunkels.
3
 * All rights reserved. 
4
 *
5
 * Redistribution and use in source and binary forms, with or without 
6
 * modification, are permitted provided that the following conditions 
7
 * are met: 
8
 * 1. Redistributions of source code must retain the above copyright 
9
 *    notice, this list of conditions and the following disclaimer. 
10
 * 2. Redistributions in binary form must reproduce the above copyright 
11
 *    notice, this list of conditions and the following disclaimer in the 
12
 *    documentation and/or other materials provided with the distribution. 
13
 * 3. The name of the author may not be used to endorse or promote
14
 *    products derived from this software without specific prior
15
 *    written permission.  
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
18
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
21
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
28
 *
29
 * This file is part of the uIP TCP/IP stack.
30
 *
31
 * $Id: tapdev.h,v 1.1.2.1 2003/10/04 22:54:17 adam Exp $
32
 *
33
 */
34

  
35
#ifndef __TAPDEV_H__
36
#define __TAPDEV_H__
37

  
38
void tapdev_init(void);
39
unsigned int tapdev_read(void);
40
void tapdev_send(void);
41

  
42
#endif /* __TAPDEV_H__ */
Modules/CommSerial/ETH01A/SW/STM32F107_ETH_uIP/Utilities/uip/uip_arch.c
1
/*
2
 * Copyright (c) 2001, Adam Dunkels.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 3. The name of the author may not be used to endorse or promote
14
 *    products derived from this software without specific prior
15
 *    written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
18
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
21
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * This file is part of the uIP TCP/IP stack.
30
 *
31
 * $Id: uip_arch.c,v 1.2.2.1 2003/10/04 22:54:17 adam Exp $
32
 *
33
 */
34

  
35

  
36
#include "uip.h"
37
#include "uip_arch.h"
38

  
39
#define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
40
#define IP_PROTO_TCP    6
41

  
42
/*-----------------------------------------------------------------------------------*/
43
void uip_add32(u8_t *op32, u16_t op16)
44
{
45

  
46
  uip_acc32[3] = op32[3] + (op16 & 0xff);
47
  uip_acc32[2] = op32[2] + (op16 >> 8);
48
  uip_acc32[1] = op32[1];
49
  uip_acc32[0] = op32[0];
50

  
51
  if(uip_acc32[2] < (op16 >> 8)) {
52
    ++uip_acc32[1];
53
    if(uip_acc32[1] == 0) {
54
      ++uip_acc32[0];
55
    }
56
  }
57

  
58

  
59
  if(uip_acc32[3] < (op16 & 0xff)) {
60
    ++uip_acc32[2];
61
    if(uip_acc32[2] == 0) {
62
      ++uip_acc32[1];
63
      if(uip_acc32[1] == 0) {
64
	++uip_acc32[0];
65
      }
66
    }
67
  }
68
}
69
/*-----------------------------------------------------------------------------------*/
70
u16_t uip_chksum(u16_t *sdata, u16_t len)
71
{
72
  u16_t acc;
73

  
74
  for (acc = 0; len > 1; len -= 2) {
75
    u16_t u = ((unsigned char *)sdata)[0] + (((unsigned char *)sdata)[1] << 8);
76
    if ((acc += u) < u) {
77
      /* Overflow, so we add the carry to acc (i.e., increase by
78
         one). */
79
      ++acc;
80
    }
81
    ++sdata;
82
  }
83

  
84
  /* add up any odd byte */
85
  if(len == 1) {
86
    acc += htons(((u16_t)(*(u8_t *)sdata)) << 8);
87
    if(acc < htons(((u16_t)(*(u8_t *)sdata)) << 8)) {
88
      ++acc;
89
    }
90
  }
91

  
92
  return acc;
93
}
94
/*-----------------------------------------------------------------------------------*/
95
u16_t uip_ipchksum(void)
96
{
97
  return uip_chksum((u16_t *)&uip_buf[UIP_LLH_LEN], 20);
98
}
99
/*-----------------------------------------------------------------------------------*/
100
u16_t uip_tcpchksum(void)
101
{
102
  u16_t hsum, sum;
103

  
104

  
105
  /* Compute the checksum of the TCP header. */
106
  hsum = uip_chksum((u16_t *)&uip_buf[20 + UIP_LLH_LEN], 20);
107

  
108
  /* Compute the checksum of the data in the TCP packet and add it to
109
     the TCP header checksum. */
110
  sum = uip_chksum((u16_t *)uip_appdata,
111
		   (u16_t)(((((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - 40)));
112

  
113
  if((sum += hsum) < hsum) {
114
    ++sum;
115
  }
116

  
117
  if((sum += BUF->srcipaddr[0]) < BUF->srcipaddr[0]) {
118
    ++sum;
119
  }
120
  if((sum += BUF->srcipaddr[1]) < BUF->srcipaddr[1]) {
121
    ++sum;
122
  }
123
  if((sum += BUF->destipaddr[0]) < BUF->destipaddr[0]) {
124
    ++sum;
125
  }
126
  if((sum += BUF->destipaddr[1]) < BUF->destipaddr[1]) {
127
    ++sum;
128
  }
129

  
130
  if((sum += (u16_t)htons((u16_t)IP_PROTO_TCP)) < (u16_t)htons((u16_t)IP_PROTO_TCP)) {
131
    ++sum;
132
  }
133

  
134
  hsum = (u16_t)htons((((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - 20);
135

  
136
  if((sum += hsum) < hsum) {
137
    ++sum;
138
  }
139

  
140
  return sum;
141
}
142

  
143

  
Modules/CommSerial/ETH01A/SW/STM32F107_ETH_uIP/Utilities/uip/uip_arch.d
1
Utilities/uip/uip_arch.o: Utilities/uip/uip_arch.c Utilities/uip/uip.h \
2
 Utilities/uip/uipopt.h Utilities/uip/httpd.h Utilities/uip/uip_arch.h
Modules/CommSerial/ETH01A/SW/STM32F107_ETH_uIP/Utilities/uip/uip.c
1
/**
2
 * \addtogroup uip
3
 * @{
4
 */
5

  
6
/**
7
 * \file
8
 * The uIP TCP/IP stack code.
9
 * \author Adam Dunkels <adam@dunkels.com>
10
 */
11

  
12
/*
13
 * Copyright (c) 2001-2003, Adam Dunkels.
14
 * All rights reserved.
15
 *
16
 * Redistribution and use in source and binary forms, with or without
17
 * modification, are permitted provided that the following conditions
18
 * are met:
19
 * 1. Redistributions of source code must retain the above copyright
20
 *    notice, this list of conditions and the following disclaimer.
21
 * 2. Redistributions in binary form must reproduce the above copyright
22
 *    notice, this list of conditions and the following disclaimer in the
23
 *    documentation and/or other materials provided with the distribution.
24
 * 3. The name of the author may not be used to endorse or promote
25
 *    products derived from this software without specific prior
26
 *    written permission.
27
 *
28
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
29
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
30
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
32
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
34
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
36
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
37
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
38
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39
 *
40
 * This file is part of the uIP TCP/IP stack.
41
 *
42
 * $Id: uip.c,v 1.62.2.10 2003/10/07 13:23:01 adam Exp $
43
 *
44
 */
45

  
46
/*
47
This is a small implementation of the IP and TCP protocols (as well as
48
some basic ICMP stuff). The implementation couples the IP, TCP and the
49
application layers very tightly. To keep the size of the compiled code
50
down, this code also features heavy usage of the goto statement.
51

  
52
The principle is that we have a small buffer, called the uip_buf, in
53
which the device driver puts an incoming packet. The TCP/IP stack
54
parses the headers in the packet, and calls upon the application. If
55
the remote host has sent data to the application, this data is present
56
in the uip_buf and the application read the data from there. It is up
57
to the application to put this data into a byte stream if needed. The
58
application will not be fed with data that is out of sequence.
59

  
60
If the application whishes to send data to the peer, it should put its
61
data into the uip_buf, 40 bytes from the start of the buffer. The
62
TCP/IP stack will calculate the checksums, and fill in the necessary
63
header fields and finally send the packet back to the peer.
64
*/
65

  
66
#include "uip.h"
67
#include "uipopt.h"
68
#include "uip_arch.h"
69
#include "string.h"
70

  
71
/*-----------------------------------------------------------------------------------*/
72
/* Variable definitions. */
73

  
74

  
75
/* 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 */
76
#if UIP_FIXEDADDR > 0
77
const u16_t uip_hostaddr[2] =
78
  {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1),
79
   HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)};
80
const u16_t uip_arp_draddr[2] =
81
  {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1),
82
   HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)};
83
const u16_t uip_arp_netmask[2] =
84
  {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1),
85
   HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)};
86
#else
87
u16_t uip_hostaddr[2];
88
u16_t uip_arp_draddr[2], uip_arp_netmask[2];
89
#endif /* UIP_FIXEDADDR */
90

  
91
u8_t uip_buf[UIP_BUFSIZE+2];   /* The packet buffer that contains
92
				incoming packets. */
93
volatile u8_t *uip_appdata;  /* The uip_appdata pointer points to
94
				application data. */
95
volatile u8_t *uip_sappdata;  /* The uip_appdata pointer points to the
96
				 application data which is to be sent. */
97
#if UIP_URGDATA > 0
98
volatile u8_t *uip_urgdata;  /* The uip_urgdata pointer points to
99
				urgent data (out-of-band data), if
100
				present. */
101
u8_t uip_urglen, uip_surglen;
102
#endif /* UIP_URGDATA > 0 */
103

  
104
u16_t uip_len, uip_slen;
105
                             /* The uip_len is either 8 or 16 bits,
106
				depending on the maximum packet
107
				size. */
108

  
109
volatile u8_t uip_flags;     /* The uip_flags variable is used for
110
				communication between the TCP/IP stack
111
				and the application program. */
112
struct uip_conn *uip_conn;   /* uip_conn always points to the current
113
				connection. */
114

  
115
struct uip_conn uip_conns[UIP_CONNS];
116
                             /* The uip_conns array holds all TCP
117
				connections. */
118
u16_t uip_listenports[UIP_LISTENPORTS];
119
                             /* The uip_listenports list all currently
120
				listning ports. */
121
#if UIP_UDP
122
struct uip_udp_conn *uip_udp_conn;
123
struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
124
#endif /* UIP_UDP */
125

  
126

  
127
static u16_t ipid;           /* Ths ipid variable is an increasing
128
				number that is used for the IP ID
129
				field. */
130

  
131
static u8_t iss[4];          /* The iss variable is used for the TCP
132
				initial sequence number. */
133

  
134
#if UIP_ACTIVE_OPEN
135
static u16_t lastport;       /* Keeps track of the last port used for
136
				a new connection. */
137
#endif /* UIP_ACTIVE_OPEN */
138

  
139
/* Temporary variables. */
140
volatile u8_t uip_acc32[4];
141
static u8_t c, opt;
142
static u16_t tmp16;
143

  
144
/* Structures and definitions. */
145
#define TCP_FIN 0x01
146
#define TCP_SYN 0x02
147
#define TCP_RST 0x04
148
#define TCP_PSH 0x08
149
#define TCP_ACK 0x10
150
#define TCP_URG 0x20
151
#define TCP_CTL 0x3f
152

  
153
#define ICMP_ECHO_REPLY 0
154
#define ICMP_ECHO       8
155

  
156
/* Macros. */
157
#define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
158
#define FBUF ((uip_tcpip_hdr *)&uip_reassbuf[0])
159
#define ICMPBUF ((uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN])
160
#define UDPBUF ((uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])
161

  
162
#if UIP_STATISTICS == 1
163
struct uip_stats uip_stat;
164
#define UIP_STAT(s) s
165
#else
166
#define UIP_STAT(s)
167
#endif /* UIP_STATISTICS == 1 */
168

  
169
#if UIP_LOGGING == 1
170
#include <stdio.h>
171
void uip_log(char *msg);
172
#define UIP_LOG(m) uip_log(m)
173
#else
174
#define UIP_LOG(m)
175
#endif /* UIP_LOGGING == 1 */
176

  
177
/*-----------------------------------------------------------------------------------*/
178
void uip_init(void)
179
{
180
  for(c = 0; c < UIP_LISTENPORTS; ++c) {
181
    uip_listenports[c] = 0;
182
  }
183
  for(c = 0; c < UIP_CONNS; ++c) {
184
    uip_conns[c].tcpstateflags = CLOSED;
185
  }
186
#if UIP_ACTIVE_OPEN
187
  lastport = 1024;
188
#endif /* UIP_ACTIVE_OPEN */
189

  
190
#if UIP_UDP
191
  for(c = 0; c < UIP_UDP_CONNS; ++c) {
192
    uip_udp_conns[c].lport = 0;
193
  }
194
#endif /* UIP_UDP */
195

  
196

  
197
  /* IPv4 initialization. */
198
#if UIP_FIXEDADDR == 0
199
  uip_hostaddr[0] = uip_hostaddr[1] = 0;
200
#endif /* UIP_FIXEDADDR */
201

  
202
}
203
/*-----------------------------------------------------------------------------------*/
204
#if UIP_ACTIVE_OPEN
205
struct uip_conn * uip_connect(u16_t *ripaddr, u16_t rport)
206
{
207
  register struct uip_conn *conn, *cconn;
208

  
209
  /* Find an unused local port. */
210
 again:
211
  ++lastport;
212

  
213
  if(lastport >= 32000) {
214
    lastport = 4096;
215
  }
216

  
217
  /* Check if this port is already in use, and if so try to find
218
     another one. */
219
  for(c = 0; c < UIP_CONNS; ++c) {
220
    conn = &uip_conns[c];
221
    if(conn->tcpstateflags != CLOSED &&
222
       conn->lport == htons(lastport)) {
223
      goto again;
224
    }
225
  }
226

  
227

  
228
  conn = 0;
229
  for(c = 0; c < UIP_CONNS; ++c) {
230
    cconn = &uip_conns[c];
231
    if(cconn->tcpstateflags == CLOSED) {
232
      conn = cconn;
233
      break;
234
    }
235
    if(cconn->tcpstateflags == TIME_WAIT) {
236
      if(conn == 0 ||
237
	 cconn->timer > uip_conn->timer) {
238
	conn = cconn;
239
      }
240
    }
241
  }
242

  
243
  if(conn == 0) {
244
    return 0;
245
  }
246

  
247
  conn->tcpstateflags = SYN_SENT;
248

  
249
  conn->snd_nxt[0] = iss[0];
250
  conn->snd_nxt[1] = iss[1];
251
  conn->snd_nxt[2] = iss[2];
252
  conn->snd_nxt[3] = iss[3];
253

  
254
  conn->initialmss = conn->mss = UIP_TCP_MSS;
255

  
256
  conn->len = 1;   /* TCP length of the SYN is one. */
257
  conn->nrtx = 0;
258
  conn->timer = 1; /* Send the SYN next time around. */
259
  conn->rto = UIP_RTO;
260
  conn->sa = 0;
261
  conn->sv = 16;
262
  conn->lport = htons(lastport);
263
  conn->rport = rport;
264
  conn->ripaddr[0] = ripaddr[0];
265
  conn->ripaddr[1] = ripaddr[1];
266

  
267
  return conn;
268
}
269
#endif /* UIP_ACTIVE_OPEN */
270
/*-----------------------------------------------------------------------------------*/
271
#if UIP_UDP
272
struct uip_udp_conn *
273
uip_udp_new(u16_t *ripaddr, u16_t rport)
274
{
275
  register struct uip_udp_conn *conn;
276

  
277
  /* Find an unused local port. */
278
 again:
279
  ++lastport;
280

  
281
  if(lastport >= 32000) {
282
    lastport = 4096;
283
  }
284

  
285
  for(c = 0; c < UIP_UDP_CONNS; ++c) {
286
    if(uip_udp_conns[c].lport == lastport) {
287
      goto again;
288
    }
289
  }
290

  
291

  
292
  conn = 0;
293
  for(c = 0; c < UIP_UDP_CONNS; ++c) {
294
    if(uip_udp_conns[c].lport == 0) {
295
      conn = &uip_udp_conns[c];
296
      break;
297
    }
298
  }
299

  
300
  if(conn == 0) {
301
    return 0;
302
  }
303

  
304
  conn->lport = HTONS(lastport);
305
  conn->rport = HTONS(rport);
306
  conn->ripaddr[0] = ripaddr[0];
307
  conn->ripaddr[1] = ripaddr[1];
308

  
309
  return conn;
310
}
311
#endif /* UIP_UDP */
312
/*-----------------------------------------------------------------------------------*/
313
void
314
uip_unlisten(u16_t port)
315
{
316
  for(c = 0; c < UIP_LISTENPORTS; ++c) {
317
    if(uip_listenports[c] == port) {
318
      uip_listenports[c] = 0;
319
      return;
320
    }
321
  }
322
}
323
/*-----------------------------------------------------------------------------------*/
324
void
325
uip_listen(u16_t port)
326
{
327
  for(c = 0; c < UIP_LISTENPORTS; ++c) {
328
    if(uip_listenports[c] == 0) {
329
      uip_listenports[c] = port;
330
      return;
331
    }
332
  }
333
}
334
/*-----------------------------------------------------------------------------------*/
335
/* XXX: IP fragment reassembly: not well-tested. */
336

  
337
#if UIP_REASSEMBLY
338
#define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN)
339
static u8_t uip_reassbuf[UIP_REASS_BUFSIZE];
340
static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)];
341
static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f,
342
				    0x0f, 0x07, 0x03, 0x01};
343
static u16_t uip_reasslen;
344
static u8_t uip_reassflags;
345
#define UIP_REASS_FLAG_LASTFRAG 0x01
346
static u8_t uip_reasstmr;
347

  
348
#define IP_HLEN 20
349
#define IP_MF   0x20
350

  
351
static u8_t
352
uip_reass(void)
353
{
354
  u16_t offset, len;
355
  u16_t i;
356

  
357
  /* If ip_reasstmr is zero, no packet is present in the buffer, so we
358
     write the IP header of the fragment into the reassembly
359
     buffer. The timer is updated with the maximum age. */
360
  if(uip_reasstmr == 0) {
361
    memcpy(uip_reassbuf, &BUF->vhl, IP_HLEN);
362
    uip_reasstmr = UIP_REASS_MAXAGE;
363
    uip_reassflags = 0;
364
    /* Clear the bitmap. */
365
    memset(uip_reassbitmap, sizeof(uip_reassbitmap), 0);
366
  }
367

  
368
  /* Check if the incoming fragment matches the one currently present
369
     in the reasembly buffer. If so, we proceed with copying the
370
     fragment into the buffer. */
371
  if(BUF->srcipaddr[0] == FBUF->srcipaddr[0] &&
372
     BUF->srcipaddr[1] == FBUF->srcipaddr[1] &&
373
     BUF->destipaddr[0] == FBUF->destipaddr[0] &&
374
     BUF->destipaddr[1] == FBUF->destipaddr[1] &&
375
     BUF->ipid[0] == FBUF->ipid[0] &&
376
     BUF->ipid[1] == FBUF->ipid[1]) {
377

  
378
    len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4;
379
    offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8;
380

  
381
    /* If the offset or the offset + fragment length overflows the
382
       reassembly buffer, we discard the entire packet. */
383
    if(offset > UIP_REASS_BUFSIZE ||
384
       offset + len > UIP_REASS_BUFSIZE) {
385
      uip_reasstmr = 0;
386
      goto nullreturn;
387
    }
388

  
389
    /* Copy the fragment into the reassembly buffer, at the right
390
       offset. */
391
    memcpy(&uip_reassbuf[IP_HLEN + offset],
392
	   (char *)BUF + (int)((BUF->vhl & 0x0f) * 4),
393
	   len);
394

  
395
    /* Update the bitmap. */
396
    if(offset / (8 * 8) == (offset + len) / (8 * 8)) {
397
      /* If the two endpoints are in the same byte, we only update
398
	 that byte. */
399
	
400
      uip_reassbitmap[offset / (8 * 8)] |=
401
	     bitmap_bits[(offset / 8 ) & 7] &
402
	     ~bitmap_bits[((offset + len) / 8 ) & 7];
403
    } else {
404
      /* If the two endpoints are in different bytes, we update the
405
	 bytes in the endpoints and fill the stuff inbetween with
406
	 0xff. */
407
      uip_reassbitmap[offset / (8 * 8)] |=
408
	bitmap_bits[(offset / 8 ) & 7];
409
      for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) {
410
	uip_reassbitmap[i] = 0xff;
411
      }
412
      uip_reassbitmap[(offset + len) / (8 * 8)] |=
413
	~bitmap_bits[((offset + len) / 8 ) & 7];
414
    }
415

  
416
    /* If this fragment has the More Fragments flag set to zero, we
417
       know that this is the last fragment, so we can calculate the
418
       size of the entire packet. We also set the
419
       IP_REASS_FLAG_LASTFRAG flag to indicate that we have received
420
       the final fragment. */
421

  
422
    if((BUF->ipoffset[0] & IP_MF) == 0) {
423
      uip_reassflags |= UIP_REASS_FLAG_LASTFRAG;
424
      uip_reasslen = offset + len;
425
    }
426

  
427
    /* Finally, we check if we have a full packet in the buffer. We do
428
       this by checking if we have the last fragment and if all bits
429
       in the bitmap are set. */
430
    if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) {
431
      /* Check all bytes up to and including all but the last byte in
432
	 the bitmap. */
433
      for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) {
434
	if(uip_reassbitmap[i] != 0xff) {
435
	  goto nullreturn;
436
	}
437
      }
438
      /* Check the last byte in the bitmap. It should contain just the
439
	 right amount of bits. */
440
      if(uip_reassbitmap[uip_reasslen / (8 * 8)] !=
441
	 (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) {
442
	goto nullreturn;
443
      }
444

  
445
      /* If we have come this far, we have a full packet in the
446
	 buffer, so we allocate a pbuf and copy the packet into it. We
447
	 also reset the timer. */
448
      uip_reasstmr = 0;
449
      memcpy(BUF, FBUF, uip_reasslen);
450

  
451
      /* Pretend to be a "normal" (i.e., not fragmented) IP packet
452
	 from now on. */
453
      BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
454
      BUF->len[0] = uip_reasslen >> 8;
455
      BUF->len[1] = uip_reasslen & 0xff;
456
      BUF->ipchksum = 0;
457
      BUF->ipchksum = ~(uip_ipchksum());
458

  
459
      return uip_reasslen;
460
    }
461
  }
462

  
463
 nullreturn:
464
  return 0;
465
}
466
#endif /* UIP_REASSEMBL */
467
/*-----------------------------------------------------------------------------------*/
468
static void
469
uip_add_rcv_nxt(u16_t n)
470
{
471
  uip_add32(uip_conn->rcv_nxt, n);
472
  uip_conn->rcv_nxt[0] = uip_acc32[0];
473
  uip_conn->rcv_nxt[1] = uip_acc32[1];
474
  uip_conn->rcv_nxt[2] = uip_acc32[2];
475
  uip_conn->rcv_nxt[3] = uip_acc32[3];
476
}
477
/*-----------------------------------------------------------------------------------*/
478
void
479
uip_process(u8_t flag)
480
{
481
  register struct uip_conn *uip_connr = uip_conn;
482

  
483
  uip_appdata = &uip_buf[40 + UIP_LLH_LEN];
484

  
485

  
486
  /* Check if we were invoked because of the perodic timer fireing. */
487
  if(flag == UIP_TIMER) {
488
#if UIP_REASSEMBLY
489
    if(uip_reasstmr != 0) {
490
      --uip_reasstmr;
491
    }   
492
#endif /* UIP_REASSEMBLY */
493
    /* Increase the initial sequence number. */
494
    if(++iss[3] == 0) {
495
      if(++iss[2] == 0) {
496
	if(++iss[1] == 0) {
497
	  ++iss[0];
498
	}
499
      }
500
    }
501
    uip_len = 0;
502
    if(uip_connr->tcpstateflags == TIME_WAIT ||
503
       uip_connr->tcpstateflags == FIN_WAIT_2) {
504
      ++(uip_connr->timer);
505
      if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) {
506
	uip_connr->tcpstateflags = CLOSED;
507
      }
508
    } else if(uip_connr->tcpstateflags != CLOSED) {
509
      /* If the connection has outstanding data, we increase the
510
	 connection's timer and see if it has reached the RTO value
511
	 in which case we retransmit. */
512
      if(uip_outstanding(uip_connr)) {
513
	if(uip_connr->timer-- == 0) {
514
	  if(uip_connr->nrtx == UIP_MAXRTX ||
515
	     ((uip_connr->tcpstateflags == SYN_SENT ||
516
	       uip_connr->tcpstateflags == SYN_RCVD) &&
517
	      uip_connr->nrtx == UIP_MAXSYNRTX)) {
518
	    uip_connr->tcpstateflags = CLOSED;
519

  
520
	    /* We call UIP_APPCALL() with uip_flags set to
521
	       UIP_TIMEDOUT to inform the application that the
522
	       connection has timed out. */
523
	    uip_flags = UIP_TIMEDOUT;
524
	    UIP_APPCALL();
525

  
526
	    /* We also send a reset packet to the remote host. */
527
	    BUF->flags = TCP_RST | TCP_ACK;
528
	    goto tcp_send_nodata;
529
	  }
530

  
531
	  /* Exponential backoff. */
532
	  uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4?
533
					 4:
534
					 uip_connr->nrtx);
535
	  ++(uip_connr->nrtx);
536
	
537
	  /* Ok, so we need to retransmit. We do this differently
538
	     depending on which state we are in. In ESTABLISHED, we
539
	     call upon the application so that it may prepare the
540
	     data for the retransmit. In SYN_RCVD, we resend the
541
	     SYNACK that we sent earlier and in LAST_ACK we have to
542
	     retransmit our FINACK. */
543
	  UIP_STAT(++uip_stat.tcp.rexmit);
544
	  switch(uip_connr->tcpstateflags & TS_MASK) {
545
	  case SYN_RCVD:
546
	    /* In the SYN_RCVD state, we should retransmit our
547
               SYNACK. */
548
	    goto tcp_send_synack;
549
	
550
#if UIP_ACTIVE_OPEN
551
	  case SYN_SENT:
552
	    /* In the SYN_SENT state, we retransmit out SYN. */
553
	    BUF->flags = 0;
554
	    goto tcp_send_syn;
555
#endif /* UIP_ACTIVE_OPEN */
556
	
557
	  case ESTABLISHED:
558
	    /* In the ESTABLISHED state, we call upon the application
559
               to do the actual retransmit after which we jump into
560
               the code for sending out the packet (the apprexmit
561
               label). */
562
	    uip_len = 0;
563
	    uip_slen = 0;
564
	    uip_flags = UIP_REXMIT;
565
	    UIP_APPCALL();
566
	    goto apprexmit;
567
	
568
	  case FIN_WAIT_1:
569
	  case CLOSING:
570
	  case LAST_ACK:
571
	    /* In all these states we should retransmit a FINACK. */
572
	    goto tcp_send_finack;
573
	
574
	  }
575
	}
576
      } else if((uip_connr->tcpstateflags & TS_MASK) == ESTABLISHED) {
577
	/* If there was no need for a retransmission, we poll the
578
           application for new data. */
579
	uip_len = 0;
580
	uip_slen = 0;
581
	uip_flags = UIP_POLL;
582
	UIP_APPCALL();
583
	goto appsend;
584
      }
585
    }
586
    goto drop;
587
  }
588
#if UIP_UDP
589
  if(flag == UIP_UDP_TIMER) {
590
    if(uip_udp_conn->lport != 0) {
591
      uip_appdata = &uip_buf[UIP_LLH_LEN + 28];
592
      uip_len = uip_slen = 0;
593
      uip_flags = UIP_POLL;
594
      UIP_UDP_APPCALL();
595
      goto udp_send;
596
    } else {
597
      goto drop;
598
    }
599
  }
600
#endif
601

  
602
  /* This is where the input processing starts. */
603
  UIP_STAT(++uip_stat.ip.recv);
604

  
605

  
606
  /* Start of IPv4 input header processing code. */
607

  
608
  /* Check validity of the IP header. */
609
  if(BUF->vhl != 0x45)  { /* IP version and header length. */
610
    UIP_STAT(++uip_stat.ip.drop);
611
    UIP_STAT(++uip_stat.ip.vhlerr);
612
    UIP_LOG("ip: invalid version or header length.");
613
    goto drop;
614
  }
615

  
616
  /* Check the size of the packet. If the size reported to us in
617
     uip_len doesn't match the size reported in the IP header, there
618
     has been a transmission error and we drop the packet. */
619

  
620
  if(BUF->len[0] != (uip_len >> 8)) { /* IP length, high byte. */
621
    uip_len = (uip_len & 0xff) | (BUF->len[0] << 8);
622
  }
623
  if(BUF->len[1] != (uip_len & 0xff)) { /* IP length, low byte. */
624
    uip_len = (uip_len & 0xff00) | BUF->len[1];
625
  }
626

  
627
  /* Check the fragment flag. */
628
  if((BUF->ipoffset[0] & 0x3f) != 0 ||
629
     BUF->ipoffset[1] != 0) {
630
#if UIP_REASSEMBLY
631
    uip_len = uip_reass();
632
    if(uip_len == 0) {
633
      goto drop;
634
    }
635
#else
636
    UIP_STAT(++uip_stat.ip.drop);
637
    UIP_STAT(++uip_stat.ip.fragerr);
638
    UIP_LOG("ip: fragment dropped.");
639
    goto drop;
640
#endif /* UIP_REASSEMBLY */
641
  }
642

  
643
  /* If we are configured to use ping IP address configuration and
644
     hasn't been assigned an IP address yet, we accept all ICMP
645
     packets. */
646
#if UIP_PINGADDRCONF
647
  if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) {
648
    if(BUF->proto == UIP_PROTO_ICMP) {
649
      UIP_LOG("ip: possible ping config packet received.");
650
      goto icmp_input;
651
    } else {
652
      UIP_LOG("ip: packet dropped since no address assigned.");
653
      goto drop;
654
    }
655
  }
656
#endif /* UIP_PINGADDRCONF */
657

  
658
  /* Check if the packet is destined for our IP address. */
659
  if(BUF->destipaddr[0] != uip_hostaddr[0]) {
660
    UIP_STAT(++uip_stat.ip.drop);
661
    UIP_LOG("ip: packet not for us.");
662
    goto drop;
663
  }
664
  if(BUF->destipaddr[1] != uip_hostaddr[1]) {
665
    UIP_STAT(++uip_stat.ip.drop);
666
    UIP_LOG("ip: packet not for us.");
667
    goto drop;
668
  }
669

  
670
#if 0
671
  // IP checksum is wrong through Netgear DSL router
672
  if (uip_ipchksum() != 0xffff) { /* Compute and check the IP header
673
				    checksum. */
674
    UIP_STAT(++uip_stat.ip.drop);
675
    UIP_STAT(++uip_stat.ip.chkerr);
676
    UIP_LOG("ip: bad checksum.");
677
    goto drop;
678
  }
679
#endif
680

  
681
  if(BUF->proto == UIP_PROTO_TCP)  /* Check for TCP packet. If so, jump
682
                                     to the tcp_input label. */
683
    goto tcp_input;
684

  
685
#if UIP_UDP
686
  if(BUF->proto == UIP_PROTO_UDP)
687
    goto udp_input;
688
#endif /* UIP_UDP */
689

  
690
  if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from
691
					here. */
692
    UIP_STAT(++uip_stat.ip.drop);
693
    UIP_STAT(++uip_stat.ip.protoerr);
694
    UIP_LOG("ip: neither tcp nor icmp.");
695
    goto drop;
696
  }
697

  
698
#if UIP_PINGADDRCONF
699
 icmp_input:
700
#endif
701
  UIP_STAT(++uip_stat.icmp.recv);
702

  
703
  /* ICMP echo (i.e., ping) processing. This is simple, we only change
704
     the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP
705
     checksum before we return the packet. */
706
  if(ICMPBUF->type != ICMP_ECHO) {
707
    UIP_STAT(++uip_stat.icmp.drop);
708
    UIP_STAT(++uip_stat.icmp.typeerr);
709
    UIP_LOG("icmp: not icmp echo.");
710
    goto drop;
711
  }
712

  
713
  /* If we are configured to use ping IP address assignment, we use
714
     the destination IP address of this ping packet and assign it to
715
     ourself. */
716
#if UIP_PINGADDRCONF
717
  if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) {
718
    uip_hostaddr[0] = BUF->destipaddr[0];
719
    uip_hostaddr[1] = BUF->destipaddr[1];
720
  }
721
#endif /* UIP_PINGADDRCONF */
722

  
723
  ICMPBUF->type = ICMP_ECHO_REPLY;
724

  
725
  if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) {
726
    ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1;
727
  } else {
728
    ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8);
729
  }
730

  
731
  /* Swap IP addresses. */
732
  tmp16 = BUF->destipaddr[0];
733
  BUF->destipaddr[0] = BUF->srcipaddr[0];
734
  BUF->srcipaddr[0] = tmp16;
735
  tmp16 = BUF->destipaddr[1];
736
  BUF->destipaddr[1] = BUF->srcipaddr[1];
737
  BUF->srcipaddr[1] = tmp16;
738

  
739
  UIP_STAT(++uip_stat.icmp.sent);
740
  goto send;
741

  
742
  /* End of IPv4 input header processing code. */
743

  
744

  
745
#if UIP_UDP
746
  /* UDP input processing. */
747
 udp_input:
748
  /* UDP processing is really just a hack. We don't do anything to the
749
     UDP/IP headers, but let the UDP application do all the hard
750
     work. If the application sets uip_slen, it has a packet to
751
     send. */
752
#if UIP_UDP_CHECKSUMS
753
  if(uip_udpchksum() != 0xffff) {
754
    UIP_STAT(++uip_stat.udp.drop);
755
    UIP_STAT(++uip_stat.udp.chkerr);
756
    UIP_LOG("udp: bad checksum.");
757
    goto drop;
758
  }
759
#endif /* UIP_UDP_CHECKSUMS */
760

  
761
  /* Demultiplex this UDP packet between the UDP "connections". */
762
  for(uip_udp_conn = &uip_udp_conns[0];
763
      uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS];
764
      ++uip_udp_conn) {
765
    if(uip_udp_conn->lport != 0 &&
766
       UDPBUF->destport == uip_udp_conn->lport &&
767
       (uip_udp_conn->rport == 0 ||
768
        UDPBUF->srcport == uip_udp_conn->rport) &&
769
       BUF->srcipaddr[0] == uip_udp_conn->ripaddr[0] &&
770
       BUF->srcipaddr[1] == uip_udp_conn->ripaddr[1]) {
771
      goto udp_found;
772
    }
773
  }
774
  goto drop;
775

  
776
 udp_found:
777
  uip_len = uip_len - 28;
778
  uip_appdata = &uip_buf[UIP_LLH_LEN + 28];
779
  uip_flags = UIP_NEWDATA;
780
  uip_slen = 0;
781
  UIP_UDP_APPCALL();
782
 udp_send:
783
  if(uip_slen == 0) {
784
    goto drop;
785
  }
786
  uip_len = uip_slen + 28;
787

  
788
  BUF->len[0] = (uip_len >> 8);
789
  BUF->len[1] = (uip_len & 0xff);
790

  
791
  BUF->proto = UIP_PROTO_UDP;
792

  
793
  UDPBUF->udplen = HTONS(uip_slen + 8);
794
  UDPBUF->udpchksum = 0;
795
#if UIP_UDP_CHECKSUMS
796
  /* Calculate UDP checksum. */
797
  UDPBUF->udpchksum = ~(uip_udpchksum());
798
  if(UDPBUF->udpchksum == 0) {
799
    UDPBUF->udpchksum = 0xffff;
800
  }
801
#endif /* UIP_UDP_CHECKSUMS */
802

  
803
  BUF->srcport  = uip_udp_conn->lport;
804
  BUF->destport = uip_udp_conn->rport;
805

  
806
  BUF->srcipaddr[0] = uip_hostaddr[0];
807
  BUF->srcipaddr[1] = uip_hostaddr[1];
808
  BUF->destipaddr[0] = uip_udp_conn->ripaddr[0];
809
  BUF->destipaddr[1] = uip_udp_conn->ripaddr[1];
810

  
811
  uip_appdata = &uip_buf[UIP_LLH_LEN + 40];
812
  goto ip_send_nolen;
813
#endif /* UIP_UDP */
814

  
815
  /* TCP input processing. */
816
 tcp_input:
817
  UIP_STAT(++uip_stat.tcp.recv);
818

  
819
  /* Start of TCP input header processing code. */
820

  
821
#if 1  // FIXME
822
  if(uip_tcpchksum() != 0xffff) {   /* Compute and check the TCP
823
				       checksum. */
824
    UIP_STAT(++uip_stat.tcp.drop);
825
    UIP_STAT(++uip_stat.tcp.chkerr);
826
    UIP_LOG("tcp: bad checksum.");
827
    goto drop;
828
  }
829
#endif
830

  
831
  /* Demultiplex this segment. */
832
  /* First check any active connections. */
833
  for(uip_connr = &uip_conns[0]; uip_connr < &uip_conns[UIP_CONNS]; ++uip_connr) {
834
    if(uip_connr->tcpstateflags != CLOSED &&
835
       BUF->destport == uip_connr->lport &&
836
       BUF->srcport == uip_connr->rport &&
837
       BUF->srcipaddr[0] == uip_connr->ripaddr[0] &&
838
       BUF->srcipaddr[1] == uip_connr->ripaddr[1]) {
839
      goto found;
840
    }
841
  }
842

  
843
  /* If we didn't find and active connection that expected the packet,
844
     either this packet is an old duplicate, or this is a SYN packet
845
     destined for a connection in LISTEN. If the SYN flag isn't set,
846
     it is an old packet and we send a RST. */
847
  if((BUF->flags & TCP_CTL) != TCP_SYN)
848
    goto reset;
849

  
850
  tmp16 = BUF->destport;
851
  /* Next, check listening connections. */
852
  for(c = 0; c < UIP_LISTENPORTS; ++c) {
853
    if(tmp16 == uip_listenports[c])
854
      goto found_listen;
855
  }
856

  
857
  /* No matching connection found, so we send a RST packet. */
858
  UIP_STAT(++uip_stat.tcp.synrst);
859
 reset:
860

  
861
  /* We do not send resets in response to resets. */
862
  if(BUF->flags & TCP_RST)
863
    goto drop;
864

  
865
  UIP_STAT(++uip_stat.tcp.rst);
866

  
867
  BUF->flags = TCP_RST | TCP_ACK;
868
  uip_len = 40;
869
  BUF->tcpoffset = 5 << 4;
870

  
871
  /* Flip the seqno and ackno fields in the TCP header. */
872
  c = BUF->seqno[3];
873
  BUF->seqno[3] = BUF->ackno[3];
874
  BUF->ackno[3] = c;
875

  
876
  c = BUF->seqno[2];
877
  BUF->seqno[2] = BUF->ackno[2];
878
  BUF->ackno[2] = c;
879

  
880
  c = BUF->seqno[1];
881
  BUF->seqno[1] = BUF->ackno[1];
882
  BUF->ackno[1] = c;
883

  
884
  c = BUF->seqno[0];
885
  BUF->seqno[0] = BUF->ackno[0];
886
  BUF->ackno[0] = c;
887

  
888
  /* We also have to increase the sequence number we are
889
     acknowledging. If the least significant byte overflowed, we need
890
     to propagate the carry to the other bytes as well. */
891
  if(++BUF->ackno[3] == 0) {
892
    if(++BUF->ackno[2] == 0) {
893
      if(++BUF->ackno[1] == 0) {
894
	++BUF->ackno[0];
895
      }
896
    }
897
  }
898

  
899
  /* Swap port numbers. */
900
  tmp16 = BUF->srcport;
901
  BUF->srcport = BUF->destport;
902
  BUF->destport = tmp16;
903

  
904
  /* Swap IP addresses. */
905
  tmp16 = BUF->destipaddr[0];
906
  BUF->destipaddr[0] = BUF->srcipaddr[0];
907
  BUF->srcipaddr[0] = tmp16;
908
  tmp16 = BUF->destipaddr[1];
909
  BUF->destipaddr[1] = BUF->srcipaddr[1];
910
  BUF->srcipaddr[1] = tmp16;
911

  
912

  
913
  /* And send out the RST packet! */
914
  goto tcp_send_noconn;
915

  
916
  /* This label will be jumped to if we matched the incoming packet
917
     with a connection in LISTEN. In that case, we should create a new
918
     connection and send a SYNACK in return. */
919
 found_listen:
920
  /* First we check if there are any connections avaliable. Unused
921
     connections are kept in the same table as used connections, but
922
     unused ones have the tcpstate set to CLOSED. Also, connections in
923
     TIME_WAIT are kept track of and we'll use the oldest one if no
924
     CLOSED connections are found. Thanks to Eddie C. Dost for a very
925
     nice algorithm for the TIME_WAIT search. */
926
  uip_connr = 0;
927
  for(c = 0; c < UIP_CONNS; ++c) {
928
    if(uip_conns[c].tcpstateflags == CLOSED) {
929
      uip_connr = &uip_conns[c];
930
      break;
931
    }
932
    if(uip_conns[c].tcpstateflags == TIME_WAIT) {
933
      if(uip_connr == 0 ||
934
	 uip_conns[c].timer > uip_connr->timer) {
935
	uip_connr = &uip_conns[c];
936
      }
937
    }
938
  }
939

  
940
  if(uip_connr == 0) {
941
    /* All connections are used already, we drop packet and hope that
942
       the remote end will retransmit the packet at a time when we
943
       have more spare connections. */
944
    UIP_STAT(++uip_stat.tcp.syndrop);
945
    UIP_LOG("tcp: found no unused connections.");
946
    goto drop;
947
  }
948
  uip_conn = uip_connr;
949

  
950
  /* Fill in the necessary fields for the new connection. */
951
  uip_connr->rto = uip_connr->timer = UIP_RTO;
952
  uip_connr->sa = 0;
953
  uip_connr->sv = 4;
954
  uip_connr->nrtx = 0;
955
  uip_connr->lport = BUF->destport;
956
  uip_connr->rport = BUF->srcport;
957
  uip_connr->ripaddr[0] = BUF->srcipaddr[0];
958
  uip_connr->ripaddr[1] = BUF->srcipaddr[1];
959
  uip_connr->tcpstateflags = SYN_RCVD;
960

  
961
  uip_connr->snd_nxt[0] = iss[0];
962
  uip_connr->snd_nxt[1] = iss[1];
963
  uip_connr->snd_nxt[2] = iss[2];
964
  uip_connr->snd_nxt[3] = iss[3];
965
  uip_connr->len = 1;
966

  
967
  /* rcv_nxt should be the seqno from the incoming packet + 1. */
968
  uip_connr->rcv_nxt[3] = BUF->seqno[3];
969
  uip_connr->rcv_nxt[2] = BUF->seqno[2];
970
  uip_connr->rcv_nxt[1] = BUF->seqno[1];
971
  uip_connr->rcv_nxt[0] = BUF->seqno[0];
972
  uip_add_rcv_nxt(1);
973

  
974
  /* Parse the TCP MSS option, if present. */
975
  if((BUF->tcpoffset & 0xf0) > 0x50) {
976
    for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
977
      opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c];
978
      if(opt == 0x00) {
979
	/* End of options. */	
980
	break;
981
      } else if(opt == 0x01) {
982
	++c;
983
	/* NOP option. */
984
      } else if(opt == 0x02 &&
985
		uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) {
986
	/* An MSS option with the right option length. */	
987
	tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
988
	  (u16_t)uip_buf[40 + UIP_LLH_LEN + 3 + c];
989
	uip_connr->initialmss = uip_connr->mss =
990
	  tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
991
	
992
	/* And we are done processing options. */
993
	break;
994
      } else {
995
	/* All other options have a length field, so that we easily
996
	   can skip past them. */
997
	if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
998
	  /* If the length field is zero, the options are malformed
999
	     and we don't process them further. */
1000
	  break;
1001
	}
1002
	c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
1003
      }
1004
    }
1005
  }
1006

  
1007
  /* Our response will be a SYNACK. */
1008
#if UIP_ACTIVE_OPEN
1009
 tcp_send_synack:
1010
  BUF->flags = TCP_ACK;
1011

  
1012
 tcp_send_syn:
1013
  BUF->flags |= TCP_SYN;
1014
#else /* UIP_ACTIVE_OPEN */
1015
 tcp_send_synack:
1016
  BUF->flags = TCP_SYN | TCP_ACK;
1017
#endif /* UIP_ACTIVE_OPEN */
1018

  
1019
  /* We send out the TCP Maximum Segment Size option with our
1020
     SYNACK. */
1021
  BUF->optdata[0] = 2;
1022
  BUF->optdata[1] = 4;
1023
  BUF->optdata[2] = (UIP_TCP_MSS) / 256;
1024
  BUF->optdata[3] = (UIP_TCP_MSS) & 255;
1025
  uip_len = 44;
1026
  BUF->tcpoffset = 6 << 4;
1027
  goto tcp_send;
1028

  
1029
  /* This label will be jumped to if we found an active connection. */
1030
 found:
1031
  uip_conn = uip_connr;
1032
  uip_flags = 0;
1033

  
1034
  /* We do a very naive form of TCP reset processing; we just accept
1035
     any RST and kill our connection. We should in fact check if the
1036
     sequence number of this reset is wihtin our advertised window
1037
     before we accept the reset. */
1038
  if(BUF->flags & TCP_RST) {
1039
    uip_connr->tcpstateflags = CLOSED;
1040
    UIP_LOG("tcp: got reset, aborting connection.");
1041
    uip_flags = UIP_ABORT;
1042
    UIP_APPCALL();
1043
    goto drop;
1044
  }
1045
  /* Calculated the length of the data, if the application has sent
1046
     any data to us. */
1047
  c = (BUF->tcpoffset >> 4) << 2;
1048
  /* uip_len will contain the length of the actual TCP data. This is
1049
     calculated by subtracing the length of the TCP header (in
1050
     c) and the length of the IP header (20 bytes). */
1051
  uip_len = uip_len - c - 20;
1052

  
1053
  /* First, check if the sequence number of the incoming packet is
1054
     what we're expecting next. If not, we send out an ACK with the
1055
     correct numbers in. */
1056
  if(uip_len > 0 &&
1057
     (BUF->seqno[0] != uip_connr->rcv_nxt[0] ||
1058
      BUF->seqno[1] != uip_connr->rcv_nxt[1] ||
1059
      BUF->seqno[2] != uip_connr->rcv_nxt[2] ||
1060
      BUF->seqno[3] != uip_connr->rcv_nxt[3])) {
1061
    goto tcp_send_ack;
1062
  }
1063

  
1064
  /* Next, check if the incoming segment acknowledges any outstanding
1065
     data. If so, we update the sequence number, reset the length of
1066
     the outstanding data, calculate RTT estimations, and reset the
1067
     retransmission timer. */
1068
  if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) {
1069
    uip_add32(uip_connr->snd_nxt, uip_connr->len);
1070
    if(BUF->ackno[0] == uip_acc32[0] &&
1071
       BUF->ackno[1] == uip_acc32[1] &&
1072
       BUF->ackno[2] == uip_acc32[2] &&
1073
       BUF->ackno[3] == uip_acc32[3]) {
1074
      /* Update sequence number. */
1075
      uip_connr->snd_nxt[0] = uip_acc32[0];
1076
      uip_connr->snd_nxt[1] = uip_acc32[1];
1077
      uip_connr->snd_nxt[2] = uip_acc32[2];
1078
      uip_connr->snd_nxt[3] = uip_acc32[3];
1079
	
1080

  
1081
      /* Do RTT estimation, unless we have done retransmissions. */
1082
      if(uip_connr->nrtx == 0) {
1083
	signed char m;
1084
	m = uip_connr->rto - uip_connr->timer;
1085
	/* This is taken directly from VJs original code in his paper */
1086
	m = m - (uip_connr->sa >> 3);
1087
	uip_connr->sa += m;
1088
	if(m < 0) {
1089
	  m = -m;
1090
	}
1091
	m = m - (uip_connr->sv >> 2);
1092
	uip_connr->sv += m;
1093
	uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv;
1094

  
1095
      }
1096
      /* Set the acknowledged flag. */
1097
      uip_flags = UIP_ACKDATA;
1098
      /* Reset the retransmission timer. */
1099
      uip_connr->timer = uip_connr->rto;
1100
    }
1101

  
1102
  }
1103

  
1104
  /* Do different things depending on in what state the connection is. */
1105
  switch(uip_connr->tcpstateflags & TS_MASK) {
1106
    /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not
1107
	implemented, since we force the application to close when the
1108
	peer sends a FIN (hence the application goes directly from
1109
	ESTABLISHED to LAST_ACK). */
1110
  case SYN_RCVD:
1111
    /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and
1112
       we are waiting for an ACK that acknowledges the data we sent
1113
       out the last time. Therefore, we want to have the UIP_ACKDATA
1114
       flag set. If so, we enter the ESTABLISHED state. */
1115
    if(uip_flags & UIP_ACKDATA) {
1116
      uip_connr->tcpstateflags = ESTABLISHED;
1117
      uip_flags = UIP_CONNECTED;
1118
      uip_connr->len = 0;
1119
      if(uip_len > 0) {
1120
        uip_flags |= UIP_NEWDATA;
1121
        uip_add_rcv_nxt(uip_len);
1122
      }
1123
      uip_slen = 0;
1124
      UIP_APPCALL();
1125
      goto appsend;
1126
    }
1127
    goto drop;
1128
#if UIP_ACTIVE_OPEN
1129
  case SYN_SENT:
1130
    /* In SYN_SENT, we wait for a SYNACK that is sent in response to
1131
       our SYN. The rcv_nxt is set to sequence number in the SYNACK
1132
       plus one, and we send an ACK. We move into the ESTABLISHED
1133
       state. */
1134
    if((uip_flags & UIP_ACKDATA) &&
1135
       BUF->flags == (TCP_SYN | TCP_ACK)) {
1136

  
1137
      /* Parse the TCP MSS option, if present. */
... Этот diff ограничен, так как превышает максимальный отображаемый размер. :@created_atf1415947855.8376319›Ã:@expires_in0