8 * The uIP TCP/IP stack code.
\r
9 * \author Adam Dunkels <adam@dunkels.com>
\r
13 * Copyright (c) 2001-2003, Adam Dunkels.
\r
14 * All rights reserved.
\r
16 * Redistribution and use in source and binary forms, with or without
\r
17 * modification, are permitted provided that the following conditions
\r
19 * 1. Redistributions of source code must retain the above copyright
\r
20 * notice, this list of conditions and the following disclaimer.
\r
21 * 2. Redistributions in binary form must reproduce the above copyright
\r
22 * notice, this list of conditions and the following disclaimer in the
\r
23 * documentation and/or other materials provided with the distribution.
\r
24 * 3. The name of the author may not be used to endorse or promote
\r
25 * products derived from this software without specific prior
\r
26 * written permission.
\r
28 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
\r
29 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
\r
30 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
\r
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
\r
32 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
\r
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
\r
34 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
\r
35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
\r
36 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
\r
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
\r
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
40 * This file is part of the uIP TCP/IP stack.
\r
42 * $Id: uip.c,v 1.62.2.10 2003/10/07 13:23:01 adam Exp $
\r
47 This is a small implementation of the IP and TCP protocols (as well as
\r
48 some basic ICMP stuff). The implementation couples the IP, TCP and the
\r
49 application layers very tightly. To keep the size of the compiled code
\r
50 down, this code also features heavy usage of the goto statement.
\r
52 The principle is that we have a small buffer, called the uip_buf, in
\r
53 which the device driver puts an incoming packet. The TCP/IP stack
\r
54 parses the headers in the packet, and calls upon the application. If
\r
55 the remote host has sent data to the application, this data is present
\r
56 in the uip_buf and the application read the data from there. It is up
\r
57 to the application to put this data into a byte stream if needed. The
\r
58 application will not be fed with data that is out of sequence.
\r
60 If the application whishes to send data to the peer, it should put its
\r
61 data into the uip_buf, 40 bytes from the start of the buffer. The
\r
62 TCP/IP stack will calculate the checksums, and fill in the necessary
\r
63 header fields and finally send the packet back to the peer.
\r
68 #include "uip_arch.h"
\r
70 /*-----------------------------------------------------------------------------------*/
\r
71 /* Variable definitions. */
\r
74 /* The IP address of this host. If it is defined to be fixed (by setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set here. Otherwise, the address */
\r
75 #if UIP_FIXEDADDR > 0
\r
76 const u16_t uip_hostaddr[2] =
\r
77 {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1),
\r
78 HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)};
\r
79 const u16_t uip_arp_draddr[2] =
\r
80 {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1),
\r
81 HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)};
\r
82 const u16_t uip_arp_netmask[2] =
\r
83 {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1),
\r
84 HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)};
\r
86 u16_t uip_hostaddr[2];
\r
87 u16_t uip_arp_draddr[2], uip_arp_netmask[2];
\r
88 #endif /* UIP_FIXEDADDR */
\r
90 u8_t uip_buf[UIP_BUFSIZE+2]; /* The packet buffer that contains
\r
91 incoming packets. */
\r
92 volatile u8_t *uip_appdata; /* The uip_appdata pointer points to
\r
93 application data. */
\r
94 volatile u8_t *uip_sappdata; /* The uip_appdata pointer points to the
\r
95 application data which is to be sent. */
\r
97 volatile u8_t *uip_urgdata; /* The uip_urgdata pointer points to
\r
98 urgent data (out-of-band data), if
\r
100 volatile u8_t uip_urglen, uip_surglen;
\r
101 #endif /* UIP_URGDATA > 0 */
\r
103 volatile u16_t uip_len, uip_slen;
\r
104 /* The uip_len is either 8 or 16 bits,
\r
105 depending on the maximum packet
\r
108 volatile u8_t uip_flags; /* The uip_flags variable is used for
\r
109 communication between the TCP/IP stack
\r
110 and the application program. */
\r
111 struct uip_conn *uip_conn; /* uip_conn always points to the current
\r
114 struct uip_conn uip_conns[UIP_CONNS];
\r
115 /* The uip_conns array holds all TCP
\r
117 u16_t uip_listenports[UIP_LISTENPORTS];
\r
118 /* The uip_listenports list all currently
\r
121 struct uip_udp_conn *uip_udp_conn;
\r
122 struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
\r
123 #endif /* UIP_UDP */
\r
126 static u16_t ipid; /* Ths ipid variable is an increasing
\r
127 number that is used for the IP ID
\r
130 static u8_t iss[4]; /* The iss variable is used for the TCP
\r
131 initial sequence number. */
\r
133 #if UIP_ACTIVE_OPEN
\r
134 static u16_t lastport; /* Keeps track of the last port used for
\r
135 a new connection. */
\r
136 #endif /* UIP_ACTIVE_OPEN */
\r
138 /* Temporary variables. */
\r
139 volatile u8_t uip_acc32[4];
\r
140 static u8_t c, opt;
\r
141 static u16_t tmp16;
\r
143 /* Structures and definitions. */
\r
144 #define TCP_FIN 0x01
\r
145 #define TCP_SYN 0x02
\r
146 #define TCP_RST 0x04
\r
147 #define TCP_PSH 0x08
\r
148 #define TCP_ACK 0x10
\r
149 #define TCP_URG 0x20
\r
150 #define TCP_CTL 0x3f
\r
152 #define ICMP_ECHO_REPLY 0
\r
153 #define ICMP_ECHO 8
\r
156 #define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
\r
157 #define FBUF ((uip_tcpip_hdr *)&uip_reassbuf[0])
\r
158 #define ICMPBUF ((uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN])
\r
159 #define UDPBUF ((uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])
\r
161 #if UIP_STATISTICS == 1
\r
162 struct uip_stats uip_stat;
\r
163 #define UIP_STAT(s) s
\r
165 #define UIP_STAT(s)
\r
166 #endif /* UIP_STATISTICS == 1 */
\r
168 #if UIP_LOGGING == 1
\r
170 void uip_log(char *msg);
\r
171 #define UIP_LOG(m) uip_log(m)
\r
174 #endif /* UIP_LOGGING == 1 */
\r
176 /*-----------------------------------------------------------------------------------*/
\r
180 for(c = 0; c < UIP_LISTENPORTS; ++c) {
\r
181 uip_listenports[c] = 0;
\r
183 for(c = 0; c < UIP_CONNS; ++c) {
\r
184 uip_conns[c].tcpstateflags = CLOSED;
\r
186 #if UIP_ACTIVE_OPEN
\r
188 #endif /* UIP_ACTIVE_OPEN */
\r
191 for(c = 0; c < UIP_UDP_CONNS; ++c) {
\r
192 uip_udp_conns[c].lport = 0;
\r
194 #endif /* UIP_UDP */
\r
197 /* IPv4 initialization. */
\r
198 #if UIP_FIXEDADDR == 0
\r
199 uip_hostaddr[0] = uip_hostaddr[1] = 0;
\r
200 #endif /* UIP_FIXEDADDR */
\r
203 /*-----------------------------------------------------------------------------------*/
\r
204 #if UIP_ACTIVE_OPEN
\r
206 uip_connect(u16_t *ripaddr, u16_t rport)
\r
208 register struct uip_conn *conn, *cconn;
\r
210 /* Find an unused local port. */
\r
214 if(lastport >= 32000) {
\r
218 /* Check if this port is already in use, and if so try to find
\r
220 for(c = 0; c < UIP_CONNS; ++c) {
\r
221 conn = &uip_conns[c];
\r
222 if(conn->tcpstateflags != CLOSED &&
\r
223 conn->lport == htons(lastport)) {
\r
230 for(c = 0; c < UIP_CONNS; ++c) {
\r
231 cconn = &uip_conns[c];
\r
232 if(cconn->tcpstateflags == CLOSED) {
\r
236 if(cconn->tcpstateflags == TIME_WAIT) {
\r
238 cconn->timer > uip_conn->timer) {
\r
248 conn->tcpstateflags = SYN_SENT;
\r
250 conn->snd_nxt[0] = iss[0];
\r
251 conn->snd_nxt[1] = iss[1];
\r
252 conn->snd_nxt[2] = iss[2];
\r
253 conn->snd_nxt[3] = iss[3];
\r
255 conn->initialmss = conn->mss = UIP_TCP_MSS;
\r
257 conn->len = 1; /* TCP length of the SYN is one. */
\r
259 conn->timer = 1; /* Send the SYN next time around. */
\r
260 conn->rto = UIP_RTO;
\r
263 conn->lport = htons(lastport);
\r
264 conn->rport = rport;
\r
265 conn->ripaddr[0] = ripaddr[0];
\r
266 conn->ripaddr[1] = ripaddr[1];
\r
270 #endif /* UIP_ACTIVE_OPEN */
\r
271 /*-----------------------------------------------------------------------------------*/
\r
273 struct uip_udp_conn *
\r
274 uip_udp_new(u16_t *ripaddr, u16_t rport)
\r
276 register struct uip_udp_conn *conn;
\r
278 /* Find an unused local port. */
\r
282 if(lastport >= 32000) {
\r
286 for(c = 0; c < UIP_UDP_CONNS; ++c) {
\r
287 if(uip_udp_conns[c].lport == lastport) {
\r
294 for(c = 0; c < UIP_UDP_CONNS; ++c) {
\r
295 if(uip_udp_conns[c].lport == 0) {
\r
296 conn = &uip_udp_conns[c];
\r
305 conn->lport = HTONS(lastport);
\r
306 conn->rport = HTONS(rport);
\r
307 conn->ripaddr[0] = ripaddr[0];
\r
308 conn->ripaddr[1] = ripaddr[1];
\r
312 #endif /* UIP_UDP */
\r
313 /*-----------------------------------------------------------------------------------*/
\r
315 uip_unlisten(u16_t port)
\r
317 for(c = 0; c < UIP_LISTENPORTS; ++c) {
\r
318 if(uip_listenports[c] == port) {
\r
319 uip_listenports[c] = 0;
\r
324 /*-----------------------------------------------------------------------------------*/
\r
326 uip_listen(u16_t port)
\r
328 for(c = 0; c < UIP_LISTENPORTS; ++c) {
\r
329 if(uip_listenports[c] == 0) {
\r
330 uip_listenports[c] = port;
\r
335 /*-----------------------------------------------------------------------------------*/
\r
336 /* XXX: IP fragment reassembly: not well-tested. */
\r
339 #define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN)
\r
340 static u8_t uip_reassbuf[UIP_REASS_BUFSIZE];
\r
341 static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)];
\r
342 static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f,
\r
343 0x0f, 0x07, 0x03, 0x01};
\r
344 static u16_t uip_reasslen;
\r
345 static u8_t uip_reassflags;
\r
346 #define UIP_REASS_FLAG_LASTFRAG 0x01
\r
347 static u8_t uip_reasstmr;
\r
358 /* If ip_reasstmr is zero, no packet is present in the buffer, so we
\r
359 write the IP header of the fragment into the reassembly
\r
360 buffer. The timer is updated with the maximum age. */
\r
361 if(uip_reasstmr == 0) {
\r
362 memcpy(uip_reassbuf, &BUF->vhl, IP_HLEN);
\r
363 uip_reasstmr = UIP_REASS_MAXAGE;
\r
364 uip_reassflags = 0;
\r
365 /* Clear the bitmap. */
\r
366 memset(uip_reassbitmap, sizeof(uip_reassbitmap), 0);
\r
369 /* Check if the incoming fragment matches the one currently present
\r
370 in the reasembly buffer. If so, we proceed with copying the
\r
371 fragment into the buffer. */
\r
372 if(BUF->srcipaddr[0] == FBUF->srcipaddr[0] &&
\r
373 BUF->srcipaddr[1] == FBUF->srcipaddr[1] &&
\r
374 BUF->destipaddr[0] == FBUF->destipaddr[0] &&
\r
375 BUF->destipaddr[1] == FBUF->destipaddr[1] &&
\r
376 BUF->ipid[0] == FBUF->ipid[0] &&
\r
377 BUF->ipid[1] == FBUF->ipid[1]) {
\r
379 len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4;
\r
380 offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8;
\r
382 /* If the offset or the offset + fragment length overflows the
\r
383 reassembly buffer, we discard the entire packet. */
\r
384 if(offset > UIP_REASS_BUFSIZE ||
\r
385 offset + len > UIP_REASS_BUFSIZE) {
\r
390 /* Copy the fragment into the reassembly buffer, at the right
\r
392 memcpy(&uip_reassbuf[IP_HLEN + offset],
\r
393 (char *)BUF + (int)((BUF->vhl & 0x0f) * 4),
\r
396 /* Update the bitmap. */
\r
397 if(offset / (8 * 8) == (offset + len) / (8 * 8)) {
\r
398 /* If the two endpoints are in the same byte, we only update
\r
401 uip_reassbitmap[offset / (8 * 8)] |=
\r
402 bitmap_bits[(offset / 8 ) & 7] &
\r
403 ~bitmap_bits[((offset + len) / 8 ) & 7];
\r
405 /* If the two endpoints are in different bytes, we update the
\r
406 bytes in the endpoints and fill the stuff inbetween with
\r
408 uip_reassbitmap[offset / (8 * 8)] |=
\r
409 bitmap_bits[(offset / 8 ) & 7];
\r
410 for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) {
\r
411 uip_reassbitmap[i] = 0xff;
\r
413 uip_reassbitmap[(offset + len) / (8 * 8)] |=
\r
414 ~bitmap_bits[((offset + len) / 8 ) & 7];
\r
417 /* If this fragment has the More Fragments flag set to zero, we
\r
418 know that this is the last fragment, so we can calculate the
\r
419 size of the entire packet. We also set the
\r
420 IP_REASS_FLAG_LASTFRAG flag to indicate that we have received
\r
421 the final fragment. */
\r
423 if((BUF->ipoffset[0] & IP_MF) == 0) {
\r
424 uip_reassflags |= UIP_REASS_FLAG_LASTFRAG;
\r
425 uip_reasslen = offset + len;
\r
428 /* Finally, we check if we have a full packet in the buffer. We do
\r
429 this by checking if we have the last fragment and if all bits
\r
430 in the bitmap are set. */
\r
431 if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) {
\r
432 /* Check all bytes up to and including all but the last byte in
\r
434 for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) {
\r
435 if(uip_reassbitmap[i] != 0xff) {
\r
439 /* Check the last byte in the bitmap. It should contain just the
\r
440 right amount of bits. */
\r
441 if(uip_reassbitmap[uip_reasslen / (8 * 8)] !=
\r
442 (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) {
\r
446 /* If we have come this far, we have a full packet in the
\r
447 buffer, so we allocate a pbuf and copy the packet into it. We
\r
448 also reset the timer. */
\r
450 memcpy(BUF, FBUF, uip_reasslen);
\r
452 /* Pretend to be a "normal" (i.e., not fragmented) IP packet
\r
454 BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
\r
455 BUF->len[0] = uip_reasslen >> 8;
\r
456 BUF->len[1] = uip_reasslen & 0xff;
\r
458 BUF->ipchksum = ~(uip_ipchksum());
\r
460 return uip_reasslen;
\r
467 #endif /* UIP_REASSEMBL */
\r
468 /*-----------------------------------------------------------------------------------*/
\r
470 uip_add_rcv_nxt(u16_t n)
\r
472 uip_add32(uip_conn->rcv_nxt, n);
\r
473 uip_conn->rcv_nxt[0] = uip_acc32[0];
\r
474 uip_conn->rcv_nxt[1] = uip_acc32[1];
\r
475 uip_conn->rcv_nxt[2] = uip_acc32[2];
\r
476 uip_conn->rcv_nxt[3] = uip_acc32[3];
\r
478 /*-----------------------------------------------------------------------------------*/
\r
480 uip_process(u8_t flag)
\r
482 register struct uip_conn *uip_connr = uip_conn;
\r
484 uip_appdata = &uip_buf[40 + UIP_LLH_LEN];
\r
487 /* Check if we were invoked because of the perodic timer fireing. */
\r
488 if(flag == UIP_TIMER) {
\r
490 if(uip_reasstmr != 0) {
\r
493 #endif /* UIP_REASSEMBLY */
\r
494 /* Increase the initial sequence number. */
\r
495 if(++iss[3] == 0) {
\r
496 if(++iss[2] == 0) {
\r
497 if(++iss[1] == 0) {
\r
503 if(uip_connr->tcpstateflags == TIME_WAIT ||
\r
504 uip_connr->tcpstateflags == FIN_WAIT_2) {
\r
505 ++(uip_connr->timer);
\r
506 if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) {
\r
507 uip_connr->tcpstateflags = CLOSED;
\r
509 } else if(uip_connr->tcpstateflags != CLOSED) {
\r
510 /* If the connection has outstanding data, we increase the
\r
511 connection's timer and see if it has reached the RTO value
\r
512 in which case we retransmit. */
\r
513 if(uip_outstanding(uip_connr)) {
\r
514 if(uip_connr->timer-- == 0) {
\r
515 if(uip_connr->nrtx == UIP_MAXRTX ||
\r
516 ((uip_connr->tcpstateflags == SYN_SENT ||
\r
517 uip_connr->tcpstateflags == SYN_RCVD) &&
\r
518 uip_connr->nrtx == UIP_MAXSYNRTX)) {
\r
519 uip_connr->tcpstateflags = CLOSED;
\r
521 /* We call UIP_APPCALL() with uip_flags set to
\r
522 UIP_TIMEDOUT to inform the application that the
\r
523 connection has timed out. */
\r
524 uip_flags = UIP_TIMEDOUT;
\r
527 /* We also send a reset packet to the remote host. */
\r
528 BUF->flags = TCP_RST | TCP_ACK;
\r
529 goto tcp_send_nodata;
\r
532 /* Exponential backoff. */
\r
533 uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4?
\r
536 ++(uip_connr->nrtx);
\r
538 /* Ok, so we need to retransmit. We do this differently
\r
539 depending on which state we are in. In ESTABLISHED, we
\r
540 call upon the application so that it may prepare the
\r
541 data for the retransmit. In SYN_RCVD, we resend the
\r
542 SYNACK that we sent earlier and in LAST_ACK we have to
\r
543 retransmit our FINACK. */
\r
544 UIP_STAT(++uip_stat.tcp.rexmit);
\r
545 switch(uip_connr->tcpstateflags & TS_MASK) {
\r
547 /* In the SYN_RCVD state, we should retransmit our
\r
549 goto tcp_send_synack;
\r
551 #if UIP_ACTIVE_OPEN
\r
553 /* In the SYN_SENT state, we retransmit out SYN. */
\r
556 #endif /* UIP_ACTIVE_OPEN */
\r
559 /* In the ESTABLISHED state, we call upon the application
\r
560 to do the actual retransmit after which we jump into
\r
561 the code for sending out the packet (the apprexmit
\r
565 uip_flags = UIP_REXMIT;
\r
572 /* In all these states we should retransmit a FINACK. */
\r
573 goto tcp_send_finack;
\r
577 } else if((uip_connr->tcpstateflags & TS_MASK) == ESTABLISHED) {
\r
578 /* If there was no need for a retransmission, we poll the
\r
579 application for new data. */
\r
582 uip_flags = UIP_POLL;
\r
590 if(flag == UIP_UDP_TIMER) {
\r
591 if(uip_udp_conn->lport != 0) {
\r
592 uip_appdata = &uip_buf[UIP_LLH_LEN + 28];
\r
593 uip_len = uip_slen = 0;
\r
594 uip_flags = UIP_POLL;
\r
603 /* This is where the input processing starts. */
\r
604 UIP_STAT(++uip_stat.ip.recv);
\r
607 /* Start of IPv4 input header processing code. */
\r
609 /* Check validity of the IP header. */
\r
610 if(BUF->vhl != 0x45) { /* IP version and header length. */
\r
611 UIP_STAT(++uip_stat.ip.drop);
\r
612 UIP_STAT(++uip_stat.ip.vhlerr);
\r
613 UIP_LOG("ip: invalid version or header length.");
\r
617 /* Check the size of the packet. If the size reported to us in
\r
618 uip_len doesn't match the size reported in the IP header, there
\r
619 has been a transmission error and we drop the packet. */
\r
621 if(BUF->len[0] != (uip_len >> 8)) { /* IP length, high byte. */
\r
622 uip_len = (uip_len & 0xff) | (BUF->len[0] << 8);
\r
624 if(BUF->len[1] != (uip_len & 0xff)) { /* IP length, low byte. */
\r
625 uip_len = (uip_len & 0xff00) | BUF->len[1];
\r
628 /* Check the fragment flag. */
\r
629 if((BUF->ipoffset[0] & 0x3f) != 0 ||
\r
630 BUF->ipoffset[1] != 0) {
\r
632 uip_len = uip_reass();
\r
637 UIP_STAT(++uip_stat.ip.drop);
\r
638 UIP_STAT(++uip_stat.ip.fragerr);
\r
639 UIP_LOG("ip: fragment dropped.");
\r
641 #endif /* UIP_REASSEMBLY */
\r
644 /* If we are configured to use ping IP address configuration and
\r
645 hasn't been assigned an IP address yet, we accept all ICMP
\r
647 #if UIP_PINGADDRCONF
\r
648 if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) {
\r
649 if(BUF->proto == UIP_PROTO_ICMP) {
\r
650 UIP_LOG("ip: possible ping config packet received.");
\r
653 UIP_LOG("ip: packet dropped since no address assigned.");
\r
657 #endif /* UIP_PINGADDRCONF */
\r
659 /* Check if the packet is destined for our IP address. */
\r
660 if(BUF->destipaddr[0] != uip_hostaddr[0]) {
\r
661 UIP_STAT(++uip_stat.ip.drop);
\r
662 UIP_LOG("ip: packet not for us.");
\r
665 if(BUF->destipaddr[1] != uip_hostaddr[1]) {
\r
666 UIP_STAT(++uip_stat.ip.drop);
\r
667 UIP_LOG("ip: packet not for us.");
\r
672 // IP checksum is wrong through Netgear DSL router
\r
673 if (uip_ipchksum() != 0xffff) { /* Compute and check the IP header
\r
675 UIP_STAT(++uip_stat.ip.drop);
\r
676 UIP_STAT(++uip_stat.ip.chkerr);
\r
677 UIP_LOG("ip: bad checksum.");
\r
682 if(BUF->proto == UIP_PROTO_TCP) /* Check for TCP packet. If so, jump
\r
683 to the tcp_input label. */
\r
687 if(BUF->proto == UIP_PROTO_UDP)
\r
689 #endif /* UIP_UDP */
\r
691 if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from
\r
693 UIP_STAT(++uip_stat.ip.drop);
\r
694 UIP_STAT(++uip_stat.ip.protoerr);
\r
695 UIP_LOG("ip: neither tcp nor icmp.");
\r
700 UIP_STAT(++uip_stat.icmp.recv);
\r
702 /* ICMP echo (i.e., ping) processing. This is simple, we only change
\r
703 the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP
\r
704 checksum before we return the packet. */
\r
705 if(ICMPBUF->type != ICMP_ECHO) {
\r
706 UIP_STAT(++uip_stat.icmp.drop);
\r
707 UIP_STAT(++uip_stat.icmp.typeerr);
\r
708 UIP_LOG("icmp: not icmp echo.");
\r
712 /* If we are configured to use ping IP address assignment, we use
\r
713 the destination IP address of this ping packet and assign it to
\r
715 #if UIP_PINGADDRCONF
\r
716 if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) {
\r
717 uip_hostaddr[0] = BUF->destipaddr[0];
\r
718 uip_hostaddr[1] = BUF->destipaddr[1];
\r
720 #endif /* UIP_PINGADDRCONF */
\r
722 ICMPBUF->type = ICMP_ECHO_REPLY;
\r
724 if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) {
\r
725 ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1;
\r
727 ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8);
\r
730 /* Swap IP addresses. */
\r
731 tmp16 = BUF->destipaddr[0];
\r
732 BUF->destipaddr[0] = BUF->srcipaddr[0];
\r
733 BUF->srcipaddr[0] = tmp16;
\r
734 tmp16 = BUF->destipaddr[1];
\r
735 BUF->destipaddr[1] = BUF->srcipaddr[1];
\r
736 BUF->srcipaddr[1] = tmp16;
\r
738 UIP_STAT(++uip_stat.icmp.sent);
\r
741 /* End of IPv4 input header processing code. */
\r
745 /* UDP input processing. */
\r
747 /* UDP processing is really just a hack. We don't do anything to the
\r
748 UDP/IP headers, but let the UDP application do all the hard
\r
749 work. If the application sets uip_slen, it has a packet to
\r
751 #if UIP_UDP_CHECKSUMS
\r
752 if(uip_udpchksum() != 0xffff) {
\r
753 UIP_STAT(++uip_stat.udp.drop);
\r
754 UIP_STAT(++uip_stat.udp.chkerr);
\r
755 UIP_LOG("udp: bad checksum.");
\r
758 #endif /* UIP_UDP_CHECKSUMS */
\r
760 /* Demultiplex this UDP packet between the UDP "connections". */
\r
761 for(uip_udp_conn = &uip_udp_conns[0];
\r
762 uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS];
\r
764 if(uip_udp_conn->lport != 0 &&
\r
765 UDPBUF->destport == uip_udp_conn->lport &&
\r
766 (uip_udp_conn->rport == 0 ||
\r
767 UDPBUF->srcport == uip_udp_conn->rport) &&
\r
768 BUF->srcipaddr[0] == uip_udp_conn->ripaddr[0] &&
\r
769 BUF->srcipaddr[1] == uip_udp_conn->ripaddr[1]) {
\r
776 uip_len = uip_len - 28;
\r
777 uip_appdata = &uip_buf[UIP_LLH_LEN + 28];
\r
778 uip_flags = UIP_NEWDATA;
\r
782 if(uip_slen == 0) {
\r
785 uip_len = uip_slen + 28;
\r
787 BUF->len[0] = (uip_len >> 8);
\r
788 BUF->len[1] = (uip_len & 0xff);
\r
790 BUF->proto = UIP_PROTO_UDP;
\r
792 UDPBUF->udplen = HTONS(uip_slen + 8);
\r
793 UDPBUF->udpchksum = 0;
\r
794 #if UIP_UDP_CHECKSUMS
\r
795 /* Calculate UDP checksum. */
\r
796 UDPBUF->udpchksum = ~(uip_udpchksum());
\r
797 if(UDPBUF->udpchksum == 0) {
\r
798 UDPBUF->udpchksum = 0xffff;
\r
800 #endif /* UIP_UDP_CHECKSUMS */
\r
802 BUF->srcport = uip_udp_conn->lport;
\r
803 BUF->destport = uip_udp_conn->rport;
\r
805 BUF->srcipaddr[0] = uip_hostaddr[0];
\r
806 BUF->srcipaddr[1] = uip_hostaddr[1];
\r
807 BUF->destipaddr[0] = uip_udp_conn->ripaddr[0];
\r
808 BUF->destipaddr[1] = uip_udp_conn->ripaddr[1];
\r
810 uip_appdata = &uip_buf[UIP_LLH_LEN + 40];
\r
811 goto ip_send_nolen;
\r
812 #endif /* UIP_UDP */
\r
814 /* TCP input processing. */
\r
816 UIP_STAT(++uip_stat.tcp.recv);
\r
818 /* Start of TCP input header processing code. */
\r
821 if(uip_tcpchksum() != 0xffff) { /* Compute and check the TCP
\r
823 UIP_STAT(++uip_stat.tcp.drop);
\r
824 UIP_STAT(++uip_stat.tcp.chkerr);
\r
825 UIP_LOG("tcp: bad checksum.");
\r
830 /* Demultiplex this segment. */
\r
831 /* First check any active connections. */
\r
832 for(uip_connr = &uip_conns[0]; uip_connr < &uip_conns[UIP_CONNS]; ++uip_connr) {
\r
833 if(uip_connr->tcpstateflags != CLOSED &&
\r
834 BUF->destport == uip_connr->lport &&
\r
835 BUF->srcport == uip_connr->rport &&
\r
836 BUF->srcipaddr[0] == uip_connr->ripaddr[0] &&
\r
837 BUF->srcipaddr[1] == uip_connr->ripaddr[1]) {
\r
842 /* If we didn't find and active connection that expected the packet,
\r
843 either this packet is an old duplicate, or this is a SYN packet
\r
844 destined for a connection in LISTEN. If the SYN flag isn't set,
\r
845 it is an old packet and we send a RST. */
\r
846 if((BUF->flags & TCP_CTL) != TCP_SYN)
\r
849 tmp16 = BUF->destport;
\r
850 /* Next, check listening connections. */
\r
851 for(c = 0; c < UIP_LISTENPORTS; ++c) {
\r
852 if(tmp16 == uip_listenports[c])
\r
856 /* No matching connection found, so we send a RST packet. */
\r
857 UIP_STAT(++uip_stat.tcp.synrst);
\r
860 /* We do not send resets in response to resets. */
\r
861 if(BUF->flags & TCP_RST)
\r
864 UIP_STAT(++uip_stat.tcp.rst);
\r
866 BUF->flags = TCP_RST | TCP_ACK;
\r
868 BUF->tcpoffset = 5 << 4;
\r
870 /* Flip the seqno and ackno fields in the TCP header. */
\r
872 BUF->seqno[3] = BUF->ackno[3];
\r
876 BUF->seqno[2] = BUF->ackno[2];
\r
880 BUF->seqno[1] = BUF->ackno[1];
\r
884 BUF->seqno[0] = BUF->ackno[0];
\r
887 /* We also have to increase the sequence number we are
\r
888 acknowledging. If the least significant byte overflowed, we need
\r
889 to propagate the carry to the other bytes as well. */
\r
890 if(++BUF->ackno[3] == 0) {
\r
891 if(++BUF->ackno[2] == 0) {
\r
892 if(++BUF->ackno[1] == 0) {
\r
898 /* Swap port numbers. */
\r
899 tmp16 = BUF->srcport;
\r
900 BUF->srcport = BUF->destport;
\r
901 BUF->destport = tmp16;
\r
903 /* Swap IP addresses. */
\r
904 tmp16 = BUF->destipaddr[0];
\r
905 BUF->destipaddr[0] = BUF->srcipaddr[0];
\r
906 BUF->srcipaddr[0] = tmp16;
\r
907 tmp16 = BUF->destipaddr[1];
\r
908 BUF->destipaddr[1] = BUF->srcipaddr[1];
\r
909 BUF->srcipaddr[1] = tmp16;
\r
912 /* And send out the RST packet! */
\r
913 goto tcp_send_noconn;
\r
915 /* This label will be jumped to if we matched the incoming packet
\r
916 with a connection in LISTEN. In that case, we should create a new
\r
917 connection and send a SYNACK in return. */
\r
919 /* First we check if there are any connections avaliable. Unused
\r
920 connections are kept in the same table as used connections, but
\r
921 unused ones have the tcpstate set to CLOSED. Also, connections in
\r
922 TIME_WAIT are kept track of and we'll use the oldest one if no
\r
923 CLOSED connections are found. Thanks to Eddie C. Dost for a very
\r
924 nice algorithm for the TIME_WAIT search. */
\r
926 for(c = 0; c < UIP_CONNS; ++c) {
\r
927 if(uip_conns[c].tcpstateflags == CLOSED) {
\r
928 uip_connr = &uip_conns[c];
\r
931 if(uip_conns[c].tcpstateflags == TIME_WAIT) {
\r
932 if(uip_connr == 0 ||
\r
933 uip_conns[c].timer > uip_connr->timer) {
\r
934 uip_connr = &uip_conns[c];
\r
939 if(uip_connr == 0) {
\r
940 /* All connections are used already, we drop packet and hope that
\r
941 the remote end will retransmit the packet at a time when we
\r
942 have more spare connections. */
\r
943 UIP_STAT(++uip_stat.tcp.syndrop);
\r
944 UIP_LOG("tcp: found no unused connections.");
\r
947 uip_conn = uip_connr;
\r
949 /* Fill in the necessary fields for the new connection. */
\r
950 uip_connr->rto = uip_connr->timer = UIP_RTO;
\r
952 uip_connr->sv = 4;
\r
953 uip_connr->nrtx = 0;
\r
954 uip_connr->lport = BUF->destport;
\r
955 uip_connr->rport = BUF->srcport;
\r
956 uip_connr->ripaddr[0] = BUF->srcipaddr[0];
\r
957 uip_connr->ripaddr[1] = BUF->srcipaddr[1];
\r
958 uip_connr->tcpstateflags = SYN_RCVD;
\r
960 uip_connr->snd_nxt[0] = iss[0];
\r
961 uip_connr->snd_nxt[1] = iss[1];
\r
962 uip_connr->snd_nxt[2] = iss[2];
\r
963 uip_connr->snd_nxt[3] = iss[3];
\r
964 uip_connr->len = 1;
\r
966 /* rcv_nxt should be the seqno from the incoming packet + 1. */
\r
967 uip_connr->rcv_nxt[3] = BUF->seqno[3];
\r
968 uip_connr->rcv_nxt[2] = BUF->seqno[2];
\r
969 uip_connr->rcv_nxt[1] = BUF->seqno[1];
\r
970 uip_connr->rcv_nxt[0] = BUF->seqno[0];
\r
971 uip_add_rcv_nxt(1);
\r
973 /* Parse the TCP MSS option, if present. */
\r
974 if((BUF->tcpoffset & 0xf0) > 0x50) {
\r
975 for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
\r
976 opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c];
\r
978 /* End of options. */
\r
980 } else if(opt == 0x01) {
\r
983 } else if(opt == 0x02 &&
\r
984 uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) {
\r
985 /* An MSS option with the right option length. */
\r
986 tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
\r
987 (u16_t)uip_buf[40 + UIP_LLH_LEN + 3 + c];
\r
988 uip_connr->initialmss = uip_connr->mss =
\r
989 tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
\r
991 /* And we are done processing options. */
\r
994 /* All other options have a length field, so that we easily
\r
995 can skip past them. */
\r
996 if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
\r
997 /* If the length field is zero, the options are malformed
\r
998 and we don't process them further. */
\r
1001 c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
\r
1006 /* Our response will be a SYNACK. */
\r
1007 #if UIP_ACTIVE_OPEN
\r
1009 BUF->flags = TCP_ACK;
\r
1012 BUF->flags |= TCP_SYN;
\r
1013 #else /* UIP_ACTIVE_OPEN */
\r
1015 BUF->flags = TCP_SYN | TCP_ACK;
\r
1016 #endif /* UIP_ACTIVE_OPEN */
\r
1018 /* We send out the TCP Maximum Segment Size option with our
\r
1020 BUF->optdata[0] = 2;
\r
1021 BUF->optdata[1] = 4;
\r
1022 BUF->optdata[2] = (UIP_TCP_MSS) / 256;
\r
1023 BUF->optdata[3] = (UIP_TCP_MSS) & 255;
\r
1025 BUF->tcpoffset = 6 << 4;
\r
1028 /* This label will be jumped to if we found an active connection. */
\r
1030 uip_conn = uip_connr;
\r
1033 /* We do a very naive form of TCP reset processing; we just accept
\r
1034 any RST and kill our connection. We should in fact check if the
\r
1035 sequence number of this reset is wihtin our advertised window
\r
1036 before we accept the reset. */
\r
1037 if(BUF->flags & TCP_RST) {
\r
1038 uip_connr->tcpstateflags = CLOSED;
\r
1039 UIP_LOG("tcp: got reset, aborting connection.");
\r
1040 uip_flags = UIP_ABORT;
\r
1044 /* Calculated the length of the data, if the application has sent
\r
1045 any data to us. */
\r
1046 c = (BUF->tcpoffset >> 4) << 2;
\r
1047 /* uip_len will contain the length of the actual TCP data. This is
\r
1048 calculated by subtracing the length of the TCP header (in
\r
1049 c) and the length of the IP header (20 bytes). */
\r
1050 uip_len = uip_len - c - 20;
\r
1052 /* First, check if the sequence number of the incoming packet is
\r
1053 what we're expecting next. If not, we send out an ACK with the
\r
1054 correct numbers in. */
\r
1056 (BUF->seqno[0] != uip_connr->rcv_nxt[0] ||
\r
1057 BUF->seqno[1] != uip_connr->rcv_nxt[1] ||
\r
1058 BUF->seqno[2] != uip_connr->rcv_nxt[2] ||
\r
1059 BUF->seqno[3] != uip_connr->rcv_nxt[3])) {
\r
1060 goto tcp_send_ack;
\r
1063 /* Next, check if the incoming segment acknowledges any outstanding
\r
1064 data. If so, we update the sequence number, reset the length of
\r
1065 the outstanding data, calculate RTT estimations, and reset the
\r
1066 retransmission timer. */
\r
1067 if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) {
\r
1068 uip_add32(uip_connr->snd_nxt, uip_connr->len);
\r
1069 if(BUF->ackno[0] == uip_acc32[0] &&
\r
1070 BUF->ackno[1] == uip_acc32[1] &&
\r
1071 BUF->ackno[2] == uip_acc32[2] &&
\r
1072 BUF->ackno[3] == uip_acc32[3]) {
\r
1073 /* Update sequence number. */
\r
1074 uip_connr->snd_nxt[0] = uip_acc32[0];
\r
1075 uip_connr->snd_nxt[1] = uip_acc32[1];
\r
1076 uip_connr->snd_nxt[2] = uip_acc32[2];
\r
1077 uip_connr->snd_nxt[3] = uip_acc32[3];
\r
1080 /* Do RTT estimation, unless we have done retransmissions. */
\r
1081 if(uip_connr->nrtx == 0) {
\r
1083 m = uip_connr->rto - uip_connr->timer;
\r
1084 /* This is taken directly from VJs original code in his paper */
\r
1085 m = m - (uip_connr->sa >> 3);
\r
1086 uip_connr->sa += m;
\r
1090 m = m - (uip_connr->sv >> 2);
\r
1091 uip_connr->sv += m;
\r
1092 uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv;
\r
1095 /* Set the acknowledged flag. */
\r
1096 uip_flags = UIP_ACKDATA;
\r
1097 /* Reset the retransmission timer. */
\r
1098 uip_connr->timer = uip_connr->rto;
\r
1103 /* Do different things depending on in what state the connection is. */
\r
1104 switch(uip_connr->tcpstateflags & TS_MASK) {
\r
1105 /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not
\r
1106 implemented, since we force the application to close when the
\r
1107 peer sends a FIN (hence the application goes directly from
\r
1108 ESTABLISHED to LAST_ACK). */
\r
1110 /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and
\r
1111 we are waiting for an ACK that acknowledges the data we sent
\r
1112 out the last time. Therefore, we want to have the UIP_ACKDATA
\r
1113 flag set. If so, we enter the ESTABLISHED state. */
\r
1114 if(uip_flags & UIP_ACKDATA) {
\r
1115 uip_connr->tcpstateflags = ESTABLISHED;
\r
1116 uip_flags = UIP_CONNECTED;
\r
1117 uip_connr->len = 0;
\r
1119 uip_flags |= UIP_NEWDATA;
\r
1120 uip_add_rcv_nxt(uip_len);
\r
1127 #if UIP_ACTIVE_OPEN
\r
1129 /* In SYN_SENT, we wait for a SYNACK that is sent in response to
\r
1130 our SYN. The rcv_nxt is set to sequence number in the SYNACK
\r
1131 plus one, and we send an ACK. We move into the ESTABLISHED
\r
1133 if((uip_flags & UIP_ACKDATA) &&
\r
1134 BUF->flags == (TCP_SYN | TCP_ACK)) {
\r
1136 /* Parse the TCP MSS option, if present. */
\r
1137 if((BUF->tcpoffset & 0xf0) > 0x50) {
\r
1138 for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
\r
1139 opt = uip_buf[40 + UIP_LLH_LEN + c];
\r
1141 /* End of options. */
\r
1143 } else if(opt == 0x01) {
\r
1146 } else if(opt == 0x02 &&
\r
1147 uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) {
\r
1148 /* An MSS option with the right option length. */
\r
1149 tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
\r
1150 uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c];
\r
1151 uip_connr->initialmss =
\r
1152 uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
\r
1154 /* And we are done processing options. */
\r
1157 /* All other options have a length field, so that we easily
\r
1158 can skip past them. */
\r
1159 if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
\r
1160 /* If the length field is zero, the options are malformed
\r
1161 and we don't process them further. */
\r
1164 c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
\r
1168 uip_connr->tcpstateflags = ESTABLISHED;
\r
1169 uip_connr->rcv_nxt[0] = BUF->seqno[0];
\r
1170 uip_connr->rcv_nxt[1] = BUF->seqno[1];
\r
1171 uip_connr->rcv_nxt[2] = BUF->seqno[2];
\r
1172 uip_connr->rcv_nxt[3] = BUF->seqno[3];
\r
1173 uip_add_rcv_nxt(1);
\r
1174 uip_flags = UIP_CONNECTED | UIP_NEWDATA;
\r
1175 uip_connr->len = 0;
\r
1182 #endif /* UIP_ACTIVE_OPEN */
\r
1185 /* In the ESTABLISHED state, we call upon the application to feed
\r
1186 data into the uip_buf. If the UIP_ACKDATA flag is set, the
\r
1187 application should put new data into the buffer, otherwise we are
\r
1188 retransmitting an old segment, and the application should put that
\r
1189 data into the buffer.
\r
1191 If the incoming packet is a FIN, we should close the connection on
\r
1192 this side as well, and we send out a FIN and enter the LAST_ACK
\r
1193 state. We require that there is no outstanding data; otherwise the
\r
1194 sequence numbers will be screwed up. */
\r
1196 if(BUF->flags & TCP_FIN) {
\r
1197 if(uip_outstanding(uip_connr)) {
\r
1200 uip_add_rcv_nxt(1 + uip_len);
\r
1201 uip_flags = UIP_CLOSE;
\r
1203 uip_flags |= UIP_NEWDATA;
\r
1206 uip_connr->len = 1;
\r
1207 uip_connr->tcpstateflags = LAST_ACK;
\r
1208 uip_connr->nrtx = 0;
\r
1210 BUF->flags = TCP_FIN | TCP_ACK;
\r
1211 goto tcp_send_nodata;
\r
1214 /* Check the URG flag. If this is set, the segment carries urgent
\r
1215 data that we must pass to the application. */
\r
1216 if(BUF->flags & TCP_URG) {
\r
1217 #if UIP_URGDATA > 0
\r
1218 uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1];
\r
1219 if(uip_urglen > uip_len) {
\r
1220 /* There is more urgent data in the next segment to come. */
\r
1221 uip_urglen = uip_len;
\r
1223 uip_add_rcv_nxt(uip_urglen);
\r
1224 uip_len -= uip_urglen;
\r
1225 uip_urgdata = uip_appdata;
\r
1226 uip_appdata += uip_urglen;
\r
1229 #endif /* UIP_URGDATA > 0 */
\r
1230 uip_appdata += (BUF->urgp[0] << 8) | BUF->urgp[1];
\r
1231 uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1];
\r
1235 /* If uip_len > 0 we have TCP data in the packet, and we flag this
\r
1236 by setting the UIP_NEWDATA flag and update the sequence number
\r
1237 we acknowledge. If the application has stopped the dataflow
\r
1238 using uip_stop(), we must not accept any data packets from the
\r
1240 if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) {
\r
1241 uip_flags |= UIP_NEWDATA;
\r
1242 uip_add_rcv_nxt(uip_len);
\r
1245 /* Check if the available buffer space advertised by the other end
\r
1246 is smaller than the initial MSS for this connection. If so, we
\r
1247 set the current MSS to the window size to ensure that the
\r
1248 application does not send more data than the other end can
\r
1251 If the remote host advertises a zero window, we set the MSS to
\r
1252 the initial MSS so that the application will send an entire MSS
\r
1253 of data. This data will not be acknowledged by the receiver,
\r
1254 and the application will retransmit it. This is called the
\r
1255 "persistent timer" and uses the retransmission mechanim.
\r
1257 tmp16 = ((u16_t)BUF->wnd[0] << 8) + (u16_t)BUF->wnd[1];
\r
1258 if(tmp16 > uip_connr->initialmss ||
\r
1260 tmp16 = uip_connr->initialmss;
\r
1262 uip_connr->mss = tmp16;
\r
1264 /* If this packet constitutes an ACK for outstanding data (flagged
\r
1265 by the UIP_ACKDATA flag, we should call the application since it
\r
1266 might want to send more data. If the incoming packet had data
\r
1267 from the peer (as flagged by the UIP_NEWDATA flag), the
\r
1268 application must also be notified.
\r
1270 When the application is called, the global variable uip_len
\r
1271 contains the length of the incoming data. The application can
\r
1272 access the incoming data through the global pointer
\r
1273 uip_appdata, which usually points 40 bytes into the uip_buf
\r
1276 If the application wishes to send any data, this data should be
\r
1277 put into the uip_appdata and the length of the data should be
\r
1278 put into uip_len. If the application don't have any data to
\r
1279 send, uip_len must be set to 0. */
\r
1280 if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) {
\r
1286 if(uip_flags & UIP_ABORT) {
\r
1288 uip_connr->tcpstateflags = CLOSED;
\r
1289 BUF->flags = TCP_RST | TCP_ACK;
\r
1290 goto tcp_send_nodata;
\r
1293 if(uip_flags & UIP_CLOSE) {
\r
1295 uip_connr->len = 1;
\r
1296 uip_connr->tcpstateflags = FIN_WAIT_1;
\r
1297 uip_connr->nrtx = 0;
\r
1298 BUF->flags = TCP_FIN | TCP_ACK;
\r
1299 goto tcp_send_nodata;
\r
1302 /* If uip_slen > 0, the application has data to be sent. */
\r
1303 if(uip_slen > 0) {
\r
1305 /* If the connection has acknowledged data, the contents of
\r
1306 the ->len variable should be discarded. */
\r
1307 if((uip_flags & UIP_ACKDATA) != 0) {
\r
1308 uip_connr->len = 0;
\r
1311 /* If the ->len variable is non-zero the connection has
\r
1312 already data in transit and cannot send anymore right
\r
1314 if(uip_connr->len == 0) {
\r
1316 /* The application cannot send more than what is allowed by
\r
1317 the mss (the minumum of the MSS and the available
\r
1319 if(uip_slen > uip_connr->mss) {
\r
1320 uip_slen = uip_connr->mss;
\r
1323 /* Remember how much data we send out now so that we know
\r
1324 when everything has been acknowledged. */
\r
1325 uip_connr->len = uip_slen;
\r
1328 /* If the application already had unacknowledged data, we
\r
1329 make sure that the application does not send (i.e.,
\r
1330 retransmit) out more than it previously sent out. */
\r
1331 uip_slen = uip_connr->len;
\r
1334 uip_connr->len = 0;
\r
1336 uip_connr->nrtx = 0;
\r
1338 uip_appdata = uip_sappdata;
\r
1340 /* If the application has data to be sent, or if the incoming
\r
1341 packet had new data in it, we must send out a packet. */
\r
1342 if(uip_slen > 0 && uip_connr->len > 0) {
\r
1343 /* Add the length of the IP and TCP headers. */
\r
1344 uip_len = uip_connr->len + UIP_TCPIP_HLEN;
\r
1345 /* We always set the ACK flag in response packets. */
\r
1346 BUF->flags = TCP_ACK | TCP_PSH;
\r
1347 /* Send the packet. */
\r
1348 goto tcp_send_noopts;
\r
1350 /* If there is no data to send, just send out a pure ACK if
\r
1351 there is newdata. */
\r
1352 if(uip_flags & UIP_NEWDATA) {
\r
1353 uip_len = UIP_TCPIP_HLEN;
\r
1354 BUF->flags = TCP_ACK;
\r
1355 goto tcp_send_noopts;
\r
1360 /* We can close this connection if the peer has acknowledged our
\r
1361 FIN. This is indicated by the UIP_ACKDATA flag. */
\r
1362 if(uip_flags & UIP_ACKDATA) {
\r
1363 uip_connr->tcpstateflags = CLOSED;
\r
1364 uip_flags = UIP_CLOSE;
\r
1370 /* The application has closed the connection, but the remote host
\r
1371 hasn't closed its end yet. Thus we do nothing but wait for a
\r
1372 FIN from the other side. */
\r
1374 uip_add_rcv_nxt(uip_len);
\r
1376 if(BUF->flags & TCP_FIN) {
\r
1377 if(uip_flags & UIP_ACKDATA) {
\r
1378 uip_connr->tcpstateflags = TIME_WAIT;
\r
1379 uip_connr->timer = 0;
\r
1380 uip_connr->len = 0;
\r
1382 uip_connr->tcpstateflags = CLOSING;
\r
1384 uip_add_rcv_nxt(1);
\r
1385 uip_flags = UIP_CLOSE;
\r
1387 goto tcp_send_ack;
\r
1388 } else if(uip_flags & UIP_ACKDATA) {
\r
1389 uip_connr->tcpstateflags = FIN_WAIT_2;
\r
1390 uip_connr->len = 0;
\r
1394 goto tcp_send_ack;
\r
1400 uip_add_rcv_nxt(uip_len);
\r
1402 if(BUF->flags & TCP_FIN) {
\r
1403 uip_connr->tcpstateflags = TIME_WAIT;
\r
1404 uip_connr->timer = 0;
\r
1405 uip_add_rcv_nxt(1);
\r
1406 uip_flags = UIP_CLOSE;
\r
1408 goto tcp_send_ack;
\r
1411 goto tcp_send_ack;
\r
1416 goto tcp_send_ack;
\r
1419 if(uip_flags & UIP_ACKDATA) {
\r
1420 uip_connr->tcpstateflags = TIME_WAIT;
\r
1421 uip_connr->timer = 0;
\r
1427 /* We jump here when we are ready to send the packet, and just want
\r
1428 to set the appropriate TCP sequence numbers in the TCP header. */
\r
1430 BUF->flags = TCP_ACK;
\r
1434 BUF->tcpoffset = 5 << 4;
\r
1436 /* We're done with the input processing. We are now ready to send a
\r
1437 reply. Our job is to fill in all the fields of the TCP and IP
\r
1438 headers before calculating the checksum and finally send the
\r
1440 BUF->ackno[0] = uip_connr->rcv_nxt[0];
\r
1441 BUF->ackno[1] = uip_connr->rcv_nxt[1];
\r
1442 BUF->ackno[2] = uip_connr->rcv_nxt[2];
\r
1443 BUF->ackno[3] = uip_connr->rcv_nxt[3];
\r
1445 BUF->seqno[0] = uip_connr->snd_nxt[0];
\r
1446 BUF->seqno[1] = uip_connr->snd_nxt[1];
\r
1447 BUF->seqno[2] = uip_connr->snd_nxt[2];
\r
1448 BUF->seqno[3] = uip_connr->snd_nxt[3];
\r
1450 BUF->proto = UIP_PROTO_TCP;
\r
1452 BUF->srcport = uip_connr->lport;
\r
1453 BUF->destport = uip_connr->rport;
\r
1455 BUF->srcipaddr[0] = uip_hostaddr[0];
\r
1456 BUF->srcipaddr[1] = uip_hostaddr[1];
\r
1457 BUF->destipaddr[0] = uip_connr->ripaddr[0];
\r
1458 BUF->destipaddr[1] = uip_connr->ripaddr[1];
\r
1461 if(uip_connr->tcpstateflags & UIP_STOPPED) {
\r
1462 /* If the connection has issued uip_stop(), we advertise a zero
\r
1463 window so that the remote host will stop sending data. */
\r
1464 BUF->wnd[0] = BUF->wnd[1] = 0;
\r
1466 BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8);
\r
1467 BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff);
\r
1472 BUF->len[0] = (uip_len >> 8);
\r
1473 BUF->len[1] = (uip_len & 0xff);
\r
1475 /* Calculate TCP checksum. */
\r
1476 BUF->tcpchksum = 0;
\r
1477 BUF->tcpchksum = ~(uip_tcpchksum());
\r
1483 BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
\r
1484 BUF->ttl = UIP_TTL;
\r
1486 BUF->ipid[0] = ipid >> 8;
\r
1487 BUF->ipid[1] = ipid & 0xff;
\r
1489 /* Calculate IP checksum. */
\r
1490 BUF->ipchksum = 0;
\r
1491 BUF->ipchksum = ~(uip_ipchksum());
\r
1493 UIP_STAT(++uip_stat.tcp.sent);
\r
1495 UIP_STAT(++uip_stat.ip.sent);
\r
1496 /* Return and let the caller do the actual transmission. */
\r
1502 /*-----------------------------------------------------------------------------------*/
\r
1506 return HTONS(val);
\r
1508 /*-----------------------------------------------------------------------------------*/
\r