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