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