]> git.sur5r.net Git - freertos/blob - Demo/Common/ethernet/uIP/uip-1.0/uip/uip.c
Start to re-arrange files to include FreeRTOS+ in main download.
[freertos] / Demo / Common / ethernet / uIP / uip-1.0 / uip / uip.c
1 #define DEBUG_PRINTF(...) /*printf(__VA_ARGS__)*/\r
2 \r
3 /**\r
4  * \defgroup uip The uIP TCP/IP stack\r
5  * @{\r
6  *\r
7  * uIP is an implementation of the TCP/IP protocol stack intended for\r
8  * small 8-bit and 16-bit microcontrollers.\r
9  *\r
10  * uIP provides the necessary protocols for Internet communication,\r
11  * with a very small code footprint and RAM requirements - the uIP\r
12  * code size is on the order of a few kilobytes and RAM usage is on\r
13  * the order of a few hundred bytes.\r
14  */\r
15 \r
16 /**\r
17  * \file\r
18  * The uIP TCP/IP stack code.\r
19  * \author Adam Dunkels <adam@dunkels.com>\r
20  */\r
21 \r
22 /*\r
23  * Copyright (c) 2001-2003, Adam Dunkels.\r
24  * All rights reserved.\r
25  *\r
26  * Redistribution and use in source and binary forms, with or without\r
27  * modification, are permitted provided that the following conditions\r
28  * are met:\r
29  * 1. Redistributions of source code must retain the above copyright\r
30  *    notice, this list of conditions and the following disclaimer.\r
31  * 2. Redistributions in binary form must reproduce the above copyright\r
32  *    notice, this list of conditions and the following disclaimer in the\r
33  *    documentation and/or other materials provided with the distribution.\r
34  * 3. The name of the author may not be used to endorse or promote\r
35  *    products derived from this software without specific prior\r
36  *    written permission.\r
37  *\r
38  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS\r
39  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
40  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
41  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY\r
42  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
43  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE\r
44  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
45  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\r
46  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
47  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
48  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
49  *\r
50  * This file is part of the uIP TCP/IP stack.\r
51  *\r
52  * $Id: uip.c,v 1.65 2006/06/11 21:46:39 adam Exp $\r
53  *\r
54  */\r
55 \r
56 /*\r
57  * uIP is a small implementation of the IP, UDP and TCP protocols (as\r
58  * well as some basic ICMP stuff). The implementation couples the IP,\r
59  * UDP, TCP and the application layers very tightly. To keep the size\r
60  * of the compiled code down, this code frequently uses the goto\r
61  * statement. While it would be possible to break the uip_process()\r
62  * function into many smaller functions, this would increase the code\r
63  * size because of the overhead of parameter passing and the fact that\r
64  * the optimier would not be as efficient.\r
65  *\r
66  * The principle is that we have a small buffer, called the uip_buf,\r
67  * in which the device driver puts an incoming packet. The TCP/IP\r
68  * stack parses the headers in the packet, and calls the\r
69  * application. If the remote host has sent data to the application,\r
70  * this data is present in the uip_buf and the application read the\r
71  * data from there. It is up to the application to put this data into\r
72  * a byte stream if needed. The application will not be fed with data\r
73  * that is out of sequence.\r
74  *\r
75  * If the application whishes to send data to the peer, it should put\r
76  * its data into the uip_buf. The uip_appdata pointer points to the\r
77  * first available byte. The TCP/IP stack will calculate the\r
78  * checksums, and fill in the necessary header fields and finally send\r
79  * the packet back to the peer.\r
80 */\r
81 \r
82 #include "uip.h"\r
83 #include "uipopt.h"\r
84 #include "uip_arch.h"\r
85 \r
86 #if UIP_CONF_IPV6\r
87 #include "uip-neighbor.h"\r
88 #endif /* UIP_CONF_IPV6 */\r
89 \r
90 #include <string.h>\r
91 \r
92 /*---------------------------------------------------------------------------*/\r
93 /* Variable definitions. */\r
94 \r
95 \r
96 /* The IP address of this host. If it is defined to be fixed (by\r
97    setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set\r
98    here. Otherwise, the address */\r
99 #if UIP_FIXEDADDR > 0\r
100 const uip_ipaddr_t uip_hostaddr =\r
101   {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1),\r
102    HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)};\r
103 const uip_ipaddr_t uip_draddr =\r
104   {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1),\r
105    HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)};\r
106 const uip_ipaddr_t uip_netmask =\r
107   {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1),\r
108    HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)};\r
109 #else\r
110 uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask;\r
111 #endif /* UIP_FIXEDADDR */\r
112 \r
113 static const uip_ipaddr_t all_ones_addr =\r
114 #if UIP_CONF_IPV6\r
115   {0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff};\r
116 #else /* UIP_CONF_IPV6 */\r
117   {0xffff,0xffff};\r
118 #endif /* UIP_CONF_IPV6 */\r
119 static const uip_ipaddr_t all_zeroes_addr =\r
120 #if UIP_CONF_IPV6\r
121   {0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000};\r
122 #else /* UIP_CONF_IPV6 */\r
123   {0x0000,0x0000};\r
124 #endif /* UIP_CONF_IPV6 */\r
125 \r
126 #if UIP_FIXEDETHADDR\r
127 const struct uip_eth_addr uip_ethaddr = {{UIP_ETHADDR0,\r
128                                           UIP_ETHADDR1,\r
129                                           UIP_ETHADDR2,\r
130                                           UIP_ETHADDR3,\r
131                                           UIP_ETHADDR4,\r
132                                           UIP_ETHADDR5}};\r
133 #else\r
134 struct uip_eth_addr uip_ethaddr = {{0,0,0,0,0,0}};\r
135 #endif\r
136 \r
137 #ifndef UIP_CONF_EXTERNAL_BUFFER\r
138 \r
139 #ifdef __ICCARM__\r
140         #pragma data_alignment=4\r
141                 u8_t uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains incoming packets. */\r
142 #else\r
143         u8_t uip_buf[UIP_BUFSIZE + 2] ALIGN_STRUCT_END; /* The packet buffer that contains incoming packets. */\r
144 #endif\r
145 \r
146 #endif /* UIP_CONF_EXTERNAL_BUFFER */\r
147 \r
148 void *uip_appdata;               /* The uip_appdata pointer points to\r
149                                     application data. */\r
150 void *uip_sappdata;              /* The uip_appdata pointer points to\r
151                                     the application data which is to\r
152                                     be sent. */\r
153 #if UIP_URGDATA > 0\r
154 void *uip_urgdata;               /* The uip_urgdata pointer points to\r
155                                     urgent data (out-of-band data), if\r
156                                     present. */\r
157 u16_t uip_urglen, uip_surglen;\r
158 #endif /* UIP_URGDATA > 0 */\r
159 \r
160 u16_t uip_len, uip_slen;\r
161                              /* The uip_len is either 8 or 16 bits,\r
162                                 depending on the maximum packet\r
163                                 size. */\r
164 \r
165 u8_t uip_flags;     /* The uip_flags variable is used for\r
166                                 communication between the TCP/IP stack\r
167                                 and the application program. */\r
168 struct uip_conn *uip_conn;   /* uip_conn always points to the current\r
169                                 connection. */\r
170 \r
171 struct uip_conn uip_conns[UIP_CONNS];\r
172                              /* The uip_conns array holds all TCP\r
173                                 connections. */\r
174 u16_t uip_listenports[UIP_LISTENPORTS];\r
175                              /* The uip_listenports list all currently\r
176                                 listning ports. */\r
177 #if UIP_UDP\r
178 struct uip_udp_conn *uip_udp_conn;\r
179 struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];\r
180 #endif /* UIP_UDP */\r
181 \r
182 static u16_t ipid;           /* Ths ipid variable is an increasing\r
183                                 number that is used for the IP ID\r
184                                 field. */\r
185 \r
186 void uip_setipid(u16_t id) { ipid = id; }\r
187 \r
188 static u8_t iss[4];          /* The iss variable is used for the TCP\r
189                                 initial sequence number. */\r
190 \r
191 #if UIP_ACTIVE_OPEN\r
192 static u16_t lastport;       /* Keeps track of the last port used for\r
193                                 a new connection. */\r
194 #endif /* UIP_ACTIVE_OPEN */\r
195 \r
196 /* Temporary variables. */\r
197 u8_t uip_acc32[4];\r
198 static u8_t c, opt;\r
199 static u16_t tmp16;\r
200 \r
201 /* Structures and definitions. */\r
202 #define TCP_FIN 0x01\r
203 #define TCP_SYN 0x02\r
204 #define TCP_RST 0x04\r
205 #define TCP_PSH 0x08\r
206 #define TCP_ACK 0x10\r
207 #define TCP_URG 0x20\r
208 #define TCP_CTL 0x3f\r
209 \r
210 #define TCP_OPT_END     0   /* End of TCP options list */\r
211 #define TCP_OPT_NOOP    1   /* "No-operation" TCP option */\r
212 #define TCP_OPT_MSS     2   /* Maximum segment size TCP option */\r
213 \r
214 #define TCP_OPT_MSS_LEN 4   /* Length of TCP MSS option. */\r
215 \r
216 #define ICMP_ECHO_REPLY 0\r
217 #define ICMP_ECHO       8\r
218 \r
219 #define ICMP6_ECHO_REPLY             129\r
220 #define ICMP6_ECHO                   128\r
221 #define ICMP6_NEIGHBOR_SOLICITATION  135\r
222 #define ICMP6_NEIGHBOR_ADVERTISEMENT 136\r
223 \r
224 #define ICMP6_FLAG_S (1 << 6)\r
225 \r
226 #define ICMP6_OPTION_SOURCE_LINK_ADDRESS 1\r
227 #define ICMP6_OPTION_TARGET_LINK_ADDRESS 2\r
228 \r
229 \r
230 /* Macros. */\r
231 #define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])\r
232 #define FBUF ((struct uip_tcpip_hdr *)&uip_reassbuf[0])\r
233 #define ICMPBUF ((struct uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN])\r
234 #define UDPBUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])\r
235 \r
236 \r
237 #if UIP_STATISTICS == 1\r
238 struct uip_stats uip_stat;\r
239 #define UIP_STAT(s) s\r
240 #else\r
241 #define UIP_STAT(s)\r
242 #endif /* UIP_STATISTICS == 1 */\r
243 \r
244 #if UIP_LOGGING == 1\r
245 #include <stdio.h>\r
246 void uip_log(char *msg);\r
247 #define UIP_LOG(m) uip_log(m)\r
248 #else\r
249 #define UIP_LOG(m)\r
250 #endif /* UIP_LOGGING == 1 */\r
251 \r
252 #if ! UIP_ARCH_ADD32\r
253 void\r
254 uip_add32(u8_t *op32, u16_t op16)\r
255 {\r
256   uip_acc32[3] = op32[3] + (op16 & 0xff);\r
257   uip_acc32[2] = op32[2] + (op16 >> 8);\r
258   uip_acc32[1] = op32[1];\r
259   uip_acc32[0] = op32[0];\r
260 \r
261   if(uip_acc32[2] < (op16 >> 8)) {\r
262     ++uip_acc32[1];\r
263     if(uip_acc32[1] == 0) {\r
264       ++uip_acc32[0];\r
265     }\r
266   }\r
267 \r
268 \r
269   if(uip_acc32[3] < (op16 & 0xff)) {\r
270     ++uip_acc32[2];\r
271     if(uip_acc32[2] == 0) {\r
272       ++uip_acc32[1];\r
273       if(uip_acc32[1] == 0) {\r
274         ++uip_acc32[0];\r
275       }\r
276     }\r
277   }\r
278 }\r
279 \r
280 #endif /* UIP_ARCH_ADD32 */\r
281 \r
282 #if ! UIP_ARCH_CHKSUM\r
283 /*---------------------------------------------------------------------------*/\r
284 static u16_t\r
285 chksum(u16_t sum, const u8_t *data, u16_t len)\r
286 {\r
287   u16_t t;\r
288   const u8_t *dataptr;\r
289   const u8_t *last_byte;\r
290 \r
291   dataptr = data;\r
292   last_byte = data + len - 1;\r
293 \r
294   while(dataptr < last_byte) {  /* At least two more bytes */\r
295     t = (dataptr[0] << 8) + dataptr[1];\r
296     sum += t;\r
297     if(sum < t) {\r
298       sum++;            /* carry */\r
299     }\r
300     dataptr += 2;\r
301   }\r
302 \r
303   if(dataptr == last_byte) {\r
304     t = (dataptr[0] << 8) + 0;\r
305     sum += t;\r
306     if(sum < t) {\r
307       sum++;            /* carry */\r
308     }\r
309   }\r
310 \r
311   /* Return sum in host byte order. */\r
312   return sum;\r
313 }\r
314 /*---------------------------------------------------------------------------*/\r
315 u16_t\r
316 uip_chksum(u16_t *data, u16_t len)\r
317 {\r
318   return htons(chksum(0, (u8_t *)data, len));\r
319 }\r
320 /*---------------------------------------------------------------------------*/\r
321 #ifndef UIP_ARCH_IPCHKSUM\r
322 u16_t\r
323 uip_ipchksum(void)\r
324 {\r
325   u16_t sum;\r
326 \r
327   sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN);\r
328   DEBUG_PRINTF("uip_ipchksum: sum 0x%04x\n", sum);\r
329   return (sum == 0) ? 0xffff : htons(sum);\r
330 }\r
331 #endif\r
332 /*---------------------------------------------------------------------------*/\r
333 static u16_t\r
334 upper_layer_chksum(u8_t proto)\r
335 {\r
336   u16_t upper_layer_len;\r
337   u16_t sum;\r
338 \r
339 #if UIP_CONF_IPV6\r
340   upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]);\r
341 #else /* UIP_CONF_IPV6 */\r
342   upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN;\r
343 #endif /* UIP_CONF_IPV6 */\r
344 \r
345   /* First sum pseudoheader. */\r
346 \r
347   /* IP protocol and length fields. This addition cannot carry. */\r
348   sum = upper_layer_len + proto;\r
349   /* Sum IP source and destination addresses. */\r
350   sum = chksum(sum, (u8_t *)&BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t));\r
351 \r
352   /* Sum TCP header and data. */\r
353   sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN],\r
354                upper_layer_len);\r
355 \r
356   return (sum == 0) ? 0xffff : htons(sum);\r
357 }\r
358 /*---------------------------------------------------------------------------*/\r
359 #if UIP_CONF_IPV6\r
360 u16_t\r
361 uip_icmp6chksum(void)\r
362 {\r
363   return upper_layer_chksum(UIP_PROTO_ICMP6);\r
364 \r
365 }\r
366 #endif /* UIP_CONF_IPV6 */\r
367 /*---------------------------------------------------------------------------*/\r
368 u16_t\r
369 uip_tcpchksum(void)\r
370 {\r
371   return upper_layer_chksum(UIP_PROTO_TCP);\r
372 }\r
373 /*---------------------------------------------------------------------------*/\r
374 #if UIP_UDP_CHECKSUMS\r
375 u16_t\r
376 uip_udpchksum(void)\r
377 {\r
378   return upper_layer_chksum(UIP_PROTO_UDP);\r
379 }\r
380 #endif /* UIP_UDP_CHECKSUMS */\r
381 #endif /* UIP_ARCH_CHKSUM */\r
382 /*---------------------------------------------------------------------------*/\r
383 void\r
384 uip_init(void)\r
385 {\r
386   for(c = 0; c < UIP_LISTENPORTS; ++c) {\r
387     uip_listenports[c] = 0;\r
388   }\r
389   for(c = 0; c < UIP_CONNS; ++c) {\r
390     uip_conns[c].tcpstateflags = UIP_CLOSED;\r
391   }\r
392 #if UIP_ACTIVE_OPEN\r
393   lastport = 1024;\r
394 #endif /* UIP_ACTIVE_OPEN */\r
395 \r
396 #if UIP_UDP\r
397   for(c = 0; c < UIP_UDP_CONNS; ++c) {\r
398     uip_udp_conns[c].lport = 0;\r
399   }\r
400 #endif /* UIP_UDP */\r
401 \r
402 \r
403   /* IPv4 initialization. */\r
404 #if UIP_FIXEDADDR == 0\r
405   /*  uip_hostaddr[0] = uip_hostaddr[1] = 0;*/\r
406 #endif /* UIP_FIXEDADDR */\r
407 \r
408 }\r
409 /*---------------------------------------------------------------------------*/\r
410 #if UIP_ACTIVE_OPEN\r
411 struct uip_conn *\r
412 uip_connect(uip_ipaddr_t *ripaddr, u16_t rport)\r
413 {\r
414   register struct uip_conn *conn, *cconn;\r
415 \r
416   /* Find an unused local port. */\r
417  again:\r
418   ++lastport;\r
419 \r
420   if(lastport >= 32000) {\r
421     lastport = 4096;\r
422   }\r
423 \r
424   /* Check if this port is already in use, and if so try to find\r
425      another one. */\r
426   for(c = 0; c < UIP_CONNS; ++c) {\r
427     conn = &uip_conns[c];\r
428     if(conn->tcpstateflags != UIP_CLOSED &&\r
429        conn->lport == htons(lastport)) {\r
430       goto again;\r
431     }\r
432   }\r
433 \r
434   conn = 0;\r
435   for(c = 0; c < UIP_CONNS; ++c) {\r
436     cconn = &uip_conns[c];\r
437     if(cconn->tcpstateflags == UIP_CLOSED) {\r
438       conn = cconn;\r
439       break;\r
440     }\r
441     if(cconn->tcpstateflags == UIP_TIME_WAIT) {\r
442       if(conn == 0 ||\r
443          cconn->timer > conn->timer) {\r
444         conn = cconn;\r
445       }\r
446     }\r
447   }\r
448 \r
449   if(conn == 0) {\r
450     return 0;\r
451   }\r
452 \r
453   conn->tcpstateflags = UIP_SYN_SENT;\r
454 \r
455   conn->snd_nxt[0] = iss[0];\r
456   conn->snd_nxt[1] = iss[1];\r
457   conn->snd_nxt[2] = iss[2];\r
458   conn->snd_nxt[3] = iss[3];\r
459 \r
460   conn->initialmss = conn->mss = UIP_TCP_MSS;\r
461 \r
462   conn->len = 1;   /* TCP length of the SYN is one. */\r
463   conn->nrtx = 0;\r
464   conn->timer = 1; /* Send the SYN next time around. */\r
465   conn->rto = UIP_RTO;\r
466   conn->sa = 0;\r
467   conn->sv = 16;   /* Initial value of the RTT variance. */\r
468   conn->lport = htons(lastport);\r
469   conn->rport = rport;\r
470   uip_ipaddr_copy(&conn->ripaddr, ripaddr);\r
471 \r
472   return conn;\r
473 }\r
474 #endif /* UIP_ACTIVE_OPEN */\r
475 /*---------------------------------------------------------------------------*/\r
476 #if UIP_UDP\r
477 struct uip_udp_conn *\r
478 uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport)\r
479 {\r
480   register struct uip_udp_conn *conn;\r
481 \r
482   /* Find an unused local port. */\r
483  again:\r
484   ++lastport;\r
485 \r
486   if(lastport >= 32000) {\r
487     lastport = 4096;\r
488   }\r
489 \r
490   for(c = 0; c < UIP_UDP_CONNS; ++c) {\r
491     if(uip_udp_conns[c].lport == htons(lastport)) {\r
492       goto again;\r
493     }\r
494   }\r
495 \r
496 \r
497   conn = 0;\r
498   for(c = 0; c < UIP_UDP_CONNS; ++c) {\r
499     if(uip_udp_conns[c].lport == 0) {\r
500       conn = &uip_udp_conns[c];\r
501       break;\r
502     }\r
503   }\r
504 \r
505   if(conn == 0) {\r
506     return 0;\r
507   }\r
508 \r
509   conn->lport = HTONS(lastport);\r
510   conn->rport = rport;\r
511   if(ripaddr == NULL) {\r
512     memset(conn->ripaddr, 0, sizeof(uip_ipaddr_t));\r
513   } else {\r
514     uip_ipaddr_copy(&conn->ripaddr, ripaddr);\r
515   }\r
516   conn->ttl = UIP_TTL;\r
517 \r
518   return conn;\r
519 }\r
520 #endif /* UIP_UDP */\r
521 /*---------------------------------------------------------------------------*/\r
522 void\r
523 uip_unlisten(u16_t port)\r
524 {\r
525   for(c = 0; c < UIP_LISTENPORTS; ++c) {\r
526     if(uip_listenports[c] == port) {\r
527       uip_listenports[c] = 0;\r
528       return;\r
529     }\r
530   }\r
531 }\r
532 /*---------------------------------------------------------------------------*/\r
533 void\r
534 uip_listen(u16_t port)\r
535 {\r
536   for(c = 0; c < UIP_LISTENPORTS; ++c) {\r
537     if(uip_listenports[c] == 0) {\r
538       uip_listenports[c] = port;\r
539       return;\r
540     }\r
541   }\r
542 }\r
543 /*---------------------------------------------------------------------------*/\r
544 /* XXX: IP fragment reassembly: not well-tested. */\r
545 \r
546 #if UIP_REASSEMBLY && !UIP_CONF_IPV6\r
547 #define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN)\r
548 static u8_t uip_reassbuf[UIP_REASS_BUFSIZE];\r
549 static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)];\r
550 static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f,\r
551                                     0x0f, 0x07, 0x03, 0x01};\r
552 static u16_t uip_reasslen;\r
553 static u8_t uip_reassflags;\r
554 #define UIP_REASS_FLAG_LASTFRAG 0x01\r
555 static u8_t uip_reasstmr;\r
556 \r
557 #define IP_MF   0x20\r
558 \r
559 static u8_t\r
560 uip_reass(void)\r
561 {\r
562   u16_t offset, len;\r
563   u16_t i;\r
564 \r
565   /* If ip_reasstmr is zero, no packet is present in the buffer, so we\r
566      write the IP header of the fragment into the reassembly\r
567      buffer. The timer is updated with the maximum age. */\r
568   if(uip_reasstmr == 0) {\r
569     memcpy(uip_reassbuf, &BUF->vhl, UIP_IPH_LEN);\r
570     uip_reasstmr = UIP_REASS_MAXAGE;\r
571     uip_reassflags = 0;\r
572     /* Clear the bitmap. */\r
573     memset(uip_reassbitmap, 0, sizeof(uip_reassbitmap));\r
574   }\r
575 \r
576   /* Check if the incoming fragment matches the one currently present\r
577      in the reasembly buffer. If so, we proceed with copying the\r
578      fragment into the buffer. */\r
579   if(BUF->srcipaddr[0] == FBUF->srcipaddr[0] &&\r
580      BUF->srcipaddr[1] == FBUF->srcipaddr[1] &&\r
581      BUF->destipaddr[0] == FBUF->destipaddr[0] &&\r
582      BUF->destipaddr[1] == FBUF->destipaddr[1] &&\r
583      BUF->ipid[0] == FBUF->ipid[0] &&\r
584      BUF->ipid[1] == FBUF->ipid[1]) {\r
585 \r
586     len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4;\r
587     offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8;\r
588 \r
589     /* If the offset or the offset + fragment length overflows the\r
590        reassembly buffer, we discard the entire packet. */\r
591     if(offset > UIP_REASS_BUFSIZE ||\r
592        offset + len > UIP_REASS_BUFSIZE) {\r
593       uip_reasstmr = 0;\r
594       goto nullreturn;\r
595     }\r
596 \r
597     /* Copy the fragment into the reassembly buffer, at the right\r
598        offset. */\r
599     memcpy(&uip_reassbuf[UIP_IPH_LEN + offset],\r
600            (char *)BUF + (int)((BUF->vhl & 0x0f) * 4),\r
601            len);\r
602 \r
603     /* Update the bitmap. */\r
604     if(offset / (8 * 8) == (offset + len) / (8 * 8)) {\r
605       /* If the two endpoints are in the same byte, we only update\r
606          that byte. */\r
607 \r
608       uip_reassbitmap[offset / (8 * 8)] |=\r
609              bitmap_bits[(offset / 8 ) & 7] &\r
610              ~bitmap_bits[((offset + len) / 8 ) & 7];\r
611     } else {\r
612       /* If the two endpoints are in different bytes, we update the\r
613          bytes in the endpoints and fill the stuff inbetween with\r
614          0xff. */\r
615       uip_reassbitmap[offset / (8 * 8)] |=\r
616         bitmap_bits[(offset / 8 ) & 7];\r
617       for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) {\r
618         uip_reassbitmap[i] = 0xff;\r
619       }\r
620       uip_reassbitmap[(offset + len) / (8 * 8)] |=\r
621         ~bitmap_bits[((offset + len) / 8 ) & 7];\r
622     }\r
623 \r
624     /* If this fragment has the More Fragments flag set to zero, we\r
625        know that this is the last fragment, so we can calculate the\r
626        size of the entire packet. We also set the\r
627        IP_REASS_FLAG_LASTFRAG flag to indicate that we have received\r
628        the final fragment. */\r
629 \r
630     if((BUF->ipoffset[0] & IP_MF) == 0) {\r
631       uip_reassflags |= UIP_REASS_FLAG_LASTFRAG;\r
632       uip_reasslen = offset + len;\r
633     }\r
634 \r
635     /* Finally, we check if we have a full packet in the buffer. We do\r
636        this by checking if we have the last fragment and if all bits\r
637        in the bitmap are set. */\r
638     if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) {\r
639       /* Check all bytes up to and including all but the last byte in\r
640          the bitmap. */\r
641       for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) {\r
642         if(uip_reassbitmap[i] != 0xff) {\r
643           goto nullreturn;\r
644         }\r
645       }\r
646       /* Check the last byte in the bitmap. It should contain just the\r
647          right amount of bits. */\r
648       if(uip_reassbitmap[uip_reasslen / (8 * 8)] !=\r
649          (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) {\r
650         goto nullreturn;\r
651       }\r
652 \r
653       /* If we have come this far, we have a full packet in the\r
654          buffer, so we allocate a pbuf and copy the packet into it. We\r
655          also reset the timer. */\r
656       uip_reasstmr = 0;\r
657       memcpy(BUF, FBUF, uip_reasslen);\r
658 \r
659       /* Pretend to be a "normal" (i.e., not fragmented) IP packet\r
660          from now on. */\r
661       BUF->ipoffset[0] = BUF->ipoffset[1] = 0;\r
662       BUF->len[0] = uip_reasslen >> 8;\r
663       BUF->len[1] = uip_reasslen & 0xff;\r
664       BUF->ipchksum = 0;\r
665       BUF->ipchksum = ~(uip_ipchksum());\r
666 \r
667       return uip_reasslen;\r
668     }\r
669   }\r
670 \r
671  nullreturn:\r
672   return 0;\r
673 }\r
674 #endif /* UIP_REASSEMBLY */\r
675 /*---------------------------------------------------------------------------*/\r
676 static void\r
677 uip_add_rcv_nxt(u16_t n)\r
678 {\r
679   uip_add32(uip_conn->rcv_nxt, n);\r
680   uip_conn->rcv_nxt[0] = uip_acc32[0];\r
681   uip_conn->rcv_nxt[1] = uip_acc32[1];\r
682   uip_conn->rcv_nxt[2] = uip_acc32[2];\r
683   uip_conn->rcv_nxt[3] = uip_acc32[3];\r
684 }\r
685 /*---------------------------------------------------------------------------*/\r
686 void\r
687 uip_process(u8_t flag)\r
688 {\r
689   register struct uip_conn *uip_connr = uip_conn;\r
690 \r
691   ( void ) all_ones_addr;\r
692 \r
693 #if UIP_UDP\r
694   if(flag == UIP_UDP_SEND_CONN) {\r
695     goto udp_send;\r
696   }\r
697 #endif /* UIP_UDP */\r
698 \r
699   uip_sappdata = uip_appdata = &uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN];\r
700 \r
701   /* Check if we were invoked because of a poll request for a\r
702      particular connection. */\r
703   if(flag == UIP_POLL_REQUEST) {\r
704     if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED &&\r
705        !uip_outstanding(uip_connr)) {\r
706         uip_flags = UIP_POLL;\r
707         UIP_APPCALL();\r
708         goto appsend;\r
709     }\r
710     goto drop;\r
711 \r
712     /* Check if we were invoked because of the perodic timer fireing. */\r
713   } else if(flag == UIP_TIMER) {\r
714 #if UIP_REASSEMBLY\r
715     if(uip_reasstmr != 0) {\r
716       --uip_reasstmr;\r
717     }\r
718 #endif /* UIP_REASSEMBLY */\r
719     /* Increase the initial sequence number. */\r
720     if(++iss[3] == 0) {\r
721       if(++iss[2] == 0) {\r
722         if(++iss[1] == 0) {\r
723           ++iss[0];\r
724         }\r
725       }\r
726     }\r
727 \r
728     /* Reset the length variables. */\r
729     uip_len = 0;\r
730     uip_slen = 0;\r
731 \r
732     /* Check if the connection is in a state in which we simply wait\r
733        for the connection to time out. If so, we increase the\r
734        connection's timer and remove the connection if it times\r
735        out. */\r
736     if(uip_connr->tcpstateflags == UIP_TIME_WAIT ||\r
737        uip_connr->tcpstateflags == UIP_FIN_WAIT_2) {\r
738       ++(uip_connr->timer);\r
739       if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) {\r
740         uip_connr->tcpstateflags = UIP_CLOSED;\r
741       }\r
742     } else if(uip_connr->tcpstateflags != UIP_CLOSED) {\r
743       /* If the connection has outstanding data, we increase the\r
744          connection's timer and see if it has reached the RTO value\r
745          in which case we retransmit. */\r
746       if(uip_outstanding(uip_connr)) {\r
747           uip_connr->timer = uip_connr->timer - 1;\r
748         if(uip_connr->timer == 0) {\r
749           if(uip_connr->nrtx == UIP_MAXRTX ||\r
750              ((uip_connr->tcpstateflags == UIP_SYN_SENT ||\r
751                uip_connr->tcpstateflags == UIP_SYN_RCVD) &&\r
752               uip_connr->nrtx == UIP_MAXSYNRTX)) {\r
753             uip_connr->tcpstateflags = UIP_CLOSED;\r
754 \r
755             /* We call UIP_APPCALL() with uip_flags set to\r
756                UIP_TIMEDOUT to inform the application that the\r
757                connection has timed out. */\r
758             uip_flags = UIP_TIMEDOUT;\r
759             UIP_APPCALL();\r
760 \r
761             /* We also send a reset packet to the remote host. */\r
762             BUF->flags = TCP_RST | TCP_ACK;\r
763             goto tcp_send_nodata;\r
764           }\r
765 \r
766           /* Exponential backoff. */\r
767           uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4?\r
768                                          4:\r
769                                          uip_connr->nrtx);\r
770           ++(uip_connr->nrtx);\r
771 \r
772           /* Ok, so we need to retransmit. We do this differently\r
773              depending on which state we are in. In ESTABLISHED, we\r
774              call upon the application so that it may prepare the\r
775              data for the retransmit. In SYN_RCVD, we resend the\r
776              SYNACK that we sent earlier and in LAST_ACK we have to\r
777              retransmit our FINACK. */\r
778           UIP_STAT(++uip_stat.tcp.rexmit);\r
779           switch(uip_connr->tcpstateflags & UIP_TS_MASK) {\r
780           case UIP_SYN_RCVD:\r
781             /* In the SYN_RCVD state, we should retransmit our\r
782                SYNACK. */\r
783             goto tcp_send_synack;\r
784 \r
785 #if UIP_ACTIVE_OPEN\r
786           case UIP_SYN_SENT:\r
787             /* In the SYN_SENT state, we retransmit out SYN. */\r
788             BUF->flags = 0;\r
789             goto tcp_send_syn;\r
790 #endif /* UIP_ACTIVE_OPEN */\r
791 \r
792           case UIP_ESTABLISHED:\r
793             /* In the ESTABLISHED state, we call upon the application\r
794                to do the actual retransmit after which we jump into\r
795                the code for sending out the packet (the apprexmit\r
796                label). */\r
797             uip_flags = UIP_REXMIT;\r
798             UIP_APPCALL();\r
799             goto apprexmit;\r
800 \r
801           case UIP_FIN_WAIT_1:\r
802           case UIP_CLOSING:\r
803           case UIP_LAST_ACK:\r
804             /* In all these states we should retransmit a FINACK. */\r
805             goto tcp_send_finack;\r
806 \r
807           }\r
808         }\r
809       } else if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) {\r
810         /* If there was no need for a retransmission, we poll the\r
811            application for new data. */\r
812         uip_flags = UIP_POLL;\r
813         UIP_APPCALL();\r
814         goto appsend;\r
815       }\r
816     }\r
817     goto drop;\r
818   }\r
819 #if UIP_UDP\r
820   if(flag == UIP_UDP_TIMER) {\r
821     if(uip_udp_conn->lport != 0) {\r
822       uip_conn = NULL;\r
823       uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];\r
824       uip_len = uip_slen = 0;\r
825       uip_flags = UIP_POLL;\r
826       UIP_UDP_APPCALL();\r
827       goto udp_send;\r
828     } else {\r
829       goto drop;\r
830     }\r
831   }\r
832 #endif\r
833 \r
834   /* This is where the input processing starts. */\r
835   UIP_STAT(++uip_stat.ip.recv);\r
836 \r
837   /* Start of IP input header processing code. */\r
838 \r
839 #if UIP_CONF_IPV6\r
840   /* Check validity of the IP header. */\r
841   if((BUF->vtc & 0xf0) != 0x60)  { /* IP version and header length. */\r
842     UIP_STAT(++uip_stat.ip.drop);\r
843     UIP_STAT(++uip_stat.ip.vhlerr);\r
844     UIP_LOG("ipv6: invalid version.");\r
845     goto drop;\r
846   }\r
847 #else /* UIP_CONF_IPV6 */\r
848   /* Check validity of the IP header. */\r
849   if(BUF->vhl != 0x45)  { /* IP version and header length. */\r
850     UIP_STAT(++uip_stat.ip.drop);\r
851     UIP_STAT(++uip_stat.ip.vhlerr);\r
852     UIP_LOG("ip: invalid version or header length.");\r
853     goto drop;\r
854   }\r
855 #endif /* UIP_CONF_IPV6 */\r
856 \r
857   /* Check the size of the packet. If the size reported to us in\r
858      uip_len is smaller the size reported in the IP header, we assume\r
859      that the packet has been corrupted in transit. If the size of\r
860      uip_len is larger than the size reported in the IP packet header,\r
861      the packet has been padded and we set uip_len to the correct\r
862      value.. */\r
863 \r
864   if((BUF->len[0] << 8) + BUF->len[1] <= uip_len) {\r
865     uip_len = (BUF->len[0] << 8) + BUF->len[1];\r
866 #if UIP_CONF_IPV6\r
867     uip_len += 40; /* The length reported in the IPv6 header is the\r
868                       length of the payload that follows the\r
869                       header. However, uIP uses the uip_len variable\r
870                       for holding the size of the entire packet,\r
871                       including the IP header. For IPv4 this is not a\r
872                       problem as the length field in the IPv4 header\r
873                       contains the length of the entire packet. But\r
874                       for IPv6 we need to add the size of the IPv6\r
875                       header (40 bytes). */\r
876 #endif /* UIP_CONF_IPV6 */\r
877   } else {\r
878     UIP_LOG("ip: packet shorter than reported in IP header.");\r
879     goto drop;\r
880   }\r
881 \r
882 #if !UIP_CONF_IPV6\r
883   /* Check the fragment flag. */\r
884   if((BUF->ipoffset[0] & 0x3f) != 0 ||\r
885      BUF->ipoffset[1] != 0) {\r
886 #if UIP_REASSEMBLY\r
887     uip_len = uip_reass();\r
888     if(uip_len == 0) {\r
889       goto drop;\r
890     }\r
891 #else /* UIP_REASSEMBLY */\r
892     UIP_STAT(++uip_stat.ip.drop);\r
893     UIP_STAT(++uip_stat.ip.fragerr);\r
894     UIP_LOG("ip: fragment dropped.");\r
895     goto drop;\r
896 #endif /* UIP_REASSEMBLY */\r
897   }\r
898 #endif /* UIP_CONF_IPV6 */\r
899 \r
900   if(uip_ipaddr_cmp(uip_hostaddr, all_zeroes_addr)) {\r
901     /* If we are configured to use ping IP address configuration and\r
902        hasn't been assigned an IP address yet, we accept all ICMP\r
903        packets. */\r
904 #if UIP_PINGADDRCONF && !UIP_CONF_IPV6\r
905     if(BUF->proto == UIP_PROTO_ICMP) {\r
906       UIP_LOG("ip: possible ping config packet received.");\r
907       goto icmp_input;\r
908     } else {\r
909       UIP_LOG("ip: packet dropped since no address assigned.");\r
910       goto drop;\r
911     }\r
912 #endif /* UIP_PINGADDRCONF */\r
913 \r
914   } else {\r
915     /* If IP broadcast support is configured, we check for a broadcast\r
916        UDP packet, which may be destined to us. */\r
917 #if UIP_BROADCAST\r
918     DEBUG_PRINTF("UDP IP checksum 0x%04x\n", uip_ipchksum());\r
919     if(BUF->proto == UIP_PROTO_UDP &&\r
920        uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr)\r
921        /*&&\r
922          uip_ipchksum() == 0xffff*/) {\r
923       goto udp_input;\r
924     }\r
925 #endif /* UIP_BROADCAST */\r
926 \r
927     /* Check if the packet is destined for our IP address. */\r
928 #if !UIP_CONF_IPV6\r
929     if(!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr)) {\r
930       UIP_STAT(++uip_stat.ip.drop);\r
931       goto drop;\r
932     }\r
933 #else /* UIP_CONF_IPV6 */\r
934     /* For IPv6, packet reception is a little trickier as we need to\r
935        make sure that we listen to certain multicast addresses (all\r
936        hosts multicast address, and the solicited-node multicast\r
937        address) as well. However, we will cheat here and accept all\r
938        multicast packets that are sent to the ff02::/16 addresses. */\r
939     if(!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr) &&\r
940        BUF->destipaddr[0] != HTONS(0xff02)) {\r
941       UIP_STAT(++uip_stat.ip.drop);\r
942       goto drop;\r
943     }\r
944 #endif /* UIP_CONF_IPV6 */\r
945   }\r
946 \r
947 #if !UIP_CONF_IPV6\r
948   if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header\r
949                                     checksum. */\r
950     UIP_STAT(++uip_stat.ip.drop);\r
951     UIP_STAT(++uip_stat.ip.chkerr);\r
952     UIP_LOG("ip: bad checksum.");\r
953     goto drop;\r
954   }\r
955 #endif /* UIP_CONF_IPV6 */\r
956 \r
957   if(BUF->proto == UIP_PROTO_TCP) { /* Check for TCP packet. If so,\r
958                                        proceed with TCP input\r
959                                        processing. */\r
960     goto tcp_input;\r
961   }\r
962 \r
963 #if UIP_UDP\r
964   if(BUF->proto == UIP_PROTO_UDP) {\r
965     goto udp_input;\r
966   }\r
967 #endif /* UIP_UDP */\r
968 \r
969 #if !UIP_CONF_IPV6\r
970   /* ICMPv4 processing code follows. */\r
971   if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from\r
972                                         here. */\r
973     UIP_STAT(++uip_stat.ip.drop);\r
974     UIP_STAT(++uip_stat.ip.protoerr);\r
975     UIP_LOG("ip: neither tcp nor icmp.");\r
976     goto drop;\r
977   }\r
978 \r
979 #if UIP_PINGADDRCONF\r
980  icmp_input:\r
981 #endif /* UIP_PINGADDRCONF */\r
982   UIP_STAT(++uip_stat.icmp.recv);\r
983 \r
984   /* ICMP echo (i.e., ping) processing. This is simple, we only change\r
985      the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP\r
986      checksum before we return the packet. */\r
987   if(ICMPBUF->type != ICMP_ECHO) {\r
988     UIP_STAT(++uip_stat.icmp.drop);\r
989     UIP_STAT(++uip_stat.icmp.typeerr);\r
990     UIP_LOG("icmp: not icmp echo.");\r
991     goto drop;\r
992   }\r
993 \r
994   /* If we are configured to use ping IP address assignment, we use\r
995      the destination IP address of this ping packet and assign it to\r
996      ourself. */\r
997 #if UIP_PINGADDRCONF\r
998   if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) {\r
999     uip_hostaddr[0] = BUF->destipaddr[0];\r
1000     uip_hostaddr[1] = BUF->destipaddr[1];\r
1001   }\r
1002 #endif /* UIP_PINGADDRCONF */\r
1003 \r
1004   ICMPBUF->type = ICMP_ECHO_REPLY;\r
1005 \r
1006   if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) {\r
1007     ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1;\r
1008   } else {\r
1009     ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8);\r
1010   }\r
1011 \r
1012   /* Swap IP addresses. */\r
1013   uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);\r
1014   uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);\r
1015 \r
1016   UIP_STAT(++uip_stat.icmp.sent);\r
1017   goto send;\r
1018 \r
1019   /* End of IPv4 input header processing code. */\r
1020 #else /* !UIP_CONF_IPV6 */\r
1021 \r
1022   /* This is IPv6 ICMPv6 processing code. */\r
1023   DEBUG_PRINTF("icmp6_input: length %d\n", uip_len);\r
1024 \r
1025   if(BUF->proto != UIP_PROTO_ICMP6) { /* We only allow ICMPv6 packets from\r
1026                                          here. */\r
1027     UIP_STAT(++uip_stat.ip.drop);\r
1028     UIP_STAT(++uip_stat.ip.protoerr);\r
1029     UIP_LOG("ip: neither tcp nor icmp6.");\r
1030     goto drop;\r
1031   }\r
1032 \r
1033   UIP_STAT(++uip_stat.icmp.recv);\r
1034 \r
1035   /* If we get a neighbor solicitation for our address we should send\r
1036      a neighbor advertisement message back. */\r
1037   if(ICMPBUF->type == ICMP6_NEIGHBOR_SOLICITATION) {\r
1038     if(uip_ipaddr_cmp(ICMPBUF->icmp6data, uip_hostaddr)) {\r
1039 \r
1040       if(ICMPBUF->options[0] == ICMP6_OPTION_SOURCE_LINK_ADDRESS) {\r
1041         /* Save the sender's address in our neighbor list. */\r
1042         uip_neighbor_add(ICMPBUF->srcipaddr, &(ICMPBUF->options[2]));\r
1043       }\r
1044 \r
1045       /* We should now send a neighbor advertisement back to where the\r
1046          neighbor solicication came from. */\r
1047       ICMPBUF->type = ICMP6_NEIGHBOR_ADVERTISEMENT;\r
1048       ICMPBUF->flags = ICMP6_FLAG_S; /* Solicited flag. */\r
1049 \r
1050       ICMPBUF->reserved1 = ICMPBUF->reserved2 = ICMPBUF->reserved3 = 0;\r
1051 \r
1052       uip_ipaddr_copy(ICMPBUF->destipaddr, ICMPBUF->srcipaddr);\r
1053       uip_ipaddr_copy(ICMPBUF->srcipaddr, uip_hostaddr);\r
1054       ICMPBUF->options[0] = ICMP6_OPTION_TARGET_LINK_ADDRESS;\r
1055       ICMPBUF->options[1] = 1;  /* Options length, 1 = 8 bytes. */\r
1056       memcpy(&(ICMPBUF->options[2]), &uip_ethaddr, sizeof(uip_ethaddr));\r
1057       ICMPBUF->icmpchksum = 0;\r
1058       ICMPBUF->icmpchksum = ~uip_icmp6chksum();\r
1059       goto send;\r
1060 \r
1061     }\r
1062     goto drop;\r
1063   } else if(ICMPBUF->type == ICMP6_ECHO) {\r
1064     /* ICMP echo (i.e., ping) processing. This is simple, we only\r
1065        change the ICMP type from ECHO to ECHO_REPLY and update the\r
1066        ICMP checksum before we return the packet. */\r
1067 \r
1068     ICMPBUF->type = ICMP6_ECHO_REPLY;\r
1069 \r
1070     uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);\r
1071     uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);\r
1072     ICMPBUF->icmpchksum = 0;\r
1073     ICMPBUF->icmpchksum = ~uip_icmp6chksum();\r
1074 \r
1075     UIP_STAT(++uip_stat.icmp.sent);\r
1076     goto send;\r
1077   } else {\r
1078     DEBUG_PRINTF("Unknown icmp6 message type %d\n", ICMPBUF->type);\r
1079     UIP_STAT(++uip_stat.icmp.drop);\r
1080     UIP_STAT(++uip_stat.icmp.typeerr);\r
1081     UIP_LOG("icmp: unknown ICMP message.");\r
1082     goto drop;\r
1083   }\r
1084 \r
1085   /* End of IPv6 ICMP processing. */\r
1086 \r
1087 #endif /* !UIP_CONF_IPV6 */\r
1088 \r
1089 #if UIP_UDP\r
1090   /* UDP input processing. */\r
1091  udp_input:\r
1092   /* UDP processing is really just a hack. We don't do anything to the\r
1093      UDP/IP headers, but let the UDP application do all the hard\r
1094      work. If the application sets uip_slen, it has a packet to\r
1095      send. */\r
1096 #if UIP_UDP_CHECKSUMS\r
1097   uip_len = uip_len - UIP_IPUDPH_LEN;\r
1098   uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];\r
1099   if(UDPBUF->udpchksum != 0 && uip_udpchksum() != 0xffff) {\r
1100     UIP_STAT(++uip_stat.udp.drop);\r
1101     UIP_STAT(++uip_stat.udp.chkerr);\r
1102     UIP_LOG("udp: bad checksum.");\r
1103     goto drop;\r
1104   }\r
1105 #else /* UIP_UDP_CHECKSUMS */\r
1106   uip_len = uip_len - UIP_IPUDPH_LEN;\r
1107 #endif /* UIP_UDP_CHECKSUMS */\r
1108 \r
1109   /* Demultiplex this UDP packet between the UDP "connections". */\r
1110   for(uip_udp_conn = &uip_udp_conns[0];\r
1111       uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS];\r
1112       ++uip_udp_conn) {\r
1113     /* If the local UDP port is non-zero, the connection is considered\r
1114        to be used. If so, the local port number is checked against the\r
1115        destination port number in the received packet. If the two port\r
1116        numbers match, the remote port number is checked if the\r
1117        connection is bound to a remote port. Finally, if the\r
1118        connection is bound to a remote IP address, the source IP\r
1119        address of the packet is checked. */\r
1120     if(uip_udp_conn->lport != 0 &&\r
1121        UDPBUF->destport == uip_udp_conn->lport &&\r
1122        (uip_udp_conn->rport == 0 ||\r
1123         UDPBUF->srcport == uip_udp_conn->rport) &&\r
1124        (uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) ||\r
1125         uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) ||\r
1126         uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr))) {\r
1127       goto udp_found;\r
1128     }\r
1129   }\r
1130   UIP_LOG("udp: no matching connection found");\r
1131   goto drop;\r
1132 \r
1133  udp_found:\r
1134   UIP_STAT(++uip_stat.udp.recv);\r
1135   uip_conn = NULL;\r
1136   uip_flags = UIP_NEWDATA;\r
1137   uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];\r
1138   uip_slen = 0;\r
1139   UIP_UDP_APPCALL();\r
1140  udp_send:\r
1141   if(uip_slen == 0) {\r
1142     goto drop;\r
1143   }\r
1144   uip_len = uip_slen + UIP_IPUDPH_LEN;\r
1145 \r
1146 #if UIP_CONF_IPV6\r
1147   /* For IPv6, the IP length field does not include the IPv6 IP header\r
1148      length. */\r
1149   BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);\r
1150   BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);\r
1151 #else /* UIP_CONF_IPV6 */\r
1152   BUF->len[0] = (uip_len >> 8);\r
1153   BUF->len[1] = (uip_len & 0xff);\r
1154 #endif /* UIP_CONF_IPV6 */\r
1155 \r
1156   BUF->ttl = uip_udp_conn->ttl;\r
1157   BUF->proto = UIP_PROTO_UDP;\r
1158 \r
1159   UDPBUF->udplen = HTONS(uip_slen + UIP_UDPH_LEN);\r
1160   UDPBUF->udpchksum = 0;\r
1161 \r
1162   BUF->srcport  = uip_udp_conn->lport;\r
1163   BUF->destport = uip_udp_conn->rport;\r
1164 \r
1165   uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);\r
1166   uip_ipaddr_copy(BUF->destipaddr, uip_udp_conn->ripaddr);\r
1167 \r
1168   uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN];\r
1169 \r
1170 #if UIP_UDP_CHECKSUMS\r
1171   /* Calculate UDP checksum. */\r
1172   UDPBUF->udpchksum = ~(uip_udpchksum());\r
1173   if(UDPBUF->udpchksum == 0) {\r
1174     UDPBUF->udpchksum = 0xffff;\r
1175   }\r
1176 #endif /* UIP_UDP_CHECKSUMS */\r
1177   UIP_STAT(++uip_stat.udp.sent);\r
1178   goto ip_send_nolen;\r
1179 #endif /* UIP_UDP */\r
1180 \r
1181   /* TCP input processing. */\r
1182  tcp_input:\r
1183   UIP_STAT(++uip_stat.tcp.recv);\r
1184 \r
1185   /* Start of TCP input header processing code. */\r
1186 \r
1187   if(uip_tcpchksum() != 0xffff) {   /* Compute and check the TCP\r
1188                                        checksum. */\r
1189     UIP_STAT(++uip_stat.tcp.drop);\r
1190     UIP_STAT(++uip_stat.tcp.chkerr);\r
1191     UIP_LOG("tcp: bad checksum.");\r
1192     goto drop;\r
1193   }\r
1194 \r
1195 \r
1196   /* Demultiplex this segment. */\r
1197   /* First check any active connections. */\r
1198   for(uip_connr = &uip_conns[0]; uip_connr <= &uip_conns[UIP_CONNS - 1];\r
1199       ++uip_connr) {\r
1200     if(uip_connr->tcpstateflags != UIP_CLOSED &&\r
1201        BUF->destport == uip_connr->lport &&\r
1202        BUF->srcport == uip_connr->rport &&\r
1203        uip_ipaddr_cmp(BUF->srcipaddr, uip_connr->ripaddr)) {\r
1204       goto found;\r
1205     }\r
1206   }\r
1207 \r
1208   /* If we didn't find and active connection that expected the packet,\r
1209      either this packet is an old duplicate, or this is a SYN packet\r
1210      destined for a connection in LISTEN. If the SYN flag isn't set,\r
1211      it is an old packet and we send a RST. */\r
1212   if((BUF->flags & TCP_CTL) != TCP_SYN) {\r
1213     goto reset;\r
1214   }\r
1215 \r
1216   tmp16 = BUF->destport;\r
1217   /* Next, check listening connections. */\r
1218   for(c = 0; c < UIP_LISTENPORTS; ++c) {\r
1219     if(tmp16 == uip_listenports[c])\r
1220       goto found_listen;\r
1221   }\r
1222 \r
1223   /* No matching connection found, so we send a RST packet. */\r
1224   UIP_STAT(++uip_stat.tcp.synrst);\r
1225  reset:\r
1226 \r
1227   /* We do not send resets in response to resets. */\r
1228   if(BUF->flags & TCP_RST) {\r
1229     goto drop;\r
1230   }\r
1231 \r
1232   UIP_STAT(++uip_stat.tcp.rst);\r
1233 \r
1234   BUF->flags = TCP_RST | TCP_ACK;\r
1235   uip_len = UIP_IPTCPH_LEN;\r
1236   BUF->tcpoffset = 5 << 4;\r
1237 \r
1238   /* Flip the seqno and ackno fields in the TCP header. */\r
1239   c = BUF->seqno[3];\r
1240   BUF->seqno[3] = BUF->ackno[3];\r
1241   BUF->ackno[3] = c;\r
1242 \r
1243   c = BUF->seqno[2];\r
1244   BUF->seqno[2] = BUF->ackno[2];\r
1245   BUF->ackno[2] = c;\r
1246 \r
1247   c = BUF->seqno[1];\r
1248   BUF->seqno[1] = BUF->ackno[1];\r
1249   BUF->ackno[1] = c;\r
1250 \r
1251   c = BUF->seqno[0];\r
1252   BUF->seqno[0] = BUF->ackno[0];\r
1253   BUF->ackno[0] = c;\r
1254 \r
1255   /* We also have to increase the sequence number we are\r
1256      acknowledging. If the least significant byte overflowed, we need\r
1257      to propagate the carry to the other bytes as well. */\r
1258   if(++BUF->ackno[3] == 0) {\r
1259     if(++BUF->ackno[2] == 0) {\r
1260       if(++BUF->ackno[1] == 0) {\r
1261         ++BUF->ackno[0];\r
1262       }\r
1263     }\r
1264   }\r
1265 \r
1266   /* Swap port numbers. */\r
1267   tmp16 = BUF->srcport;\r
1268   BUF->srcport = BUF->destport;\r
1269   BUF->destport = tmp16;\r
1270 \r
1271   /* Swap IP addresses. */\r
1272   uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);\r
1273   uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);\r
1274 \r
1275   /* And send out the RST packet! */\r
1276   goto tcp_send_noconn;\r
1277 \r
1278   /* This label will be jumped to if we matched the incoming packet\r
1279      with a connection in LISTEN. In that case, we should create a new\r
1280      connection and send a SYNACK in return. */\r
1281  found_listen:\r
1282   /* First we check if there are any connections avaliable. Unused\r
1283      connections are kept in the same table as used connections, but\r
1284      unused ones have the tcpstate set to CLOSED. Also, connections in\r
1285      TIME_WAIT are kept track of and we'll use the oldest one if no\r
1286      CLOSED connections are found. Thanks to Eddie C. Dost for a very\r
1287      nice algorithm for the TIME_WAIT search. */\r
1288   uip_connr = 0;\r
1289   for(c = 0; c < UIP_CONNS; ++c) {\r
1290     if(uip_conns[c].tcpstateflags == UIP_CLOSED) {\r
1291       uip_connr = &uip_conns[c];\r
1292       break;\r
1293     }\r
1294     if(uip_conns[c].tcpstateflags == UIP_TIME_WAIT) {\r
1295       if(uip_connr == 0 ||\r
1296          uip_conns[c].timer > uip_connr->timer) {\r
1297         uip_connr = &uip_conns[c];\r
1298       }\r
1299     }\r
1300   }\r
1301 \r
1302   if(uip_connr == 0) {\r
1303     /* All connections are used already, we drop packet and hope that\r
1304        the remote end will retransmit the packet at a time when we\r
1305        have more spare connections. */\r
1306     UIP_STAT(++uip_stat.tcp.syndrop);\r
1307     UIP_LOG("tcp: found no unused connections.");\r
1308     goto drop;\r
1309   }\r
1310   uip_conn = uip_connr;\r
1311 \r
1312   /* Fill in the necessary fields for the new connection. */\r
1313   uip_connr->rto = uip_connr->timer = UIP_RTO;\r
1314   uip_connr->sa = 0;\r
1315   uip_connr->sv = 4;\r
1316   uip_connr->nrtx = 0;\r
1317   uip_connr->lport = BUF->destport;\r
1318   uip_connr->rport = BUF->srcport;\r
1319   uip_ipaddr_copy(uip_connr->ripaddr, BUF->srcipaddr);\r
1320   uip_connr->tcpstateflags = UIP_SYN_RCVD;\r
1321 \r
1322   uip_connr->snd_nxt[0] = iss[0];\r
1323   uip_connr->snd_nxt[1] = iss[1];\r
1324   uip_connr->snd_nxt[2] = iss[2];\r
1325   uip_connr->snd_nxt[3] = iss[3];\r
1326   uip_connr->len = 1;\r
1327 \r
1328   /* rcv_nxt should be the seqno from the incoming packet + 1. */\r
1329   uip_connr->rcv_nxt[3] = BUF->seqno[3];\r
1330   uip_connr->rcv_nxt[2] = BUF->seqno[2];\r
1331   uip_connr->rcv_nxt[1] = BUF->seqno[1];\r
1332   uip_connr->rcv_nxt[0] = BUF->seqno[0];\r
1333   uip_add_rcv_nxt(1);\r
1334 \r
1335   /* Parse the TCP MSS option, if present. */\r
1336   if((BUF->tcpoffset & 0xf0) > 0x50) {\r
1337     for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {\r
1338       opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c];\r
1339       if(opt == TCP_OPT_END) {\r
1340         /* End of options. */\r
1341         break;\r
1342       } else if(opt == TCP_OPT_NOOP) {\r
1343         ++c;\r
1344         /* NOP option. */\r
1345       } else if(opt == TCP_OPT_MSS &&\r
1346                 uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {\r
1347         /* An MSS option with the right option length. */\r
1348         tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |\r
1349           (u16_t)uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c];\r
1350         uip_connr->initialmss = uip_connr->mss =\r
1351           tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;\r
1352 \r
1353         /* And we are done processing options. */\r
1354         break;\r
1355       } else {\r
1356         /* All other options have a length field, so that we easily\r
1357            can skip past them. */\r
1358         if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {\r
1359           /* If the length field is zero, the options are malformed\r
1360              and we don't process them further. */\r
1361           break;\r
1362         }\r
1363         c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];\r
1364       }\r
1365     }\r
1366   }\r
1367 \r
1368   /* Our response will be a SYNACK. */\r
1369 #if UIP_ACTIVE_OPEN\r
1370  tcp_send_synack:\r
1371   BUF->flags = TCP_ACK;\r
1372 \r
1373  tcp_send_syn:\r
1374   BUF->flags |= TCP_SYN;\r
1375 #else /* UIP_ACTIVE_OPEN */\r
1376  tcp_send_synack:\r
1377   BUF->flags = TCP_SYN | TCP_ACK;\r
1378 #endif /* UIP_ACTIVE_OPEN */\r
1379 \r
1380   /* We send out the TCP Maximum Segment Size option with our\r
1381      SYNACK. */\r
1382   BUF->optdata[0] = TCP_OPT_MSS;\r
1383   BUF->optdata[1] = TCP_OPT_MSS_LEN;\r
1384   BUF->optdata[2] = (UIP_TCP_MSS) / 256;\r
1385   BUF->optdata[3] = (UIP_TCP_MSS) & 255;\r
1386   uip_len = UIP_IPTCPH_LEN + TCP_OPT_MSS_LEN;\r
1387   BUF->tcpoffset = ((UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4) << 4;\r
1388   goto tcp_send;\r
1389 \r
1390   /* This label will be jumped to if we found an active connection. */\r
1391  found:\r
1392   uip_conn = uip_connr;\r
1393   uip_flags = 0;\r
1394   /* We do a very naive form of TCP reset processing; we just accept\r
1395      any RST and kill our connection. We should in fact check if the\r
1396      sequence number of this reset is wihtin our advertised window\r
1397      before we accept the reset. */\r
1398   if(BUF->flags & TCP_RST) {\r
1399     uip_connr->tcpstateflags = UIP_CLOSED;\r
1400     UIP_LOG("tcp: got reset, aborting connection.");\r
1401     uip_flags = UIP_ABORT;\r
1402     UIP_APPCALL();\r
1403     goto drop;\r
1404   }\r
1405   /* Calculated the length of the data, if the application has sent\r
1406      any data to us. */\r
1407   c = (BUF->tcpoffset >> 4) << 2;\r
1408   /* uip_len will contain the length of the actual TCP data. This is\r
1409      calculated by subtracing the length of the TCP header (in\r
1410      c) and the length of the IP header (20 bytes). */\r
1411   uip_len = uip_len - c - UIP_IPH_LEN;\r
1412 \r
1413   /* First, check if the sequence number of the incoming packet is\r
1414      what we're expecting next. If not, we send out an ACK with the\r
1415      correct numbers in. */\r
1416   if(!(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) &&\r
1417        ((BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)))) {\r
1418     if((uip_len > 0 || ((BUF->flags & (TCP_SYN | TCP_FIN)) != 0)) &&\r
1419        (BUF->seqno[0] != uip_connr->rcv_nxt[0] ||\r
1420         BUF->seqno[1] != uip_connr->rcv_nxt[1] ||\r
1421         BUF->seqno[2] != uip_connr->rcv_nxt[2] ||\r
1422         BUF->seqno[3] != uip_connr->rcv_nxt[3])) {\r
1423       goto tcp_send_ack;\r
1424     }\r
1425   }\r
1426 \r
1427   /* Next, check if the incoming segment acknowledges any outstanding\r
1428      data. If so, we update the sequence number, reset the length of\r
1429      the outstanding data, calculate RTT estimations, and reset the\r
1430      retransmission timer. */\r
1431   if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) {\r
1432     uip_add32(uip_connr->snd_nxt, uip_connr->len);\r
1433 \r
1434     if(BUF->ackno[0] == uip_acc32[0] &&\r
1435        BUF->ackno[1] == uip_acc32[1] &&\r
1436        BUF->ackno[2] == uip_acc32[2] &&\r
1437        BUF->ackno[3] == uip_acc32[3]) {\r
1438       /* Update sequence number. */\r
1439       uip_connr->snd_nxt[0] = uip_acc32[0];\r
1440       uip_connr->snd_nxt[1] = uip_acc32[1];\r
1441       uip_connr->snd_nxt[2] = uip_acc32[2];\r
1442       uip_connr->snd_nxt[3] = uip_acc32[3];\r
1443 \r
1444 \r
1445       /* Do RTT estimation, unless we have done retransmissions. */\r
1446       if(uip_connr->nrtx == 0) {\r
1447         signed char m;\r
1448         m = uip_connr->rto - uip_connr->timer;\r
1449         /* This is taken directly from VJs original code in his paper */\r
1450         m = m - (uip_connr->sa >> 3);\r
1451         uip_connr->sa += m;\r
1452         if(m < 0) {\r
1453           m = -m;\r
1454         }\r
1455         m = m - (uip_connr->sv >> 2);\r
1456         uip_connr->sv += m;\r
1457         uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv;\r
1458 \r
1459       }\r
1460       /* Set the acknowledged flag. */\r
1461       uip_flags = UIP_ACKDATA;\r
1462       /* Reset the retransmission timer. */\r
1463       uip_connr->timer = uip_connr->rto;\r
1464 \r
1465       /* Reset length of outstanding data. */\r
1466       uip_connr->len = 0;\r
1467     }\r
1468 \r
1469   }\r
1470 \r
1471   /* Do different things depending on in what state the connection is. */\r
1472   switch(uip_connr->tcpstateflags & UIP_TS_MASK) {\r
1473     /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not\r
1474         implemented, since we force the application to close when the\r
1475         peer sends a FIN (hence the application goes directly from\r
1476         ESTABLISHED to LAST_ACK). */\r
1477   case UIP_SYN_RCVD:\r
1478     /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and\r
1479        we are waiting for an ACK that acknowledges the data we sent\r
1480        out the last time. Therefore, we want to have the UIP_ACKDATA\r
1481        flag set. If so, we enter the ESTABLISHED state. */\r
1482     if(uip_flags & UIP_ACKDATA) {\r
1483       uip_connr->tcpstateflags = UIP_ESTABLISHED;\r
1484       uip_flags = UIP_CONNECTED;\r
1485       uip_connr->len = 0;\r
1486       if(uip_len > 0) {\r
1487         uip_flags |= UIP_NEWDATA;\r
1488         uip_add_rcv_nxt(uip_len);\r
1489       }\r
1490       uip_slen = 0;\r
1491       UIP_APPCALL();\r
1492       goto appsend;\r
1493     }\r
1494     goto drop;\r
1495 #if UIP_ACTIVE_OPEN\r
1496   case UIP_SYN_SENT:\r
1497     /* In SYN_SENT, we wait for a SYNACK that is sent in response to\r
1498        our SYN. The rcv_nxt is set to sequence number in the SYNACK\r
1499        plus one, and we send an ACK. We move into the ESTABLISHED\r
1500        state. */\r
1501     if((uip_flags & UIP_ACKDATA) &&\r
1502        (BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)) {\r
1503 \r
1504       /* Parse the TCP MSS option, if present. */\r
1505       if((BUF->tcpoffset & 0xf0) > 0x50) {\r
1506         for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {\r
1507           opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c];\r
1508           if(opt == TCP_OPT_END) {\r
1509             /* End of options. */\r
1510             break;\r
1511           } else if(opt == TCP_OPT_NOOP) {\r
1512             ++c;\r
1513             /* NOP option. */\r
1514           } else if(opt == TCP_OPT_MSS &&\r
1515                     uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {\r
1516             /* An MSS option with the right option length. */\r
1517             tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |\r
1518               uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c];\r
1519             uip_connr->initialmss =\r
1520               uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;\r
1521 \r
1522             /* And we are done processing options. */\r
1523             break;\r
1524           } else {\r
1525             /* All other options have a length field, so that we easily\r
1526                can skip past them. */\r
1527             if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {\r
1528               /* If the length field is zero, the options are malformed\r
1529                  and we don't process them further. */\r
1530               break;\r
1531             }\r
1532             c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];\r
1533           }\r
1534         }\r
1535       }\r
1536       uip_connr->tcpstateflags = UIP_ESTABLISHED;\r
1537       uip_connr->rcv_nxt[0] = BUF->seqno[0];\r
1538       uip_connr->rcv_nxt[1] = BUF->seqno[1];\r
1539       uip_connr->rcv_nxt[2] = BUF->seqno[2];\r
1540       uip_connr->rcv_nxt[3] = BUF->seqno[3];\r
1541       uip_add_rcv_nxt(1);\r
1542       uip_flags = UIP_CONNECTED | UIP_NEWDATA;\r
1543       uip_connr->len = 0;\r
1544       uip_len = 0;\r
1545       uip_slen = 0;\r
1546       UIP_APPCALL();\r
1547       goto appsend;\r
1548     }\r
1549     /* Inform the application that the connection failed */\r
1550     uip_flags = UIP_ABORT;\r
1551     UIP_APPCALL();\r
1552     /* The connection is closed after we send the RST */\r
1553     uip_conn->tcpstateflags = UIP_CLOSED;\r
1554     goto reset;\r
1555 #endif /* UIP_ACTIVE_OPEN */\r
1556 \r
1557   case UIP_ESTABLISHED:\r
1558     /* In the ESTABLISHED state, we call upon the application to feed\r
1559     data into the uip_buf. If the UIP_ACKDATA flag is set, the\r
1560     application should put new data into the buffer, otherwise we are\r
1561     retransmitting an old segment, and the application should put that\r
1562     data into the buffer.\r
1563 \r
1564     If the incoming packet is a FIN, we should close the connection on\r
1565     this side as well, and we send out a FIN and enter the LAST_ACK\r
1566     state. We require that there is no outstanding data; otherwise the\r
1567     sequence numbers will be screwed up. */\r
1568 \r
1569     if(BUF->flags & TCP_FIN && !(uip_connr->tcpstateflags & UIP_STOPPED)) {\r
1570       if(uip_outstanding(uip_connr)) {\r
1571         goto drop;\r
1572       }\r
1573       uip_add_rcv_nxt(1 + uip_len);\r
1574       uip_flags |= UIP_CLOSE;\r
1575       if(uip_len > 0) {\r
1576         uip_flags |= UIP_NEWDATA;\r
1577       }\r
1578       UIP_APPCALL();\r
1579       uip_connr->len = 1;\r
1580       uip_connr->tcpstateflags = UIP_LAST_ACK;\r
1581       uip_connr->nrtx = 0;\r
1582     tcp_send_finack:\r
1583       BUF->flags = TCP_FIN | TCP_ACK;\r
1584       goto tcp_send_nodata;\r
1585     }\r
1586 \r
1587     /* Check the URG flag. If this is set, the segment carries urgent\r
1588        data that we must pass to the application. */\r
1589     if((BUF->flags & TCP_URG) != 0) {\r
1590 #if UIP_URGDATA > 0\r
1591       uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1];\r
1592       if(uip_urglen > uip_len) {\r
1593         /* There is more urgent data in the next segment to come. */\r
1594         uip_urglen = uip_len;\r
1595       }\r
1596       uip_add_rcv_nxt(uip_urglen);\r
1597       uip_len -= uip_urglen;\r
1598       uip_urgdata = uip_appdata;\r
1599       uip_appdata += uip_urglen;\r
1600     } else {\r
1601       uip_urglen = 0;\r
1602 #else /* UIP_URGDATA > 0 */\r
1603       uip_appdata = ((char *)uip_appdata) + ((BUF->urgp[0] << 8) | BUF->urgp[1]);\r
1604       uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1];\r
1605 #endif /* UIP_URGDATA > 0 */\r
1606     }\r
1607 \r
1608     /* If uip_len > 0 we have TCP data in the packet, and we flag this\r
1609        by setting the UIP_NEWDATA flag and update the sequence number\r
1610        we acknowledge. If the application has stopped the dataflow\r
1611        using uip_stop(), we must not accept any data packets from the\r
1612        remote host. */\r
1613     if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) {\r
1614       uip_flags |= UIP_NEWDATA;\r
1615       uip_add_rcv_nxt(uip_len);\r
1616     }\r
1617 \r
1618     /* Check if the available buffer space advertised by the other end\r
1619        is smaller than the initial MSS for this connection. If so, we\r
1620        set the current MSS to the window size to ensure that the\r
1621        application does not send more data than the other end can\r
1622        handle.\r
1623 \r
1624        If the remote host advertises a zero window, we set the MSS to\r
1625        the initial MSS so that the application will send an entire MSS\r
1626        of data. This data will not be acknowledged by the receiver,\r
1627        and the application will retransmit it. This is called the\r
1628        "persistent timer" and uses the retransmission mechanim.\r
1629     */\r
1630     tmp16 = ((u16_t)BUF->wnd[0] << 8) + (u16_t)BUF->wnd[1];\r
1631     if(tmp16 > uip_connr->initialmss ||\r
1632        tmp16 == 0) {\r
1633       tmp16 = uip_connr->initialmss;\r
1634     }\r
1635     uip_connr->mss = tmp16;\r
1636 \r
1637     /* If this packet constitutes an ACK for outstanding data (flagged\r
1638        by the UIP_ACKDATA flag, we should call the application since it\r
1639        might want to send more data. If the incoming packet had data\r
1640        from the peer (as flagged by the UIP_NEWDATA flag), the\r
1641        application must also be notified.\r
1642 \r
1643        When the application is called, the global variable uip_len\r
1644        contains the length of the incoming data. The application can\r
1645        access the incoming data through the global pointer\r
1646        uip_appdata, which usually points UIP_IPTCPH_LEN + UIP_LLH_LEN\r
1647        bytes into the uip_buf array.\r
1648 \r
1649        If the application wishes to send any data, this data should be\r
1650        put into the uip_appdata and the length of the data should be\r
1651        put into uip_len. If the application don't have any data to\r
1652        send, uip_len must be set to 0. */\r
1653     if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) {\r
1654       uip_slen = 0;\r
1655       UIP_APPCALL();\r
1656 \r
1657     appsend:\r
1658 \r
1659       if(uip_flags & UIP_ABORT) {\r
1660         uip_slen = 0;\r
1661         uip_connr->tcpstateflags = UIP_CLOSED;\r
1662         BUF->flags = TCP_RST | TCP_ACK;\r
1663         goto tcp_send_nodata;\r
1664       }\r
1665 \r
1666       if(uip_flags & UIP_CLOSE) {\r
1667         uip_slen = 0;\r
1668         uip_connr->len = 1;\r
1669         uip_connr->tcpstateflags = UIP_FIN_WAIT_1;\r
1670         uip_connr->nrtx = 0;\r
1671         BUF->flags = TCP_FIN | TCP_ACK;\r
1672         goto tcp_send_nodata;\r
1673       }\r
1674 \r
1675       /* If uip_slen > 0, the application has data to be sent. */\r
1676       if(uip_slen > 0) {\r
1677 \r
1678         /* If the connection has acknowledged data, the contents of\r
1679            the ->len variable should be discarded. */\r
1680         if((uip_flags & UIP_ACKDATA) != 0) {\r
1681           uip_connr->len = 0;\r
1682         }\r
1683 \r
1684         /* If the ->len variable is non-zero the connection has\r
1685            already data in transit and cannot send anymore right\r
1686            now. */\r
1687         if(uip_connr->len == 0) {\r
1688 \r
1689           /* The application cannot send more than what is allowed by\r
1690              the mss (the minumum of the MSS and the available\r
1691              window). */\r
1692           if(uip_slen > uip_connr->mss) {\r
1693             uip_slen = uip_connr->mss;\r
1694           }\r
1695 \r
1696           /* Remember how much data we send out now so that we know\r
1697              when everything has been acknowledged. */\r
1698           uip_connr->len = uip_slen;\r
1699         } else {\r
1700 \r
1701           /* If the application already had unacknowledged data, we\r
1702              make sure that the application does not send (i.e.,\r
1703              retransmit) out more than it previously sent out. */\r
1704           uip_slen = uip_connr->len;\r
1705         }\r
1706       }\r
1707       uip_connr->nrtx = 0;\r
1708     apprexmit:\r
1709       uip_appdata = uip_sappdata;\r
1710 \r
1711       /* If the application has data to be sent, or if the incoming\r
1712          packet had new data in it, we must send out a packet. */\r
1713       if(uip_slen > 0 && uip_connr->len > 0) {\r
1714         /* Add the length of the IP and TCP headers. */\r
1715         uip_len = uip_connr->len + UIP_TCPIP_HLEN;\r
1716         /* We always set the ACK flag in response packets. */\r
1717         BUF->flags = TCP_ACK | TCP_PSH;\r
1718         /* Send the packet. */\r
1719         goto tcp_send_noopts;\r
1720       }\r
1721       /* If there is no data to send, just send out a pure ACK if\r
1722          there is newdata. */\r
1723       if(uip_flags & UIP_NEWDATA) {\r
1724         uip_len = UIP_TCPIP_HLEN;\r
1725         BUF->flags = TCP_ACK;\r
1726         goto tcp_send_noopts;\r
1727       }\r
1728     }\r
1729     goto drop;\r
1730   case UIP_LAST_ACK:\r
1731     /* We can close this connection if the peer has acknowledged our\r
1732        FIN. This is indicated by the UIP_ACKDATA flag. */\r
1733     if(uip_flags & UIP_ACKDATA) {\r
1734       uip_connr->tcpstateflags = UIP_CLOSED;\r
1735       uip_flags = UIP_CLOSE;\r
1736       UIP_APPCALL();\r
1737     }\r
1738     break;\r
1739 \r
1740   case UIP_FIN_WAIT_1:\r
1741     /* The application has closed the connection, but the remote host\r
1742        hasn't closed its end yet. Thus we do nothing but wait for a\r
1743        FIN from the other side. */\r
1744     if(uip_len > 0) {\r
1745       uip_add_rcv_nxt(uip_len);\r
1746     }\r
1747     if(BUF->flags & TCP_FIN) {\r
1748       if(uip_flags & UIP_ACKDATA) {\r
1749         uip_connr->tcpstateflags = UIP_TIME_WAIT;\r
1750         uip_connr->timer = 0;\r
1751         uip_connr->len = 0;\r
1752       } else {\r
1753         uip_connr->tcpstateflags = UIP_CLOSING;\r
1754       }\r
1755       uip_add_rcv_nxt(1);\r
1756       uip_flags = UIP_CLOSE;\r
1757       UIP_APPCALL();\r
1758       goto tcp_send_ack;\r
1759     } else if(uip_flags & UIP_ACKDATA) {\r
1760       uip_connr->tcpstateflags = UIP_FIN_WAIT_2;\r
1761       uip_connr->len = 0;\r
1762       goto drop;\r
1763     }\r
1764     if(uip_len > 0) {\r
1765       goto tcp_send_ack;\r
1766     }\r
1767     goto drop;\r
1768 \r
1769   case UIP_FIN_WAIT_2:\r
1770     if(uip_len > 0) {\r
1771       uip_add_rcv_nxt(uip_len);\r
1772     }\r
1773     if(BUF->flags & TCP_FIN) {\r
1774       uip_connr->tcpstateflags = UIP_TIME_WAIT;\r
1775       uip_connr->timer = 0;\r
1776       uip_add_rcv_nxt(1);\r
1777       uip_flags = UIP_CLOSE;\r
1778       UIP_APPCALL();\r
1779       goto tcp_send_ack;\r
1780     }\r
1781     if(uip_len > 0) {\r
1782       goto tcp_send_ack;\r
1783     }\r
1784     goto drop;\r
1785 \r
1786   case UIP_TIME_WAIT:\r
1787     goto tcp_send_ack;\r
1788 \r
1789   case UIP_CLOSING:\r
1790     if(uip_flags & UIP_ACKDATA) {\r
1791       uip_connr->tcpstateflags = UIP_TIME_WAIT;\r
1792       uip_connr->timer = 0;\r
1793     }\r
1794   }\r
1795   goto drop;\r
1796 \r
1797 \r
1798   /* We jump here when we are ready to send the packet, and just want\r
1799      to set the appropriate TCP sequence numbers in the TCP header. */\r
1800  tcp_send_ack:\r
1801   BUF->flags = TCP_ACK;\r
1802  tcp_send_nodata:\r
1803   uip_len = UIP_IPTCPH_LEN;\r
1804  tcp_send_noopts:\r
1805   BUF->tcpoffset = (UIP_TCPH_LEN / 4) << 4;\r
1806  tcp_send:\r
1807   /* We're done with the input processing. We are now ready to send a\r
1808      reply. Our job is to fill in all the fields of the TCP and IP\r
1809      headers before calculating the checksum and finally send the\r
1810      packet. */\r
1811   BUF->ackno[0] = uip_connr->rcv_nxt[0];\r
1812   BUF->ackno[1] = uip_connr->rcv_nxt[1];\r
1813   BUF->ackno[2] = uip_connr->rcv_nxt[2];\r
1814   BUF->ackno[3] = uip_connr->rcv_nxt[3];\r
1815 \r
1816   BUF->seqno[0] = uip_connr->snd_nxt[0];\r
1817   BUF->seqno[1] = uip_connr->snd_nxt[1];\r
1818   BUF->seqno[2] = uip_connr->snd_nxt[2];\r
1819   BUF->seqno[3] = uip_connr->snd_nxt[3];\r
1820 \r
1821   BUF->proto = UIP_PROTO_TCP;\r
1822 \r
1823   BUF->srcport  = uip_connr->lport;\r
1824   BUF->destport = uip_connr->rport;\r
1825 \r
1826   uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);\r
1827   uip_ipaddr_copy(BUF->destipaddr, uip_connr->ripaddr);\r
1828 \r
1829   if(uip_connr->tcpstateflags & UIP_STOPPED) {\r
1830     /* If the connection has issued uip_stop(), we advertise a zero\r
1831        window so that the remote host will stop sending data. */\r
1832     BUF->wnd[0] = BUF->wnd[1] = 0;\r
1833   } else {\r
1834     BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8);\r
1835     BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff);\r
1836   }\r
1837 \r
1838  tcp_send_noconn:\r
1839   BUF->ttl = UIP_TTL;\r
1840 #if UIP_CONF_IPV6\r
1841   /* For IPv6, the IP length field does not include the IPv6 IP header\r
1842      length. */\r
1843   BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);\r
1844   BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);\r
1845 #else /* UIP_CONF_IPV6 */\r
1846   BUF->len[0] = (uip_len >> 8);\r
1847   BUF->len[1] = (uip_len & 0xff);\r
1848 #endif /* UIP_CONF_IPV6 */\r
1849 \r
1850   BUF->urgp[0] = BUF->urgp[1] = 0;\r
1851 \r
1852   /* Calculate TCP checksum. */\r
1853   BUF->tcpchksum = 0;\r
1854   BUF->tcpchksum = ~(uip_tcpchksum());\r
1855 \r
1856 #if UIP_UDP\r
1857  ip_send_nolen:\r
1858 #endif /* UIP_UDP */\r
1859 \r
1860 #if UIP_CONF_IPV6\r
1861   BUF->vtc = 0x60;\r
1862   BUF->tcflow = 0x00;\r
1863   BUF->flow = 0x00;\r
1864 #else /* UIP_CONF_IPV6 */\r
1865   BUF->vhl = 0x45;\r
1866   BUF->tos = 0;\r
1867   BUF->ipoffset[0] = BUF->ipoffset[1] = 0;\r
1868   ++ipid;\r
1869   BUF->ipid[0] = ipid >> 8;\r
1870   BUF->ipid[1] = ipid & 0xff;\r
1871   /* Calculate IP checksum. */\r
1872   BUF->ipchksum = 0;\r
1873   BUF->ipchksum = ~(uip_ipchksum());\r
1874   DEBUG_PRINTF("uip ip_send_nolen: chkecum 0x%04x\n", uip_ipchksum());\r
1875 #endif /* UIP_CONF_IPV6 */\r
1876 \r
1877   UIP_STAT(++uip_stat.tcp.sent);\r
1878  send:\r
1879   DEBUG_PRINTF("Sending packet with length %d (%d)\n", uip_len,\r
1880                (BUF->len[0] << 8) | BUF->len[1]);\r
1881 \r
1882   UIP_STAT(++uip_stat.ip.sent);\r
1883   /* Return and let the caller do the actual transmission. */\r
1884   uip_flags = 0;\r
1885   return;\r
1886  drop:\r
1887   uip_len = 0;\r
1888   uip_flags = 0;\r
1889   return;\r
1890 }\r
1891 /*---------------------------------------------------------------------------*/\r
1892 u16_t\r
1893 htons(u16_t val)\r
1894 {\r
1895   return HTONS(val);\r
1896 }\r
1897 /*---------------------------------------------------------------------------*/\r
1898 void\r
1899 uip_send(const void *data, int len)\r
1900 {\r
1901   if(len > 0) {\r
1902     uip_slen = len;\r
1903     if(data != uip_sappdata) {\r
1904       memcpy(uip_sappdata, (data), uip_slen);\r
1905     }\r
1906   }\r
1907 }\r
1908 /** @} */\r