FreeRTOS
[armadillo_firmware.git] / FreeRTOS / Common / ethernet / FreeTCPIP / uip.c
blobc03dde4eb616e0f695ae193e2cbc87c2f025d63c
1 //#define DEBUG_PRINTF( ... ) /*printf(__VA_ARGS__)*/
3 /**
4 * \addtogroup uip
5 * @{
6 */
8 /**
9 * \file
10 * The uIP TCP/IP stack code.
11 * \author Adam Dunkels <adam@dunkels.com>
15 * Copyright (c) 2001-2003, Adam Dunkels.
16 * All rights reserved.
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 * 1. Redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in the
25 * documentation and/or other materials provided with the distribution.
26 * 3. The name of the author may not be used to endorse or promote
27 * products derived from this software without specific prior
28 * written permission.
30 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
31 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
34 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
36 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
37 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
38 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
39 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
40 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 * This file is part of the uIP TCP/IP stack.
44 * $Id: uip.c,v 1.15 2008/10/15 08:08:32 adamdunkels Exp $
49 * uIP is a small implementation of the IP, UDP and TCP protocols (as
50 * well as some basic ICMP stuff). The implementation couples the IP,
51 * UDP, TCP and the application layers very tightly. To keep the size
52 * of the compiled code down, this code frequently uses the goto
53 * statement. While it would be possible to break the uip_process()
54 * function into many smaller functions, this would increase the code
55 * size because of the overhead of parameter passing and the fact that
56 * the optimier would not be as efficient.
58 * The principle is that we have a small buffer, called the uip_buf,
59 * in which the device driver puts an incoming packet. The TCP/IP
60 * stack parses the headers in the packet, and calls the
61 * application. If the remote host has sent data to the application,
62 * this data is present in the uip_buf and the application read the
63 * data from there. It is up to the application to put this data into
64 * a byte stream if needed. The application will not be fed with data
65 * that is out of sequence.
67 * If the application whishes to send data to the peer, it should put
68 * its data into the uip_buf. The uip_appdata pointer points to the
69 * first available byte. The TCP/IP stack will calculate the
70 * checksums, and fill in the necessary header fields and finally send
71 * the packet back to the peer.
73 #include "net/uip.h"
74 #include "net/uipopt.h"
75 #include "net/uip_arp.h"
76 #include "net/uip_arch.h"
78 #if !UIP_CONF_IPV6 /* If UIP_CONF_IPV6 is defined, we compile the
79 uip6.c file instead of this one. Therefore
80 this #ifndef removes the entire compilation
81 output of the uip.c file */
83 #if UIP_CONF_IPV6
84 #include "net/uip-neighbor.h"
85 #endif /* UIP_CONF_IPV6 */
87 #include <string.h>
89 /*---------------------------------------------------------------------------*/
91 /* Variable definitions. */
93 /* The IP address of this host. If it is defined to be fixed (by
94 setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set
95 here. Otherwise, the address */
96 #if UIP_FIXEDADDR > 0
97 const uip_ipaddr_t uip_hostaddr = { UIP_IPADDR0, UIP_IPADDR1, UIP_IPADDR2, UIP_IPADDR3 };
98 const uip_ipaddr_t uip_draddr = { UIP_DRIPADDR0, UIP_DRIPADDR1, UIP_DRIPADDR2, UIP_DRIPADDR3 };
99 const uip_ipaddr_t uip_netmask = { UIP_NETMASK0, UIP_NETMASK1, UIP_NETMASK2, UIP_NETMASK3 };
100 #else
101 uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask;
102 #endif /* UIP_FIXEDADDR */
104 const uip_ipaddr_t uip_broadcast_addr =
105 #if UIP_CONF_IPV6
106 { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } };
107 #else /* UIP_CONF_IPV6 */
110 0xff, 0xff, 0xff, 0xff
113 #endif /* UIP_CONF_IPV6 */
114 const uip_ipaddr_t uip_all_zeroes_addr = { { 0x0, /* rest is 0 */ } };
116 #if UIP_FIXEDETHADDR
117 const struct uip_eth_addr uip_ethaddr = { { UIP_ETHADDR0, UIP_ETHADDR1, UIP_ETHADDR2, UIP_ETHADDR3, UIP_ETHADDR4, UIP_ETHADDR5 } };
118 #else
119 struct uip_eth_addr uip_ethaddr = { { 0, 0, 0, 0, 0, 0 } };
120 #endif
121 #ifndef UIP_CONF_EXTERNAL_BUFFER
122 u8_t uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains
123 incoming packets. */
124 #endif /* UIP_CONF_EXTERNAL_BUFFER */
126 void *uip_appdata; /* The uip_appdata pointer points to
127 application data. */
128 void *uip_sappdata; /* The uip_appdata pointer points to
129 the application data which is to
130 be sent. */
131 #if UIP_URGDATA > 0
132 void *uip_urgdata; /* The uip_urgdata pointer points to
133 urgent data (out-of-band data), if
134 present. */
135 u16_t uip_urglen, uip_surglen;
136 #endif /* UIP_URGDATA > 0 */
138 u16_t uip_len, uip_slen;
140 /* The uip_len is either 8 or 16 bits,
141 depending on the maximum packet
142 size. */
143 u8_t uip_flags; /* The uip_flags variable is used for
144 communication between the TCP/IP stack
145 and the application program. */
146 struct uip_conn *uip_conn; /* uip_conn always points to the current
147 connection. */
149 struct uip_conn uip_conns[UIP_CONNS];
151 /* The uip_conns array holds all TCP
152 connections. */
153 u16_t uip_listenports[UIP_LISTENPORTS];
155 /* The uip_listenports list all currently
156 listning ports. */
157 #if UIP_UDP
158 struct uip_udp_conn *uip_udp_conn;
159 struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
160 #endif /* UIP_UDP */
162 static u16_t ipid; /* Ths ipid variable is an increasing
163 number that is used for the IP ID
164 field. */
166 void uip_setipid( u16_t id )
168 ipid = id;
171 static u8_t iss[4]; /* The iss variable is used for the TCP
172 initial sequence number. */
174 #if UIP_ACTIVE_OPEN
175 static u16_t lastport; /* Keeps track of the last port used for
176 a new connection. */
177 #endif /* UIP_ACTIVE_OPEN */
179 /* Temporary variables. */
180 u8_t uip_acc32[4];
181 static u8_t c, opt;
182 static u16_t tmp16;
184 /* Structures and definitions. */
185 #define TCP_FIN 0x01
186 #define TCP_SYN 0x02
187 #define TCP_RST 0x04
188 #define TCP_PSH 0x08
189 #define TCP_ACK 0x10
190 #define TCP_URG 0x20
191 #define TCP_CTL 0x3f
193 #define TCP_OPT_END 0 /* End of TCP options list */
194 #define TCP_OPT_NOOP 1 /* "No-operation" TCP option */
195 #define TCP_OPT_MSS 2 /* Maximum segment size TCP option */
197 #define TCP_OPT_MSS_LEN 4 /* Length of TCP MSS option. */
199 #define ICMP_ECHO_REPLY 0
200 #define ICMP_ECHO 8
202 #define ICMP_DEST_UNREACHABLE 3
203 #define ICMP_PORT_UNREACHABLE 3
205 #define ICMP6_ECHO_REPLY 129
206 #define ICMP6_ECHO 128
207 #define ICMP6_NEIGHBOR_SOLICITATION 135
208 #define ICMP6_NEIGHBOR_ADVERTISEMENT 136
210 #define ICMP6_FLAG_S ( 1 << 6 )
211 #define ICMP6_OPTION_SOURCE_LINK_ADDRESS 1
212 #define ICMP6_OPTION_TARGET_LINK_ADDRESS 2
214 /* Macros. */
215 #define BUF ( ( struct uip_tcpip_hdr * ) &uip_buf[UIP_LLH_LEN] )
216 #define FBUF ( ( struct uip_tcpip_hdr * ) &uip_reassbuf[0] )
217 #define ICMPBUF ( ( struct uip_icmpip_hdr * ) &uip_buf[UIP_LLH_LEN] )
218 #define UDPBUF ( ( struct uip_udpip_hdr * ) &uip_buf[UIP_LLH_LEN] )
219 #if UIP_STATISTICS == 1
220 struct uip_stats uip_stat;
221 #define UIP_STAT( s ) s
222 #else
223 #define UIP_STAT( s )
224 #endif /* UIP_STATISTICS == 1 */
226 #if UIP_LOGGING == 1
227 #include <stdio.h>
228 void uip_log( char *msg );
229 #define UIP_LOG( m ) uip_log( m )
230 #else
231 #define UIP_LOG( m )
232 #endif /* UIP_LOGGING == 1 */
234 #if !UIP_ARCH_ADD32
235 void uip_add32( u8_t *op32, u16_t op16 )
237 uip_acc32[3] = op32[3] + ( op16 & 0xff );
238 uip_acc32[2] = op32[2] + ( op16 >> 8 );
239 uip_acc32[1] = op32[1];
240 uip_acc32[0] = op32[0];
242 if( uip_acc32[2] < (op16 >> 8) )
244 ++uip_acc32[1];
245 if( uip_acc32[1] == 0 )
247 ++uip_acc32[0];
251 if( uip_acc32[3] < (op16 & 0xff) )
253 ++uip_acc32[2];
254 if( uip_acc32[2] == 0 )
256 ++uip_acc32[1];
257 if( uip_acc32[1] == 0 )
259 ++uip_acc32[0];
265 #endif /* UIP_ARCH_ADD32 */
267 #if !UIP_ARCH_CHKSUM
269 /*---------------------------------------------------------------------------*/
270 static u16_t chksum( u16_t sum, const u8_t *data, u16_t len )
272 u16_t t;
273 const u8_t *dataptr;
274 const u8_t *last_byte;
276 dataptr = data;
277 last_byte = data + len - 1;
279 while( dataptr < last_byte )
280 { /* At least two more bytes */
281 t = ( dataptr[0] << 8 ) + dataptr[1];
282 sum += t;
283 if( sum < t )
285 sum++; /* carry */
288 dataptr += 2;
291 if( dataptr == last_byte )
293 t = ( dataptr[0] << 8 ) + 0;
294 sum += t;
295 if( sum < t )
297 sum++; /* carry */
301 /* Return sum in host byte order. */
302 return sum;
305 /*---------------------------------------------------------------------------*/
306 u16_t uip_chksum( u16_t *data, u16_t len )
308 return htons( chksum(0, ( u8_t * ) data, len) );
311 /*---------------------------------------------------------------------------*/
312 #ifndef UIP_ARCH_IPCHKSUM
313 u16_t uip_ipchksum( void )
315 u16_t sum;
317 sum = chksum( 0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN );
319 //DEBUG_PRINTF( "uip_ipchksum: sum 0x%04x\n", sum );
320 return( sum == 0 ) ? 0xffff : htons( sum );
323 #endif
325 /*---------------------------------------------------------------------------*/
326 static u16_t upper_layer_chksum( u8_t proto )
328 u16_t upper_layer_len;
329 u16_t sum;
331 #if UIP_CONF_IPV6
332 upper_layer_len = ( ((u16_t) (BUF->len[0]) << 8) + BUF->len[1] );
333 #else /* UIP_CONF_IPV6 */
334 upper_layer_len = ( ((u16_t) (BUF->len[0]) << 8) + BUF->len[1] ) - UIP_IPH_LEN;
335 #endif /* UIP_CONF_IPV6 */
337 /* First sum pseudoheader. */
339 /* IP protocol and length fields. This addition cannot carry. */
340 sum = upper_layer_len + proto;
342 /* Sum IP source and destination addresses. */
343 sum = chksum( sum, ( u8_t * ) &BUF->srcipaddr, 2 * sizeof(uip_ipaddr_t) );
345 /* Sum TCP header and data. */
346 sum = chksum( sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], upper_layer_len );
348 return( sum == 0 ) ? 0xffff : htons( sum );
351 /*---------------------------------------------------------------------------*/
352 #if UIP_CONF_IPV6
353 u16_t uip_icmp6chksum( void )
355 return upper_layer_chksum( UIP_PROTO_ICMP6 );
358 #endif /* UIP_CONF_IPV6 */
360 /*---------------------------------------------------------------------------*/
361 u16_t uip_tcpchksum( void )
363 return upper_layer_chksum( UIP_PROTO_TCP );
366 /*---------------------------------------------------------------------------*/
367 #if UIP_UDP_CHECKSUMS
368 u16_t uip_udpchksum( void )
370 return upper_layer_chksum( UIP_PROTO_UDP );
373 #endif /* UIP_UDP_CHECKSUMS */
374 #endif /* UIP_ARCH_CHKSUM */
376 /*---------------------------------------------------------------------------*/
377 void uip_init( void )
379 for( c = 0; c < UIP_LISTENPORTS; ++c )
381 uip_listenports[c] = 0;
384 for( c = 0; c < UIP_CONNS; ++c )
386 uip_conns[c].tcpstateflags = UIP_CLOSED;
389 #if UIP_ACTIVE_OPEN
390 lastport = 1024;
391 #endif /* UIP_ACTIVE_OPEN */
393 #if UIP_UDP
394 for( c = 0; c < UIP_UDP_CONNS; ++c )
396 uip_udp_conns[c].lport = 0;
399 #endif /* UIP_UDP */
401 /* IPv4 initialization. */
402 #if UIP_FIXEDADDR == 0
403 /* uip_hostaddr[0] = uip_hostaddr[1] = 0;*/
404 #endif /* UIP_FIXEDADDR */
407 /*---------------------------------------------------------------------------*/
408 #if UIP_ACTIVE_OPEN
409 struct uip_conn *uip_connect( uip_ipaddr_t *ripaddr, u16_t rport )
411 register struct uip_conn *conn, *cconn;
413 /* Find an unused local port. */
414 again:
415 ++lastport;
417 if( lastport >= 32000 )
419 lastport = 4096;
422 /* Check if this port is already in use, and if so try to find
423 another one. */
424 for( c = 0; c < UIP_CONNS; ++c )
426 conn = &uip_conns[c];
427 if( conn->tcpstateflags != UIP_CLOSED && conn->lport == htons(lastport) )
429 goto again;
433 conn = 0;
434 for( c = 0; c < UIP_CONNS; ++c )
436 cconn = &uip_conns[c];
437 if( cconn->tcpstateflags == UIP_CLOSED )
439 conn = cconn;
440 break;
443 if( cconn->tcpstateflags == UIP_TIME_WAIT )
445 if( conn == 0 || cconn->timer > conn->timer )
447 conn = cconn;
452 if( conn == 0 )
454 return 0;
457 conn->tcpstateflags = UIP_SYN_SENT;
459 conn->snd_nxt[0] = iss[0];
460 conn->snd_nxt[1] = iss[1];
461 conn->snd_nxt[2] = iss[2];
462 conn->snd_nxt[3] = iss[3];
464 conn->initialmss = conn->mss = UIP_TCP_MSS;
466 conn->len = 1; /* TCP length of the SYN is one. */
467 conn->nrtx = 0;
468 conn->timer = 1; /* Send the SYN next time around. */
469 conn->rto = UIP_RTO;
470 conn->sa = 0;
471 conn->sv = 16; /* Initial value of the RTT variance. */
472 conn->lport = htons( lastport );
473 conn->rport = rport;
474 uip_ipaddr_copy( &conn->ripaddr, ripaddr );
476 return conn;
479 #endif /* UIP_ACTIVE_OPEN */
481 /*---------------------------------------------------------------------------*/
482 #if UIP_UDP
483 struct uip_udp_conn *uip_udp_new( const uip_ipaddr_t *ripaddr, u16_t rport )
485 register struct uip_udp_conn *conn;
487 /* Find an unused local port. */
488 again:
489 ++lastport;
491 if( lastport >= 32000 )
493 lastport = 4096;
496 for( c = 0; c < UIP_UDP_CONNS; ++c )
498 if( uip_udp_conns[c].lport == htons(lastport) )
500 goto again;
504 conn = 0;
505 for( c = 0; c < UIP_UDP_CONNS; ++c )
507 if( uip_udp_conns[c].lport == 0 )
509 conn = &uip_udp_conns[c];
510 break;
514 if( conn == 0 )
516 return 0;
519 conn->lport = HTONS( lastport );
520 conn->rport = rport;
521 if( ripaddr == NULL )
523 memset( &conn->ripaddr, 0, sizeof(uip_ipaddr_t) );
525 else
527 uip_ipaddr_copy( &conn->ripaddr, ripaddr );
530 conn->ttl = UIP_TTL;
532 return conn;
535 #endif /* UIP_UDP */
537 /*---------------------------------------------------------------------------*/
538 void uip_unlisten( u16_t port )
540 for( c = 0; c < UIP_LISTENPORTS; ++c )
542 if( uip_listenports[c] == port )
544 uip_listenports[c] = 0;
545 return;
550 /*---------------------------------------------------------------------------*/
551 void uip_listen( u16_t port )
553 for( c = 0; c < UIP_LISTENPORTS; ++c )
555 if( uip_listenports[c] == 0 )
557 uip_listenports[c] = port;
558 return;
563 /*---------------------------------------------------------------------------*/
565 /* XXX: IP fragment reassembly: not well-tested. */
566 #if UIP_REASSEMBLY && !UIP_CONF_IPV6
567 #define UIP_REASS_BUFSIZE ( UIP_BUFSIZE - UIP_LLH_LEN )
568 static u8_t uip_reassbuf[UIP_REASS_BUFSIZE];
569 static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / ( 8 * 8 )];
570 static const u8_t bitmap_bits[8] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
571 static u16_t uip_reasslen;
572 static u8_t uip_reassflags;
573 #define UIP_REASS_FLAG_LASTFRAG 0x01
574 static u8_t uip_reasstmr;
576 #define IP_MF 0x20
578 static u8_t uip_reass( void )
580 u16_t offset, len;
581 u16_t i;
583 /* If ip_reasstmr is zero, no packet is present in the buffer, so we
584 write the IP header of the fragment into the reassembly
585 buffer. The timer is updated with the maximum age. */
586 if( uip_reasstmr == 0 )
588 memcpy( uip_reassbuf, &BUF->vhl, UIP_IPH_LEN );
589 uip_reasstmr = UIP_REASS_MAXAGE;
590 uip_reassflags = 0;
592 /* Clear the bitmap. */
593 memset( uip_reassbitmap, 0, sizeof(uip_reassbitmap) );
596 /* Check if the incoming fragment matches the one currently present
597 in the reasembly buffer. If so, we proceed with copying the
598 fragment into the buffer. */
601 BUF->srcipaddr[0] == FBUF->srcipaddr[0] &&
602 BUF->srcipaddr[1] == FBUF->srcipaddr[1] &&
603 BUF->destipaddr[0] == FBUF->destipaddr[0] &&
604 BUF->destipaddr[1] == FBUF->destipaddr[1] &&
605 BUF->ipid[0] == FBUF->ipid[0] &&
606 BUF->ipid[1] == FBUF->ipid[1]
609 len = ( BUF->len[0] << 8 ) + BUF->len[1] - ( BUF->vhl & 0x0f ) * 4;
610 offset = ( ((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1] ) * 8;
612 /* If the offset or the offset + fragment length overflows the
613 reassembly buffer, we discard the entire packet. */
614 if( offset > UIP_REASS_BUFSIZE || offset + len > UIP_REASS_BUFSIZE )
616 uip_reasstmr = 0;
617 goto nullreturn;
620 /* Copy the fragment into the reassembly buffer, at the right
621 offset. */
622 memcpy( &uip_reassbuf[UIP_IPH_LEN + offset], ( char * ) BUF + ( int ) ((BUF->vhl & 0x0f) * 4), len );
624 /* Update the bitmap. */
625 if( offset / (8 * 8) == (offset + len) / (8 * 8) )
627 /* If the two endpoints are in the same byte, we only update
628 that byte. */
629 uip_reassbitmap[offset / ( 8 * 8 )] |= bitmap_bits[( offset / 8 ) & 7] &~bitmap_bits[( (offset + len) / 8 ) & 7];
631 else
633 /* If the two endpoints are in different bytes, we update the
634 bytes in the endpoints and fill the stuff inbetween with
635 0xff. */
636 uip_reassbitmap[offset / ( 8 * 8 )] |= bitmap_bits[( offset / 8 ) & 7];
637 for( i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i )
639 uip_reassbitmap[i] = 0xff;
642 uip_reassbitmap[( offset + len ) / ( 8 * 8 )] |= ~bitmap_bits[( (offset + len) / 8 ) & 7];
645 /* If this fragment has the More Fragments flag set to zero, we
646 know that this is the last fragment, so we can calculate the
647 size of the entire packet. We also set the
648 IP_REASS_FLAG_LASTFRAG flag to indicate that we have received
649 the final fragment. */
650 if( (BUF->ipoffset[0] & IP_MF) == 0 )
652 uip_reassflags |= UIP_REASS_FLAG_LASTFRAG;
653 uip_reasslen = offset + len;
656 /* Finally, we check if we have a full packet in the buffer. We do
657 this by checking if we have the last fragment and if all bits
658 in the bitmap are set. */
659 if( uip_reassflags & UIP_REASS_FLAG_LASTFRAG )
661 /* Check all bytes up to and including all but the last byte in
662 the bitmap. */
663 for( i = 0; i < uip_reasslen / (8 * 8) - 1; ++i )
665 if( uip_reassbitmap[i] != 0xff )
667 goto nullreturn;
671 /* Check the last byte in the bitmap. It should contain just the
672 right amount of bits. */
673 if( uip_reassbitmap[uip_reasslen / (8 * 8)] != (u8_t)~bitmap_bits[uip_reasslen / 8 & 7] )
675 goto nullreturn;
678 /* If we have come this far, we have a full packet in the
679 buffer, so we allocate a pbuf and copy the packet into it. We
680 also reset the timer. */
681 uip_reasstmr = 0;
682 memcpy( BUF, FBUF, uip_reasslen );
684 /* Pretend to be a "normal" (i.e., not fragmented) IP packet
685 from now on. */
686 BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
687 BUF->len[0] = uip_reasslen >> 8;
688 BUF->len[1] = uip_reasslen & 0xff;
689 BUF->ipchksum = 0;
690 BUF->ipchksum = ~( uip_ipchksum() );
692 return uip_reasslen;
696 nullreturn:
697 return 0;
700 #endif /* UIP_REASSEMBLY */
702 /*---------------------------------------------------------------------------*/
703 static void uip_add_rcv_nxt( u16_t n )
705 uip_add32( uip_conn->rcv_nxt, n );
706 uip_conn->rcv_nxt[0] = uip_acc32[0];
707 uip_conn->rcv_nxt[1] = uip_acc32[1];
708 uip_conn->rcv_nxt[2] = uip_acc32[2];
709 uip_conn->rcv_nxt[3] = uip_acc32[3];
712 /*---------------------------------------------------------------------------*/
713 void uip_process( u8_t flag )
715 register struct uip_conn *uip_connr = uip_conn;
717 #if UIP_UDP
718 if( flag == UIP_UDP_SEND_CONN )
720 goto udp_send;
723 #endif /* UIP_UDP */
725 uip_sappdata = uip_appdata = &uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN];
727 /* Check if we were invoked because of a poll request for a
728 particular connection. */
729 if( flag == UIP_POLL_REQUEST )
731 if( (uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED && !uip_outstanding(uip_connr) )
733 uip_flags = UIP_POLL;
734 UIP_APPCALL();
735 goto appsend;
738 goto drop;
740 /* Check if we were invoked because of the perodic timer fireing. */
742 else if( flag == UIP_TIMER )
744 #if UIP_REASSEMBLY
745 if( uip_reasstmr != 0 )
747 --uip_reasstmr;
750 #endif /* UIP_REASSEMBLY */
752 /* Increase the initial sequence number. */
753 if( ++iss[3] == 0 )
755 if( ++iss[2] == 0 )
757 if( ++iss[1] == 0 )
759 ++iss[0];
764 /* Reset the length variables. */
765 uip_len = 0;
766 uip_slen = 0;
768 /* Check if the connection is in a state in which we simply wait
769 for the connection to time out. If so, we increase the
770 connection's timer and remove the connection if it times
771 out. */
772 if( uip_connr->tcpstateflags == UIP_TIME_WAIT || uip_connr->tcpstateflags == UIP_FIN_WAIT_2 )
774 ++( uip_connr->timer );
775 if( uip_connr->timer == UIP_TIME_WAIT_TIMEOUT )
777 uip_connr->tcpstateflags = UIP_CLOSED;
780 else if( uip_connr->tcpstateflags != UIP_CLOSED )
782 /* If the connection has outstanding data, we increase the
783 connection's timer and see if it has reached the RTO value
784 in which case we retransmit. */
785 if( uip_outstanding(uip_connr) )
787 if( uip_connr->timer-- == 0 )
791 uip_connr->nrtx == UIP_MAXRTX ||
793 (uip_connr->tcpstateflags == UIP_SYN_SENT || uip_connr->tcpstateflags == UIP_SYN_RCVD) &&
794 uip_connr->nrtx == UIP_MAXSYNRTX
798 uip_connr->tcpstateflags = UIP_CLOSED;
800 /* We call UIP_APPCALL() with uip_flags set to
801 UIP_TIMEDOUT to inform the application that the
802 connection has timed out. */
803 uip_flags = UIP_TIMEDOUT;
804 UIP_APPCALL();
806 /* We also send a reset packet to the remote host. */
807 BUF->flags = TCP_RST | TCP_ACK;
808 goto tcp_send_nodata;
811 /* Exponential backoff. */
812 uip_connr->timer = UIP_RTO << ( uip_connr->nrtx > 4 ? 4 : uip_connr->nrtx );
813 ++( uip_connr->nrtx );
815 /* Ok, so we need to retransmit. We do this differently
816 depending on which state we are in. In ESTABLISHED, we
817 call upon the application so that it may prepare the
818 data for the retransmit. In SYN_RCVD, we resend the
819 SYNACK that we sent earlier and in LAST_ACK we have to
820 retransmit our FINACK. */
821 UIP_STAT( ++uip_stat.tcp.rexmit );
822 switch( uip_connr->tcpstateflags & UIP_TS_MASK )
824 case UIP_SYN_RCVD:
825 /* In the SYN_RCVD state, we should retransmit our
826 SYNACK. */
827 goto tcp_send_synack;
829 #if UIP_ACTIVE_OPEN
831 case UIP_SYN_SENT:
832 /* In the SYN_SENT state, we retransmit out SYN. */
833 BUF->flags = 0;
834 goto tcp_send_syn;
835 #endif /* UIP_ACTIVE_OPEN */
837 case UIP_ESTABLISHED:
838 /* In the ESTABLISHED state, we call upon the application
839 to do the actual retransmit after which we jump into
840 the code for sending out the packet (the apprexmit
841 label). */
842 uip_flags = UIP_REXMIT;
843 UIP_APPCALL();
844 goto apprexmit;
846 case UIP_FIN_WAIT_1:
847 case UIP_CLOSING:
848 case UIP_LAST_ACK:
849 /* In all these states we should retransmit a FINACK. */
850 goto tcp_send_finack;
854 else if( (uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED )
856 /* If there was no need for a retransmission, we poll the
857 application for new data. */
858 uip_flags = UIP_POLL;
859 UIP_APPCALL();
860 goto appsend;
864 goto drop;
867 #if UIP_UDP
868 if( flag == UIP_UDP_TIMER )
870 if( uip_udp_conn->lport != 0 )
872 uip_conn = NULL;
873 uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
874 uip_len = uip_slen = 0;
875 uip_flags = UIP_POLL;
876 UIP_UDP_APPCALL();
877 goto udp_send;
879 else
881 goto drop;
885 #endif
887 /* This is where the input processing starts. */
888 UIP_STAT( ++uip_stat.ip.recv );
890 /* Start of IP input header processing code. */
891 #if UIP_CONF_IPV6
892 /* Check validity of the IP header. */
893 if( (BUF->vtc & 0xf0) != 0x60 )
894 { /* IP version and header length. */
895 UIP_STAT( ++uip_stat.ip.drop );
896 UIP_STAT( ++uip_stat.ip.vhlerr );
897 UIP_LOG( "ipv6: invalid version." );
898 goto drop;
901 #else /* UIP_CONF_IPV6 */
902 /* Check validity of the IP header. */
903 if( BUF->vhl != 0x45 )
904 { /* IP version and header length. */
905 UIP_STAT( ++uip_stat.ip.drop );
906 UIP_STAT( ++uip_stat.ip.vhlerr );
907 UIP_LOG( "ip: invalid version or header length." );
908 goto drop;
911 #endif /* UIP_CONF_IPV6 */
913 /* Check the size of the packet. If the size reported to us in
914 uip_len is smaller the size reported in the IP header, we assume
915 that the packet has been corrupted in transit. If the size of
916 uip_len is larger than the size reported in the IP packet header,
917 the packet has been padded and we set uip_len to the correct
918 value.. */
919 if( (BUF->len[0] << 8) + BUF->len[1] <= uip_len )
921 uip_len = ( BUF->len[0] << 8 ) + BUF->len[1];
922 #if UIP_CONF_IPV6
923 uip_len += 40; /* The length reported in the IPv6 header is the
924 length of the payload that follows the
925 header. However, uIP uses the uip_len variable
926 for holding the size of the entire packet,
927 including the IP header. For IPv4 this is not a
928 problem as the length field in the IPv4 header
929 contains the length of the entire packet. But
930 for IPv6 we need to add the size of the IPv6
931 header (40 bytes). */
932 #endif /* UIP_CONF_IPV6 */
934 else
936 UIP_LOG( "ip: packet shorter than reported in IP header." );
937 goto drop;
940 #if !UIP_CONF_IPV6
941 /* Check the fragment flag. */
942 if( (BUF->ipoffset[0] & 0x3f) != 0 || BUF->ipoffset[1] != 0 )
944 #if UIP_REASSEMBLY
945 uip_len = uip_reass();
946 if( uip_len == 0 )
948 goto drop;
951 #else /* UIP_REASSEMBLY */
952 UIP_STAT( ++uip_stat.ip.drop );
953 UIP_STAT( ++uip_stat.ip.fragerr );
954 UIP_LOG( "ip: fragment dropped." );
955 goto drop;
956 #endif /* UIP_REASSEMBLY */
959 #endif /* UIP_CONF_IPV6 */
961 if( uip_ipaddr_cmp(&uip_hostaddr, &uip_all_zeroes_addr) )
963 /* If we are configured to use ping IP address configuration and
964 hasn't been assigned an IP address yet, we accept all ICMP
965 packets. */
966 #if UIP_PINGADDRCONF && !UIP_CONF_IPV6
967 if( BUF->proto == UIP_PROTO_ICMP )
969 UIP_LOG( "ip: possible ping config packet received." );
970 goto icmp_input;
972 else
974 UIP_LOG( "ip: packet dropped since no address assigned." );
975 goto drop;
978 #endif /* UIP_PINGADDRCONF */
980 else
982 /* If IP broadcast support is configured, we check for a broadcast
983 UDP packet, which may be destined to us. */
984 #if UIP_BROADCAST
985 //DEBUG_PRINTF( "UDP IP checksum 0x%04x\n", uip_ipchksum() );
986 if( BUF->proto == UIP_PROTO_UDP && uip_ipaddr_cmp(&BUF->destipaddr, &uip_broadcast_addr) /*&&
987 uip_ipchksum() == 0xffff*/ )
989 goto udp_input;
992 #endif /* UIP_BROADCAST */
994 /* Check if the packet is destined for our IP address. */
995 #if !UIP_CONF_IPV6
996 if( !uip_ipaddr_cmp(&BUF->destipaddr, &uip_hostaddr) )
998 UIP_STAT( ++uip_stat.ip.drop );
999 goto drop;
1002 #else /* UIP_CONF_IPV6 */
1003 /* For IPv6, packet reception is a little trickier as we need to
1004 make sure that we listen to certain multicast addresses (all
1005 hosts multicast address, and the solicited-node multicast
1006 address) as well. However, we will cheat here and accept all
1007 multicast packets that are sent to the ff02::/16 addresses. */
1008 if( !uip_ipaddr_cmp(&BUF->destipaddr, &uip_hostaddr) && BUF->destipaddr.u16[0] != HTONS(0xff02) )
1010 UIP_STAT( ++uip_stat.ip.drop );
1011 goto drop;
1014 #endif /* UIP_CONF_IPV6 */
1017 #if !UIP_CONF_IPV6
1018 if( uip_ipchksum() != 0xffff )
1019 { /* Compute and check the IP header
1020 checksum. */
1021 UIP_STAT( ++uip_stat.ip.drop );
1022 UIP_STAT( ++uip_stat.ip.chkerr );
1023 UIP_LOG( "ip: bad checksum." );
1024 goto drop;
1027 #endif /* UIP_CONF_IPV6 */
1029 if( BUF->proto == UIP_PROTO_TCP )
1030 { /* Check for TCP packet. If so,
1031 proceed with TCP input
1032 processing. */
1033 goto tcp_input;
1036 #if UIP_UDP
1037 if( BUF->proto == UIP_PROTO_UDP )
1039 goto udp_input;
1042 #endif /* UIP_UDP */
1044 #if !UIP_CONF_IPV6
1045 /* ICMPv4 processing code follows. */
1046 if( BUF->proto != UIP_PROTO_ICMP )
1047 { /* We only allow ICMP packets from
1048 here. */
1049 UIP_STAT( ++uip_stat.ip.drop );
1050 UIP_STAT( ++uip_stat.ip.protoerr );
1051 UIP_LOG( "ip: neither tcp nor icmp." );
1052 goto drop;
1055 #if UIP_PINGADDRCONF
1056 icmp_input :
1057 #endif /* UIP_PINGADDRCONF */
1058 UIP_STAT( ++uip_stat.icmp.recv );
1060 /* ICMP echo (i.e., ping) processing. This is simple, we only change
1061 the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP
1062 checksum before we return the packet. */
1063 if( ICMPBUF->type != ICMP_ECHO )
1065 UIP_STAT( ++uip_stat.icmp.drop );
1066 UIP_STAT( ++uip_stat.icmp.typeerr );
1067 UIP_LOG( "icmp: not icmp echo." );
1068 goto drop;
1071 /* If we are configured to use ping IP address assignment, we use
1072 the destination IP address of this ping packet and assign it to
1073 ourself. */
1074 #if UIP_PINGADDRCONF
1075 if( uip_ipaddr_cmp(&uip_hostaddr, &uip_all_zeroes_addr) )
1077 uip_hostaddr = BUF->destipaddr;
1080 #endif /* UIP_PINGADDRCONF */
1082 ICMPBUF->type = ICMP_ECHO_REPLY;
1084 if( ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8)) )
1086 ICMPBUF->icmpchksum += HTONS( ICMP_ECHO << 8 ) + 1;
1088 else
1090 ICMPBUF->icmpchksum += HTONS( ICMP_ECHO << 8 );
1093 /* Swap IP addresses. */
1094 uip_ipaddr_copy( &BUF->destipaddr, &BUF->srcipaddr );
1095 uip_ipaddr_copy( &BUF->srcipaddr, &uip_hostaddr );
1097 UIP_STAT( ++uip_stat.icmp.sent );
1098 BUF->ttl = UIP_TTL;
1099 goto ip_send_nolen;
1101 /* End of IPv4 input header processing code. */
1102 #else /* !UIP_CONF_IPV6 */
1103 /* This is IPv6 ICMPv6 processing code. */
1105 //DEBUG_PRINTF( "icmp6_input: length %d\n", uip_len );
1106 if( BUF->proto != UIP_PROTO_ICMP6 )
1107 { /* We only allow ICMPv6 packets from
1108 here. */
1109 UIP_STAT( ++uip_stat.ip.drop );
1110 UIP_STAT( ++uip_stat.ip.protoerr );
1111 UIP_LOG( "ip: neither tcp nor icmp6." );
1112 goto drop;
1115 UIP_STAT( ++uip_stat.icmp.recv );
1117 /* If we get a neighbor solicitation for our address we should send
1118 a neighbor advertisement message back. */
1119 if( ICMPBUF->type == ICMP6_NEIGHBOR_SOLICITATION )
1121 if( uip_ipaddr_cmp(&ICMPBUF->icmp6data, &uip_hostaddr) )
1123 if( ICMPBUF->options[0] == ICMP6_OPTION_SOURCE_LINK_ADDRESS )
1125 /* Save the sender's address in our neighbor list. */
1126 uip_neighbor_add( &ICMPBUF->srcipaddr, &(ICMPBUF->options[2]) );
1129 /* We should now send a neighbor advertisement back to where the
1130 neighbor solicication came from. */
1131 ICMPBUF->type = ICMP6_NEIGHBOR_ADVERTISEMENT;
1132 ICMPBUF->flags = ICMP6_FLAG_S; /* Solicited flag. */
1134 ICMPBUF->reserved1 = ICMPBUF->reserved2 = ICMPBUF->reserved3 = 0;
1136 uip_ipaddr_copy( &ICMPBUF->destipaddr, &ICMPBUF->srcipaddr );
1137 uip_ipaddr_copy( &ICMPBUF->srcipaddr, &uip_hostaddr );
1138 ICMPBUF->options[0] = ICMP6_OPTION_TARGET_LINK_ADDRESS;
1139 ICMPBUF->options[1] = 1; /* Options length, 1 = 8 bytes. */
1140 memcpy( &(ICMPBUF->options[2]), &uip_ethaddr, sizeof(uip_ethaddr) );
1141 ICMPBUF->icmpchksum = 0;
1142 ICMPBUF->icmpchksum = ~uip_icmp6chksum();
1144 goto send;
1147 goto drop;
1149 else if( ICMPBUF->type == ICMP6_ECHO )
1151 /* ICMP echo (i.e., ping) processing. This is simple, we only
1152 change the ICMP type from ECHO to ECHO_REPLY and update the
1153 ICMP checksum before we return the packet. */
1154 ICMPBUF->type = ICMP6_ECHO_REPLY;
1156 uip_ipaddr_copy( &BUF->destipaddr, &BUF->srcipaddr );
1157 uip_ipaddr_copy( &BUF->srcipaddr, &uip_hostaddr );
1158 ICMPBUF->icmpchksum = 0;
1159 ICMPBUF->icmpchksum = ~uip_icmp6chksum();
1161 UIP_STAT( ++uip_stat.icmp.sent );
1162 goto send;
1164 else
1166 //DEBUG_PRINTF( "Unknown icmp6 message type %d\n", ICMPBUF->type );
1167 UIP_STAT( ++uip_stat.icmp.drop );
1168 UIP_STAT( ++uip_stat.icmp.typeerr );
1169 UIP_LOG( "icmp: unknown ICMP message." );
1170 goto drop;
1173 /* End of IPv6 ICMP processing. */
1174 #endif /* !UIP_CONF_IPV6 */
1176 #if UIP_UDP
1177 /* UDP input processing. */
1178 udp_input :
1179 /* UDP processing is really just a hack. We don't do anything to the
1180 UDP/IP headers, but let the UDP application do all the hard
1181 work. If the application sets uip_slen, it has a packet to
1182 send. */
1183 #if UIP_UDP_CHECKSUMS
1184 uip_len = uip_len - UIP_IPUDPH_LEN;
1185 uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
1186 if( UDPBUF->udpchksum != 0 && uip_udpchksum() != 0xffff )
1188 UIP_STAT( ++uip_stat.udp.drop );
1189 UIP_STAT( ++uip_stat.udp.chkerr );
1190 UIP_LOG( "udp: bad checksum." );
1191 goto drop;
1194 #else /* UIP_UDP_CHECKSUMS */
1195 uip_len = uip_len - UIP_IPUDPH_LEN;
1196 #endif /* UIP_UDP_CHECKSUMS */
1198 /* Demultiplex this UDP packet between the UDP "connections". */
1199 for( uip_udp_conn = &uip_udp_conns[0]; uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS]; ++uip_udp_conn )
1201 /* If the local UDP port is non-zero, the connection is considered
1202 to be used. If so, the local port number is checked against the
1203 destination port number in the received packet. If the two port
1204 numbers match, the remote port number is checked if the
1205 connection is bound to a remote port. Finally, if the
1206 connection is bound to a remote IP address, the source IP
1207 address of the packet is checked. */
1210 uip_udp_conn->lport != 0 &&
1211 UDPBUF->destport == uip_udp_conn->lport &&
1212 (uip_udp_conn->rport == 0 || UDPBUF->srcport == uip_udp_conn->rport) &&
1214 uip_ipaddr_cmp(&uip_udp_conn->ripaddr, &uip_all_zeroes_addr) ||
1215 uip_ipaddr_cmp(&uip_udp_conn->ripaddr, &uip_broadcast_addr) ||
1216 uip_ipaddr_cmp(&BUF->srcipaddr, &uip_udp_conn->ripaddr)
1220 goto udp_found;
1224 UIP_LOG( "udp: no matching connection found" );
1225 #if UIP_CONF_ICMP_DEST_UNREACH && !UIP_CONF_IPV6
1226 /* Copy fields from packet header into payload of this ICMP packet. */
1227 memcpy( &(ICMPBUF->payload[0]), ICMPBUF, UIP_IPH_LEN + 8 );
1229 /* Set the ICMP type and code. */
1230 ICMPBUF->type = ICMP_DEST_UNREACHABLE;
1231 ICMPBUF->icode = ICMP_PORT_UNREACHABLE;
1233 /* Calculate the ICMP checksum. */
1234 ICMPBUF->icmpchksum = 0;
1235 ICMPBUF->icmpchksum = ~uip_chksum( ( u16_t * ) &(ICMPBUF->type), 36 );
1237 /* Set the IP destination address to be the source address of the
1238 original packet. */
1239 uip_ipaddr_copy( &BUF->destipaddr, &BUF->srcipaddr );
1241 /* Set our IP address as the source address. */
1242 uip_ipaddr_copy( &BUF->srcipaddr, &uip_hostaddr );
1244 /* The size of the ICMP destination unreachable packet is 36 + the
1245 size of the IP header (20) = 56. */
1246 uip_len = 36 + UIP_IPH_LEN;
1247 ICMPBUF->len[0] = 0;
1248 ICMPBUF->len[1] = ( u8_t ) uip_len;
1249 ICMPBUF->ttl = UIP_TTL;
1250 ICMPBUF->proto = UIP_PROTO_ICMP;
1252 goto ip_send_nolen;
1253 #else /* UIP_CONF_ICMP_DEST_UNREACH */
1254 goto drop;
1255 #endif /* UIP_CONF_ICMP_DEST_UNREACH */
1257 udp_found : uip_conn = NULL;
1258 uip_flags = UIP_NEWDATA;
1259 uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
1260 uip_slen = 0;
1261 UIP_UDP_APPCALL();
1263 udp_send:
1264 if( uip_slen == 0 )
1266 goto drop;
1269 uip_len = uip_slen + UIP_IPUDPH_LEN;
1271 #if UIP_CONF_IPV6
1272 /* For IPv6, the IP length field does not include the IPv6 IP header
1273 length. */
1274 BUF->len[0] = ( (uip_len - UIP_IPH_LEN) >> 8 );
1275 BUF->len[1] = ( (uip_len - UIP_IPH_LEN) & 0xff );
1276 #else /* UIP_CONF_IPV6 */
1277 BUF->len[0] = ( uip_len >> 8 );
1278 BUF->len[1] = ( uip_len & 0xff );
1279 #endif /* UIP_CONF_IPV6 */
1281 BUF->ttl = uip_udp_conn->ttl;
1282 BUF->proto = UIP_PROTO_UDP;
1284 UDPBUF->udplen = HTONS( uip_slen + UIP_UDPH_LEN );
1285 UDPBUF->udpchksum = 0;
1287 BUF->srcport = uip_udp_conn->lport;
1288 BUF->destport = uip_udp_conn->rport;
1290 uip_ipaddr_copy( &BUF->srcipaddr, &uip_hostaddr );
1291 uip_ipaddr_copy( &BUF->destipaddr, &uip_udp_conn->ripaddr );
1293 uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN];
1295 #if UIP_UDP_CHECKSUMS
1296 /* Calculate UDP checksum. */
1297 UDPBUF->udpchksum = ~( uip_udpchksum() );
1298 if( UDPBUF->udpchksum == 0 )
1300 UDPBUF->udpchksum = 0xffff;
1303 #endif /* UIP_UDP_CHECKSUMS */
1305 goto ip_send_nolen;
1306 #endif /* UIP_UDP */
1308 /* TCP input processing. */
1309 tcp_input : UIP_STAT( ++uip_stat.tcp.recv );
1311 /* Start of TCP input header processing code. */
1312 if( uip_tcpchksum() != 0xffff )
1313 { /* Compute and check the TCP
1314 checksum. */
1315 UIP_STAT( ++uip_stat.tcp.drop );
1316 UIP_STAT( ++uip_stat.tcp.chkerr );
1317 UIP_LOG( "tcp: bad checksum." );
1318 goto drop;
1321 /* Demultiplex this segment. */
1323 /* First check any active connections. */
1324 for( uip_connr = &uip_conns[0]; uip_connr <= &uip_conns[UIP_CONNS - 1]; ++uip_connr )
1328 uip_connr->tcpstateflags != UIP_CLOSED &&
1329 BUF->destport == uip_connr->lport &&
1330 BUF->srcport == uip_connr->rport &&
1331 uip_ipaddr_cmp(&BUF->srcipaddr, &uip_connr->ripaddr)
1334 goto found;
1338 /* If we didn't find and active connection that expected the packet,
1339 either this packet is an old duplicate, or this is a SYN packet
1340 destined for a connection in LISTEN. If the SYN flag isn't set,
1341 it is an old packet and we send a RST. */
1342 if( (BUF->flags & TCP_CTL) != TCP_SYN )
1344 goto reset;
1347 tmp16 = BUF->destport;
1349 /* Next, check listening connections. */
1350 for( c = 0; c < UIP_LISTENPORTS; ++c )
1352 if( tmp16 == uip_listenports[c] )
1354 goto found_listen;
1358 /* No matching connection found, so we send a RST packet. */
1359 UIP_STAT( ++uip_stat.tcp.synrst );
1361 reset:
1362 /* We do not send resets in response to resets. */
1363 if( BUF->flags & TCP_RST )
1365 goto drop;
1368 UIP_STAT( ++uip_stat.tcp.rst );
1370 BUF->flags = TCP_RST | TCP_ACK;
1371 uip_len = UIP_IPTCPH_LEN;
1372 BUF->tcpoffset = 5 << 4;
1374 /* Flip the seqno and ackno fields in the TCP header. */
1375 c = BUF->seqno[3];
1376 BUF->seqno[3] = BUF->ackno[3];
1377 BUF->ackno[3] = c;
1379 c = BUF->seqno[2];
1380 BUF->seqno[2] = BUF->ackno[2];
1381 BUF->ackno[2] = c;
1383 c = BUF->seqno[1];
1384 BUF->seqno[1] = BUF->ackno[1];
1385 BUF->ackno[1] = c;
1387 c = BUF->seqno[0];
1388 BUF->seqno[0] = BUF->ackno[0];
1389 BUF->ackno[0] = c;
1391 /* We also have to increase the sequence number we are
1392 acknowledging. If the least significant byte overflowed, we need
1393 to propagate the carry to the other bytes as well. */
1394 if( ++BUF->ackno[3] == 0 )
1396 if( ++BUF->ackno[2] == 0 )
1398 if( ++BUF->ackno[1] == 0 )
1400 ++BUF->ackno[0];
1405 /* Swap port numbers. */
1406 tmp16 = BUF->srcport;
1407 BUF->srcport = BUF->destport;
1408 BUF->destport = tmp16;
1410 /* Swap IP addresses. */
1411 uip_ipaddr_copy( &BUF->destipaddr, &BUF->srcipaddr );
1412 uip_ipaddr_copy( &BUF->srcipaddr, &uip_hostaddr );
1414 /* And send out the RST packet! */
1415 goto tcp_send_noconn;
1417 /* This label will be jumped to if we matched the incoming packet
1418 with a connection in LISTEN. In that case, we should create a new
1419 connection and send a SYNACK in return. */
1420 found_listen:
1421 /* First we check if there are any connections avaliable. Unused
1422 connections are kept in the same table as used connections, but
1423 unused ones have the tcpstate set to CLOSED. Also, connections in
1424 TIME_WAIT are kept track of and we'll use the oldest one if no
1425 CLOSED connections are found. Thanks to Eddie C. Dost for a very
1426 nice algorithm for the TIME_WAIT search. */
1427 uip_connr = 0;
1428 for( c = 0; c < UIP_CONNS; ++c )
1430 if( uip_conns[c].tcpstateflags == UIP_CLOSED )
1432 uip_connr = &uip_conns[c];
1433 break;
1436 if( uip_conns[c].tcpstateflags == UIP_TIME_WAIT )
1438 if( uip_connr == 0 || uip_conns[c].timer > uip_connr->timer )
1440 uip_connr = &uip_conns[c];
1445 if( uip_connr == 0 )
1447 /* All connections are used already, we drop packet and hope that
1448 the remote end will retransmit the packet at a time when we
1449 have more spare connections. */
1450 UIP_STAT( ++uip_stat.tcp.syndrop );
1451 UIP_LOG( "tcp: found no unused connections." );
1452 goto drop;
1455 uip_conn = uip_connr;
1457 /* Fill in the necessary fields for the new connection. */
1458 uip_connr->rto = uip_connr->timer = UIP_RTO;
1459 uip_connr->sa = 0;
1460 uip_connr->sv = 4;
1461 uip_connr->nrtx = 0;
1462 uip_connr->lport = BUF->destport;
1463 uip_connr->rport = BUF->srcport;
1464 uip_ipaddr_copy( &uip_connr->ripaddr, &BUF->srcipaddr );
1465 uip_connr->tcpstateflags = UIP_SYN_RCVD;
1467 uip_connr->snd_nxt[0] = iss[0];
1468 uip_connr->snd_nxt[1] = iss[1];
1469 uip_connr->snd_nxt[2] = iss[2];
1470 uip_connr->snd_nxt[3] = iss[3];
1471 uip_connr->len = 1;
1473 /* rcv_nxt should be the seqno from the incoming packet + 1. */
1474 uip_connr->rcv_nxt[3] = BUF->seqno[3];
1475 uip_connr->rcv_nxt[2] = BUF->seqno[2];
1476 uip_connr->rcv_nxt[1] = BUF->seqno[1];
1477 uip_connr->rcv_nxt[0] = BUF->seqno[0];
1478 uip_add_rcv_nxt( 1 );
1480 /* Parse the TCP MSS option, if present. */
1481 if( (BUF->tcpoffset & 0xf0) > 0x50 )
1483 for( c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2; )
1485 opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c];
1486 if( opt == TCP_OPT_END )
1488 /* End of options. */
1489 break;
1491 else if( opt == TCP_OPT_NOOP )
1493 ++c;
1495 /* NOP option. */
1497 else if( opt == TCP_OPT_MSS && uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN )
1499 /* An MSS option with the right option length. */
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];
1501 uip_connr->initialmss = uip_connr->mss = tmp16 > UIP_TCP_MSS ? UIP_TCP_MSS : tmp16;
1503 /* And we are done processing options. */
1504 break;
1506 else
1508 /* All other options have a length field, so that we easily
1509 can skip past them. */
1510 if( uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0 )
1512 /* If the length field is zero, the options are malformed
1513 and we don't process them further. */
1514 break;
1517 c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
1522 /* Our response will be a SYNACK. */
1523 #if UIP_ACTIVE_OPEN
1524 tcp_send_synack : BUF->flags = TCP_ACK;
1526 tcp_send_syn:
1527 BUF->flags |= TCP_SYN;
1528 #else /* UIP_ACTIVE_OPEN */
1529 tcp_send_synack : BUF->flags = TCP_SYN | TCP_ACK;
1530 #endif /* UIP_ACTIVE_OPEN */
1532 /* We send out the TCP Maximum Segment Size option with our
1533 SYNACK. */
1534 BUF->optdata[0] = TCP_OPT_MSS;
1535 BUF->optdata[1] = TCP_OPT_MSS_LEN;
1536 BUF->optdata[2] = ( UIP_TCP_MSS ) / 256;
1537 BUF->optdata[3] = ( UIP_TCP_MSS ) & 255;
1538 uip_len = UIP_IPTCPH_LEN + TCP_OPT_MSS_LEN;
1539 BUF->tcpoffset = ( (UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4 ) << 4;
1540 goto tcp_send;
1542 /* This label will be jumped to if we found an active connection. */
1543 found:
1544 uip_conn = uip_connr;
1545 uip_flags = 0;
1547 /* We do a very naive form of TCP reset processing; we just accept
1548 any RST and kill our connection. We should in fact check if the
1549 sequence number of this reset is wihtin our advertised window
1550 before we accept the reset. */
1551 if( BUF->flags & TCP_RST )
1553 uip_connr->tcpstateflags = UIP_CLOSED;
1554 UIP_LOG( "tcp: got reset, aborting connection." );
1555 uip_flags = UIP_ABORT;
1556 UIP_APPCALL();
1557 goto drop;
1560 /* Calculate the length of the data, if the application has sent
1561 any data to us. */
1562 c = ( BUF->tcpoffset >> 4 ) << 2;
1564 /* uip_len will contain the length of the actual TCP data. This is
1565 calculated by subtracing the length of the TCP header (in
1566 c) and the length of the IP header (20 bytes). */
1567 uip_len = uip_len - c - UIP_IPH_LEN;
1569 /* First, check if the sequence number of the incoming packet is
1570 what we're expecting next. If not, we send out an ACK with the
1571 correct numbers in. */
1572 if( !(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) && ((BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK))) )
1576 (uip_len > 0 || ((BUF->flags & (TCP_SYN | TCP_FIN)) != 0)) &&
1578 BUF->seqno[0] != uip_connr->rcv_nxt[0] ||
1579 BUF->seqno[1] != uip_connr->rcv_nxt[1] ||
1580 BUF->seqno[2] != uip_connr->rcv_nxt[2] ||
1581 BUF->seqno[3] != uip_connr->rcv_nxt[3]
1585 goto tcp_send_ack;
1589 /* Next, check if the incoming segment acknowledges any outstanding
1590 data. If so, we update the sequence number, reset the length of
1591 the outstanding data, calculate RTT estimations, and reset the
1592 retransmission timer. */
1593 if( (BUF->flags & TCP_ACK) && uip_outstanding(uip_connr) )
1595 uip_add32( uip_connr->snd_nxt, uip_connr->len );
1599 BUF->ackno[0] == uip_acc32[0] &&
1600 BUF->ackno[1] == uip_acc32[1] &&
1601 BUF->ackno[2] == uip_acc32[2] &&
1602 BUF->ackno[3] == uip_acc32[3]
1605 /* Update sequence number. */
1606 uip_connr->snd_nxt[0] = uip_acc32[0];
1607 uip_connr->snd_nxt[1] = uip_acc32[1];
1608 uip_connr->snd_nxt[2] = uip_acc32[2];
1609 uip_connr->snd_nxt[3] = uip_acc32[3];
1611 /* Do RTT estimation, unless we have done retransmissions. */
1612 if( uip_connr->nrtx == 0 )
1614 signed char m;
1615 m = uip_connr->rto - uip_connr->timer;
1617 /* This is taken directly from VJs original code in his paper */
1618 m = m - ( uip_connr->sa >> 3 );
1619 uip_connr->sa += m;
1620 if( m < 0 )
1622 m = -m;
1625 m = m - ( uip_connr->sv >> 2 );
1626 uip_connr->sv += m;
1627 uip_connr->rto = ( uip_connr->sa >> 3 ) + uip_connr->sv;
1630 /* Set the acknowledged flag. */
1631 uip_flags = UIP_ACKDATA;
1633 /* Reset the retransmission timer. */
1634 uip_connr->timer = uip_connr->rto;
1636 /* Reset length of outstanding data. */
1637 uip_connr->len = 0;
1641 /* Do different things depending on in what state the connection is. */
1642 switch( uip_connr->tcpstateflags & UIP_TS_MASK )
1644 /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not
1645 implemented, since we force the application to close when the
1646 peer sends a FIN (hence the application goes directly from
1647 ESTABLISHED to LAST_ACK). */
1648 case UIP_SYN_RCVD:
1649 /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and
1650 we are waiting for an ACK that acknowledges the data we sent
1651 out the last time. Therefore, we want to have the UIP_ACKDATA
1652 flag set. If so, we enter the ESTABLISHED state. */
1653 if( uip_flags & UIP_ACKDATA )
1655 uip_connr->tcpstateflags = UIP_ESTABLISHED;
1656 uip_flags = UIP_CONNECTED;
1657 uip_connr->len = 0;
1658 if( uip_len > 0 )
1660 uip_flags |= UIP_NEWDATA;
1661 uip_add_rcv_nxt( uip_len );
1664 uip_slen = 0;
1665 UIP_APPCALL();
1666 goto appsend;
1669 goto drop;
1670 #if UIP_ACTIVE_OPEN
1672 case UIP_SYN_SENT:
1673 /* In SYN_SENT, we wait for a SYNACK that is sent in response to
1674 our SYN. The rcv_nxt is set to sequence number in the SYNACK
1675 plus one, and we send an ACK. We move into the ESTABLISHED
1676 state. */
1677 if( (uip_flags & UIP_ACKDATA) && (BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK) )
1679 /* Parse the TCP MSS option, if present. */
1680 if( (BUF->tcpoffset & 0xf0) > 0x50 )
1682 for( c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2; )
1684 opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c];
1685 if( opt == TCP_OPT_END )
1687 /* End of options. */
1688 break;
1690 else if( opt == TCP_OPT_NOOP )
1692 ++c;
1694 /* NOP option. */
1696 else if( opt == TCP_OPT_MSS && uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN )
1698 /* An MSS option with the right option length. */
1699 tmp16 = ( uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8 ) | uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c];
1700 uip_connr->initialmss = uip_connr->mss = tmp16 > UIP_TCP_MSS ? UIP_TCP_MSS : tmp16;
1702 /* And we are done processing options. */
1703 break;
1705 else
1707 /* All other options have a length field, so that we easily
1708 can skip past them. */
1709 if( uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0 )
1711 /* If the length field is zero, the options are malformed
1712 and we don't process them further. */
1713 break;
1716 c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
1721 uip_connr->tcpstateflags = UIP_ESTABLISHED;
1722 uip_connr->rcv_nxt[0] = BUF->seqno[0];
1723 uip_connr->rcv_nxt[1] = BUF->seqno[1];
1724 uip_connr->rcv_nxt[2] = BUF->seqno[2];
1725 uip_connr->rcv_nxt[3] = BUF->seqno[3];
1726 uip_add_rcv_nxt( 1 );
1727 uip_flags = UIP_CONNECTED | UIP_NEWDATA;
1728 uip_connr->len = 0;
1729 uip_len = 0;
1730 uip_slen = 0;
1731 UIP_APPCALL();
1732 goto appsend;
1735 /* Inform the application that the connection failed */
1736 uip_flags = UIP_ABORT;
1737 UIP_APPCALL();
1739 /* The connection is closed after we send the RST */
1740 uip_conn->tcpstateflags = UIP_CLOSED;
1741 goto reset;
1742 #endif /* UIP_ACTIVE_OPEN */
1744 case UIP_ESTABLISHED:
1745 /* In the ESTABLISHED state, we call upon the application to feed
1746 data into the uip_buf. If the UIP_ACKDATA flag is set, the
1747 application should put new data into the buffer, otherwise we are
1748 retransmitting an old segment, and the application should put that
1749 data into the buffer.
1751 If the incoming packet is a FIN, we should close the connection on
1752 this side as well, and we send out a FIN and enter the LAST_ACK
1753 state. We require that there is no outstanding data; otherwise the
1754 sequence numbers will be screwed up. */
1755 if( BUF->flags & TCP_FIN && !(uip_connr->tcpstateflags & UIP_STOPPED) )
1757 if( uip_outstanding(uip_connr) )
1759 goto drop;
1762 uip_add_rcv_nxt( 1 + uip_len );
1763 uip_flags |= UIP_CLOSE;
1764 if( uip_len > 0 )
1766 uip_flags |= UIP_NEWDATA;
1769 UIP_APPCALL();
1770 uip_connr->len = 1;
1771 uip_connr->tcpstateflags = UIP_LAST_ACK;
1772 uip_connr->nrtx = 0;
1773 tcp_send_finack:
1774 BUF->flags = TCP_FIN | TCP_ACK;
1775 goto tcp_send_nodata;
1778 /* Check the URG flag. If this is set, the segment carries urgent
1779 data that we must pass to the application. */
1780 if( (BUF->flags & TCP_URG) != 0 )
1782 #if UIP_URGDATA > 0
1783 uip_urglen = ( BUF->urgp[0] << 8 ) | BUF->urgp[1];
1784 if( uip_urglen > uip_len )
1786 /* There is more urgent data in the next segment to come. */
1787 uip_urglen = uip_len;
1790 uip_add_rcv_nxt( uip_urglen );
1791 uip_len -= uip_urglen;
1792 uip_urgdata = uip_appdata;
1793 uip_appdata += uip_urglen;
1795 else
1797 uip_urglen = 0;
1798 #else /* UIP_URGDATA > 0 */
1799 uip_appdata = ( ( char * ) uip_appdata ) + ( (BUF->urgp[0] << 8) | BUF->urgp[1] );
1800 uip_len -= ( BUF->urgp[0] << 8 ) | BUF->urgp[1];
1801 #endif /* UIP_URGDATA > 0 */
1804 /* If uip_len > 0 we have TCP data in the packet, and we flag this
1805 by setting the UIP_NEWDATA flag and update the sequence number
1806 we acknowledge. If the application has stopped the dataflow
1807 using uip_stop(), we must not accept any data packets from the
1808 remote host. */
1809 if( uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED) )
1811 uip_flags |= UIP_NEWDATA;
1812 uip_add_rcv_nxt( uip_len );
1815 /* Check if the available buffer space advertised by the other end
1816 is smaller than the initial MSS for this connection. If so, we
1817 set the current MSS to the window size to ensure that the
1818 application does not send more data than the other end can
1819 handle.
1821 If the remote host advertises a zero window, we set the MSS to
1822 the initial MSS so that the application will send an entire MSS
1823 of data. This data will not be acknowledged by the receiver,
1824 and the application will retransmit it. This is called the
1825 "persistent timer" and uses the retransmission mechanim.
1827 tmp16 = ( (u16_t) BUF->wnd[0] << 8 ) + ( u16_t ) BUF->wnd[1];
1828 if( tmp16 > uip_connr->initialmss || tmp16 == 0 )
1830 tmp16 = uip_connr->initialmss;
1833 uip_connr->mss = tmp16;
1835 /* If this packet constitutes an ACK for outstanding data (flagged
1836 by the UIP_ACKDATA flag, we should call the application since it
1837 might want to send more data. If the incoming packet had data
1838 from the peer (as flagged by the UIP_NEWDATA flag), the
1839 application must also be notified.
1841 When the application is called, the global variable uip_len
1842 contains the length of the incoming data. The application can
1843 access the incoming data through the global pointer
1844 uip_appdata, which usually points UIP_IPTCPH_LEN + UIP_LLH_LEN
1845 bytes into the uip_buf array.
1847 If the application wishes to send any data, this data should be
1848 put into the uip_appdata and the length of the data should be
1849 put into uip_len. If the application don't have any data to
1850 send, uip_len must be set to 0. */
1851 if( uip_flags & (UIP_NEWDATA | UIP_ACKDATA) )
1853 uip_slen = 0;
1854 UIP_APPCALL();
1856 appsend:
1857 if( uip_flags & UIP_ABORT )
1859 uip_slen = 0;
1860 uip_connr->tcpstateflags = UIP_CLOSED;
1861 BUF->flags = TCP_RST | TCP_ACK;
1862 goto tcp_send_nodata;
1865 if( uip_flags & UIP_CLOSE )
1867 uip_slen = 0;
1868 uip_connr->len = 1;
1869 uip_connr->tcpstateflags = UIP_FIN_WAIT_1;
1870 uip_connr->nrtx = 0;
1871 BUF->flags = TCP_FIN | TCP_ACK;
1872 goto tcp_send_nodata;
1875 /* If uip_slen > 0, the application has data to be sent. */
1876 if( uip_slen > 0 )
1878 /* If the connection has acknowledged data, the contents of
1879 the ->len variable should be discarded. */
1880 if( (uip_flags & UIP_ACKDATA) != 0 )
1882 uip_connr->len = 0;
1885 /* If the ->len variable is non-zero the connection has
1886 already data in transit and cannot send anymore right
1887 now. */
1888 if( uip_connr->len == 0 )
1890 /* The application cannot send more than what is allowed by
1891 the mss (the minumum of the MSS and the available
1892 window). */
1893 if( uip_slen > uip_connr->mss )
1895 uip_slen = uip_connr->mss;
1898 /* Remember how much data we send out now so that we know
1899 when everything has been acknowledged. */
1900 uip_connr->len = uip_slen;
1902 else
1904 /* If the application already had unacknowledged data, we
1905 make sure that the application does not send (i.e.,
1906 retransmit) out more than it previously sent out. */
1907 uip_slen = uip_connr->len;
1911 uip_connr->nrtx = 0;
1912 apprexmit:
1913 uip_appdata = uip_sappdata;
1915 /* If the application has data to be sent, or if the incoming
1916 packet had new data in it, we must send out a packet. */
1917 if( uip_slen > 0 && uip_connr->len > 0 )
1919 /* Add the length of the IP and TCP headers. */
1920 uip_len = uip_connr->len + UIP_TCPIP_HLEN;
1922 /* We always set the ACK flag in response packets. */
1923 BUF->flags = TCP_ACK | TCP_PSH;
1925 /* Send the packet. */
1926 goto tcp_send_noopts;
1929 /* If there is no data to send, just send out a pure ACK if
1930 there is newdata. */
1931 if( uip_flags & UIP_NEWDATA )
1933 uip_len = UIP_TCPIP_HLEN;
1934 BUF->flags = TCP_ACK;
1935 goto tcp_send_noopts;
1939 goto drop;
1941 case UIP_LAST_ACK:
1942 /* We can close this connection if the peer has acknowledged our
1943 FIN. This is indicated by the UIP_ACKDATA flag. */
1944 if( uip_flags & UIP_ACKDATA )
1946 uip_connr->tcpstateflags = UIP_CLOSED;
1947 uip_flags = UIP_CLOSE;
1948 UIP_APPCALL();
1951 break;
1953 case UIP_FIN_WAIT_1:
1954 /* The application has closed the connection, but the remote host
1955 hasn't closed its end yet. Thus we do nothing but wait for a
1956 FIN from the other side. */
1957 if( uip_len > 0 )
1959 uip_add_rcv_nxt( uip_len );
1962 if( BUF->flags & TCP_FIN )
1964 if( uip_flags & UIP_ACKDATA )
1966 uip_connr->tcpstateflags = UIP_TIME_WAIT;
1967 uip_connr->timer = 0;
1968 uip_connr->len = 0;
1970 else
1972 uip_connr->tcpstateflags = UIP_CLOSING;
1975 uip_add_rcv_nxt( 1 );
1976 uip_flags = UIP_CLOSE;
1977 UIP_APPCALL();
1978 goto tcp_send_ack;
1980 else if( uip_flags & UIP_ACKDATA )
1982 uip_connr->tcpstateflags = UIP_FIN_WAIT_2;
1983 uip_connr->len = 0;
1984 goto drop;
1987 if( uip_len > 0 )
1989 goto tcp_send_ack;
1992 goto drop;
1994 case UIP_FIN_WAIT_2:
1995 if( uip_len > 0 )
1997 uip_add_rcv_nxt( uip_len );
2000 if( BUF->flags & TCP_FIN )
2002 uip_connr->tcpstateflags = UIP_TIME_WAIT;
2003 uip_connr->timer = 0;
2004 uip_add_rcv_nxt( 1 );
2005 uip_flags = UIP_CLOSE;
2006 UIP_APPCALL();
2007 goto tcp_send_ack;
2010 if( uip_len > 0 )
2012 goto tcp_send_ack;
2015 goto drop;
2017 case UIP_TIME_WAIT:
2018 goto tcp_send_ack;
2020 case UIP_CLOSING:
2021 if( uip_flags & UIP_ACKDATA )
2023 uip_connr->tcpstateflags = UIP_TIME_WAIT;
2024 uip_connr->timer = 0;
2028 goto drop;
2030 /* We jump here when we are ready to send the packet, and just want
2031 to set the appropriate TCP sequence numbers in the TCP header. */
2032 tcp_send_ack:
2033 BUF->flags = TCP_ACK;
2035 tcp_send_nodata:
2036 uip_len = UIP_IPTCPH_LEN;
2038 tcp_send_noopts:
2039 BUF->tcpoffset = ( UIP_TCPH_LEN / 4 ) << 4;
2041 /* We're done with the input processing. We are now ready to send a
2042 reply. Our job is to fill in all the fields of the TCP and IP
2043 headers before calculating the checksum and finally send the
2044 packet. */
2045 tcp_send:
2046 BUF->ackno[0] = uip_connr->rcv_nxt[0];
2047 BUF->ackno[1] = uip_connr->rcv_nxt[1];
2048 BUF->ackno[2] = uip_connr->rcv_nxt[2];
2049 BUF->ackno[3] = uip_connr->rcv_nxt[3];
2051 BUF->seqno[0] = uip_connr->snd_nxt[0];
2052 BUF->seqno[1] = uip_connr->snd_nxt[1];
2053 BUF->seqno[2] = uip_connr->snd_nxt[2];
2054 BUF->seqno[3] = uip_connr->snd_nxt[3];
2056 BUF->proto = UIP_PROTO_TCP;
2058 BUF->srcport = uip_connr->lport;
2059 BUF->destport = uip_connr->rport;
2061 uip_ipaddr_copy( &BUF->srcipaddr, &uip_hostaddr );
2062 uip_ipaddr_copy( &BUF->destipaddr, &uip_connr->ripaddr );
2064 if( uip_connr->tcpstateflags & UIP_STOPPED )
2066 /* If the connection has issued uip_stop(), we advertise a zero
2067 window so that the remote host will stop sending data. */
2068 BUF->wnd[0] = BUF->wnd[1] = 0;
2070 else
2072 BUF->wnd[0] = ( (UIP_RECEIVE_WINDOW) >> 8 );
2073 BUF->wnd[1] = ( (UIP_RECEIVE_WINDOW) & 0xff );
2076 tcp_send_noconn:
2077 BUF->ttl = UIP_TTL;
2078 #if UIP_CONF_IPV6
2079 /* For IPv6, the IP length field does not include the IPv6 IP header
2080 length. */
2081 BUF->len[0] = ( (uip_len - UIP_IPH_LEN) >> 8 );
2082 BUF->len[1] = ( (uip_len - UIP_IPH_LEN) & 0xff );
2083 #else /* UIP_CONF_IPV6 */
2084 BUF->len[0] = ( uip_len >> 8 );
2085 BUF->len[1] = ( uip_len & 0xff );
2086 #endif /* UIP_CONF_IPV6 */
2088 BUF->urgp[0] = BUF->urgp[1] = 0;
2090 /* Calculate TCP checksum. */
2091 BUF->tcpchksum = 0;
2092 BUF->tcpchksum = ~( uip_tcpchksum() );
2094 ip_send_nolen:
2095 #if UIP_CONF_IPV6
2096 BUF->vtc = 0x60;
2097 BUF->tcflow = 0x00;
2098 BUF->flow = 0x00;
2099 #else /* UIP_CONF_IPV6 */
2100 BUF->vhl = 0x45;
2101 BUF->tos = 0;
2102 BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
2103 ++ipid;
2104 BUF->ipid[0] = ipid >> 8;
2105 BUF->ipid[1] = ipid & 0xff;
2107 /* Calculate IP checksum. */
2108 BUF->ipchksum = 0;
2109 BUF->ipchksum = ~( uip_ipchksum() );
2111 //DEBUG_PRINTF( "uip ip_send_nolen: chkecum 0x%04x\n", uip_ipchksum() );
2112 #endif /* UIP_CONF_IPV6 */
2113 UIP_STAT( ++uip_stat.tcp.sent );
2114 #if UIP_CONF_IPV6
2115 send :
2116 #endif /* UIP_CONF_IPV6 */
2118 //DEBUG_PRINTF( "Sending packet with length %d (%d)\n", uip_len, (BUF->len[0] << 8) | BUF->len[1] );
2119 UIP_STAT( ++uip_stat.ip.sent );
2121 /* Return and let the caller do the actual transmission. */
2122 uip_flags = 0;
2123 return;
2125 drop:
2126 uip_len = 0;
2127 uip_flags = 0;
2128 return;
2131 /*---------------------------------------------------------------------------*/
2132 u16_t htons( u16_t val )
2134 return HTONS( val );
2137 u32_t htonl( u32_t val )
2139 return HTONL( val );
2142 /*---------------------------------------------------------------------------*/
2143 void uip_send( const void *data, int len )
2145 int copylen;
2146 #define MIN( a, b ) ( (a) < (b) ? (a) : (b) )
2147 copylen = MIN( len, UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN - ( int )
2148 (( char * ) uip_sappdata - ( char * ) &uip_buf[UIP_LLH_LEN + UIP_TCPIP_HLEN]) );
2149 if( copylen > 0 )
2151 uip_slen = copylen;
2152 if( data != uip_sappdata )
2154 memcpy( uip_sappdata, (data), uip_slen );
2159 /*---------------------------------------------------------------------------*/
2161 /** @} */
2162 #endif /* UIP_CONF_IPV6 */