]> git.sur5r.net Git - freertos/blob - Demo/uIP_Demo_IAR_ARM7/uip/uip.c
First version under SVN is V4.0.1
[freertos] / Demo / uIP_Demo_IAR_ARM7 / uip / uip.c
1 /**\r
2  * \addtogroup uip\r
3  * @{\r
4  */\r
5 \r
6 /**\r
7  * \file\r
8  * The uIP TCP/IP stack code.\r
9  * \author Adam Dunkels <adam@dunkels.com>\r
10  */\r
11 \r
12 /*\r
13  * Copyright (c) 2001-2003, Adam Dunkels.\r
14  * All rights reserved.\r
15  *\r
16  * Redistribution and use in source and binary forms, with or without\r
17  * modification, are permitted provided that the following conditions\r
18  * are met:\r
19  * 1. Redistributions of source code must retain the above copyright\r
20  *    notice, this list of conditions and the following disclaimer.\r
21  * 2. Redistributions in binary form must reproduce the above copyright\r
22  *    notice, this list of conditions and the following disclaimer in the\r
23  *    documentation and/or other materials provided with the distribution.\r
24  * 3. The name of the author may not be used to endorse or promote\r
25  *    products derived from this software without specific prior\r
26  *    written permission.\r
27  *\r
28  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS\r
29  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
30  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY\r
32  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE\r
34  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\r
36  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
39  *\r
40  * This file is part of the uIP TCP/IP stack.\r
41  *\r
42  * $Id: uip.c,v 1.62.2.10 2003/10/07 13:23:01 adam Exp $\r
43  *\r
44  */\r
45 \r
46 /*\r
47 This is a small implementation of the IP and TCP protocols (as well as\r
48 some basic ICMP stuff). The implementation couples the IP, TCP and the\r
49 application layers very tightly. To keep the size of the compiled code\r
50 down, this code also features heavy usage of the goto statement.\r
51 \r
52 The principle is that we have a small buffer, called the uip_buf, in\r
53 which the device driver puts an incoming packet. The TCP/IP stack\r
54 parses the headers in the packet, and calls upon the application. If\r
55 the remote host has sent data to the application, this data is present\r
56 in the uip_buf and the application read the data from there. It is up\r
57 to the application to put this data into a byte stream if needed. The\r
58 application will not be fed with data that is out of sequence.\r
59 \r
60 If the application whishes to send data to the peer, it should put its\r
61 data into the uip_buf, 40 bytes from the start of the buffer. The\r
62 TCP/IP stack will calculate the checksums, and fill in the necessary\r
63 header fields and finally send the packet back to the peer.\r
64 */\r
65 \r
66 #include "uip.h"\r
67 #include "uipopt.h"\r
68 #include "uip_arch.h"\r
69 \r
70 /*-----------------------------------------------------------------------------------*/\r
71 /* Variable definitions. */\r
72 \r
73 \r
74 /* The IP address of this host. If it is defined to be fixed (by setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set here. Otherwise, the address */\r
75 #if UIP_FIXEDADDR > 0\r
76 const u16_t uip_hostaddr[2] =\r
77   {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1),\r
78    HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)};\r
79 const u16_t uip_arp_draddr[2] =\r
80   {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1),\r
81    HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)};\r
82 const u16_t uip_arp_netmask[2] =\r
83   {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1),\r
84    HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)};\r
85 #else\r
86 u16_t uip_hostaddr[2];\r
87 u16_t uip_arp_draddr[2], uip_arp_netmask[2];\r
88 #endif /* UIP_FIXEDADDR */\r
89 \r
90 u8_t uip_buf[UIP_BUFSIZE+2];   /* The packet buffer that contains\r
91                                 incoming packets. */\r
92 volatile u8_t *uip_appdata;  /* The uip_appdata pointer points to\r
93                                 application data. */\r
94 volatile u8_t *uip_sappdata;  /* The uip_appdata pointer points to the\r
95                                  application data which is to be sent. */\r
96 #if UIP_URGDATA > 0\r
97 volatile u8_t *uip_urgdata;  /* The uip_urgdata pointer points to\r
98                                 urgent data (out-of-band data), if\r
99                                 present. */\r
100 volatile u8_t uip_urglen, uip_surglen;\r
101 #endif /* UIP_URGDATA > 0 */\r
102 \r
103 volatile u16_t uip_len, uip_slen;\r
104                              /* The uip_len is either 8 or 16 bits,\r
105                                 depending on the maximum packet\r
106                                 size. */\r
107 \r
108 volatile u8_t uip_flags;     /* The uip_flags variable is used for\r
109                                 communication between the TCP/IP stack\r
110                                 and the application program. */\r
111 struct uip_conn *uip_conn;   /* uip_conn always points to the current\r
112                                 connection. */\r
113 \r
114 struct uip_conn uip_conns[UIP_CONNS];\r
115                              /* The uip_conns array holds all TCP\r
116                                 connections. */\r
117 u16_t uip_listenports[UIP_LISTENPORTS];\r
118                              /* The uip_listenports list all currently\r
119                                 listning ports. */\r
120 #if UIP_UDP\r
121 struct uip_udp_conn *uip_udp_conn;\r
122 struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];\r
123 #endif /* UIP_UDP */\r
124 \r
125 \r
126 static u16_t ipid;           /* Ths ipid variable is an increasing\r
127                                 number that is used for the IP ID\r
128                                 field. */\r
129 \r
130 static u8_t iss[4];          /* The iss variable is used for the TCP\r
131                                 initial sequence number. */\r
132 \r
133 #if UIP_ACTIVE_OPEN\r
134 static u16_t lastport;       /* Keeps track of the last port used for\r
135                                 a new connection. */\r
136 #endif /* UIP_ACTIVE_OPEN */\r
137 \r
138 /* Temporary variables. */\r
139 volatile u8_t uip_acc32[4];\r
140 static u8_t c, opt;\r
141 static u16_t tmp16;\r
142 \r
143 /* Structures and definitions. */\r
144 #define TCP_FIN 0x01\r
145 #define TCP_SYN 0x02\r
146 #define TCP_RST 0x04\r
147 #define TCP_PSH 0x08\r
148 #define TCP_ACK 0x10\r
149 #define TCP_URG 0x20\r
150 #define TCP_CTL 0x3f\r
151 \r
152 #define ICMP_ECHO_REPLY 0\r
153 #define ICMP_ECHO       8\r
154 \r
155 /* Macros. */\r
156 #define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])\r
157 #define FBUF ((uip_tcpip_hdr *)&uip_reassbuf[0])\r
158 #define ICMPBUF ((uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN])\r
159 #define UDPBUF ((uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])\r
160 \r
161 #if UIP_STATISTICS == 1\r
162 struct uip_stats uip_stat;\r
163 #define UIP_STAT(s) s\r
164 #else\r
165 #define UIP_STAT(s)\r
166 #endif /* UIP_STATISTICS == 1 */\r
167 \r
168 #if UIP_LOGGING == 1\r
169 #include <stdio.h>\r
170 void uip_log(char *msg);\r
171 #define UIP_LOG(m) uip_log(m)\r
172 #else\r
173 #define UIP_LOG(m)\r
174 #endif /* UIP_LOGGING == 1 */\r
175 \r
176 /*-----------------------------------------------------------------------------------*/\r
177 void\r
178 uip_init(void)\r
179 {\r
180   for(c = 0; c < UIP_LISTENPORTS; ++c) {\r
181     uip_listenports[c] = 0;\r
182   }\r
183   for(c = 0; c < UIP_CONNS; ++c) {\r
184     uip_conns[c].tcpstateflags = CLOSED;\r
185   }\r
186 #if UIP_ACTIVE_OPEN\r
187   lastport = 1024;\r
188 #endif /* UIP_ACTIVE_OPEN */\r
189 \r
190 #if UIP_UDP\r
191   for(c = 0; c < UIP_UDP_CONNS; ++c) {\r
192     uip_udp_conns[c].lport = 0;\r
193   }\r
194 #endif /* UIP_UDP */\r
195 \r
196 \r
197   /* IPv4 initialization. */\r
198 #if UIP_FIXEDADDR == 0\r
199   uip_hostaddr[0] = uip_hostaddr[1] = 0;\r
200 #endif /* UIP_FIXEDADDR */\r
201 \r
202 }\r
203 /*-----------------------------------------------------------------------------------*/\r
204 #if UIP_ACTIVE_OPEN\r
205 struct uip_conn *\r
206 uip_connect(u16_t *ripaddr, u16_t rport)\r
207 {\r
208   register struct uip_conn *conn, *cconn;\r
209 \r
210   /* Find an unused local port. */\r
211  again:\r
212   ++lastport;\r
213 \r
214   if(lastport >= 32000) {\r
215     lastport = 4096;\r
216   }\r
217 \r
218   /* Check if this port is already in use, and if so try to find\r
219      another one. */\r
220   for(c = 0; c < UIP_CONNS; ++c) {\r
221     conn = &uip_conns[c];\r
222     if(conn->tcpstateflags != CLOSED &&\r
223        conn->lport == htons(lastport)) {\r
224       goto again;\r
225     }\r
226   }\r
227 \r
228 \r
229   conn = 0;\r
230   for(c = 0; c < UIP_CONNS; ++c) {\r
231     cconn = &uip_conns[c];\r
232     if(cconn->tcpstateflags == CLOSED) {\r
233       conn = cconn;\r
234       break;\r
235     }\r
236     if(cconn->tcpstateflags == TIME_WAIT) {\r
237       if(conn == 0 ||\r
238          cconn->timer > uip_conn->timer) {\r
239         conn = cconn;\r
240       }\r
241     }\r
242   }\r
243 \r
244   if(conn == 0) {\r
245     return 0;\r
246   }\r
247 \r
248   conn->tcpstateflags = SYN_SENT;\r
249 \r
250   conn->snd_nxt[0] = iss[0];\r
251   conn->snd_nxt[1] = iss[1];\r
252   conn->snd_nxt[2] = iss[2];\r
253   conn->snd_nxt[3] = iss[3];\r
254 \r
255   conn->initialmss = conn->mss = UIP_TCP_MSS;\r
256 \r
257   conn->len = 1;   /* TCP length of the SYN is one. */\r
258   conn->nrtx = 0;\r
259   conn->timer = 1; /* Send the SYN next time around. */\r
260   conn->rto = UIP_RTO;\r
261   conn->sa = 0;\r
262   conn->sv = 16;\r
263   conn->lport = htons(lastport);\r
264   conn->rport = rport;\r
265   conn->ripaddr[0] = ripaddr[0];\r
266   conn->ripaddr[1] = ripaddr[1];\r
267 \r
268   return conn;\r
269 }\r
270 #endif /* UIP_ACTIVE_OPEN */\r
271 /*-----------------------------------------------------------------------------------*/\r
272 #if UIP_UDP\r
273 struct uip_udp_conn *\r
274 uip_udp_new(u16_t *ripaddr, u16_t rport)\r
275 {\r
276   register struct uip_udp_conn *conn;\r
277 \r
278   /* Find an unused local port. */\r
279  again:\r
280   ++lastport;\r
281 \r
282   if(lastport >= 32000) {\r
283     lastport = 4096;\r
284   }\r
285 \r
286   for(c = 0; c < UIP_UDP_CONNS; ++c) {\r
287     if(uip_udp_conns[c].lport == lastport) {\r
288       goto again;\r
289     }\r
290   }\r
291 \r
292 \r
293   conn = 0;\r
294   for(c = 0; c < UIP_UDP_CONNS; ++c) {\r
295     if(uip_udp_conns[c].lport == 0) {\r
296       conn = &uip_udp_conns[c];\r
297       break;\r
298     }\r
299   }\r
300 \r
301   if(conn == 0) {\r
302     return 0;\r
303   }\r
304 \r
305   conn->lport = HTONS(lastport);\r
306   conn->rport = HTONS(rport);\r
307   conn->ripaddr[0] = ripaddr[0];\r
308   conn->ripaddr[1] = ripaddr[1];\r
309 \r
310   return conn;\r
311 }\r
312 #endif /* UIP_UDP */\r
313 /*-----------------------------------------------------------------------------------*/\r
314 void\r
315 uip_unlisten(u16_t port)\r
316 {\r
317   for(c = 0; c < UIP_LISTENPORTS; ++c) {\r
318     if(uip_listenports[c] == port) {\r
319       uip_listenports[c] = 0;\r
320       return;\r
321     }\r
322   }\r
323 }\r
324 /*-----------------------------------------------------------------------------------*/\r
325 void\r
326 uip_listen(u16_t port)\r
327 {\r
328   for(c = 0; c < UIP_LISTENPORTS; ++c) {\r
329     if(uip_listenports[c] == 0) {\r
330       uip_listenports[c] = port;\r
331       return;\r
332     }\r
333   }\r
334 }\r
335 /*-----------------------------------------------------------------------------------*/\r
336 /* XXX: IP fragment reassembly: not well-tested. */\r
337 \r
338 #if UIP_REASSEMBLY\r
339 #define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN)\r
340 static u8_t uip_reassbuf[UIP_REASS_BUFSIZE];\r
341 static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)];\r
342 static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f,\r
343                                     0x0f, 0x07, 0x03, 0x01};\r
344 static u16_t uip_reasslen;\r
345 static u8_t uip_reassflags;\r
346 #define UIP_REASS_FLAG_LASTFRAG 0x01\r
347 static u8_t uip_reasstmr;\r
348 \r
349 #define IP_HLEN 20\r
350 #define IP_MF   0x20\r
351 \r
352 static u8_t\r
353 uip_reass(void)\r
354 {\r
355   u16_t offset, len;\r
356   u16_t i;\r
357 \r
358   /* If ip_reasstmr is zero, no packet is present in the buffer, so we\r
359      write the IP header of the fragment into the reassembly\r
360      buffer. The timer is updated with the maximum age. */\r
361   if(uip_reasstmr == 0) {\r
362     memcpy(uip_reassbuf, &BUF->vhl, IP_HLEN);\r
363     uip_reasstmr = UIP_REASS_MAXAGE;\r
364     uip_reassflags = 0;\r
365     /* Clear the bitmap. */\r
366     memset(uip_reassbitmap, sizeof(uip_reassbitmap), 0);\r
367   }\r
368 \r
369   /* Check if the incoming fragment matches the one currently present\r
370      in the reasembly buffer. If so, we proceed with copying the\r
371      fragment into the buffer. */\r
372   if(BUF->srcipaddr[0] == FBUF->srcipaddr[0] &&\r
373      BUF->srcipaddr[1] == FBUF->srcipaddr[1] &&\r
374      BUF->destipaddr[0] == FBUF->destipaddr[0] &&\r
375      BUF->destipaddr[1] == FBUF->destipaddr[1] &&\r
376      BUF->ipid[0] == FBUF->ipid[0] &&\r
377      BUF->ipid[1] == FBUF->ipid[1]) {\r
378 \r
379     len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4;\r
380     offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8;\r
381 \r
382     /* If the offset or the offset + fragment length overflows the\r
383        reassembly buffer, we discard the entire packet. */\r
384     if(offset > UIP_REASS_BUFSIZE ||\r
385        offset + len > UIP_REASS_BUFSIZE) {\r
386       uip_reasstmr = 0;\r
387       goto nullreturn;\r
388     }\r
389 \r
390     /* Copy the fragment into the reassembly buffer, at the right\r
391        offset. */\r
392     memcpy(&uip_reassbuf[IP_HLEN + offset],\r
393            (char *)BUF + (int)((BUF->vhl & 0x0f) * 4),\r
394            len);\r
395 \r
396     /* Update the bitmap. */\r
397     if(offset / (8 * 8) == (offset + len) / (8 * 8)) {\r
398       /* If the two endpoints are in the same byte, we only update\r
399          that byte. */\r
400         \r
401       uip_reassbitmap[offset / (8 * 8)] |=\r
402              bitmap_bits[(offset / 8 ) & 7] &\r
403              ~bitmap_bits[((offset + len) / 8 ) & 7];\r
404     } else {\r
405       /* If the two endpoints are in different bytes, we update the\r
406          bytes in the endpoints and fill the stuff inbetween with\r
407          0xff. */\r
408       uip_reassbitmap[offset / (8 * 8)] |=\r
409         bitmap_bits[(offset / 8 ) & 7];\r
410       for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) {\r
411         uip_reassbitmap[i] = 0xff;\r
412       }\r
413       uip_reassbitmap[(offset + len) / (8 * 8)] |=\r
414         ~bitmap_bits[((offset + len) / 8 ) & 7];\r
415     }\r
416 \r
417     /* If this fragment has the More Fragments flag set to zero, we\r
418        know that this is the last fragment, so we can calculate the\r
419        size of the entire packet. We also set the\r
420        IP_REASS_FLAG_LASTFRAG flag to indicate that we have received\r
421        the final fragment. */\r
422 \r
423     if((BUF->ipoffset[0] & IP_MF) == 0) {\r
424       uip_reassflags |= UIP_REASS_FLAG_LASTFRAG;\r
425       uip_reasslen = offset + len;\r
426     }\r
427 \r
428     /* Finally, we check if we have a full packet in the buffer. We do\r
429        this by checking if we have the last fragment and if all bits\r
430        in the bitmap are set. */\r
431     if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) {\r
432       /* Check all bytes up to and including all but the last byte in\r
433          the bitmap. */\r
434       for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) {\r
435         if(uip_reassbitmap[i] != 0xff) {\r
436           goto nullreturn;\r
437         }\r
438       }\r
439       /* Check the last byte in the bitmap. It should contain just the\r
440          right amount of bits. */\r
441       if(uip_reassbitmap[uip_reasslen / (8 * 8)] !=\r
442          (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) {\r
443         goto nullreturn;\r
444       }\r
445 \r
446       /* If we have come this far, we have a full packet in the\r
447          buffer, so we allocate a pbuf and copy the packet into it. We\r
448          also reset the timer. */\r
449       uip_reasstmr = 0;\r
450       memcpy(BUF, FBUF, uip_reasslen);\r
451 \r
452       /* Pretend to be a "normal" (i.e., not fragmented) IP packet\r
453          from now on. */\r
454       BUF->ipoffset[0] = BUF->ipoffset[1] = 0;\r
455       BUF->len[0] = uip_reasslen >> 8;\r
456       BUF->len[1] = uip_reasslen & 0xff;\r
457       BUF->ipchksum = 0;\r
458       BUF->ipchksum = ~(uip_ipchksum());\r
459 \r
460       return uip_reasslen;\r
461     }\r
462   }\r
463 \r
464  nullreturn:\r
465   return 0;\r
466 }\r
467 #endif /* UIP_REASSEMBL */\r
468 /*-----------------------------------------------------------------------------------*/\r
469 static void\r
470 uip_add_rcv_nxt(u16_t n)\r
471 {\r
472   uip_add32(uip_conn->rcv_nxt, n);\r
473   uip_conn->rcv_nxt[0] = uip_acc32[0];\r
474   uip_conn->rcv_nxt[1] = uip_acc32[1];\r
475   uip_conn->rcv_nxt[2] = uip_acc32[2];\r
476   uip_conn->rcv_nxt[3] = uip_acc32[3];\r
477 }\r
478 /*-----------------------------------------------------------------------------------*/\r
479 void\r
480 uip_process(u8_t flag)\r
481 {\r
482   register struct uip_conn *uip_connr = uip_conn;\r
483 \r
484   uip_appdata = &uip_buf[40 + UIP_LLH_LEN];\r
485 \r
486 \r
487   /* Check if we were invoked because of the perodic timer fireing. */\r
488   if(flag == UIP_TIMER) {\r
489 #if UIP_REASSEMBLY\r
490     if(uip_reasstmr != 0) {\r
491       --uip_reasstmr;\r
492     }\r
493 #endif /* UIP_REASSEMBLY */\r
494     /* Increase the initial sequence number. */\r
495     if(++iss[3] == 0) {\r
496       if(++iss[2] == 0) {\r
497         if(++iss[1] == 0) {\r
498           ++iss[0];\r
499         }\r
500       }\r
501     }\r
502     uip_len = 0;\r
503     if(uip_connr->tcpstateflags == TIME_WAIT ||\r
504        uip_connr->tcpstateflags == FIN_WAIT_2) {\r
505       ++(uip_connr->timer);\r
506       if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) {\r
507         uip_connr->tcpstateflags = CLOSED;\r
508       }\r
509     } else if(uip_connr->tcpstateflags != CLOSED) {\r
510       /* If the connection has outstanding data, we increase the\r
511          connection's timer and see if it has reached the RTO value\r
512          in which case we retransmit. */\r
513       if(uip_outstanding(uip_connr)) {\r
514         if(uip_connr->timer-- == 0) {\r
515           if(uip_connr->nrtx == UIP_MAXRTX ||\r
516              ((uip_connr->tcpstateflags == SYN_SENT ||\r
517                uip_connr->tcpstateflags == SYN_RCVD) &&\r
518               uip_connr->nrtx == UIP_MAXSYNRTX)) {\r
519             uip_connr->tcpstateflags = CLOSED;\r
520 \r
521             /* We call UIP_APPCALL() with uip_flags set to\r
522                UIP_TIMEDOUT to inform the application that the\r
523                connection has timed out. */\r
524             uip_flags = UIP_TIMEDOUT;\r
525             UIP_APPCALL();\r
526 \r
527             /* We also send a reset packet to the remote host. */\r
528             BUF->flags = TCP_RST | TCP_ACK;\r
529             goto tcp_send_nodata;\r
530           }\r
531 \r
532           /* Exponential backoff. */\r
533           uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4?\r
534                                          4:\r
535                                          uip_connr->nrtx);\r
536           ++(uip_connr->nrtx);\r
537         \r
538           /* Ok, so we need to retransmit. We do this differently\r
539              depending on which state we are in. In ESTABLISHED, we\r
540              call upon the application so that it may prepare the\r
541              data for the retransmit. In SYN_RCVD, we resend the\r
542              SYNACK that we sent earlier and in LAST_ACK we have to\r
543              retransmit our FINACK. */\r
544           UIP_STAT(++uip_stat.tcp.rexmit);\r
545           switch(uip_connr->tcpstateflags & TS_MASK) {\r
546           case SYN_RCVD:\r
547             /* In the SYN_RCVD state, we should retransmit our\r
548                SYNACK. */\r
549             goto tcp_send_synack;\r
550         \r
551 #if UIP_ACTIVE_OPEN\r
552           case SYN_SENT:\r
553             /* In the SYN_SENT state, we retransmit out SYN. */\r
554             BUF->flags = 0;\r
555             goto tcp_send_syn;\r
556 #endif /* UIP_ACTIVE_OPEN */\r
557         \r
558           case ESTABLISHED:\r
559             /* In the ESTABLISHED state, we call upon the application\r
560                to do the actual retransmit after which we jump into\r
561                the code for sending out the packet (the apprexmit\r
562                label). */\r
563             uip_len = 0;\r
564             uip_slen = 0;\r
565             uip_flags = UIP_REXMIT;\r
566             UIP_APPCALL();\r
567             goto apprexmit;\r
568         \r
569           case FIN_WAIT_1:\r
570           case CLOSING:\r
571           case LAST_ACK:\r
572             /* In all these states we should retransmit a FINACK. */\r
573             goto tcp_send_finack;\r
574         \r
575           }\r
576         }\r
577       } else if((uip_connr->tcpstateflags & TS_MASK) == ESTABLISHED) {\r
578         /* If there was no need for a retransmission, we poll the\r
579            application for new data. */\r
580         uip_len = 0;\r
581         uip_slen = 0;\r
582         uip_flags = UIP_POLL;\r
583         UIP_APPCALL();\r
584         goto appsend;\r
585       }\r
586     }\r
587     goto drop;\r
588   }\r
589 #if UIP_UDP\r
590   if(flag == UIP_UDP_TIMER) {\r
591     if(uip_udp_conn->lport != 0) {\r
592       uip_appdata = &uip_buf[UIP_LLH_LEN + 28];\r
593       uip_len = uip_slen = 0;\r
594       uip_flags = UIP_POLL;\r
595       UIP_UDP_APPCALL();\r
596       goto udp_send;\r
597     } else {\r
598       goto drop;\r
599     }\r
600   }\r
601 #endif\r
602 \r
603   /* This is where the input processing starts. */\r
604   UIP_STAT(++uip_stat.ip.recv);\r
605 \r
606 \r
607   /* Start of IPv4 input header processing code. */\r
608 \r
609   /* Check validity of the IP header. */\r
610   if(BUF->vhl != 0x45)  { /* IP version and header length. */\r
611     UIP_STAT(++uip_stat.ip.drop);\r
612     UIP_STAT(++uip_stat.ip.vhlerr);\r
613     UIP_LOG("ip: invalid version or header length.");\r
614     goto drop;\r
615   }\r
616 \r
617   /* Check the size of the packet. If the size reported to us in\r
618      uip_len doesn't match the size reported in the IP header, there\r
619      has been a transmission error and we drop the packet. */\r
620 \r
621   if(BUF->len[0] != (uip_len >> 8)) { /* IP length, high byte. */\r
622     uip_len = (uip_len & 0xff) | (BUF->len[0] << 8);\r
623   }\r
624   if(BUF->len[1] != (uip_len & 0xff)) { /* IP length, low byte. */\r
625     uip_len = (uip_len & 0xff00) | BUF->len[1];\r
626   }\r
627 \r
628   /* Check the fragment flag. */\r
629   if((BUF->ipoffset[0] & 0x3f) != 0 ||\r
630      BUF->ipoffset[1] != 0) {\r
631 #if UIP_REASSEMBLY\r
632     uip_len = uip_reass();\r
633     if(uip_len == 0) {\r
634       goto drop;\r
635     }\r
636 #else\r
637     UIP_STAT(++uip_stat.ip.drop);\r
638     UIP_STAT(++uip_stat.ip.fragerr);\r
639     UIP_LOG("ip: fragment dropped.");\r
640     goto drop;\r
641 #endif /* UIP_REASSEMBLY */\r
642   }\r
643 \r
644   /* If we are configured to use ping IP address configuration and\r
645      hasn't been assigned an IP address yet, we accept all ICMP\r
646      packets. */\r
647 #if UIP_PINGADDRCONF\r
648   if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) {\r
649     if(BUF->proto == UIP_PROTO_ICMP) {\r
650       UIP_LOG("ip: possible ping config packet received.");\r
651       goto icmp_input;\r
652     } else {\r
653       UIP_LOG("ip: packet dropped since no address assigned.");\r
654       goto drop;\r
655     }\r
656   }\r
657 #endif /* UIP_PINGADDRCONF */\r
658 \r
659   /* Check if the packet is destined for our IP address. */\r
660   if(BUF->destipaddr[0] != uip_hostaddr[0]) {\r
661     UIP_STAT(++uip_stat.ip.drop);\r
662     UIP_LOG("ip: packet not for us.");\r
663     goto drop;\r
664   }\r
665   if(BUF->destipaddr[1] != uip_hostaddr[1]) {\r
666     UIP_STAT(++uip_stat.ip.drop);\r
667     UIP_LOG("ip: packet not for us.");\r
668     goto drop;\r
669   }\r
670 \r
671 #if 0\r
672   // IP checksum is wrong through Netgear DSL router\r
673   if (uip_ipchksum() != 0xffff) { /* Compute and check the IP header\r
674                                     checksum. */\r
675     UIP_STAT(++uip_stat.ip.drop);\r
676     UIP_STAT(++uip_stat.ip.chkerr);\r
677     UIP_LOG("ip: bad checksum.");\r
678     goto drop;\r
679   }\r
680 #endif\r
681 \r
682   if(BUF->proto == UIP_PROTO_TCP)  /* Check for TCP packet. If so, jump\r
683                                      to the tcp_input label. */\r
684     goto tcp_input;\r
685 \r
686 #if UIP_UDP\r
687   if(BUF->proto == UIP_PROTO_UDP)\r
688     goto udp_input;\r
689 #endif /* UIP_UDP */\r
690 \r
691   if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from\r
692                                         here. */\r
693     UIP_STAT(++uip_stat.ip.drop);\r
694     UIP_STAT(++uip_stat.ip.protoerr);\r
695     UIP_LOG("ip: neither tcp nor icmp.");\r
696     goto drop;\r
697   }\r
698 \r
699 #if UIP_PINGADDRCONF\r
700  icmp_input:\r
701 #endif\r
702   UIP_STAT(++uip_stat.icmp.recv);\r
703 \r
704   /* ICMP echo (i.e., ping) processing. This is simple, we only change\r
705      the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP\r
706      checksum before we return the packet. */\r
707   if(ICMPBUF->type != ICMP_ECHO) {\r
708     UIP_STAT(++uip_stat.icmp.drop);\r
709     UIP_STAT(++uip_stat.icmp.typeerr);\r
710     UIP_LOG("icmp: not icmp echo.");\r
711     goto drop;\r
712   }\r
713 \r
714   /* If we are configured to use ping IP address assignment, we use\r
715      the destination IP address of this ping packet and assign it to\r
716      ourself. */\r
717 #if UIP_PINGADDRCONF\r
718   if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) {\r
719     uip_hostaddr[0] = BUF->destipaddr[0];\r
720     uip_hostaddr[1] = BUF->destipaddr[1];\r
721   }\r
722 #endif /* UIP_PINGADDRCONF */\r
723 \r
724   ICMPBUF->type = ICMP_ECHO_REPLY;\r
725 \r
726   if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) {\r
727     ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1;\r
728   } else {\r
729     ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8);\r
730   }\r
731 \r
732   /* Swap IP addresses. */\r
733   tmp16 = BUF->destipaddr[0];\r
734   BUF->destipaddr[0] = BUF->srcipaddr[0];\r
735   BUF->srcipaddr[0] = tmp16;\r
736   tmp16 = BUF->destipaddr[1];\r
737   BUF->destipaddr[1] = BUF->srcipaddr[1];\r
738   BUF->srcipaddr[1] = tmp16;\r
739 \r
740   UIP_STAT(++uip_stat.icmp.sent);\r
741   goto send;\r
742 \r
743   /* End of IPv4 input header processing code. */\r
744 \r
745 \r
746 #if UIP_UDP\r
747   /* UDP input processing. */\r
748  udp_input:\r
749   /* UDP processing is really just a hack. We don't do anything to the\r
750      UDP/IP headers, but let the UDP application do all the hard\r
751      work. If the application sets uip_slen, it has a packet to\r
752      send. */\r
753 #if UIP_UDP_CHECKSUMS\r
754   if(uip_udpchksum() != 0xffff) {\r
755     UIP_STAT(++uip_stat.udp.drop);\r
756     UIP_STAT(++uip_stat.udp.chkerr);\r
757     UIP_LOG("udp: bad checksum.");\r
758     goto drop;\r
759   }\r
760 #endif /* UIP_UDP_CHECKSUMS */\r
761 \r
762   /* Demultiplex this UDP packet between the UDP "connections". */\r
763   for(uip_udp_conn = &uip_udp_conns[0];\r
764       uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS];\r
765       ++uip_udp_conn) {\r
766     if(uip_udp_conn->lport != 0 &&\r
767        UDPBUF->destport == uip_udp_conn->lport &&\r
768        (uip_udp_conn->rport == 0 ||\r
769         UDPBUF->srcport == uip_udp_conn->rport) &&\r
770        BUF->srcipaddr[0] == uip_udp_conn->ripaddr[0] &&\r
771        BUF->srcipaddr[1] == uip_udp_conn->ripaddr[1]) {\r
772       goto udp_found;\r
773     }\r
774   }\r
775   goto drop;\r
776 \r
777  udp_found:\r
778   uip_len = uip_len - 28;\r
779   uip_appdata = &uip_buf[UIP_LLH_LEN + 28];\r
780   uip_flags = UIP_NEWDATA;\r
781   uip_slen = 0;\r
782   UIP_UDP_APPCALL();\r
783  udp_send:\r
784   if(uip_slen == 0) {\r
785     goto drop;\r
786   }\r
787   uip_len = uip_slen + 28;\r
788 \r
789   BUF->len[0] = (uip_len >> 8);\r
790   BUF->len[1] = (uip_len & 0xff);\r
791 \r
792   BUF->proto = UIP_PROTO_UDP;\r
793 \r
794   UDPBUF->udplen = HTONS(uip_slen + 8);\r
795   UDPBUF->udpchksum = 0;\r
796 #if UIP_UDP_CHECKSUMS\r
797   /* Calculate UDP checksum. */\r
798   UDPBUF->udpchksum = ~(uip_udpchksum());\r
799   if(UDPBUF->udpchksum == 0) {\r
800     UDPBUF->udpchksum = 0xffff;\r
801   }\r
802 #endif /* UIP_UDP_CHECKSUMS */\r
803 \r
804   BUF->srcport  = uip_udp_conn->lport;\r
805   BUF->destport = uip_udp_conn->rport;\r
806 \r
807   BUF->srcipaddr[0] = uip_hostaddr[0];\r
808   BUF->srcipaddr[1] = uip_hostaddr[1];\r
809   BUF->destipaddr[0] = uip_udp_conn->ripaddr[0];\r
810   BUF->destipaddr[1] = uip_udp_conn->ripaddr[1];\r
811 \r
812   uip_appdata = &uip_buf[UIP_LLH_LEN + 40];\r
813   goto ip_send_nolen;\r
814 #endif /* UIP_UDP */\r
815 \r
816   /* TCP input processing. */\r
817  tcp_input:\r
818   UIP_STAT(++uip_stat.tcp.recv);\r
819 \r
820   /* Start of TCP input header processing code. */\r
821 \r
822 #if 1  // FIXME\r
823   if(uip_tcpchksum() != 0xffff) {   /* Compute and check the TCP\r
824                                        checksum. */\r
825     UIP_STAT(++uip_stat.tcp.drop);\r
826     UIP_STAT(++uip_stat.tcp.chkerr);\r
827     UIP_LOG("tcp: bad checksum.");\r
828     goto drop;\r
829   }\r
830 #endif\r
831 \r
832   /* Demultiplex this segment. */\r
833   /* First check any active connections. */\r
834   for(uip_connr = &uip_conns[0]; uip_connr < &uip_conns[UIP_CONNS]; ++uip_connr) {\r
835     if(uip_connr->tcpstateflags != CLOSED &&\r
836        BUF->destport == uip_connr->lport &&\r
837        BUF->srcport == uip_connr->rport &&\r
838        BUF->srcipaddr[0] == uip_connr->ripaddr[0] &&\r
839        BUF->srcipaddr[1] == uip_connr->ripaddr[1]) {\r
840       goto found;\r
841     }\r
842   }\r
843 \r
844   /* If we didn't find and active connection that expected the packet,\r
845      either this packet is an old duplicate, or this is a SYN packet\r
846      destined for a connection in LISTEN. If the SYN flag isn't set,\r
847      it is an old packet and we send a RST. */\r
848   if((BUF->flags & TCP_CTL) != TCP_SYN)\r
849     goto reset;\r
850 \r
851   tmp16 = BUF->destport;\r
852   /* Next, check listening connections. */\r
853   for(c = 0; c < UIP_LISTENPORTS; ++c) {\r
854     if(tmp16 == uip_listenports[c])\r
855       goto found_listen;\r
856   }\r
857 \r
858   /* No matching connection found, so we send a RST packet. */\r
859   UIP_STAT(++uip_stat.tcp.synrst);\r
860  reset:\r
861 \r
862   /* We do not send resets in response to resets. */\r
863   if(BUF->flags & TCP_RST)\r
864     goto drop;\r
865 \r
866   UIP_STAT(++uip_stat.tcp.rst);\r
867 \r
868   BUF->flags = TCP_RST | TCP_ACK;\r
869   uip_len = 40;\r
870   BUF->tcpoffset = 5 << 4;\r
871 \r
872   /* Flip the seqno and ackno fields in the TCP header. */\r
873   c = BUF->seqno[3];\r
874   BUF->seqno[3] = BUF->ackno[3];\r
875   BUF->ackno[3] = c;\r
876 \r
877   c = BUF->seqno[2];\r
878   BUF->seqno[2] = BUF->ackno[2];\r
879   BUF->ackno[2] = c;\r
880 \r
881   c = BUF->seqno[1];\r
882   BUF->seqno[1] = BUF->ackno[1];\r
883   BUF->ackno[1] = c;\r
884 \r
885   c = BUF->seqno[0];\r
886   BUF->seqno[0] = BUF->ackno[0];\r
887   BUF->ackno[0] = c;\r
888 \r
889   /* We also have to increase the sequence number we are\r
890      acknowledging. If the least significant byte overflowed, we need\r
891      to propagate the carry to the other bytes as well. */\r
892   if(++BUF->ackno[3] == 0) {\r
893     if(++BUF->ackno[2] == 0) {\r
894       if(++BUF->ackno[1] == 0) {\r
895         ++BUF->ackno[0];\r
896       }\r
897     }\r
898   }\r
899 \r
900   /* Swap port numbers. */\r
901   tmp16 = BUF->srcport;\r
902   BUF->srcport = BUF->destport;\r
903   BUF->destport = tmp16;\r
904 \r
905   /* Swap IP addresses. */\r
906   tmp16 = BUF->destipaddr[0];\r
907   BUF->destipaddr[0] = BUF->srcipaddr[0];\r
908   BUF->srcipaddr[0] = tmp16;\r
909   tmp16 = BUF->destipaddr[1];\r
910   BUF->destipaddr[1] = BUF->srcipaddr[1];\r
911   BUF->srcipaddr[1] = tmp16;\r
912 \r
913 \r
914   /* And send out the RST packet! */\r
915   goto tcp_send_noconn;\r
916 \r
917   /* This label will be jumped to if we matched the incoming packet\r
918      with a connection in LISTEN. In that case, we should create a new\r
919      connection and send a SYNACK in return. */\r
920  found_listen:\r
921   /* First we check if there are any connections avaliable. Unused\r
922      connections are kept in the same table as used connections, but\r
923      unused ones have the tcpstate set to CLOSED. Also, connections in\r
924      TIME_WAIT are kept track of and we'll use the oldest one if no\r
925      CLOSED connections are found. Thanks to Eddie C. Dost for a very\r
926      nice algorithm for the TIME_WAIT search. */\r
927   uip_connr = 0;\r
928   for(c = 0; c < UIP_CONNS; ++c) {\r
929     if(uip_conns[c].tcpstateflags == CLOSED) {\r
930       uip_connr = &uip_conns[c];\r
931       break;\r
932     }\r
933     if(uip_conns[c].tcpstateflags == TIME_WAIT) {\r
934       if(uip_connr == 0 ||\r
935          uip_conns[c].timer > uip_connr->timer) {\r
936         uip_connr = &uip_conns[c];\r
937       }\r
938     }\r
939   }\r
940 \r
941   if(uip_connr == 0) {\r
942     /* All connections are used already, we drop packet and hope that\r
943        the remote end will retransmit the packet at a time when we\r
944        have more spare connections. */\r
945     UIP_STAT(++uip_stat.tcp.syndrop);\r
946     UIP_LOG("tcp: found no unused connections.");\r
947     goto drop;\r
948   }\r
949   uip_conn = uip_connr;\r
950 \r
951   /* Fill in the necessary fields for the new connection. */\r
952   uip_connr->rto = uip_connr->timer = UIP_RTO;\r
953   uip_connr->sa = 0;\r
954   uip_connr->sv = 4;\r
955   uip_connr->nrtx = 0;\r
956   uip_connr->lport = BUF->destport;\r
957   uip_connr->rport = BUF->srcport;\r
958   uip_connr->ripaddr[0] = BUF->srcipaddr[0];\r
959   uip_connr->ripaddr[1] = BUF->srcipaddr[1];\r
960   uip_connr->tcpstateflags = SYN_RCVD;\r
961 \r
962   uip_connr->snd_nxt[0] = iss[0];\r
963   uip_connr->snd_nxt[1] = iss[1];\r
964   uip_connr->snd_nxt[2] = iss[2];\r
965   uip_connr->snd_nxt[3] = iss[3];\r
966   uip_connr->len = 1;\r
967 \r
968   /* rcv_nxt should be the seqno from the incoming packet + 1. */\r
969   uip_connr->rcv_nxt[3] = BUF->seqno[3];\r
970   uip_connr->rcv_nxt[2] = BUF->seqno[2];\r
971   uip_connr->rcv_nxt[1] = BUF->seqno[1];\r
972   uip_connr->rcv_nxt[0] = BUF->seqno[0];\r
973   uip_add_rcv_nxt(1);\r
974 \r
975   /* Parse the TCP MSS option, if present. */\r
976   if((BUF->tcpoffset & 0xf0) > 0x50) {\r
977     for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {\r
978       opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c];\r
979       if(opt == 0x00) {\r
980         /* End of options. */   \r
981         break;\r
982       } else if(opt == 0x01) {\r
983         ++c;\r
984         /* NOP option. */\r
985       } else if(opt == 0x02 &&\r
986                 uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) {\r
987         /* An MSS option with the right option length. */       \r
988         tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |\r
989           (u16_t)uip_buf[40 + UIP_LLH_LEN + 3 + c];\r
990         uip_connr->initialmss = uip_connr->mss =\r
991           tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;\r
992         \r
993         /* And we are done processing options. */\r
994         break;\r
995       } else {\r
996         /* All other options have a length field, so that we easily\r
997            can skip past them. */\r
998         if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {\r
999           /* If the length field is zero, the options are malformed\r
1000              and we don't process them further. */\r
1001           break;\r
1002         }\r
1003         c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];\r
1004       }\r
1005     }\r
1006   }\r
1007 \r
1008   /* Our response will be a SYNACK. */\r
1009 #if UIP_ACTIVE_OPEN\r
1010  tcp_send_synack:\r
1011   BUF->flags = TCP_ACK;\r
1012 \r
1013  tcp_send_syn:\r
1014   BUF->flags |= TCP_SYN;\r
1015 #else /* UIP_ACTIVE_OPEN */\r
1016  tcp_send_synack:\r
1017   BUF->flags = TCP_SYN | TCP_ACK;\r
1018 #endif /* UIP_ACTIVE_OPEN */\r
1019 \r
1020   /* We send out the TCP Maximum Segment Size option with our\r
1021      SYNACK. */\r
1022   BUF->optdata[0] = 2;\r
1023   BUF->optdata[1] = 4;\r
1024   BUF->optdata[2] = (UIP_TCP_MSS) / 256;\r
1025   BUF->optdata[3] = (UIP_TCP_MSS) & 255;\r
1026   uip_len = 44;\r
1027   BUF->tcpoffset = 6 << 4;\r
1028   goto tcp_send;\r
1029 \r
1030   /* This label will be jumped to if we found an active connection. */\r
1031  found:\r
1032   uip_conn = uip_connr;\r
1033   uip_flags = 0;\r
1034 \r
1035   /* We do a very naive form of TCP reset processing; we just accept\r
1036      any RST and kill our connection. We should in fact check if the\r
1037      sequence number of this reset is wihtin our advertised window\r
1038      before we accept the reset. */\r
1039   if(BUF->flags & TCP_RST) {\r
1040     uip_connr->tcpstateflags = CLOSED;\r
1041     UIP_LOG("tcp: got reset, aborting connection.");\r
1042     uip_flags = UIP_ABORT;\r
1043     UIP_APPCALL();\r
1044     goto drop;\r
1045   }\r
1046   /* Calculated the length of the data, if the application has sent\r
1047      any data to us. */\r
1048   c = (BUF->tcpoffset >> 4) << 2;\r
1049   /* uip_len will contain the length of the actual TCP data. This is\r
1050      calculated by subtracing the length of the TCP header (in\r
1051      c) and the length of the IP header (20 bytes). */\r
1052   uip_len = uip_len - c - 20;\r
1053 \r
1054   /* First, check if the sequence number of the incoming packet is\r
1055      what we're expecting next. If not, we send out an ACK with the\r
1056      correct numbers in. */\r
1057   if(uip_len > 0 &&\r
1058      (BUF->seqno[0] != uip_connr->rcv_nxt[0] ||\r
1059       BUF->seqno[1] != uip_connr->rcv_nxt[1] ||\r
1060       BUF->seqno[2] != uip_connr->rcv_nxt[2] ||\r
1061       BUF->seqno[3] != uip_connr->rcv_nxt[3])) {\r
1062     goto tcp_send_ack;\r
1063   }\r
1064 \r
1065   /* Next, check if the incoming segment acknowledges any outstanding\r
1066      data. If so, we update the sequence number, reset the length of\r
1067      the outstanding data, calculate RTT estimations, and reset the\r
1068      retransmission timer. */\r
1069   if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) {\r
1070     uip_add32(uip_connr->snd_nxt, uip_connr->len);\r
1071     if(BUF->ackno[0] == uip_acc32[0] &&\r
1072        BUF->ackno[1] == uip_acc32[1] &&\r
1073        BUF->ackno[2] == uip_acc32[2] &&\r
1074        BUF->ackno[3] == uip_acc32[3]) {\r
1075       /* Update sequence number. */\r
1076       uip_connr->snd_nxt[0] = uip_acc32[0];\r
1077       uip_connr->snd_nxt[1] = uip_acc32[1];\r
1078       uip_connr->snd_nxt[2] = uip_acc32[2];\r
1079       uip_connr->snd_nxt[3] = uip_acc32[3];\r
1080         \r
1081 \r
1082       /* Do RTT estimation, unless we have done retransmissions. */\r
1083       if(uip_connr->nrtx == 0) {\r
1084         signed char m;\r
1085         m = uip_connr->rto - uip_connr->timer;\r
1086         /* This is taken directly from VJs original code in his paper */\r
1087         m = m - (uip_connr->sa >> 3);\r
1088         uip_connr->sa += m;\r
1089         if(m < 0) {\r
1090           m = -m;\r
1091         }\r
1092         m = m - (uip_connr->sv >> 2);\r
1093         uip_connr->sv += m;\r
1094         uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv;\r
1095 \r
1096       }\r
1097       /* Set the acknowledged flag. */\r
1098       uip_flags = UIP_ACKDATA;\r
1099       /* Reset the retransmission timer. */\r
1100       uip_connr->timer = uip_connr->rto;\r
1101     }\r
1102 \r
1103   }\r
1104 \r
1105   /* Do different things depending on in what state the connection is. */\r
1106   switch(uip_connr->tcpstateflags & TS_MASK) {\r
1107     /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not\r
1108         implemented, since we force the application to close when the\r
1109         peer sends a FIN (hence the application goes directly from\r
1110         ESTABLISHED to LAST_ACK). */\r
1111   case SYN_RCVD:\r
1112     /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and\r
1113        we are waiting for an ACK that acknowledges the data we sent\r
1114        out the last time. Therefore, we want to have the UIP_ACKDATA\r
1115        flag set. If so, we enter the ESTABLISHED state. */\r
1116     if(uip_flags & UIP_ACKDATA) {\r
1117       uip_connr->tcpstateflags = ESTABLISHED;\r
1118       uip_flags = UIP_CONNECTED;\r
1119       uip_connr->len = 0;\r
1120       if(uip_len > 0) {\r
1121         uip_flags |= UIP_NEWDATA;\r
1122         uip_add_rcv_nxt(uip_len);\r
1123       }\r
1124       uip_slen = 0;\r
1125       UIP_APPCALL();\r
1126       goto appsend;\r
1127     }\r
1128     goto drop;\r
1129 #if UIP_ACTIVE_OPEN\r
1130   case SYN_SENT:\r
1131     /* In SYN_SENT, we wait for a SYNACK that is sent in response to\r
1132        our SYN. The rcv_nxt is set to sequence number in the SYNACK\r
1133        plus one, and we send an ACK. We move into the ESTABLISHED\r
1134        state. */\r
1135     if((uip_flags & UIP_ACKDATA) &&\r
1136        BUF->flags == (TCP_SYN | TCP_ACK)) {\r
1137 \r
1138       /* Parse the TCP MSS option, if present. */\r
1139       if((BUF->tcpoffset & 0xf0) > 0x50) {\r
1140         for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {\r
1141           opt = uip_buf[40 + UIP_LLH_LEN + c];\r
1142           if(opt == 0x00) {\r
1143             /* End of options. */       \r
1144             break;\r
1145           } else if(opt == 0x01) {\r
1146             ++c;\r
1147             /* NOP option. */\r
1148           } else if(opt == 0x02 &&\r
1149                     uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) {\r
1150             /* An MSS option with the right option length. */\r
1151             tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |\r
1152               uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c];\r
1153             uip_connr->initialmss =\r
1154               uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;\r
1155 \r
1156             /* And we are done processing options. */\r
1157             break;\r
1158           } else {\r
1159             /* All other options have a length field, so that we easily\r
1160                can skip past them. */\r
1161             if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {\r
1162               /* If the length field is zero, the options are malformed\r
1163                  and we don't process them further. */\r
1164               break;\r
1165             }\r
1166             c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];\r
1167           }\r
1168         }\r
1169       }\r
1170       uip_connr->tcpstateflags = ESTABLISHED;\r
1171       uip_connr->rcv_nxt[0] = BUF->seqno[0];\r
1172       uip_connr->rcv_nxt[1] = BUF->seqno[1];\r
1173       uip_connr->rcv_nxt[2] = BUF->seqno[2];\r
1174       uip_connr->rcv_nxt[3] = BUF->seqno[3];\r
1175       uip_add_rcv_nxt(1);\r
1176       uip_flags = UIP_CONNECTED | UIP_NEWDATA;\r
1177       uip_connr->len = 0;\r
1178       uip_len = 0;\r
1179       uip_slen = 0;\r
1180       UIP_APPCALL();\r
1181       goto appsend;\r
1182     }\r
1183     goto reset;\r
1184 #endif /* UIP_ACTIVE_OPEN */\r
1185 \r
1186   case ESTABLISHED:\r
1187     /* In the ESTABLISHED state, we call upon the application to feed\r
1188     data into the uip_buf. If the UIP_ACKDATA flag is set, the\r
1189     application should put new data into the buffer, otherwise we are\r
1190     retransmitting an old segment, and the application should put that\r
1191     data into the buffer.\r
1192 \r
1193     If the incoming packet is a FIN, we should close the connection on\r
1194     this side as well, and we send out a FIN and enter the LAST_ACK\r
1195     state. We require that there is no outstanding data; otherwise the\r
1196     sequence numbers will be screwed up. */\r
1197 \r
1198     if(BUF->flags & TCP_FIN) {\r
1199       if(uip_outstanding(uip_connr)) {\r
1200         goto drop;\r
1201       }\r
1202       uip_add_rcv_nxt(1 + uip_len);\r
1203       uip_flags = UIP_CLOSE;\r
1204       if(uip_len > 0) {\r
1205         uip_flags |= UIP_NEWDATA;\r
1206       }\r
1207       UIP_APPCALL();\r
1208       uip_connr->len = 1;\r
1209       uip_connr->tcpstateflags = LAST_ACK;\r
1210       uip_connr->nrtx = 0;\r
1211     tcp_send_finack:\r
1212       BUF->flags = TCP_FIN | TCP_ACK;\r
1213       goto tcp_send_nodata;\r
1214     }\r
1215 \r
1216     /* Check the URG flag. If this is set, the segment carries urgent\r
1217        data that we must pass to the application. */\r
1218     if(BUF->flags & TCP_URG) {\r
1219 #if UIP_URGDATA > 0\r
1220       uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1];\r
1221       if(uip_urglen > uip_len) {\r
1222         /* There is more urgent data in the next segment to come. */\r
1223         uip_urglen = uip_len;\r
1224       }\r
1225       uip_add_rcv_nxt(uip_urglen);\r
1226       uip_len -= uip_urglen;\r
1227       uip_urgdata = uip_appdata;\r
1228       uip_appdata += uip_urglen;\r
1229     } else {\r
1230       uip_urglen = 0;\r
1231 #endif /* UIP_URGDATA > 0 */\r
1232       uip_appdata += (BUF->urgp[0] << 8) | BUF->urgp[1];\r
1233       uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1];\r
1234     }\r
1235 \r
1236 \r
1237     /* If uip_len > 0 we have TCP data in the packet, and we flag this\r
1238        by setting the UIP_NEWDATA flag and update the sequence number\r
1239        we acknowledge. If the application has stopped the dataflow\r
1240        using uip_stop(), we must not accept any data packets from the\r
1241        remote host. */\r
1242     if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) {\r
1243       uip_flags |= UIP_NEWDATA;\r
1244       uip_add_rcv_nxt(uip_len);\r
1245     }\r
1246 \r
1247     /* Check if the available buffer space advertised by the other end\r
1248        is smaller than the initial MSS for this connection. If so, we\r
1249        set the current MSS to the window size to ensure that the\r
1250        application does not send more data than the other end can\r
1251        handle.\r
1252 \r
1253        If the remote host advertises a zero window, we set the MSS to\r
1254        the initial MSS so that the application will send an entire MSS\r
1255        of data. This data will not be acknowledged by the receiver,\r
1256        and the application will retransmit it. This is called the\r
1257        "persistent timer" and uses the retransmission mechanim.\r
1258     */\r
1259     tmp16 = ((u16_t)BUF->wnd[0] << 8) + (u16_t)BUF->wnd[1];\r
1260     if(tmp16 > uip_connr->initialmss ||\r
1261        tmp16 == 0) {\r
1262       tmp16 = uip_connr->initialmss;\r
1263     }\r
1264     uip_connr->mss = tmp16;\r
1265 \r
1266     /* If this packet constitutes an ACK for outstanding data (flagged\r
1267        by the UIP_ACKDATA flag, we should call the application since it\r
1268        might want to send more data. If the incoming packet had data\r
1269        from the peer (as flagged by the UIP_NEWDATA flag), the\r
1270        application must also be notified.\r
1271 \r
1272        When the application is called, the global variable uip_len\r
1273        contains the length of the incoming data. The application can\r
1274        access the incoming data through the global pointer\r
1275        uip_appdata, which usually points 40 bytes into the uip_buf\r
1276        array.\r
1277 \r
1278        If the application wishes to send any data, this data should be\r
1279        put into the uip_appdata and the length of the data should be\r
1280        put into uip_len. If the application don't have any data to\r
1281        send, uip_len must be set to 0. */\r
1282     if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) {\r
1283       uip_slen = 0;\r
1284       UIP_APPCALL();\r
1285 \r
1286     appsend:\r
1287 \r
1288       if(uip_flags & UIP_ABORT) {\r
1289         uip_slen = 0;\r
1290         uip_connr->tcpstateflags = CLOSED;\r
1291         BUF->flags = TCP_RST | TCP_ACK;\r
1292         goto tcp_send_nodata;\r
1293       }\r
1294 \r
1295       if(uip_flags & UIP_CLOSE) {\r
1296         uip_slen = 0;\r
1297         uip_connr->len = 1;\r
1298         uip_connr->tcpstateflags = FIN_WAIT_1;\r
1299         uip_connr->nrtx = 0;\r
1300         BUF->flags = TCP_FIN | TCP_ACK;\r
1301         goto tcp_send_nodata;   \r
1302       }\r
1303 \r
1304       /* If uip_slen > 0, the application has data to be sent. */\r
1305       if(uip_slen > 0) {\r
1306 \r
1307         /* If the connection has acknowledged data, the contents of\r
1308            the ->len variable should be discarded. */\r
1309         if((uip_flags & UIP_ACKDATA) != 0) {\r
1310           uip_connr->len = 0;\r
1311         }\r
1312 \r
1313         /* If the ->len variable is non-zero the connection has\r
1314            already data in transit and cannot send anymore right\r
1315            now. */\r
1316         if(uip_connr->len == 0) {\r
1317 \r
1318           /* The application cannot send more than what is allowed by\r
1319              the mss (the minumum of the MSS and the available\r
1320              window). */\r
1321           if(uip_slen > uip_connr->mss) {\r
1322             uip_slen = uip_connr->mss;\r
1323           }\r
1324 \r
1325           /* Remember how much data we send out now so that we know\r
1326              when everything has been acknowledged. */\r
1327           uip_connr->len = uip_slen;\r
1328         } else {\r
1329 \r
1330           /* If the application already had unacknowledged data, we\r
1331              make sure that the application does not send (i.e.,\r
1332              retransmit) out more than it previously sent out. */\r
1333           uip_slen = uip_connr->len;\r
1334         }\r
1335       } else {\r
1336         uip_connr->len = 0;\r
1337       }\r
1338       uip_connr->nrtx = 0;\r
1339     apprexmit:\r
1340       uip_appdata = uip_sappdata;\r
1341 \r
1342       /* If the application has data to be sent, or if the incoming\r
1343          packet had new data in it, we must send out a packet. */\r
1344       if(uip_slen > 0 && uip_connr->len > 0) {\r
1345         /* Add the length of the IP and TCP headers. */\r
1346         uip_len = uip_connr->len + UIP_TCPIP_HLEN;\r
1347         /* We always set the ACK flag in response packets. */\r
1348         BUF->flags = TCP_ACK | TCP_PSH;\r
1349         /* Send the packet. */\r
1350         goto tcp_send_noopts;\r
1351       }\r
1352       /* If there is no data to send, just send out a pure ACK if\r
1353          there is newdata. */\r
1354       if(uip_flags & UIP_NEWDATA) {\r
1355         uip_len = UIP_TCPIP_HLEN;\r
1356         BUF->flags = TCP_ACK;\r
1357         goto tcp_send_noopts;\r
1358       }\r
1359     }\r
1360     goto drop;\r
1361   case LAST_ACK:\r
1362     /* We can close this connection if the peer has acknowledged our\r
1363        FIN. This is indicated by the UIP_ACKDATA flag. */\r
1364     if(uip_flags & UIP_ACKDATA) {\r
1365       uip_connr->tcpstateflags = CLOSED;\r
1366       uip_flags = UIP_CLOSE;\r
1367       UIP_APPCALL();\r
1368     }\r
1369     break;\r
1370 \r
1371   case FIN_WAIT_1:\r
1372     /* The application has closed the connection, but the remote host\r
1373        hasn't closed its end yet. Thus we do nothing but wait for a\r
1374        FIN from the other side. */\r
1375     if(uip_len > 0) {\r
1376       uip_add_rcv_nxt(uip_len);\r
1377     }\r
1378     if(BUF->flags & TCP_FIN) {\r
1379       if(uip_flags & UIP_ACKDATA) {\r
1380         uip_connr->tcpstateflags = TIME_WAIT;\r
1381         uip_connr->timer = 0;\r
1382         uip_connr->len = 0;\r
1383       } else {\r
1384         uip_connr->tcpstateflags = CLOSING;\r
1385       }\r
1386       uip_add_rcv_nxt(1);\r
1387       uip_flags = UIP_CLOSE;\r
1388       UIP_APPCALL();\r
1389       goto tcp_send_ack;\r
1390     } else if(uip_flags & UIP_ACKDATA) {\r
1391       uip_connr->tcpstateflags = FIN_WAIT_2;\r
1392       uip_connr->len = 0;\r
1393       goto drop;\r
1394     }\r
1395     if(uip_len > 0) {\r
1396       goto tcp_send_ack;\r
1397     }\r
1398     goto drop;\r
1399 \r
1400   case FIN_WAIT_2:\r
1401     if(uip_len > 0) {\r
1402       uip_add_rcv_nxt(uip_len);\r
1403     }\r
1404     if(BUF->flags & TCP_FIN) {\r
1405       uip_connr->tcpstateflags = TIME_WAIT;\r
1406       uip_connr->timer = 0;\r
1407       uip_add_rcv_nxt(1);\r
1408       uip_flags = UIP_CLOSE;\r
1409       UIP_APPCALL();\r
1410       goto tcp_send_ack;\r
1411     }\r
1412     if(uip_len > 0) {\r
1413       goto tcp_send_ack;\r
1414     }\r
1415     goto drop;\r
1416 \r
1417   case TIME_WAIT:\r
1418     goto tcp_send_ack;\r
1419 \r
1420   case CLOSING:\r
1421     if(uip_flags & UIP_ACKDATA) {\r
1422       uip_connr->tcpstateflags = TIME_WAIT;\r
1423       uip_connr->timer = 0;\r
1424     }\r
1425   }\r
1426   goto drop;\r
1427 \r
1428 \r
1429   /* We jump here when we are ready to send the packet, and just want\r
1430      to set the appropriate TCP sequence numbers in the TCP header. */\r
1431  tcp_send_ack:\r
1432   BUF->flags = TCP_ACK;\r
1433  tcp_send_nodata:\r
1434   uip_len = 40;\r
1435  tcp_send_noopts:\r
1436   BUF->tcpoffset = 5 << 4;\r
1437  tcp_send:\r
1438   /* We're done with the input processing. We are now ready to send a\r
1439      reply. Our job is to fill in all the fields of the TCP and IP\r
1440      headers before calculating the checksum and finally send the\r
1441      packet. */\r
1442   BUF->ackno[0] = uip_connr->rcv_nxt[0];\r
1443   BUF->ackno[1] = uip_connr->rcv_nxt[1];\r
1444   BUF->ackno[2] = uip_connr->rcv_nxt[2];\r
1445   BUF->ackno[3] = uip_connr->rcv_nxt[3];\r
1446 \r
1447   BUF->seqno[0] = uip_connr->snd_nxt[0];\r
1448   BUF->seqno[1] = uip_connr->snd_nxt[1];\r
1449   BUF->seqno[2] = uip_connr->snd_nxt[2];\r
1450   BUF->seqno[3] = uip_connr->snd_nxt[3];\r
1451 \r
1452   BUF->proto = UIP_PROTO_TCP;\r
1453 \r
1454   BUF->srcport  = uip_connr->lport;\r
1455   BUF->destport = uip_connr->rport;\r
1456 \r
1457   BUF->srcipaddr[0] = uip_hostaddr[0];\r
1458   BUF->srcipaddr[1] = uip_hostaddr[1];\r
1459   BUF->destipaddr[0] = uip_connr->ripaddr[0];\r
1460   BUF->destipaddr[1] = uip_connr->ripaddr[1];\r
1461 \r
1462 \r
1463   if(uip_connr->tcpstateflags & UIP_STOPPED) {\r
1464     /* If the connection has issued uip_stop(), we advertise a zero\r
1465        window so that the remote host will stop sending data. */\r
1466     BUF->wnd[0] = BUF->wnd[1] = 0;\r
1467   } else {\r
1468     BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8);\r
1469     BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff);\r
1470   }\r
1471 \r
1472  tcp_send_noconn:\r
1473 \r
1474   BUF->len[0] = (uip_len >> 8);\r
1475   BUF->len[1] = (uip_len & 0xff);\r
1476 \r
1477   /* Calculate TCP checksum. */\r
1478   BUF->tcpchksum = 0;\r
1479   BUF->tcpchksum = ~(uip_tcpchksum());\r
1480 \r
1481 \r
1482 #if UIP_UDP\r
1483  ip_send_nolen:\r
1484 #endif\r
1485 \r
1486   BUF->vhl = 0x45;\r
1487   BUF->tos = 0;\r
1488   BUF->ipoffset[0] = BUF->ipoffset[1] = 0;\r
1489   BUF->ttl  = UIP_TTL;\r
1490   ++ipid;\r
1491   BUF->ipid[0] = ipid >> 8;\r
1492   BUF->ipid[1] = ipid & 0xff;\r
1493 \r
1494   /* Calculate IP checksum. */\r
1495   BUF->ipchksum = 0;\r
1496   BUF->ipchksum = ~(uip_ipchksum());\r
1497 \r
1498   UIP_STAT(++uip_stat.tcp.sent);\r
1499  send:\r
1500   UIP_STAT(++uip_stat.ip.sent);\r
1501   /* Return and let the caller do the actual transmission. */\r
1502   return;\r
1503  drop:\r
1504   uip_len = 0;\r
1505   return;\r
1506 }\r
1507 /*-----------------------------------------------------------------------------------*/\r
1508 u16_t\r
1509 htons(u16_t val)\r
1510 {\r
1511   return HTONS(val);\r
1512 }\r
1513 /*-----------------------------------------------------------------------------------*/\r
1514 /** @} */\r