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