1 #define DEBUG_PRINTF( ... ) /*printf(__VA_ARGS__)*/
\r
4 * \defgroup uip The uIP TCP/IP stack
\r
7 * uIP is an implementation of the TCP/IP protocol stack intended for
\r
8 * small 8-bit and 16-bit microcontrollers.
\r
10 * uIP provides the necessary protocols for Internet communication,
\r
11 * with a very small code footprint and RAM requirements - the uIP
\r
12 * code size is on the order of a few kilobytes and RAM usage is on
\r
13 * the order of a few hundred bytes.
\r
18 * The uIP TCP/IP stack code.
\r
19 * \author Adam Dunkels <adam@dunkels.com>
\r
23 * Copyright (c) 2001-2003, Adam Dunkels.
\r
24 * All rights reserved.
\r
26 * Redistribution and use in source and binary forms, with or without
\r
27 * modification, are permitted provided that the following conditions
\r
29 * 1. Redistributions of source code must retain the above copyright
\r
30 * notice, this list of conditions and the following disclaimer.
\r
31 * 2. Redistributions in binary form must reproduce the above copyright
\r
32 * notice, this list of conditions and the following disclaimer in the
\r
33 * documentation and/or other materials provided with the distribution.
\r
34 * 3. The name of the author may not be used to endorse or promote
\r
35 * products derived from this software without specific prior
\r
36 * written permission.
\r
38 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
\r
39 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
\r
40 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
\r
41 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
\r
42 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
\r
43 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
\r
44 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
\r
45 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
\r
46 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
\r
47 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
\r
48 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
50 * This file is part of the uIP TCP/IP stack.
\r
52 * $Id: uip.c,v 1.65 2006/06/11 21:46:39 adam Exp $
\r
57 * uIP is a small implementation of the IP, UDP and TCP protocols (as
\r
58 * well as some basic ICMP stuff). The implementation couples the IP,
\r
59 * UDP, TCP and the application layers very tightly. To keep the size
\r
60 * of the compiled code down, this code frequently uses the goto
\r
61 * statement. While it would be possible to break the uip_process()
\r
62 * function into many smaller functions, this would increase the code
\r
63 * size because of the overhead of parameter passing and the fact that
\r
64 * the optimier would not be as efficient.
\r
66 * The principle is that we have a small buffer, called the uip_buf,
\r
67 * in which the device driver puts an incoming packet. The TCP/IP
\r
68 * stack parses the headers in the packet, and calls the
\r
69 * application. If the remote host has sent data to the application,
\r
70 * this data is present in the uip_buf and the application read the
\r
71 * data from there. It is up to the application to put this data into
\r
72 * a byte stream if needed. The application will not be fed with data
\r
73 * that is out of sequence.
\r
75 * If the application whishes to send data to the peer, it should put
\r
76 * its data into the uip_buf. The uip_appdata pointer points to the
\r
77 * first available byte. The TCP/IP stack will calculate the
\r
78 * checksums, and fill in the necessary header fields and finally send
\r
79 * the packet back to the peer.
\r
83 #include "uip_arch.h"
\r
84 #include "uip_arp.h"
\r
85 #include "FreeRTOS.h"
\r
88 #include "uip-neighbor.h"
\r
89 #endif /* UIP_CONF_IPV6 */
\r
93 /*---------------------------------------------------------------------------*/
\r
95 /* Variable definitions. */
\r
97 /* The IP address of this host. If it is defined to be fixed (by
\r
98 setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set
\r
99 here. Otherwise, the address */
\r
100 #if UIP_FIXEDADDR > 0
\r
101 const uip_ipaddr_t uip_hostaddr = { HTONS( (UIP_IPADDR0 << 8) | UIP_IPADDR1 ), HTONS( (UIP_IPADDR2 << 8) | UIP_IPADDR3 ) };
\r
102 const uip_ipaddr_t uip_draddr = { HTONS( (UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1 ), HTONS( (UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3 ) };
\r
103 const uip_ipaddr_t uip_netmask = { HTONS( (UIP_NETMASK0 << 8) | UIP_NETMASK1 ), HTONS( (UIP_NETMASK2 << 8) | UIP_NETMASK3 ) };
\r
105 uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask;
\r
106 #endif /* UIP_FIXEDADDR */
\r
108 static const uip_ipaddr_t all_ones_addr =
\r
110 { 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff };
\r
111 #else /* UIP_CONF_IPV6 */
\r
115 #endif /* UIP_CONF_IPV6 */
\r
116 static const uip_ipaddr_t all_zeroes_addr =
\r
118 { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 };
\r
119 #else /* UIP_CONF_IPV6 */
\r
123 #endif /* UIP_CONF_IPV6 */
\r
125 #if UIP_FIXEDETHADDR
\r
126 const struct uip_eth_addr uip_ethaddr = { { UIP_ETHADDR0, UIP_ETHADDR1, UIP_ETHADDR2, UIP_ETHADDR3, UIP_ETHADDR4, UIP_ETHADDR5 } };
\r
128 struct uip_eth_addr uip_ethaddr = { { 0, 0, 0, 0, 0, 0 } };
\r
130 #ifndef UIP_CONF_EXTERNAL_BUFFER
\r
132 #pragma data_alignment = 4
\r
133 u8_t uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains incoming packets. */
\r
135 u8_t uip_buf[UIP_BUFSIZE + 2] ALIGN_STRUCT_END; /* The packet buffer that contains incoming packets. */
\r
137 #endif /* UIP_CONF_EXTERNAL_BUFFER */
\r
139 void *uip_appdata; /* The uip_appdata pointer points to
\r
140 application data. */
\r
141 void *uip_sappdata; /* The uip_appdata pointer points to
\r
142 the application data which is to
\r
144 #if UIP_URGDATA > 0
\r
145 void *uip_urgdata; /* The uip_urgdata pointer points to
\r
146 urgent data (out-of-band data), if
\r
148 u16_t uip_urglen, uip_surglen;
\r
149 #endif /* UIP_URGDATA > 0 */
\r
151 u16_t uip_len, uip_slen;
\r
153 /* The uip_len is either 8 or 16 bits,
\r
154 depending on the maximum packet
\r
156 u8_t uip_flags; /* The uip_flags variable is used for
\r
157 communication between the TCP/IP stack
\r
158 and the application program. */
\r
159 struct uip_conn *uip_conn; /* uip_conn always points to the current
\r
162 struct uip_conn uip_conns[UIP_CONNS];
\r
164 /* The uip_conns array holds all TCP
\r
166 u16_t uip_listenports[UIP_LISTENPORTS];
\r
168 /* The uip_listenports list all currently
\r
171 struct uip_udp_conn *uip_udp_conn;
\r
172 struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
\r
173 #endif /* UIP_UDP */
\r
175 static u16_t ipid; /* Ths ipid variable is an increasing
\r
176 number that is used for the IP ID
\r
179 void uip_setipid( u16_t id )
\r
184 static u8_t iss[4]; /* The iss variable is used for the TCP
\r
185 initial sequence number. */
\r
187 #if UIP_ACTIVE_OPEN
\r
188 static u16_t lastport; /* Keeps track of the last port used for
\r
189 a new connection. */
\r
190 #endif /* UIP_ACTIVE_OPEN */
\r
192 /* Temporary variables. */
\r
194 static u8_t c, opt;
\r
195 static u16_t tmp16;
\r
197 /* Structures and definitions. */
\r
198 #define TCP_FIN 0x01
\r
199 #define TCP_SYN 0x02
\r
200 #define TCP_RST 0x04
\r
201 #define TCP_PSH 0x08
\r
202 #define TCP_ACK 0x10
\r
203 #define TCP_URG 0x20
\r
204 #define TCP_CTL 0x3f
\r
206 #define TCP_OPT_END 0 /* End of TCP options list */
\r
207 #define TCP_OPT_NOOP 1 /* "No-operation" TCP option */
\r
208 #define TCP_OPT_MSS 2 /* Maximum segment size TCP option */
\r
210 #define TCP_OPT_MSS_LEN 4 /* Length of TCP MSS option. */
\r
212 #define ICMP_ECHO_REPLY 0
\r
213 #define ICMP_ECHO 8
\r
215 #define ICMP6_ECHO_REPLY 129
\r
216 #define ICMP6_ECHO 128
\r
217 #define ICMP6_NEIGHBOR_SOLICITATION 135
\r
218 #define ICMP6_NEIGHBOR_ADVERTISEMENT 136
\r
220 #define ICMP6_FLAG_S ( 1 << 6 )
\r
221 #define ICMP6_OPTION_SOURCE_LINK_ADDRESS 1
\r
222 #define ICMP6_OPTION_TARGET_LINK_ADDRESS 2
\r
225 #define BUF ( ( struct uip_tcpip_hdr * ) &uip_buf[UIP_LLH_LEN] )
\r
226 #define FBUF ( ( struct uip_tcpip_hdr * ) &uip_reassbuf[0] )
\r
227 #define ICMPBUF ( ( struct uip_icmpip_hdr * ) &uip_buf[UIP_LLH_LEN] )
\r
228 #define UDPBUF ( ( struct uip_udpip_hdr * ) &uip_buf[UIP_LLH_LEN] )
\r
229 #if UIP_STATISTICS == 1
\r
230 struct uip_stats uip_stat;
\r
231 #define UIP_STAT( s ) s
\r
233 #define UIP_STAT( s )
\r
234 #endif /* UIP_STATISTICS == 1 */
\r
236 #if UIP_LOGGING == 1
\r
238 void uip_log( char *msg );
\r
239 #define UIP_LOG( m ) uip_log( m )
\r
241 #define UIP_LOG( m )
\r
242 #endif /* UIP_LOGGING == 1 */
\r
244 #if !UIP_ARCH_ADD32
\r
245 void uip_add32( u8_t *op32, u16_t op16 )
\r
247 uip_acc32[3] = op32[3] + ( op16 & 0xff );
\r
248 uip_acc32[2] = op32[2] + ( op16 >> 8 );
\r
249 uip_acc32[1] = op32[1];
\r
250 uip_acc32[0] = op32[0];
\r
252 if( uip_acc32[2] < (op16 >> 8) )
\r
255 if( uip_acc32[1] == 0 )
\r
261 if( uip_acc32[3] < (op16 & 0xff) )
\r
264 if( uip_acc32[2] == 0 )
\r
267 if( uip_acc32[1] == 0 )
\r
275 #endif /* UIP_ARCH_ADD32 */
\r
277 #if !UIP_ARCH_CHKSUM
\r
279 /*---------------------------------------------------------------------------*/
\r
280 static u16_t chksum( u16_t sum, const u8_t *data, u16_t len )
\r
283 const u8_t *dataptr;
\r
284 const u8_t *last_byte;
\r
287 last_byte = data + len - 1;
\r
289 while( dataptr < last_byte )
\r
290 { /* At least two more bytes */
\r
291 t = ( dataptr[0] << 8 ) + dataptr[1];
\r
301 if( dataptr == last_byte )
\r
303 t = ( dataptr[0] << 8 ) + 0;
\r
311 /* Return sum in host byte order. */
\r
315 /*---------------------------------------------------------------------------*/
\r
316 u16_t uip_chksum( u16_t *data, u16_t len )
\r
318 return htons( chksum(0, ( u8_t * ) data, len) );
\r
321 /*---------------------------------------------------------------------------*/
\r
322 #ifndef UIP_ARCH_IPCHKSUM
\r
323 u16_t uip_ipchksum( void )
\r
327 sum = chksum( 0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN );
\r
328 DEBUG_PRINTF( "uip_ipchksum: sum 0x%04x\n", sum );
\r
329 return( sum == 0 ) ? 0xffff : htons( sum );
\r
334 /*---------------------------------------------------------------------------*/
\r
335 static u16_t upper_layer_chksum( u8_t proto )
\r
337 u16_t upper_layer_len;
\r
341 upper_layer_len = ( ((u16_t) (BUF->len[0]) << 8) + BUF->len[1] );
\r
342 #else /* UIP_CONF_IPV6 */
\r
343 upper_layer_len = ( ((u16_t) (BUF->len[0]) << 8) + BUF->len[1] ) - UIP_IPH_LEN;
\r
344 #endif /* UIP_CONF_IPV6 */
\r
346 /* First sum pseudoheader. */
\r
348 /* IP protocol and length fields. This addition cannot carry. */
\r
349 sum = upper_layer_len + proto;
\r
351 /* Sum IP source and destination addresses. */
\r
352 sum = chksum( sum, ( u8_t * ) &BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t) );
\r
354 /* Sum TCP header and data. */
\r
355 sum = chksum( sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], upper_layer_len );
\r
357 return( sum == 0 ) ? 0xffff : htons( sum );
\r
360 /*---------------------------------------------------------------------------*/
\r
362 u16_t uip_icmp6chksum( void )
\r
364 return upper_layer_chksum( UIP_PROTO_ICMP6 );
\r
367 #endif /* UIP_CONF_IPV6 */
\r
369 /*---------------------------------------------------------------------------*/
\r
370 u16_t uip_tcpchksum( void )
\r
372 return upper_layer_chksum( UIP_PROTO_TCP );
\r
375 /*---------------------------------------------------------------------------*/
\r
376 #if UIP_UDP_CHECKSUMS
\r
377 u16_t uip_udpchksum( void )
\r
379 return upper_layer_chksum( UIP_PROTO_UDP );
\r
382 #endif /* UIP_UDP_CHECKSUMS */
\r
383 #endif /* UIP_ARCH_CHKSUM */
\r
385 /*---------------------------------------------------------------------------*/
\r
386 void uip_init( void )
\r
388 for( c = 0; c < UIP_LISTENPORTS; ++c )
\r
390 uip_listenports[c] = 0;
\r
393 for( c = 0; c < UIP_CONNS; ++c )
\r
395 uip_conns[c].tcpstateflags = UIP_CLOSED;
\r
398 #if UIP_ACTIVE_OPEN
\r
400 #endif /* UIP_ACTIVE_OPEN */
\r
403 for( c = 0; c < UIP_UDP_CONNS; ++c )
\r
405 uip_udp_conns[c].lport = 0;
\r
408 #endif /* UIP_UDP */
\r
410 /* IPv4 initialization. */
\r
411 #if UIP_FIXEDADDR == 0
\r
413 /* uip_hostaddr[0] = uip_hostaddr[1] = 0;*/
\r
414 #endif /* UIP_FIXEDADDR */
\r
417 /*---------------------------------------------------------------------------*/
\r
418 #if UIP_ACTIVE_OPEN
\r
419 struct uip_conn *uip_connect( uip_ipaddr_t *ripaddr, u16_t rport )
\r
421 register struct uip_conn *conn, *cconn;
\r
423 /* Find an unused local port. */
\r
427 if( lastport >= 32000 )
\r
432 /* Check if this port is already in use, and if so try to find
\r
434 for( c = 0; c < UIP_CONNS; ++c )
\r
436 conn = &uip_conns[c];
\r
437 if( conn->tcpstateflags != UIP_CLOSED && conn->lport == htons(lastport) )
\r
444 for( c = 0; c < UIP_CONNS; ++c )
\r
446 cconn = &uip_conns[c];
\r
447 if( cconn->tcpstateflags == UIP_CLOSED )
\r
453 if( cconn->tcpstateflags == UIP_TIME_WAIT )
\r
455 if( conn == 0 || cconn->timer > conn->timer )
\r
467 conn->tcpstateflags = UIP_SYN_SENT;
\r
469 conn->snd_nxt[0] = iss[0];
\r
470 conn->snd_nxt[1] = iss[1];
\r
471 conn->snd_nxt[2] = iss[2];
\r
472 conn->snd_nxt[3] = iss[3];
\r
474 conn->initialmss = conn->mss = UIP_TCP_MSS;
\r
476 conn->len = 1; /* TCP length of the SYN is one. */
\r
478 conn->timer = 1; /* Send the SYN next time around. */
\r
479 conn->rto = UIP_RTO;
\r
481 conn->sv = 16; /* Initial value of the RTT variance. */
\r
482 conn->lport = htons( lastport );
\r
483 conn->rport = rport;
\r
484 uip_ipaddr_copy( &conn->ripaddr, ripaddr );
\r
489 #endif /* UIP_ACTIVE_OPEN */
\r
491 /*---------------------------------------------------------------------------*/
\r
493 struct uip_udp_conn *uip_udp_new( uip_ipaddr_t *ripaddr, u16_t rport )
\r
495 register struct uip_udp_conn *conn;
\r
497 /* Find an unused local port. */
\r
501 if( lastport >= 32000 )
\r
506 for( c = 0; c < UIP_UDP_CONNS; ++c )
\r
508 if( uip_udp_conns[c].lport == htons(lastport) )
\r
515 for( c = 0; c < UIP_UDP_CONNS; ++c )
\r
517 if( uip_udp_conns[c].lport == 0 )
\r
519 conn = &uip_udp_conns[c];
\r
529 conn->lport = HTONS( lastport );
\r
530 conn->rport = rport;
\r
531 if( ripaddr == NULL )
\r
533 memset( conn->ripaddr, 0, sizeof(uip_ipaddr_t) );
\r
537 uip_ipaddr_copy( &conn->ripaddr, ripaddr );
\r
540 conn->ttl = UIP_TTL;
\r
545 #endif /* UIP_UDP */
\r
547 /*---------------------------------------------------------------------------*/
\r
548 void uip_unlisten( u16_t port )
\r
550 for( c = 0; c < UIP_LISTENPORTS; ++c )
\r
552 if( uip_listenports[c] == port )
\r
554 uip_listenports[c] = 0;
\r
560 /*---------------------------------------------------------------------------*/
\r
561 void uip_listen( u16_t port )
\r
563 for( c = 0; c < UIP_LISTENPORTS; ++c )
\r
565 if( uip_listenports[c] == 0 )
\r
567 uip_listenports[c] = port;
\r
573 /*---------------------------------------------------------------------------*/
\r
575 /* XXX: IP fragment reassembly: not well-tested. */
\r
576 #if UIP_REASSEMBLY && !UIP_CONF_IPV6
\r
577 #define UIP_REASS_BUFSIZE ( UIP_BUFSIZE - UIP_LLH_LEN )
\r
578 static u8_t uip_reassbuf[UIP_REASS_BUFSIZE];
\r
579 static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / ( 8 * 8 )];
\r
580 static const u8_t bitmap_bits[8] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
\r
581 static u16_t uip_reasslen;
\r
582 static u8_t uip_reassflags;
\r
583 #define UIP_REASS_FLAG_LASTFRAG 0x01
\r
584 static u8_t uip_reasstmr;
\r
588 static u8_t uip_reass( void )
\r
593 /* If ip_reasstmr is zero, no packet is present in the buffer, so we
\r
594 write the IP header of the fragment into the reassembly
\r
595 buffer. The timer is updated with the maximum age. */
\r
596 if( uip_reasstmr == 0 )
\r
598 memcpy( uip_reassbuf, &BUF->vhl, UIP_IPH_LEN );
\r
599 uip_reasstmr = UIP_REASS_MAXAGE;
\r
600 uip_reassflags = 0;
\r
602 /* Clear the bitmap. */
\r
603 memset( uip_reassbitmap, 0, sizeof(uip_reassbitmap) );
\r
606 /* Check if the incoming fragment matches the one currently present
\r
607 in the reasembly buffer. If so, we proceed with copying the
\r
608 fragment into the buffer. */
\r
611 BUF->srcipaddr[0] == FBUF->srcipaddr[0] &&
\r
612 BUF->srcipaddr[1] == FBUF->srcipaddr[1] &&
\r
613 BUF->destipaddr[0] == FBUF->destipaddr[0] &&
\r
614 BUF->destipaddr[1] == FBUF->destipaddr[1] &&
\r
615 BUF->ipid[0] == FBUF->ipid[0] &&
\r
616 BUF->ipid[1] == FBUF->ipid[1]
\r
619 len = ( BUF->len[0] << 8 ) + BUF->len[1] - ( BUF->vhl & 0x0f ) * 4;
\r
620 offset = ( ((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1] ) * 8;
\r
622 /* If the offset or the offset + fragment length overflows the
\r
623 reassembly buffer, we discard the entire packet. */
\r
624 if( offset > UIP_REASS_BUFSIZE || offset + len > UIP_REASS_BUFSIZE )
\r
630 /* Copy the fragment into the reassembly buffer, at the right
\r
632 memcpy( &uip_reassbuf[UIP_IPH_LEN + offset], ( char * ) BUF + ( int ) ((BUF->vhl & 0x0f) * 4), len );
\r
634 /* Update the bitmap. */
\r
635 if( offset / (8 * 8) == (offset + len) / (8 * 8) )
\r
637 /* If the two endpoints are in the same byte, we only update
\r
639 uip_reassbitmap[offset / ( 8 * 8 )] |= bitmap_bits[( offset / 8 ) & 7] &~bitmap_bits[( (offset + len) / 8 ) & 7];
\r
643 /* If the two endpoints are in different bytes, we update the
\r
644 bytes in the endpoints and fill the stuff inbetween with
\r
646 uip_reassbitmap[offset / ( 8 * 8 )] |= bitmap_bits[( offset / 8 ) & 7];
\r
647 for( i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i )
\r
649 uip_reassbitmap[i] = 0xff;
\r
652 uip_reassbitmap[( offset + len ) / ( 8 * 8 )] |= ~bitmap_bits[( (offset + len) / 8 ) & 7];
\r
655 /* If this fragment has the More Fragments flag set to zero, we
\r
656 know that this is the last fragment, so we can calculate the
\r
657 size of the entire packet. We also set the
\r
658 IP_REASS_FLAG_LASTFRAG flag to indicate that we have received
\r
659 the final fragment. */
\r
660 if( (BUF->ipoffset[0] & IP_MF) == 0 )
\r
662 uip_reassflags |= UIP_REASS_FLAG_LASTFRAG;
\r
663 uip_reasslen = offset + len;
\r
666 /* Finally, we check if we have a full packet in the buffer. We do
\r
667 this by checking if we have the last fragment and if all bits
\r
668 in the bitmap are set. */
\r
669 if( uip_reassflags & UIP_REASS_FLAG_LASTFRAG )
\r
671 /* Check all bytes up to and including all but the last byte in
\r
673 for( i = 0; i < uip_reasslen / (8 * 8) - 1; ++i )
\r
675 if( uip_reassbitmap[i] != 0xff )
\r
681 /* Check the last byte in the bitmap. It should contain just the
\r
682 right amount of bits. */
\r
683 if( uip_reassbitmap[uip_reasslen / (8 * 8)] != (u8_t)~bitmap_bits[uip_reasslen / 8 & 7] )
\r
688 /* If we have come this far, we have a full packet in the
\r
689 buffer, so we allocate a pbuf and copy the packet into it. We
\r
690 also reset the timer. */
\r
692 memcpy( BUF, FBUF, uip_reasslen );
\r
694 /* Pretend to be a "normal" (i.e., not fragmented) IP packet
\r
696 BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
\r
697 BUF->len[0] = uip_reasslen >> 8;
\r
698 BUF->len[1] = uip_reasslen & 0xff;
\r
700 BUF->ipchksum = ~( uip_ipchksum() );
\r
702 return uip_reasslen;
\r
710 #endif /* UIP_REASSEMBLY */
\r
712 /*---------------------------------------------------------------------------*/
\r
713 static void uip_add_rcv_nxt( u16_t n )
\r
715 uip_add32( uip_conn->rcv_nxt, n );
\r
716 uip_conn->rcv_nxt[0] = uip_acc32[0];
\r
717 uip_conn->rcv_nxt[1] = uip_acc32[1];
\r
718 uip_conn->rcv_nxt[2] = uip_acc32[2];
\r
719 uip_conn->rcv_nxt[3] = uip_acc32[3];
\r
722 /*---------------------------------------------------------------------------*/
\r
723 void uip_process( u8_t flag )
\r
725 register struct uip_conn *uip_connr = uip_conn;
\r
728 if( flag == UIP_UDP_SEND_CONN )
\r
733 #endif /* UIP_UDP */
\r
735 uip_sappdata = uip_appdata = &uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN];
\r
737 /* Check if we were invoked because of a poll request for a
\r
738 particular connection. */
\r
739 if( flag == UIP_POLL_REQUEST )
\r
741 if( (uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED && !uip_outstanding(uip_connr) )
\r
743 uip_flags = UIP_POLL;
\r
750 /* Check if we were invoked because of the perodic timer fireing. */
\r
752 else if( flag == UIP_TIMER )
\r
755 if( uip_reasstmr != 0 )
\r
760 #endif /* UIP_REASSEMBLY */
\r
762 /* Increase the initial sequence number. */
\r
763 if( ++iss[3] == 0 )
\r
765 if( ++iss[2] == 0 )
\r
767 if( ++iss[1] == 0 )
\r
774 /* Reset the length variables. */
\r
778 /* Check if the connection is in a state in which we simply wait
\r
779 for the connection to time out. If so, we increase the
\r
780 connection's timer and remove the connection if it times
\r
782 if( uip_connr->tcpstateflags == UIP_TIME_WAIT || uip_connr->tcpstateflags == UIP_FIN_WAIT_2 )
\r
784 ++( uip_connr->timer );
\r
785 if( uip_connr->timer == UIP_TIME_WAIT_TIMEOUT )
\r
787 uip_connr->tcpstateflags = UIP_CLOSED;
\r
790 else if( uip_connr->tcpstateflags != UIP_CLOSED )
\r
792 /* If the connection has outstanding data, we increase the
\r
793 connection's timer and see if it has reached the RTO value
\r
794 in which case we retransmit. */
\r
795 if( uip_outstanding(uip_connr) )
\r
797 uip_connr->timer = uip_connr->timer - 1;
\r
798 if( uip_connr->timer == 0 )
\r
802 uip_connr->nrtx == UIP_MAXRTX ||
\r
804 (uip_connr->tcpstateflags == UIP_SYN_SENT || uip_connr->tcpstateflags == UIP_SYN_RCVD) &&
\r
805 uip_connr->nrtx == UIP_MAXSYNRTX
\r
809 uip_connr->tcpstateflags = UIP_CLOSED;
\r
811 /* We call UIP_APPCALL() with uip_flags set to
\r
812 UIP_TIMEDOUT to inform the application that the
\r
813 connection has timed out. */
\r
814 uip_flags = UIP_TIMEDOUT;
\r
817 /* We also send a reset packet to the remote host. */
\r
818 BUF->flags = TCP_RST | TCP_ACK;
\r
819 goto tcp_send_nodata;
\r
822 /* Exponential backoff. */
\r
823 uip_connr->timer = UIP_RTO << ( uip_connr->nrtx > 4 ? 4 : uip_connr->nrtx );
\r
824 ++( uip_connr->nrtx );
\r
826 /* Ok, so we need to retransmit. We do this differently
\r
827 depending on which state we are in. In ESTABLISHED, we
\r
828 call upon the application so that it may prepare the
\r
829 data for the retransmit. In SYN_RCVD, we resend the
\r
830 SYNACK that we sent earlier and in LAST_ACK we have to
\r
831 retransmit our FINACK. */
\r
832 UIP_STAT( ++uip_stat.tcp.rexmit );
\r
833 switch( uip_connr->tcpstateflags & UIP_TS_MASK )
\r
836 /* In the SYN_RCVD state, we should retransmit our
\r
838 goto tcp_send_synack;
\r
840 #if UIP_ACTIVE_OPEN
\r
843 /* In the SYN_SENT state, we retransmit out SYN. */
\r
846 #endif /* UIP_ACTIVE_OPEN */
\r
848 case UIP_ESTABLISHED:
\r
849 /* In the ESTABLISHED state, we call upon the application
\r
850 to do the actual retransmit after which we jump into
\r
851 the code for sending out the packet (the apprexmit
\r
853 uip_flags = UIP_REXMIT;
\r
857 case UIP_FIN_WAIT_1:
\r
860 /* In all these states we should retransmit a FINACK. */
\r
861 goto tcp_send_finack;
\r
865 else if( (uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED )
\r
867 /* If there was no need for a retransmission, we poll the
\r
868 application for new data. */
\r
869 uip_flags = UIP_POLL;
\r
879 if( flag == UIP_UDP_TIMER )
\r
881 if( uip_udp_conn->lport != 0 )
\r
884 uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
\r
885 uip_len = uip_slen = 0;
\r
886 uip_flags = UIP_POLL;
\r
898 /* This is where the input processing starts. */
\r
899 UIP_STAT( ++uip_stat.ip.recv );
\r
901 /* Start of IP input header processing code. */
\r
904 /* Check validity of the IP header. */
\r
905 if( (BUF->vtc & 0xf0) != 0x60 )
\r
906 { /* IP version and header length. */
\r
907 UIP_STAT( ++uip_stat.ip.drop );
\r
908 UIP_STAT( ++uip_stat.ip.vhlerr );
\r
909 UIP_LOG( "ipv6: invalid version." );
\r
913 #else /* UIP_CONF_IPV6 */
\r
915 /* Check validity of the IP header. */
\r
916 if( BUF->vhl != 0x45 )
\r
917 { /* IP version and header length. */
\r
918 UIP_STAT( ++uip_stat.ip.drop );
\r
919 UIP_STAT( ++uip_stat.ip.vhlerr );
\r
920 UIP_LOG( "ip: invalid version or header length." );
\r
924 #endif /* UIP_CONF_IPV6 */
\r
926 /* Check the size of the packet. If the size reported to us in
\r
927 uip_len is smaller the size reported in the IP header, we assume
\r
928 that the packet has been corrupted in transit. If the size of
\r
929 uip_len is larger than the size reported in the IP packet header,
\r
930 the packet has been padded and we set uip_len to the correct
\r
932 if( (BUF->len[0] << 8) + BUF->len[1] <= uip_len )
\r
934 uip_len = ( BUF->len[0] << 8 ) + BUF->len[1];
\r
936 uip_len += 40; /* The length reported in the IPv6 header is the
\r
937 length of the payload that follows the
\r
938 header. However, uIP uses the uip_len variable
\r
939 for holding the size of the entire packet,
\r
940 including the IP header. For IPv4 this is not a
\r
941 problem as the length field in the IPv4 header
\r
942 contains the length of the entire packet. But
\r
943 for IPv6 we need to add the size of the IPv6
\r
944 header (40 bytes). */
\r
945 #endif /* UIP_CONF_IPV6 */
\r
949 UIP_LOG( "ip: packet shorter than reported in IP header." );
\r
955 /* Check the fragment flag. */
\r
956 if( (BUF->ipoffset[0] & 0x3f) != 0 || BUF->ipoffset[1] != 0 )
\r
959 uip_len = uip_reass();
\r
965 #else /* UIP_REASSEMBLY */
\r
966 UIP_STAT( ++uip_stat.ip.drop );
\r
967 UIP_STAT( ++uip_stat.ip.fragerr );
\r
968 UIP_LOG( "ip: fragment dropped." );
\r
970 #endif /* UIP_REASSEMBLY */
\r
973 #endif /* UIP_CONF_IPV6 */
\r
975 if( uip_ipaddr_cmp(uip_hostaddr, all_zeroes_addr) )
\r
977 /* If we are configured to use ping IP address configuration and
\r
978 hasn't been assigned an IP address yet, we accept all ICMP
\r
980 #if UIP_PINGADDRCONF && !UIP_CONF_IPV6
\r
981 if( BUF->proto == UIP_PROTO_ICMP )
\r
983 UIP_LOG( "ip: possible ping config packet received." );
\r
988 UIP_LOG( "ip: packet dropped since no address assigned." );
\r
992 #endif /* UIP_PINGADDRCONF */
\r
996 /* If IP broadcast support is configured, we check for a broadcast
\r
997 UDP packet, which may be destined to us. */
\r
999 DEBUG_PRINTF( "UDP IP checksum 0x%04x\n", uip_ipchksum() );
\r
1000 if( BUF->proto == UIP_PROTO_UDP && uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr) /*&&
\r
1001 uip_ipchksum() == 0xffff*/ )
\r
1006 #endif /* UIP_BROADCAST */
\r
1008 /* Check if the packet is destined for our IP address. */
\r
1009 #if !UIP_CONF_IPV6
\r
1010 if( !uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr) )
\r
1012 UIP_STAT( ++uip_stat.ip.drop );
\r
1016 #else /* UIP_CONF_IPV6 */
\r
1018 /* For IPv6, packet reception is a little trickier as we need to
\r
1019 make sure that we listen to certain multicast addresses (all
\r
1020 hosts multicast address, and the solicited-node multicast
\r
1021 address) as well. However, we will cheat here and accept all
\r
1022 multicast packets that are sent to the ff02::/16 addresses. */
\r
1023 if( !uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr) && BUF->destipaddr[0] != HTONS(0xff02) )
\r
1025 UIP_STAT( ++uip_stat.ip.drop );
\r
1029 #endif /* UIP_CONF_IPV6 */
\r
1032 #if !UIP_CONF_IPV6
\r
1033 if( uip_ipchksum() != 0xffff )
\r
1034 { /* Compute and check the IP header
\r
1036 UIP_STAT( ++uip_stat.ip.drop );
\r
1037 UIP_STAT( ++uip_stat.ip.chkerr );
\r
1038 UIP_LOG( "ip: bad checksum." );
\r
1042 #endif /* UIP_CONF_IPV6 */
\r
1044 if( BUF->proto == UIP_PROTO_TCP )
\r
1045 { /* Check for TCP packet. If so,
\r
1046 proceed with TCP input
\r
1052 if( BUF->proto == UIP_PROTO_UDP )
\r
1057 #endif /* UIP_UDP */
\r
1059 #if !UIP_CONF_IPV6
\r
1061 /* ICMPv4 processing code follows. */
\r
1062 if( BUF->proto != UIP_PROTO_ICMP )
\r
1063 { /* We only allow ICMP packets from
\r
1065 UIP_STAT( ++uip_stat.ip.drop );
\r
1066 UIP_STAT( ++uip_stat.ip.protoerr );
\r
1067 UIP_LOG( "ip: neither tcp nor icmp." );
\r
1071 #if UIP_PINGADDRCONF
\r
1073 #endif /* UIP_PINGADDRCONF */
\r
1074 UIP_STAT( ++uip_stat.icmp.recv );
\r
1076 /* ICMP echo (i.e., ping) processing. This is simple, we only change
\r
1077 the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP
\r
1078 checksum before we return the packet. */
\r
1079 if( ICMPBUF->type != ICMP_ECHO )
\r
1081 UIP_STAT( ++uip_stat.icmp.drop );
\r
1082 UIP_STAT( ++uip_stat.icmp.typeerr );
\r
1083 UIP_LOG( "icmp: not icmp echo." );
\r
1087 /* If we are configured to use ping IP address assignment, we use
\r
1088 the destination IP address of this ping packet and assign it to
\r
1090 #if UIP_PINGADDRCONF
\r
1091 if( (uip_hostaddr[0] | uip_hostaddr[1]) == 0 )
\r
1093 uip_hostaddr[0] = BUF->destipaddr[0];
\r
1094 uip_hostaddr[1] = BUF->destipaddr[1];
\r
1097 #endif /* UIP_PINGADDRCONF */
\r
1099 ICMPBUF->type = ICMP_ECHO_REPLY;
\r
1101 if( ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8)) )
\r
1103 ICMPBUF->icmpchksum += HTONS( ICMP_ECHO << 8 ) + 1;
\r
1107 ICMPBUF->icmpchksum += HTONS( ICMP_ECHO << 8 );
\r
1110 /* Swap IP addresses. */
\r
1111 uip_ipaddr_copy( BUF->destipaddr, BUF->srcipaddr );
\r
1112 uip_ipaddr_copy( BUF->srcipaddr, uip_hostaddr );
\r
1114 UIP_STAT( ++uip_stat.icmp.sent );
\r
1117 /* End of IPv4 input header processing code. */
\r
1118 #else /* !UIP_CONF_IPV6 */
\r
1120 /* This is IPv6 ICMPv6 processing code. */
\r
1121 DEBUG_PRINTF( "icmp6_input: length %d\n", uip_len );
\r
1123 if( BUF->proto != UIP_PROTO_ICMP6 )
\r
1124 { /* We only allow ICMPv6 packets from
\r
1126 UIP_STAT( ++uip_stat.ip.drop );
\r
1127 UIP_STAT( ++uip_stat.ip.protoerr );
\r
1128 UIP_LOG( "ip: neither tcp nor icmp6." );
\r
1132 UIP_STAT( ++uip_stat.icmp.recv );
\r
1134 /* If we get a neighbor solicitation for our address we should send
\r
1135 a neighbor advertisement message back. */
\r
1136 if( ICMPBUF->type == ICMP6_NEIGHBOR_SOLICITATION )
\r
1138 if( uip_ipaddr_cmp(ICMPBUF->icmp6data, uip_hostaddr) )
\r
1140 if( ICMPBUF->options[0] == ICMP6_OPTION_SOURCE_LINK_ADDRESS )
\r
1142 /* Save the sender's address in our neighbor list. */
\r
1143 uip_neighbor_add( ICMPBUF->srcipaddr, &(ICMPBUF->options[2]) );
\r
1146 /* We should now send a neighbor advertisement back to where the
\r
1147 neighbor solicication came from. */
\r
1148 ICMPBUF->type = ICMP6_NEIGHBOR_ADVERTISEMENT;
\r
1149 ICMPBUF->flags = ICMP6_FLAG_S; /* Solicited flag. */
\r
1151 ICMPBUF->reserved1 = ICMPBUF->reserved2 = ICMPBUF->reserved3 = 0;
\r
1153 uip_ipaddr_copy( ICMPBUF->destipaddr, ICMPBUF->srcipaddr );
\r
1154 uip_ipaddr_copy( ICMPBUF->srcipaddr, uip_hostaddr );
\r
1155 ICMPBUF->options[0] = ICMP6_OPTION_TARGET_LINK_ADDRESS;
\r
1156 ICMPBUF->options[1] = 1; /* Options length, 1 = 8 bytes. */
\r
1157 memcpy( &(ICMPBUF->options[2]), &uip_ethaddr, sizeof(uip_ethaddr) );
\r
1158 ICMPBUF->icmpchksum = 0;
\r
1159 ICMPBUF->icmpchksum = ~uip_icmp6chksum();
\r
1165 else if( ICMPBUF->type == ICMP6_ECHO )
\r
1167 /* ICMP echo (i.e., ping) processing. This is simple, we only
\r
1168 change the ICMP type from ECHO to ECHO_REPLY and update the
\r
1169 ICMP checksum before we return the packet. */
\r
1170 ICMPBUF->type = ICMP6_ECHO_REPLY;
\r
1172 uip_ipaddr_copy( BUF->destipaddr, BUF->srcipaddr );
\r
1173 uip_ipaddr_copy( BUF->srcipaddr, uip_hostaddr );
\r
1174 ICMPBUF->icmpchksum = 0;
\r
1175 ICMPBUF->icmpchksum = ~uip_icmp6chksum();
\r
1177 UIP_STAT( ++uip_stat.icmp.sent );
\r
1182 DEBUG_PRINTF( "Unknown icmp6 message type %d\n", ICMPBUF->type );
\r
1183 UIP_STAT( ++uip_stat.icmp.drop );
\r
1184 UIP_STAT( ++uip_stat.icmp.typeerr );
\r
1185 UIP_LOG( "icmp: unknown ICMP message." );
\r
1189 /* End of IPv6 ICMP processing. */
\r
1190 #endif /* !UIP_CONF_IPV6 */
\r
1194 /* UDP input processing. */
\r
1196 /* UDP processing is really just a hack. We don't do anything to the
\r
1197 UDP/IP headers, but let the UDP application do all the hard
\r
1198 work. If the application sets uip_slen, it has a packet to
\r
1200 #if UIP_UDP_CHECKSUMS
\r
1201 uip_len = uip_len - UIP_IPUDPH_LEN;
\r
1202 uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
\r
1203 if( UDPBUF->udpchksum != 0 && uip_udpchksum() != 0xffff )
\r
1205 UIP_STAT( ++uip_stat.udp.drop );
\r
1206 UIP_STAT( ++uip_stat.udp.chkerr );
\r
1207 UIP_LOG( "udp: bad checksum." );
\r
1211 #else /* UIP_UDP_CHECKSUMS */
\r
1212 uip_len = uip_len - UIP_IPUDPH_LEN;
\r
1213 #endif /* UIP_UDP_CHECKSUMS */
\r
1215 /* Demultiplex this UDP packet between the UDP "connections". */
\r
1216 for( uip_udp_conn = &uip_udp_conns[0]; uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS]; ++uip_udp_conn )
\r
1218 /* If the local UDP port is non-zero, the connection is considered
\r
1219 to be used. If so, the local port number is checked against the
\r
1220 destination port number in the received packet. If the two port
\r
1221 numbers match, the remote port number is checked if the
\r
1222 connection is bound to a remote port. Finally, if the
\r
1223 connection is bound to a remote IP address, the source IP
\r
1224 address of the packet is checked. */
\r
1227 uip_udp_conn->lport != 0 &&
\r
1228 UDPBUF->destport == uip_udp_conn->lport &&
\r
1229 (uip_udp_conn->rport == 0 || UDPBUF->srcport == uip_udp_conn->rport) &&
\r
1231 uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) ||
\r
1232 uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) ||
\r
1233 uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr)
\r
1241 UIP_LOG( "udp: no matching connection found" );
\r
1245 UIP_STAT( ++uip_stat.udp.recv );
\r
1247 uip_flags = UIP_NEWDATA;
\r
1248 uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
\r
1250 UIP_UDP_APPCALL();
\r
1252 if( uip_slen == 0 )
\r
1257 uip_len = uip_slen + UIP_IPUDPH_LEN;
\r
1261 /* For IPv6, the IP length field does not include the IPv6 IP header
\r
1263 BUF->len[0] = ( (uip_len - UIP_IPH_LEN) >> 8 );
\r
1264 BUF->len[1] = ( (uip_len - UIP_IPH_LEN) & 0xff );
\r
1265 #else /* UIP_CONF_IPV6 */
\r
1266 BUF->len[0] = ( uip_len >> 8 );
\r
1267 BUF->len[1] = ( uip_len & 0xff );
\r
1268 #endif /* UIP_CONF_IPV6 */
\r
1270 BUF->ttl = uip_udp_conn->ttl;
\r
1271 BUF->proto = UIP_PROTO_UDP;
\r
1273 UDPBUF->udplen = HTONS( uip_slen + UIP_UDPH_LEN );
\r
1274 UDPBUF->udpchksum = 0;
\r
1276 BUF->srcport = uip_udp_conn->lport;
\r
1277 BUF->destport = uip_udp_conn->rport;
\r
1279 uip_ipaddr_copy( BUF->srcipaddr, uip_hostaddr );
\r
1280 uip_ipaddr_copy( BUF->destipaddr, uip_udp_conn->ripaddr );
\r
1282 uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN];
\r
1284 #if UIP_UDP_CHECKSUMS
\r
1286 /* Calculate UDP checksum. */
\r
1287 UDPBUF->udpchksum = ~( uip_udpchksum() );
\r
1288 if( UDPBUF->udpchksum == 0 )
\r
1290 UDPBUF->udpchksum = 0xffff;
\r
1293 #endif /* UIP_UDP_CHECKSUMS */
\r
1294 UIP_STAT( ++uip_stat.udp.sent );
\r
1295 goto ip_send_nolen;
\r
1296 #endif /* UIP_UDP */
\r
1298 /* TCP input processing. */
\r
1299 tcp_input : UIP_STAT( ++uip_stat.tcp.recv );
\r
1301 /* Start of TCP input header processing code. */
\r
1302 if( uip_tcpchksum() != 0xffff )
\r
1303 { /* Compute and check the TCP
\r
1305 UIP_STAT( ++uip_stat.tcp.drop );
\r
1306 UIP_STAT( ++uip_stat.tcp.chkerr );
\r
1307 UIP_LOG( "tcp: bad checksum." );
\r
1311 /* Demultiplex this segment. */
\r
1313 /* First check any active connections. */
\r
1314 for( uip_connr = &uip_conns[0]; uip_connr <= &uip_conns[UIP_CONNS - 1]; ++uip_connr )
\r
1318 uip_connr->tcpstateflags != UIP_CLOSED &&
\r
1319 BUF->destport == uip_connr->lport &&
\r
1320 BUF->srcport == uip_connr->rport &&
\r
1321 uip_ipaddr_cmp(BUF->srcipaddr, uip_connr->ripaddr)
\r
1328 /* If we didn't find and active connection that expected the packet,
\r
1329 either this packet is an old duplicate, or this is a SYN packet
\r
1330 destined for a connection in LISTEN. If the SYN flag isn't set,
\r
1331 it is an old packet and we send a RST. */
\r
1332 if( (BUF->flags & TCP_CTL) != TCP_SYN )
\r
1337 tmp16 = BUF->destport;
\r
1339 /* Next, check listening connections. */
\r
1340 for( c = 0; c < UIP_LISTENPORTS; ++c )
\r
1342 if( tmp16 == uip_listenports[c] )
\r
1344 goto found_listen;
\r
1348 /* No matching connection found, so we send a RST packet. */
\r
1349 UIP_STAT( ++uip_stat.tcp.synrst );
\r
1351 /* We do not send resets in response to resets. */
\r
1352 if( BUF->flags & TCP_RST )
\r
1357 UIP_STAT( ++uip_stat.tcp.rst );
\r
1359 BUF->flags = TCP_RST | TCP_ACK;
\r
1360 uip_len = UIP_IPTCPH_LEN;
\r
1361 BUF->tcpoffset = 5 << 4;
\r
1363 /* Flip the seqno and ackno fields in the TCP header. */
\r
1364 c = BUF->seqno[3];
\r
1365 BUF->seqno[3] = BUF->ackno[3];
\r
1366 BUF->ackno[3] = c;
\r
1368 c = BUF->seqno[2];
\r
1369 BUF->seqno[2] = BUF->ackno[2];
\r
1370 BUF->ackno[2] = c;
\r
1372 c = BUF->seqno[1];
\r
1373 BUF->seqno[1] = BUF->ackno[1];
\r
1374 BUF->ackno[1] = c;
\r
1376 c = BUF->seqno[0];
\r
1377 BUF->seqno[0] = BUF->ackno[0];
\r
1378 BUF->ackno[0] = c;
\r
1380 /* We also have to increase the sequence number we are
\r
1381 acknowledging. If the least significant byte overflowed, we need
\r
1382 to propagate the carry to the other bytes as well. */
\r
1383 if( ++BUF->ackno[3] == 0 )
\r
1385 if( ++BUF->ackno[2] == 0 )
\r
1387 if( ++BUF->ackno[1] == 0 )
\r
1394 /* Swap port numbers. */
\r
1395 tmp16 = BUF->srcport;
\r
1396 BUF->srcport = BUF->destport;
\r
1397 BUF->destport = tmp16;
\r
1399 /* Swap IP addresses. */
\r
1400 uip_ipaddr_copy( BUF->destipaddr, BUF->srcipaddr );
\r
1401 uip_ipaddr_copy( BUF->srcipaddr, uip_hostaddr );
\r
1403 /* And send out the RST packet! */
\r
1404 goto tcp_send_noconn;
\r
1406 /* This label will be jumped to if we matched the incoming packet
\r
1407 with a connection in LISTEN. In that case, we should create a new
\r
1408 connection and send a SYNACK in return. */
\r
1410 /* First we check if there are any connections avaliable. Unused
\r
1411 connections are kept in the same table as used connections, but
\r
1412 unused ones have the tcpstate set to CLOSED. Also, connections in
\r
1413 TIME_WAIT are kept track of and we'll use the oldest one if no
\r
1414 CLOSED connections are found. Thanks to Eddie C. Dost for a very
\r
1415 nice algorithm for the TIME_WAIT search. */
\r
1417 for( c = 0; c < UIP_CONNS; ++c )
\r
1419 if( uip_conns[c].tcpstateflags == UIP_CLOSED )
\r
1421 uip_connr = &uip_conns[c];
\r
1425 if( uip_conns[c].tcpstateflags == UIP_TIME_WAIT )
\r
1427 if( uip_connr == 0 || uip_conns[c].timer > uip_connr->timer )
\r
1429 uip_connr = &uip_conns[c];
\r
1434 if( uip_connr == 0 )
\r
1436 /* All connections are used already, we drop packet and hope that
\r
1437 the remote end will retransmit the packet at a time when we
\r
1438 have more spare connections. */
\r
1439 UIP_STAT( ++uip_stat.tcp.syndrop );
\r
1440 UIP_LOG( "tcp: found no unused connections." );
\r
1444 uip_conn = uip_connr;
\r
1446 /* Fill in the necessary fields for the new connection. */
\r
1447 uip_connr->rto = uip_connr->timer = UIP_RTO;
\r
1448 uip_connr->sa = 0;
\r
1449 uip_connr->sv = 4;
\r
1450 uip_connr->nrtx = 0;
\r
1451 uip_connr->lport = BUF->destport;
\r
1452 uip_connr->rport = BUF->srcport;
\r
1453 uip_ipaddr_copy( uip_connr->ripaddr, BUF->srcipaddr );
\r
1454 uip_connr->tcpstateflags = UIP_SYN_RCVD;
\r
1456 uip_connr->snd_nxt[0] = iss[0];
\r
1457 uip_connr->snd_nxt[1] = iss[1];
\r
1458 uip_connr->snd_nxt[2] = iss[2];
\r
1459 uip_connr->snd_nxt[3] = iss[3];
\r
1460 uip_connr->len = 1;
\r
1462 /* rcv_nxt should be the seqno from the incoming packet + 1. */
\r
1463 uip_connr->rcv_nxt[3] = BUF->seqno[3];
\r
1464 uip_connr->rcv_nxt[2] = BUF->seqno[2];
\r
1465 uip_connr->rcv_nxt[1] = BUF->seqno[1];
\r
1466 uip_connr->rcv_nxt[0] = BUF->seqno[0];
\r
1467 uip_add_rcv_nxt( 1 );
\r
1469 /* Parse the TCP MSS option, if present. */
\r
1470 if( (BUF->tcpoffset & 0xf0) > 0x50 )
\r
1472 for( c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2; )
\r
1474 opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c];
\r
1475 if( opt == TCP_OPT_END )
\r
1477 /* End of options. */
\r
1480 else if( opt == TCP_OPT_NOOP )
\r
1486 else if( opt == TCP_OPT_MSS && uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN )
\r
1488 /* An MSS option with the right option length. */
\r
1489 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
1490 uip_connr->initialmss = uip_connr->mss = tmp16 > UIP_TCP_MSS ? UIP_TCP_MSS : tmp16;
\r
1492 /* And we are done processing options. */
\r
1497 /* All other options have a length field, so that we easily
\r
1498 can skip past them. */
\r
1499 if( uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0 )
\r
1501 /* If the length field is zero, the options are malformed
\r
1502 and we don't process them further. */
\r
1506 c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
\r
1511 /* Our response will be a SYNACK. */
\r
1512 #if UIP_ACTIVE_OPEN
\r
1513 tcp_send_synack : BUF->flags = TCP_ACK;
\r
1516 BUF->flags |= TCP_SYN;
\r
1517 #else /* UIP_ACTIVE_OPEN */
\r
1518 tcp_send_synack : BUF->flags = TCP_SYN | TCP_ACK;
\r
1519 #endif /* UIP_ACTIVE_OPEN */
\r
1521 /* We send out the TCP Maximum Segment Size option with our
\r
1523 BUF->optdata[0] = TCP_OPT_MSS;
\r
1524 BUF->optdata[1] = TCP_OPT_MSS_LEN;
\r
1525 BUF->optdata[2] = ( UIP_TCP_MSS ) / 256;
\r
1526 BUF->optdata[3] = ( UIP_TCP_MSS ) & 255;
\r
1527 uip_len = UIP_IPTCPH_LEN + TCP_OPT_MSS_LEN;
\r
1528 BUF->tcpoffset = ( (UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4 ) << 4;
\r
1531 /* This label will be jumped to if we found an active connection. */
\r
1533 uip_conn = uip_connr;
\r
1536 /* We do a very naive form of TCP reset processing; we just accept
\r
1537 any RST and kill our connection. We should in fact check if the
\r
1538 sequence number of this reset is wihtin our advertised window
\r
1539 before we accept the reset. */
\r
1540 if( BUF->flags & TCP_RST )
\r
1542 uip_connr->tcpstateflags = UIP_CLOSED;
\r
1543 UIP_LOG( "tcp: got reset, aborting connection." );
\r
1544 uip_flags = UIP_ABORT;
\r
1549 /* Calculated the length of the data, if the application has sent
\r
1550 any data to us. */
\r
1551 c = ( BUF->tcpoffset >> 4 ) << 2;
\r
1553 /* uip_len will contain the length of the actual TCP data. This is
\r
1554 calculated by subtracing the length of the TCP header (in
\r
1555 c) and the length of the IP header (20 bytes). */
\r
1556 uip_len = uip_len - c - UIP_IPH_LEN;
\r
1558 /* First, check if the sequence number of the incoming packet is
\r
1559 what we're expecting next. If not, we send out an ACK with the
\r
1560 correct numbers in. */
\r
1561 if( !(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) && ((BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK))) )
\r
1565 (uip_len > 0 || ((BUF->flags & (TCP_SYN | TCP_FIN)) != 0)) &&
\r
1567 BUF->seqno[0] != uip_connr->rcv_nxt[0] ||
\r
1568 BUF->seqno[1] != uip_connr->rcv_nxt[1] ||
\r
1569 BUF->seqno[2] != uip_connr->rcv_nxt[2] ||
\r
1570 BUF->seqno[3] != uip_connr->rcv_nxt[3]
\r
1574 goto tcp_send_ack;
\r
1578 /* Next, check if the incoming segment acknowledges any outstanding
\r
1579 data. If so, we update the sequence number, reset the length of
\r
1580 the outstanding data, calculate RTT estimations, and reset the
\r
1581 retransmission timer. */
\r
1582 if( (BUF->flags & TCP_ACK) && uip_outstanding(uip_connr) )
\r
1584 uip_add32( uip_connr->snd_nxt, uip_connr->len );
\r
1588 BUF->ackno[0] == uip_acc32[0] &&
\r
1589 BUF->ackno[1] == uip_acc32[1] &&
\r
1590 BUF->ackno[2] == uip_acc32[2] &&
\r
1591 BUF->ackno[3] == uip_acc32[3]
\r
1594 /* Update sequence number. */
\r
1595 uip_connr->snd_nxt[0] = uip_acc32[0];
\r
1596 uip_connr->snd_nxt[1] = uip_acc32[1];
\r
1597 uip_connr->snd_nxt[2] = uip_acc32[2];
\r
1598 uip_connr->snd_nxt[3] = uip_acc32[3];
\r
1600 /* Do RTT estimation, unless we have done retransmissions. */
\r
1601 if( uip_connr->nrtx == 0 )
\r
1604 m = uip_connr->rto - uip_connr->timer;
\r
1606 /* This is taken directly from VJs original code in his paper */
\r
1607 m = m - ( uip_connr->sa >> 3 );
\r
1608 uip_connr->sa += m;
\r
1614 m = m - ( uip_connr->sv >> 2 );
\r
1615 uip_connr->sv += m;
\r
1616 uip_connr->rto = ( uip_connr->sa >> 3 ) + uip_connr->sv;
\r
1619 /* Set the acknowledged flag. */
\r
1620 uip_flags = UIP_ACKDATA;
\r
1622 /* Reset the retransmission timer. */
\r
1623 uip_connr->timer = uip_connr->rto;
\r
1625 /* Reset length of outstanding data. */
\r
1626 uip_connr->len = 0;
\r
1630 /* Do different things depending on in what state the connection is. */
\r
1631 switch( uip_connr->tcpstateflags & UIP_TS_MASK )
\r
1633 /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not
\r
1634 implemented, since we force the application to close when the
\r
1635 peer sends a FIN (hence the application goes directly from
\r
1636 ESTABLISHED to LAST_ACK). */
\r
1637 case UIP_SYN_RCVD:
\r
1638 /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and
\r
1639 we are waiting for an ACK that acknowledges the data we sent
\r
1640 out the last time. Therefore, we want to have the UIP_ACKDATA
\r
1641 flag set. If so, we enter the ESTABLISHED state. */
\r
1642 if( uip_flags & UIP_ACKDATA )
\r
1644 uip_connr->tcpstateflags = UIP_ESTABLISHED;
\r
1645 uip_flags = UIP_CONNECTED;
\r
1646 uip_connr->len = 0;
\r
1649 uip_flags |= UIP_NEWDATA;
\r
1650 uip_add_rcv_nxt( uip_len );
\r
1659 #if UIP_ACTIVE_OPEN
\r
1661 case UIP_SYN_SENT:
\r
1662 /* In SYN_SENT, we wait for a SYNACK that is sent in response to
\r
1663 our SYN. The rcv_nxt is set to sequence number in the SYNACK
\r
1664 plus one, and we send an ACK. We move into the ESTABLISHED
\r
1666 if( (uip_flags & UIP_ACKDATA) && (BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK) )
\r
1668 /* Parse the TCP MSS option, if present. */
\r
1669 if( (BUF->tcpoffset & 0xf0) > 0x50 )
\r
1671 for( c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2; )
\r
1673 opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c];
\r
1674 if( opt == TCP_OPT_END )
\r
1676 /* End of options. */
\r
1679 else if( opt == TCP_OPT_NOOP )
\r
1685 else if( opt == TCP_OPT_MSS && uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN )
\r
1687 /* An MSS option with the right option length. */
\r
1688 tmp16 = ( uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8 ) | uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c];
\r
1689 uip_connr->initialmss = uip_connr->mss = tmp16 > UIP_TCP_MSS ? UIP_TCP_MSS : tmp16;
\r
1691 /* And we are done processing options. */
\r
1696 /* All other options have a length field, so that we easily
\r
1697 can skip past them. */
\r
1698 if( uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0 )
\r
1700 /* If the length field is zero, the options are malformed
\r
1701 and we don't process them further. */
\r
1705 c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
\r
1710 uip_connr->tcpstateflags = UIP_ESTABLISHED;
\r
1711 uip_connr->rcv_nxt[0] = BUF->seqno[0];
\r
1712 uip_connr->rcv_nxt[1] = BUF->seqno[1];
\r
1713 uip_connr->rcv_nxt[2] = BUF->seqno[2];
\r
1714 uip_connr->rcv_nxt[3] = BUF->seqno[3];
\r
1715 uip_add_rcv_nxt( 1 );
\r
1716 uip_flags = UIP_CONNECTED | UIP_NEWDATA;
\r
1717 uip_connr->len = 0;
\r
1724 /* Inform the application that the connection failed */
\r
1725 uip_flags = UIP_ABORT;
\r
1728 /* The connection is closed after we send the RST */
\r
1729 uip_conn->tcpstateflags = UIP_CLOSED;
\r
1731 #endif /* UIP_ACTIVE_OPEN */
\r
1733 case UIP_ESTABLISHED:
\r
1734 /* In the ESTABLISHED state, we call upon the application to feed
\r
1735 data into the uip_buf. If the UIP_ACKDATA flag is set, the
\r
1736 application should put new data into the buffer, otherwise we are
\r
1737 retransmitting an old segment, and the application should put that
\r
1738 data into the buffer.
\r
1740 If the incoming packet is a FIN, we should close the connection on
\r
1741 this side as well, and we send out a FIN and enter the LAST_ACK
\r
1742 state. We require that there is no outstanding data; otherwise the
\r
1743 sequence numbers will be screwed up. */
\r
1744 if( BUF->flags & TCP_FIN && !(uip_connr->tcpstateflags & UIP_STOPPED) )
\r
1746 if( uip_outstanding(uip_connr) )
\r
1751 uip_add_rcv_nxt( 1 + uip_len );
\r
1752 uip_flags |= UIP_CLOSE;
\r
1755 uip_flags |= UIP_NEWDATA;
\r
1759 uip_connr->len = 1;
\r
1760 uip_connr->tcpstateflags = UIP_LAST_ACK;
\r
1761 uip_connr->nrtx = 0;
\r
1763 BUF->flags = TCP_FIN | TCP_ACK;
\r
1764 goto tcp_send_nodata;
\r
1767 /* Check the URG flag. If this is set, the segment carries urgent
\r
1768 data that we must pass to the application. */
\r
1769 if( (BUF->flags & TCP_URG) != 0 )
\r
1771 #if UIP_URGDATA > 0
\r
1772 uip_urglen = ( BUF->urgp[0] << 8 ) | BUF->urgp[1];
\r
1773 if( uip_urglen > uip_len )
\r
1775 /* There is more urgent data in the next segment to come. */
\r
1776 uip_urglen = uip_len;
\r
1779 uip_add_rcv_nxt( uip_urglen );
\r
1780 uip_len -= uip_urglen;
\r
1781 uip_urgdata = uip_appdata;
\r
1782 uip_appdata += uip_urglen;
\r
1787 #else /* UIP_URGDATA > 0 */
\r
1788 uip_appdata = ( ( char * ) uip_appdata ) + ( (BUF->urgp[0] << 8) | BUF->urgp[1] );
\r
1789 uip_len -= ( BUF->urgp[0] << 8 ) | BUF->urgp[1];
\r
1790 #endif /* UIP_URGDATA > 0 */
\r
1793 /* If uip_len > 0 we have TCP data in the packet, and we flag this
\r
1794 by setting the UIP_NEWDATA flag and update the sequence number
\r
1795 we acknowledge. If the application has stopped the dataflow
\r
1796 using uip_stop(), we must not accept any data packets from the
\r
1798 if( uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED) )
\r
1800 uip_flags |= UIP_NEWDATA;
\r
1801 uip_add_rcv_nxt( uip_len );
\r
1804 /* Check if the available buffer space advertised by the other end
\r
1805 is smaller than the initial MSS for this connection. If so, we
\r
1806 set the current MSS to the window size to ensure that the
\r
1807 application does not send more data than the other end can
\r
1810 If the remote host advertises a zero window, we set the MSS to
\r
1811 the initial MSS so that the application will send an entire MSS
\r
1812 of data. This data will not be acknowledged by the receiver,
\r
1813 and the application will retransmit it. This is called the
\r
1814 "persistent timer" and uses the retransmission mechanim.
\r
1816 tmp16 = ( (u16_t) BUF->wnd[0] << 8 ) + ( u16_t ) BUF->wnd[1];
\r
1817 if( tmp16 > (uip_connr->initialmss * FRAME_MULTIPLE) || tmp16 == 0 )
\r
1819 tmp16 = uip_connr->initialmss * FRAME_MULTIPLE;
\r
1822 uip_connr->mss = tmp16;
\r
1824 /* If this packet constitutes an ACK for outstanding data (flagged
\r
1825 by the UIP_ACKDATA flag, we should call the application since it
\r
1826 might want to send more data. If the incoming packet had data
\r
1827 from the peer (as flagged by the UIP_NEWDATA flag), the
\r
1828 application must also be notified.
\r
1830 When the application is called, the global variable uip_len
\r
1831 contains the length of the incoming data. The application can
\r
1832 access the incoming data through the global pointer
\r
1833 uip_appdata, which usually points UIP_IPTCPH_LEN + UIP_LLH_LEN
\r
1834 bytes into the uip_buf array.
\r
1836 If the application wishes to send any data, this data should be
\r
1837 put into the uip_appdata and the length of the data should be
\r
1838 put into uip_len. If the application don't have any data to
\r
1839 send, uip_len must be set to 0. */
\r
1840 if( uip_flags & (UIP_NEWDATA | UIP_ACKDATA) )
\r
1846 if( uip_flags & UIP_ABORT )
\r
1849 uip_connr->tcpstateflags = UIP_CLOSED;
\r
1850 BUF->flags = TCP_RST | TCP_ACK;
\r
1851 goto tcp_send_nodata;
\r
1854 if( uip_flags & UIP_CLOSE )
\r
1857 uip_connr->len = 1;
\r
1858 uip_connr->tcpstateflags = UIP_FIN_WAIT_1;
\r
1859 uip_connr->nrtx = 0;
\r
1860 BUF->flags = TCP_FIN | TCP_ACK;
\r
1861 goto tcp_send_nodata;
\r
1864 /* If uip_slen > 0, the application has data to be sent. */
\r
1865 if( uip_slen > 0 )
\r
1867 /* If the connection has acknowledged data, the contents of
\r
1868 the ->len variable should be discarded. */
\r
1869 if( (uip_flags & UIP_ACKDATA) != 0 )
\r
1871 uip_connr->len = 0;
\r
1874 /* If the ->len variable is non-zero the connection has
\r
1875 already data in transit and cannot send anymore right
\r
1877 if( uip_connr->len == 0 )
\r
1879 /* The application cannot send more than what is allowed by
\r
1880 the mss (the minumum of the MSS and the available
\r
1882 if( uip_slen > uip_connr->mss )
\r
1884 uip_slen = uip_connr->mss;
\r
1887 /* Remember how much data we send out now so that we know
\r
1888 when everything has been acknowledged. */
\r
1889 uip_connr->len = uip_slen;
\r
1893 /* If the application already had unacknowledged data, we
\r
1894 make sure that the application does not send (i.e.,
\r
1895 retransmit) out more than it previously sent out. */
\r
1896 uip_slen = uip_connr->len;
\r
1900 uip_connr->nrtx = 0;
\r
1902 uip_appdata = uip_sappdata;
\r
1904 /* If the application has data to be sent, or if the incoming
\r
1905 packet had new data in it, we must send out a packet. */
\r
1906 if( uip_slen > 0 && uip_connr->len > 0 )
\r
1908 /* Add the length of the IP and TCP headers. */
\r
1909 uip_len = uip_connr->len + UIP_TCPIP_HLEN;
\r
1911 /* We always set the ACK flag in response packets. */
\r
1912 BUF->flags = TCP_ACK | TCP_PSH;
\r
1914 /* Send the packet. */
\r
1915 goto tcp_send_noopts;
\r
1918 /* If there is no data to send, just send out a pure ACK if
\r
1919 there is newdata. */
\r
1920 if( uip_flags & UIP_NEWDATA )
\r
1922 uip_len = UIP_TCPIP_HLEN;
\r
1923 BUF->flags = TCP_ACK;
\r
1924 goto tcp_send_noopts;
\r
1930 case UIP_LAST_ACK:
\r
1931 /* We can close this connection if the peer has acknowledged our
\r
1932 FIN. This is indicated by the UIP_ACKDATA flag. */
\r
1933 if( uip_flags & UIP_ACKDATA )
\r
1935 uip_connr->tcpstateflags = UIP_CLOSED;
\r
1936 uip_flags = UIP_CLOSE;
\r
1942 case UIP_FIN_WAIT_1:
\r
1943 /* The application has closed the connection, but the remote host
\r
1944 hasn't closed its end yet. Thus we do nothing but wait for a
\r
1945 FIN from the other side. */
\r
1948 uip_add_rcv_nxt( uip_len );
\r
1951 if( BUF->flags & TCP_FIN )
\r
1953 if( uip_flags & UIP_ACKDATA )
\r
1955 uip_connr->tcpstateflags = UIP_TIME_WAIT;
\r
1956 uip_connr->timer = 0;
\r
1957 uip_connr->len = 0;
\r
1961 uip_connr->tcpstateflags = UIP_CLOSING;
\r
1964 uip_add_rcv_nxt( 1 );
\r
1965 uip_flags = UIP_CLOSE;
\r
1967 goto tcp_send_ack;
\r
1969 else if( uip_flags & UIP_ACKDATA )
\r
1971 uip_connr->tcpstateflags = UIP_FIN_WAIT_2;
\r
1972 uip_connr->len = 0;
\r
1978 goto tcp_send_ack;
\r
1983 case UIP_FIN_WAIT_2:
\r
1986 uip_add_rcv_nxt( uip_len );
\r
1989 if( BUF->flags & TCP_FIN )
\r
1991 uip_connr->tcpstateflags = UIP_TIME_WAIT;
\r
1992 uip_connr->timer = 0;
\r
1993 uip_add_rcv_nxt( 1 );
\r
1994 uip_flags = UIP_CLOSE;
\r
1996 goto tcp_send_ack;
\r
2001 goto tcp_send_ack;
\r
2006 case UIP_TIME_WAIT:
\r
2007 goto tcp_send_ack;
\r
2010 if( uip_flags & UIP_ACKDATA )
\r
2012 uip_connr->tcpstateflags = UIP_TIME_WAIT;
\r
2013 uip_connr->timer = 0;
\r
2019 /* We jump here when we are ready to send the packet, and just want
\r
2020 to set the appropriate TCP sequence numbers in the TCP header. */
\r
2022 BUF->flags = TCP_ACK;
\r
2024 uip_len = UIP_IPTCPH_LEN;
\r
2026 BUF->tcpoffset = ( UIP_TCPH_LEN / 4 ) << 4;
\r
2028 /* We're done with the input processing. We are now ready to send a
\r
2029 reply. Our job is to fill in all the fields of the TCP and IP
\r
2030 headers before calculating the checksum and finally send the
\r
2032 BUF->ackno[0] = uip_connr->rcv_nxt[0];
\r
2033 BUF->ackno[1] = uip_connr->rcv_nxt[1];
\r
2034 BUF->ackno[2] = uip_connr->rcv_nxt[2];
\r
2035 BUF->ackno[3] = uip_connr->rcv_nxt[3];
\r
2037 BUF->seqno[0] = uip_connr->snd_nxt[0];
\r
2038 BUF->seqno[1] = uip_connr->snd_nxt[1];
\r
2039 BUF->seqno[2] = uip_connr->snd_nxt[2];
\r
2040 BUF->seqno[3] = uip_connr->snd_nxt[3];
\r
2042 BUF->proto = UIP_PROTO_TCP;
\r
2044 BUF->srcport = uip_connr->lport;
\r
2045 BUF->destport = uip_connr->rport;
\r
2047 uip_ipaddr_copy( BUF->srcipaddr, uip_hostaddr );
\r
2048 uip_ipaddr_copy( BUF->destipaddr, uip_connr->ripaddr );
\r
2050 if( uip_connr->tcpstateflags & UIP_STOPPED )
\r
2052 /* If the connection has issued uip_stop(), we advertise a zero
\r
2053 window so that the remote host will stop sending data. */
\r
2054 BUF->wnd[0] = BUF->wnd[1] = 0;
\r
2058 BUF->wnd[0] = ( (UIP_RECEIVE_WINDOW) >> 8 );
\r
2059 BUF->wnd[1] = ( (UIP_RECEIVE_WINDOW) & 0xff );
\r
2063 BUF->ttl = UIP_TTL;
\r
2066 /* For IPv6, the IP length field does not include the IPv6 IP header
\r
2068 BUF->len[0] = ( (uip_len - UIP_IPH_LEN) >> 8 );
\r
2069 BUF->len[1] = ( (uip_len - UIP_IPH_LEN) & 0xff );
\r
2070 #else /* UIP_CONF_IPV6 */
\r
2071 BUF->len[0] = ( uip_len >> 8 );
\r
2072 BUF->len[1] = ( uip_len & 0xff );
\r
2073 #endif /* UIP_CONF_IPV6 */
\r
2075 BUF->urgp[0] = BUF->urgp[1] = 0;
\r
2077 /* Calculate TCP checksum. */
\r
2078 BUF->tcpchksum = 0;
\r
2079 BUF->tcpchksum = ~( uip_tcpchksum() );
\r
2086 BUF->tcflow = 0x00;
\r
2088 #else /* UIP_CONF_IPV6 */
\r
2091 BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
\r
2093 BUF->ipid[0] = ipid >> 8;
\r
2094 BUF->ipid[1] = ipid & 0xff;
\r
2096 /* Calculate IP checksum. */
\r
2097 BUF->ipchksum = 0;
\r
2098 BUF->ipchksum = ~( uip_ipchksum() );
\r
2099 DEBUG_PRINTF( "uip ip_send_nolen: chkecum 0x%04x\n", uip_ipchksum() );
\r
2100 #endif /* UIP_CONF_IPV6 */
\r
2102 UIP_STAT( ++uip_stat.tcp.sent );
\r
2104 DEBUG_PRINTF( "Sending packet with length %d (%d)\n", uip_len, (BUF->len[0] << 8) | BUF->len[1] );
\r
2106 UIP_STAT( ++uip_stat.ip.sent );
\r
2108 /* Return and let the caller do the actual transmission. */
\r
2117 /*---------------------------------------------------------------------------*/
\r
2118 u16_t htons( u16_t val )
\r
2120 return HTONS( val );
\r
2123 /*---------------------------------------------------------------------------*/
\r
2124 void uip_send( const void *data, int len )
\r
2129 if( data != uip_sappdata )
\r
2131 memcpy( uip_sappdata, (data), uip_slen );
\r
2136 /*---------------------------------------------------------------------------*/
\r
2137 int uip_fast_send( int xARP )
\r
2140 #if NOT_YET_COMPLETE
\r
2142 u16_t tcplen, len1 = 0, uiAccumulatedLen = 0, len_previous = 0, split_len;
\r
2144 extern int uip_low_level_output( unsigned char *pcBuf, int ilen );
\r
2146 if( xARP == pdTRUE )
\r
2148 if( BUF->proto == UIP_PROTO_TCP && uip_slen > 1 )
\r
2150 tcplen = uip_len - UIP_TCPIP_HLEN;
\r
2152 if( tcplen > UIP_TCP_MSS )
\r
2154 split_len = UIP_TCP_MSS;
\r
2158 split_len = tcplen / 2;
\r
2161 while( tcplen > 0 )
\r
2163 uiAccumulatedLen += len1;
\r
2165 if( tcplen > split_len )
\r
2168 tcplen -= split_len;
\r
2176 uip_len = len1 + UIP_TCPIP_HLEN;
\r
2177 BUF->len[0] = uip_len >> 8;
\r
2178 BUF->len[1] = uip_len & 0xff;
\r
2179 if( iSplitNo == 0 )
\r
2183 /* Create the first packet. This is done by altering the length
\r
2184 field of the IP header and updating the checksums. */
\r
2188 /* Now, create the second packet. To do this, it is not enough to
\r
2189 just alter the length field, but we must also update the TCP
\r
2190 sequence number and point the uip_appdata to a new place in
\r
2191 memory. This place is determined by the length of the first
\r
2194 /* uip_appdata += len1;*/
\r
2195 memcpy( uip_appdata, ( u8_t * ) uip_appdata + uiAccumulatedLen, len1 );
\r
2196 uip_add32( BUF->seqno, len_previous );
\r
2197 BUF->seqno[0] = uip_acc32[0];
\r
2198 BUF->seqno[1] = uip_acc32[1];
\r
2199 BUF->seqno[2] = uip_acc32[2];
\r
2200 BUF->seqno[3] = uip_acc32[3];
\r
2203 /* Recalculate the TCP checksum. */
\r
2204 BUF->tcpchksum = 0;
\r
2205 BUF->tcpchksum = ~( uip_tcpchksum() );
\r
2207 /* Recalculate the IP checksum. */
\r
2208 BUF->ipchksum = 0;
\r
2209 BUF->ipchksum = ~( uip_ipchksum() );
\r
2211 /* Transmit the packet. */
\r
2213 uip_low_level_output( uip_buf, uip_len );
\r
2215 len_previous = len1;
\r
2221 uip_low_level_output( uip_buf, uip_len );
\r
2226 uip_low_level_output( uip_buf, uip_len );
\r