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
84 #include "uip_arch.h"
\r
87 #include "uip-neighbor.h"
\r
88 #endif /* UIP_CONF_IPV6 */
\r
92 /*---------------------------------------------------------------------------*/
\r
93 /* Variable definitions. */
\r
96 /* The IP address of this host. If it is defined to be fixed (by
\r
97 setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set
\r
98 here. Otherwise, the address */
\r
99 #if UIP_FIXEDADDR > 0
\r
100 const uip_ipaddr_t uip_hostaddr =
\r
101 {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1),
\r
102 HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)};
\r
103 const uip_ipaddr_t uip_draddr =
\r
104 {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1),
\r
105 HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)};
\r
106 const uip_ipaddr_t uip_netmask =
\r
107 {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1),
\r
108 HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)};
\r
110 uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask;
\r
111 #endif /* UIP_FIXEDADDR */
\r
113 static const uip_ipaddr_t all_ones_addr =
\r
115 {0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff};
\r
116 #else /* UIP_CONF_IPV6 */
\r
118 #endif /* UIP_CONF_IPV6 */
\r
119 static const uip_ipaddr_t all_zeroes_addr =
\r
121 {0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000};
\r
122 #else /* UIP_CONF_IPV6 */
\r
124 #endif /* UIP_CONF_IPV6 */
\r
126 #if UIP_FIXEDETHADDR
\r
127 const struct uip_eth_addr uip_ethaddr = {{UIP_ETHADDR0,
\r
134 struct uip_eth_addr uip_ethaddr = {{0,0,0,0,0,0}};
\r
137 #ifndef UIP_CONF_EXTERNAL_BUFFER
\r
138 u8_t uip_buf[UIP_BUFSIZE + 2] ALIGN_STRUCT_END; /* The packet buffer that contains
\r
139 incoming packets. */
\r
140 #endif /* UIP_CONF_EXTERNAL_BUFFER */
\r
142 void *uip_appdata; /* The uip_appdata pointer points to
\r
143 application data. */
\r
144 void *uip_sappdata; /* The uip_appdata pointer points to
\r
145 the application data which is to
\r
147 #if UIP_URGDATA > 0
\r
148 void *uip_urgdata; /* The uip_urgdata pointer points to
\r
149 urgent data (out-of-band data), if
\r
151 u16_t uip_urglen, uip_surglen;
\r
152 #endif /* UIP_URGDATA > 0 */
\r
154 u16_t uip_len, uip_slen;
\r
155 /* The uip_len is either 8 or 16 bits,
\r
156 depending on the maximum packet
\r
159 u8_t uip_flags; /* The uip_flags variable is used for
\r
160 communication between the TCP/IP stack
\r
161 and the application program. */
\r
162 struct uip_conn *uip_conn; /* uip_conn always points to the current
\r
165 struct uip_conn uip_conns[UIP_CONNS];
\r
166 /* The uip_conns array holds all TCP
\r
168 u16_t uip_listenports[UIP_LISTENPORTS];
\r
169 /* The uip_listenports list all currently
\r
172 struct uip_udp_conn *uip_udp_conn;
\r
173 struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
\r
174 #endif /* UIP_UDP */
\r
176 static u16_t ipid; /* Ths ipid variable is an increasing
\r
177 number that is used for the IP ID
\r
180 void uip_setipid(u16_t id) { ipid = id; }
\r
182 static u8_t iss[4]; /* The iss variable is used for the TCP
\r
183 initial sequence number. */
\r
185 #if UIP_ACTIVE_OPEN
\r
186 static u16_t lastport; /* Keeps track of the last port used for
\r
187 a new connection. */
\r
188 #endif /* UIP_ACTIVE_OPEN */
\r
190 /* Temporary variables. */
\r
192 static u8_t c, opt;
\r
193 static u16_t tmp16;
\r
195 /* Structures and definitions. */
\r
196 #define TCP_FIN 0x01
\r
197 #define TCP_SYN 0x02
\r
198 #define TCP_RST 0x04
\r
199 #define TCP_PSH 0x08
\r
200 #define TCP_ACK 0x10
\r
201 #define TCP_URG 0x20
\r
202 #define TCP_CTL 0x3f
\r
204 #define TCP_OPT_END 0 /* End of TCP options list */
\r
205 #define TCP_OPT_NOOP 1 /* "No-operation" TCP option */
\r
206 #define TCP_OPT_MSS 2 /* Maximum segment size TCP option */
\r
208 #define TCP_OPT_MSS_LEN 4 /* Length of TCP MSS option. */
\r
210 #define ICMP_ECHO_REPLY 0
\r
211 #define ICMP_ECHO 8
\r
213 #define ICMP6_ECHO_REPLY 129
\r
214 #define ICMP6_ECHO 128
\r
215 #define ICMP6_NEIGHBOR_SOLICITATION 135
\r
216 #define ICMP6_NEIGHBOR_ADVERTISEMENT 136
\r
218 #define ICMP6_FLAG_S (1 << 6)
\r
220 #define ICMP6_OPTION_SOURCE_LINK_ADDRESS 1
\r
221 #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
231 #if UIP_STATISTICS == 1
\r
232 struct uip_stats uip_stat;
\r
233 #define UIP_STAT(s) s
\r
235 #define UIP_STAT(s)
\r
236 #endif /* UIP_STATISTICS == 1 */
\r
238 #if UIP_LOGGING == 1
\r
240 void uip_log(char *msg);
\r
241 #define UIP_LOG(m) uip_log(m)
\r
244 #endif /* UIP_LOGGING == 1 */
\r
246 #if ! UIP_ARCH_ADD32
\r
248 uip_add32(u8_t *op32, u16_t op16)
\r
250 uip_acc32[3] = op32[3] + (op16 & 0xff);
\r
251 uip_acc32[2] = op32[2] + (op16 >> 8);
\r
252 uip_acc32[1] = op32[1];
\r
253 uip_acc32[0] = op32[0];
\r
255 if(uip_acc32[2] < (op16 >> 8)) {
\r
257 if(uip_acc32[1] == 0) {
\r
263 if(uip_acc32[3] < (op16 & 0xff)) {
\r
265 if(uip_acc32[2] == 0) {
\r
267 if(uip_acc32[1] == 0) {
\r
274 #endif /* UIP_ARCH_ADD32 */
\r
276 #if ! UIP_ARCH_CHKSUM
\r
277 /*---------------------------------------------------------------------------*/
\r
279 chksum(u16_t sum, const u8_t *data, u16_t len)
\r
282 const u8_t *dataptr;
\r
283 const u8_t *last_byte;
\r
286 last_byte = data + len - 1;
\r
288 while(dataptr < last_byte) { /* At least two more bytes */
\r
289 t = (dataptr[0] << 8) + dataptr[1];
\r
297 if(dataptr == last_byte) {
\r
298 t = (dataptr[0] << 8) + 0;
\r
305 /* Return sum in host byte order. */
\r
308 /*---------------------------------------------------------------------------*/
\r
310 uip_chksum(u16_t *data, u16_t len)
\r
312 return htons(chksum(0, (u8_t *)data, len));
\r
314 /*---------------------------------------------------------------------------*/
\r
315 #ifndef UIP_ARCH_IPCHKSUM
\r
321 sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN);
\r
322 DEBUG_PRINTF("uip_ipchksum: sum 0x%04x\n", sum);
\r
323 return (sum == 0) ? 0xffff : htons(sum);
\r
326 /*---------------------------------------------------------------------------*/
\r
328 upper_layer_chksum(u8_t proto)
\r
330 u16_t upper_layer_len;
\r
334 upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]);
\r
335 #else /* UIP_CONF_IPV6 */
\r
336 upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN;
\r
337 #endif /* UIP_CONF_IPV6 */
\r
339 /* First sum pseudoheader. */
\r
341 /* IP protocol and length fields. This addition cannot carry. */
\r
342 sum = upper_layer_len + proto;
\r
343 /* Sum IP source and destination addresses. */
\r
344 sum = chksum(sum, (u8_t *)&BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t));
\r
346 /* Sum TCP header and data. */
\r
347 sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN],
\r
350 return (sum == 0) ? 0xffff : htons(sum);
\r
352 /*---------------------------------------------------------------------------*/
\r
355 uip_icmp6chksum(void)
\r
357 return upper_layer_chksum(UIP_PROTO_ICMP6);
\r
360 #endif /* UIP_CONF_IPV6 */
\r
361 /*---------------------------------------------------------------------------*/
\r
363 uip_tcpchksum(void)
\r
365 return upper_layer_chksum(UIP_PROTO_TCP);
\r
367 /*---------------------------------------------------------------------------*/
\r
368 #if UIP_UDP_CHECKSUMS
\r
370 uip_udpchksum(void)
\r
372 return upper_layer_chksum(UIP_PROTO_UDP);
\r
374 #endif /* UIP_UDP_CHECKSUMS */
\r
375 #endif /* UIP_ARCH_CHKSUM */
\r
376 /*---------------------------------------------------------------------------*/
\r
380 for(c = 0; c < UIP_LISTENPORTS; ++c) {
\r
381 uip_listenports[c] = 0;
\r
383 for(c = 0; c < UIP_CONNS; ++c) {
\r
384 uip_conns[c].tcpstateflags = UIP_CLOSED;
\r
386 #if UIP_ACTIVE_OPEN
\r
388 #endif /* UIP_ACTIVE_OPEN */
\r
391 for(c = 0; c < UIP_UDP_CONNS; ++c) {
\r
392 uip_udp_conns[c].lport = 0;
\r
394 #endif /* UIP_UDP */
\r
397 /* IPv4 initialization. */
\r
398 #if UIP_FIXEDADDR == 0
\r
399 /* uip_hostaddr[0] = uip_hostaddr[1] = 0;*/
\r
400 #endif /* UIP_FIXEDADDR */
\r
403 /*---------------------------------------------------------------------------*/
\r
404 #if UIP_ACTIVE_OPEN
\r
406 uip_connect(uip_ipaddr_t *ripaddr, u16_t rport)
\r
408 register struct uip_conn *conn, *cconn;
\r
410 /* Find an unused local port. */
\r
414 if(lastport >= 32000) {
\r
418 /* Check if this port is already in use, and if so try to find
\r
420 for(c = 0; c < UIP_CONNS; ++c) {
\r
421 conn = &uip_conns[c];
\r
422 if(conn->tcpstateflags != UIP_CLOSED &&
\r
423 conn->lport == htons(lastport)) {
\r
429 for(c = 0; c < UIP_CONNS; ++c) {
\r
430 cconn = &uip_conns[c];
\r
431 if(cconn->tcpstateflags == UIP_CLOSED) {
\r
435 if(cconn->tcpstateflags == UIP_TIME_WAIT) {
\r
437 cconn->timer > conn->timer) {
\r
447 conn->tcpstateflags = UIP_SYN_SENT;
\r
449 conn->snd_nxt[0] = iss[0];
\r
450 conn->snd_nxt[1] = iss[1];
\r
451 conn->snd_nxt[2] = iss[2];
\r
452 conn->snd_nxt[3] = iss[3];
\r
454 conn->initialmss = conn->mss = UIP_TCP_MSS;
\r
456 conn->len = 1; /* TCP length of the SYN is one. */
\r
458 conn->timer = 1; /* Send the SYN next time around. */
\r
459 conn->rto = UIP_RTO;
\r
461 conn->sv = 16; /* Initial value of the RTT variance. */
\r
462 conn->lport = htons(lastport);
\r
463 conn->rport = rport;
\r
464 uip_ipaddr_copy(&conn->ripaddr, ripaddr);
\r
468 #endif /* UIP_ACTIVE_OPEN */
\r
469 /*---------------------------------------------------------------------------*/
\r
471 struct uip_udp_conn *
\r
472 uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport)
\r
474 register struct uip_udp_conn *conn;
\r
476 /* Find an unused local port. */
\r
480 if(lastport >= 32000) {
\r
484 for(c = 0; c < UIP_UDP_CONNS; ++c) {
\r
485 if(uip_udp_conns[c].lport == htons(lastport)) {
\r
492 for(c = 0; c < UIP_UDP_CONNS; ++c) {
\r
493 if(uip_udp_conns[c].lport == 0) {
\r
494 conn = &uip_udp_conns[c];
\r
503 conn->lport = HTONS(lastport);
\r
504 conn->rport = rport;
\r
505 if(ripaddr == NULL) {
\r
506 memset(conn->ripaddr, 0, sizeof(uip_ipaddr_t));
\r
508 uip_ipaddr_copy(&conn->ripaddr, ripaddr);
\r
510 conn->ttl = UIP_TTL;
\r
514 #endif /* UIP_UDP */
\r
515 /*---------------------------------------------------------------------------*/
\r
517 uip_unlisten(u16_t port)
\r
519 for(c = 0; c < UIP_LISTENPORTS; ++c) {
\r
520 if(uip_listenports[c] == port) {
\r
521 uip_listenports[c] = 0;
\r
526 /*---------------------------------------------------------------------------*/
\r
528 uip_listen(u16_t port)
\r
530 for(c = 0; c < UIP_LISTENPORTS; ++c) {
\r
531 if(uip_listenports[c] == 0) {
\r
532 uip_listenports[c] = port;
\r
537 /*---------------------------------------------------------------------------*/
\r
538 /* XXX: IP fragment reassembly: not well-tested. */
\r
540 #if UIP_REASSEMBLY && !UIP_CONF_IPV6
\r
541 #define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN)
\r
542 static u8_t uip_reassbuf[UIP_REASS_BUFSIZE];
\r
543 static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)];
\r
544 static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f,
\r
545 0x0f, 0x07, 0x03, 0x01};
\r
546 static u16_t uip_reasslen;
\r
547 static u8_t uip_reassflags;
\r
548 #define UIP_REASS_FLAG_LASTFRAG 0x01
\r
549 static u8_t uip_reasstmr;
\r
559 /* If ip_reasstmr is zero, no packet is present in the buffer, so we
\r
560 write the IP header of the fragment into the reassembly
\r
561 buffer. The timer is updated with the maximum age. */
\r
562 if(uip_reasstmr == 0) {
\r
563 memcpy(uip_reassbuf, &BUF->vhl, UIP_IPH_LEN);
\r
564 uip_reasstmr = UIP_REASS_MAXAGE;
\r
565 uip_reassflags = 0;
\r
566 /* Clear the bitmap. */
\r
567 memset(uip_reassbitmap, 0, sizeof(uip_reassbitmap));
\r
570 /* Check if the incoming fragment matches the one currently present
\r
571 in the reasembly buffer. If so, we proceed with copying the
\r
572 fragment into the buffer. */
\r
573 if(BUF->srcipaddr[0] == FBUF->srcipaddr[0] &&
\r
574 BUF->srcipaddr[1] == FBUF->srcipaddr[1] &&
\r
575 BUF->destipaddr[0] == FBUF->destipaddr[0] &&
\r
576 BUF->destipaddr[1] == FBUF->destipaddr[1] &&
\r
577 BUF->ipid[0] == FBUF->ipid[0] &&
\r
578 BUF->ipid[1] == FBUF->ipid[1]) {
\r
580 len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4;
\r
581 offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8;
\r
583 /* If the offset or the offset + fragment length overflows the
\r
584 reassembly buffer, we discard the entire packet. */
\r
585 if(offset > UIP_REASS_BUFSIZE ||
\r
586 offset + len > UIP_REASS_BUFSIZE) {
\r
591 /* Copy the fragment into the reassembly buffer, at the right
\r
593 memcpy(&uip_reassbuf[UIP_IPH_LEN + offset],
\r
594 (char *)BUF + (int)((BUF->vhl & 0x0f) * 4),
\r
597 /* Update the bitmap. */
\r
598 if(offset / (8 * 8) == (offset + len) / (8 * 8)) {
\r
599 /* If the two endpoints are in the same byte, we only update
\r
602 uip_reassbitmap[offset / (8 * 8)] |=
\r
603 bitmap_bits[(offset / 8 ) & 7] &
\r
604 ~bitmap_bits[((offset + len) / 8 ) & 7];
\r
606 /* If the two endpoints are in different bytes, we update the
\r
607 bytes in the endpoints and fill the stuff inbetween with
\r
609 uip_reassbitmap[offset / (8 * 8)] |=
\r
610 bitmap_bits[(offset / 8 ) & 7];
\r
611 for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) {
\r
612 uip_reassbitmap[i] = 0xff;
\r
614 uip_reassbitmap[(offset + len) / (8 * 8)] |=
\r
615 ~bitmap_bits[((offset + len) / 8 ) & 7];
\r
618 /* If this fragment has the More Fragments flag set to zero, we
\r
619 know that this is the last fragment, so we can calculate the
\r
620 size of the entire packet. We also set the
\r
621 IP_REASS_FLAG_LASTFRAG flag to indicate that we have received
\r
622 the final fragment. */
\r
624 if((BUF->ipoffset[0] & IP_MF) == 0) {
\r
625 uip_reassflags |= UIP_REASS_FLAG_LASTFRAG;
\r
626 uip_reasslen = offset + len;
\r
629 /* Finally, we check if we have a full packet in the buffer. We do
\r
630 this by checking if we have the last fragment and if all bits
\r
631 in the bitmap are set. */
\r
632 if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) {
\r
633 /* Check all bytes up to and including all but the last byte in
\r
635 for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) {
\r
636 if(uip_reassbitmap[i] != 0xff) {
\r
640 /* Check the last byte in the bitmap. It should contain just the
\r
641 right amount of bits. */
\r
642 if(uip_reassbitmap[uip_reasslen / (8 * 8)] !=
\r
643 (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) {
\r
647 /* If we have come this far, we have a full packet in the
\r
648 buffer, so we allocate a pbuf and copy the packet into it. We
\r
649 also reset the timer. */
\r
651 memcpy(BUF, FBUF, uip_reasslen);
\r
653 /* Pretend to be a "normal" (i.e., not fragmented) IP packet
\r
655 BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
\r
656 BUF->len[0] = uip_reasslen >> 8;
\r
657 BUF->len[1] = uip_reasslen & 0xff;
\r
659 BUF->ipchksum = ~(uip_ipchksum());
\r
661 return uip_reasslen;
\r
668 #endif /* UIP_REASSEMBLY */
\r
669 /*---------------------------------------------------------------------------*/
\r
671 uip_add_rcv_nxt(u16_t n)
\r
673 uip_add32(uip_conn->rcv_nxt, n);
\r
674 uip_conn->rcv_nxt[0] = uip_acc32[0];
\r
675 uip_conn->rcv_nxt[1] = uip_acc32[1];
\r
676 uip_conn->rcv_nxt[2] = uip_acc32[2];
\r
677 uip_conn->rcv_nxt[3] = uip_acc32[3];
\r
679 /*---------------------------------------------------------------------------*/
\r
681 uip_process(u8_t flag)
\r
683 register struct uip_conn *uip_connr = uip_conn;
\r
686 if(flag == UIP_UDP_SEND_CONN) {
\r
689 #endif /* UIP_UDP */
\r
691 uip_sappdata = uip_appdata = &uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN];
\r
693 /* Check if we were invoked because of a poll request for a
\r
694 particular connection. */
\r
695 if(flag == UIP_POLL_REQUEST) {
\r
696 if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED &&
\r
697 !uip_outstanding(uip_connr)) {
\r
698 uip_flags = UIP_POLL;
\r
704 /* Check if we were invoked because of the perodic timer fireing. */
\r
705 } else if(flag == UIP_TIMER) {
\r
707 if(uip_reasstmr != 0) {
\r
710 #endif /* UIP_REASSEMBLY */
\r
711 /* Increase the initial sequence number. */
\r
712 if(++iss[3] == 0) {
\r
713 if(++iss[2] == 0) {
\r
714 if(++iss[1] == 0) {
\r
720 /* Reset the length variables. */
\r
724 /* Check if the connection is in a state in which we simply wait
\r
725 for the connection to time out. If so, we increase the
\r
726 connection's timer and remove the connection if it times
\r
728 if(uip_connr->tcpstateflags == UIP_TIME_WAIT ||
\r
729 uip_connr->tcpstateflags == UIP_FIN_WAIT_2) {
\r
730 ++(uip_connr->timer);
\r
731 if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) {
\r
732 uip_connr->tcpstateflags = UIP_CLOSED;
\r
734 } else if(uip_connr->tcpstateflags != UIP_CLOSED) {
\r
735 /* If the connection has outstanding data, we increase the
\r
736 connection's timer and see if it has reached the RTO value
\r
737 in which case we retransmit. */
\r
738 if(uip_outstanding(uip_connr)) {
\r
739 if(uip_connr->timer-- == 0) {
\r
740 if(uip_connr->nrtx == UIP_MAXRTX ||
\r
741 ((uip_connr->tcpstateflags == UIP_SYN_SENT ||
\r
742 uip_connr->tcpstateflags == UIP_SYN_RCVD) &&
\r
743 uip_connr->nrtx == UIP_MAXSYNRTX)) {
\r
744 uip_connr->tcpstateflags = UIP_CLOSED;
\r
746 /* We call UIP_APPCALL() with uip_flags set to
\r
747 UIP_TIMEDOUT to inform the application that the
\r
748 connection has timed out. */
\r
749 uip_flags = UIP_TIMEDOUT;
\r
752 /* We also send a reset packet to the remote host. */
\r
753 BUF->flags = TCP_RST | TCP_ACK;
\r
754 goto tcp_send_nodata;
\r
757 /* Exponential backoff. */
\r
758 uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4?
\r
761 ++(uip_connr->nrtx);
\r
763 /* Ok, so we need to retransmit. We do this differently
\r
764 depending on which state we are in. In ESTABLISHED, we
\r
765 call upon the application so that it may prepare the
\r
766 data for the retransmit. In SYN_RCVD, we resend the
\r
767 SYNACK that we sent earlier and in LAST_ACK we have to
\r
768 retransmit our FINACK. */
\r
769 UIP_STAT(++uip_stat.tcp.rexmit);
\r
770 switch(uip_connr->tcpstateflags & UIP_TS_MASK) {
\r
772 /* In the SYN_RCVD state, we should retransmit our
\r
774 goto tcp_send_synack;
\r
776 #if UIP_ACTIVE_OPEN
\r
778 /* In the SYN_SENT state, we retransmit out SYN. */
\r
781 #endif /* UIP_ACTIVE_OPEN */
\r
783 case UIP_ESTABLISHED:
\r
784 /* In the ESTABLISHED state, we call upon the application
\r
785 to do the actual retransmit after which we jump into
\r
786 the code for sending out the packet (the apprexmit
\r
788 uip_flags = UIP_REXMIT;
\r
792 case UIP_FIN_WAIT_1:
\r
795 /* In all these states we should retransmit a FINACK. */
\r
796 goto tcp_send_finack;
\r
800 } else if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) {
\r
801 /* If there was no need for a retransmission, we poll the
\r
802 application for new data. */
\r
803 uip_flags = UIP_POLL;
\r
811 if(flag == UIP_UDP_TIMER) {
\r
812 if(uip_udp_conn->lport != 0) {
\r
814 uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
\r
815 uip_len = uip_slen = 0;
\r
816 uip_flags = UIP_POLL;
\r
825 /* This is where the input processing starts. */
\r
826 UIP_STAT(++uip_stat.ip.recv);
\r
828 /* Start of IP input header processing code. */
\r
831 /* Check validity of the IP header. */
\r
832 if((BUF->vtc & 0xf0) != 0x60) { /* IP version and header length. */
\r
833 UIP_STAT(++uip_stat.ip.drop);
\r
834 UIP_STAT(++uip_stat.ip.vhlerr);
\r
835 UIP_LOG("ipv6: invalid version.");
\r
838 #else /* UIP_CONF_IPV6 */
\r
839 /* Check validity of the IP header. */
\r
840 if(BUF->vhl != 0x45) { /* IP version and header length. */
\r
841 UIP_STAT(++uip_stat.ip.drop);
\r
842 UIP_STAT(++uip_stat.ip.vhlerr);
\r
843 UIP_LOG("ip: invalid version or header length.");
\r
846 #endif /* UIP_CONF_IPV6 */
\r
848 /* Check the size of the packet. If the size reported to us in
\r
849 uip_len is smaller the size reported in the IP header, we assume
\r
850 that the packet has been corrupted in transit. If the size of
\r
851 uip_len is larger than the size reported in the IP packet header,
\r
852 the packet has been padded and we set uip_len to the correct
\r
855 if((BUF->len[0] << 8) + BUF->len[1] <= uip_len) {
\r
856 uip_len = (BUF->len[0] << 8) + BUF->len[1];
\r
858 uip_len += 40; /* The length reported in the IPv6 header is the
\r
859 length of the payload that follows the
\r
860 header. However, uIP uses the uip_len variable
\r
861 for holding the size of the entire packet,
\r
862 including the IP header. For IPv4 this is not a
\r
863 problem as the length field in the IPv4 header
\r
864 contains the length of the entire packet. But
\r
865 for IPv6 we need to add the size of the IPv6
\r
866 header (40 bytes). */
\r
867 #endif /* UIP_CONF_IPV6 */
\r
869 UIP_LOG("ip: packet shorter than reported in IP header.");
\r
874 /* Check the fragment flag. */
\r
875 if((BUF->ipoffset[0] & 0x3f) != 0 ||
\r
876 BUF->ipoffset[1] != 0) {
\r
878 uip_len = uip_reass();
\r
882 #else /* UIP_REASSEMBLY */
\r
883 UIP_STAT(++uip_stat.ip.drop);
\r
884 UIP_STAT(++uip_stat.ip.fragerr);
\r
885 UIP_LOG("ip: fragment dropped.");
\r
887 #endif /* UIP_REASSEMBLY */
\r
889 #endif /* UIP_CONF_IPV6 */
\r
891 if(uip_ipaddr_cmp(uip_hostaddr, all_zeroes_addr)) {
\r
892 /* If we are configured to use ping IP address configuration and
\r
893 hasn't been assigned an IP address yet, we accept all ICMP
\r
895 #if UIP_PINGADDRCONF && !UIP_CONF_IPV6
\r
896 if(BUF->proto == UIP_PROTO_ICMP) {
\r
897 UIP_LOG("ip: possible ping config packet received.");
\r
900 UIP_LOG("ip: packet dropped since no address assigned.");
\r
903 #endif /* UIP_PINGADDRCONF */
\r
906 /* If IP broadcast support is configured, we check for a broadcast
\r
907 UDP packet, which may be destined to us. */
\r
909 DEBUG_PRINTF("UDP IP checksum 0x%04x\n", uip_ipchksum());
\r
910 if(BUF->proto == UIP_PROTO_UDP &&
\r
911 uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr)
\r
913 uip_ipchksum() == 0xffff*/) {
\r
916 #endif /* UIP_BROADCAST */
\r
918 /* Check if the packet is destined for our IP address. */
\r
920 if(!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr)) {
\r
921 UIP_STAT(++uip_stat.ip.drop);
\r
924 #else /* UIP_CONF_IPV6 */
\r
925 /* For IPv6, packet reception is a little trickier as we need to
\r
926 make sure that we listen to certain multicast addresses (all
\r
927 hosts multicast address, and the solicited-node multicast
\r
928 address) as well. However, we will cheat here and accept all
\r
929 multicast packets that are sent to the ff02::/16 addresses. */
\r
930 if(!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr) &&
\r
931 BUF->destipaddr[0] != HTONS(0xff02)) {
\r
932 UIP_STAT(++uip_stat.ip.drop);
\r
935 #endif /* UIP_CONF_IPV6 */
\r
939 if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header
\r
941 UIP_STAT(++uip_stat.ip.drop);
\r
942 UIP_STAT(++uip_stat.ip.chkerr);
\r
943 UIP_LOG("ip: bad checksum.");
\r
946 #endif /* UIP_CONF_IPV6 */
\r
948 if(BUF->proto == UIP_PROTO_TCP) { /* Check for TCP packet. If so,
\r
949 proceed with TCP input
\r
955 if(BUF->proto == UIP_PROTO_UDP) {
\r
958 #endif /* UIP_UDP */
\r
961 /* ICMPv4 processing code follows. */
\r
962 if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from
\r
964 UIP_STAT(++uip_stat.ip.drop);
\r
965 UIP_STAT(++uip_stat.ip.protoerr);
\r
966 UIP_LOG("ip: neither tcp nor icmp.");
\r
970 #if UIP_PINGADDRCONF
\r
972 #endif /* UIP_PINGADDRCONF */
\r
973 UIP_STAT(++uip_stat.icmp.recv);
\r
975 /* ICMP echo (i.e., ping) processing. This is simple, we only change
\r
976 the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP
\r
977 checksum before we return the packet. */
\r
978 if(ICMPBUF->type != ICMP_ECHO) {
\r
979 UIP_STAT(++uip_stat.icmp.drop);
\r
980 UIP_STAT(++uip_stat.icmp.typeerr);
\r
981 UIP_LOG("icmp: not icmp echo.");
\r
985 /* If we are configured to use ping IP address assignment, we use
\r
986 the destination IP address of this ping packet and assign it to
\r
988 #if UIP_PINGADDRCONF
\r
989 if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) {
\r
990 uip_hostaddr[0] = BUF->destipaddr[0];
\r
991 uip_hostaddr[1] = BUF->destipaddr[1];
\r
993 #endif /* UIP_PINGADDRCONF */
\r
995 ICMPBUF->type = ICMP_ECHO_REPLY;
\r
997 if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) {
\r
998 ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1;
\r
1000 ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8);
\r
1003 /* Swap IP addresses. */
\r
1004 uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
\r
1005 uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
\r
1007 UIP_STAT(++uip_stat.icmp.sent);
\r
1010 /* End of IPv4 input header processing code. */
\r
1011 #else /* !UIP_CONF_IPV6 */
\r
1013 /* This is IPv6 ICMPv6 processing code. */
\r
1014 DEBUG_PRINTF("icmp6_input: length %d\n", uip_len);
\r
1016 if(BUF->proto != UIP_PROTO_ICMP6) { /* We only allow ICMPv6 packets from
\r
1018 UIP_STAT(++uip_stat.ip.drop);
\r
1019 UIP_STAT(++uip_stat.ip.protoerr);
\r
1020 UIP_LOG("ip: neither tcp nor icmp6.");
\r
1024 UIP_STAT(++uip_stat.icmp.recv);
\r
1026 /* If we get a neighbor solicitation for our address we should send
\r
1027 a neighbor advertisement message back. */
\r
1028 if(ICMPBUF->type == ICMP6_NEIGHBOR_SOLICITATION) {
\r
1029 if(uip_ipaddr_cmp(ICMPBUF->icmp6data, uip_hostaddr)) {
\r
1031 if(ICMPBUF->options[0] == ICMP6_OPTION_SOURCE_LINK_ADDRESS) {
\r
1032 /* Save the sender's address in our neighbor list. */
\r
1033 uip_neighbor_add(ICMPBUF->srcipaddr, &(ICMPBUF->options[2]));
\r
1036 /* We should now send a neighbor advertisement back to where the
\r
1037 neighbor solicication came from. */
\r
1038 ICMPBUF->type = ICMP6_NEIGHBOR_ADVERTISEMENT;
\r
1039 ICMPBUF->flags = ICMP6_FLAG_S; /* Solicited flag. */
\r
1041 ICMPBUF->reserved1 = ICMPBUF->reserved2 = ICMPBUF->reserved3 = 0;
\r
1043 uip_ipaddr_copy(ICMPBUF->destipaddr, ICMPBUF->srcipaddr);
\r
1044 uip_ipaddr_copy(ICMPBUF->srcipaddr, uip_hostaddr);
\r
1045 ICMPBUF->options[0] = ICMP6_OPTION_TARGET_LINK_ADDRESS;
\r
1046 ICMPBUF->options[1] = 1; /* Options length, 1 = 8 bytes. */
\r
1047 memcpy(&(ICMPBUF->options[2]), &uip_ethaddr, sizeof(uip_ethaddr));
\r
1048 ICMPBUF->icmpchksum = 0;
\r
1049 ICMPBUF->icmpchksum = ~uip_icmp6chksum();
\r
1054 } else if(ICMPBUF->type == ICMP6_ECHO) {
\r
1055 /* ICMP echo (i.e., ping) processing. This is simple, we only
\r
1056 change the ICMP type from ECHO to ECHO_REPLY and update the
\r
1057 ICMP checksum before we return the packet. */
\r
1059 ICMPBUF->type = ICMP6_ECHO_REPLY;
\r
1061 uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
\r
1062 uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
\r
1063 ICMPBUF->icmpchksum = 0;
\r
1064 ICMPBUF->icmpchksum = ~uip_icmp6chksum();
\r
1066 UIP_STAT(++uip_stat.icmp.sent);
\r
1069 DEBUG_PRINTF("Unknown icmp6 message type %d\n", ICMPBUF->type);
\r
1070 UIP_STAT(++uip_stat.icmp.drop);
\r
1071 UIP_STAT(++uip_stat.icmp.typeerr);
\r
1072 UIP_LOG("icmp: unknown ICMP message.");
\r
1076 /* End of IPv6 ICMP processing. */
\r
1078 #endif /* !UIP_CONF_IPV6 */
\r
1081 /* UDP input processing. */
\r
1083 /* UDP processing is really just a hack. We don't do anything to the
\r
1084 UDP/IP headers, but let the UDP application do all the hard
\r
1085 work. If the application sets uip_slen, it has a packet to
\r
1087 #if UIP_UDP_CHECKSUMS
\r
1088 uip_len = uip_len - UIP_IPUDPH_LEN;
\r
1089 uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
\r
1090 if(UDPBUF->udpchksum != 0 && uip_udpchksum() != 0xffff) {
\r
1091 UIP_STAT(++uip_stat.udp.drop);
\r
1092 UIP_STAT(++uip_stat.udp.chkerr);
\r
1093 UIP_LOG("udp: bad checksum.");
\r
1096 #else /* UIP_UDP_CHECKSUMS */
\r
1097 uip_len = uip_len - UIP_IPUDPH_LEN;
\r
1098 #endif /* UIP_UDP_CHECKSUMS */
\r
1100 /* Demultiplex this UDP packet between the UDP "connections". */
\r
1101 for(uip_udp_conn = &uip_udp_conns[0];
\r
1102 uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS];
\r
1104 /* If the local UDP port is non-zero, the connection is considered
\r
1105 to be used. If so, the local port number is checked against the
\r
1106 destination port number in the received packet. If the two port
\r
1107 numbers match, the remote port number is checked if the
\r
1108 connection is bound to a remote port. Finally, if the
\r
1109 connection is bound to a remote IP address, the source IP
\r
1110 address of the packet is checked. */
\r
1111 if(uip_udp_conn->lport != 0 &&
\r
1112 UDPBUF->destport == uip_udp_conn->lport &&
\r
1113 (uip_udp_conn->rport == 0 ||
\r
1114 UDPBUF->srcport == uip_udp_conn->rport) &&
\r
1115 (uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) ||
\r
1116 uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) ||
\r
1117 uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr))) {
\r
1121 UIP_LOG("udp: no matching connection found");
\r
1126 uip_flags = UIP_NEWDATA;
\r
1127 uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
\r
1129 UIP_UDP_APPCALL();
\r
1131 if(uip_slen == 0) {
\r
1134 uip_len = uip_slen + UIP_IPUDPH_LEN;
\r
1137 /* For IPv6, the IP length field does not include the IPv6 IP header
\r
1139 BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
\r
1140 BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
\r
1141 #else /* UIP_CONF_IPV6 */
\r
1142 BUF->len[0] = (uip_len >> 8);
\r
1143 BUF->len[1] = (uip_len & 0xff);
\r
1144 #endif /* UIP_CONF_IPV6 */
\r
1146 BUF->ttl = uip_udp_conn->ttl;
\r
1147 BUF->proto = UIP_PROTO_UDP;
\r
1149 UDPBUF->udplen = HTONS(uip_slen + UIP_UDPH_LEN);
\r
1150 UDPBUF->udpchksum = 0;
\r
1152 BUF->srcport = uip_udp_conn->lport;
\r
1153 BUF->destport = uip_udp_conn->rport;
\r
1155 uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
\r
1156 uip_ipaddr_copy(BUF->destipaddr, uip_udp_conn->ripaddr);
\r
1158 uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN];
\r
1160 #if UIP_UDP_CHECKSUMS
\r
1161 /* Calculate UDP checksum. */
\r
1162 UDPBUF->udpchksum = ~(uip_udpchksum());
\r
1163 if(UDPBUF->udpchksum == 0) {
\r
1164 UDPBUF->udpchksum = 0xffff;
\r
1166 #endif /* UIP_UDP_CHECKSUMS */
\r
1168 goto ip_send_nolen;
\r
1169 #endif /* UIP_UDP */
\r
1171 /* TCP input processing. */
\r
1173 UIP_STAT(++uip_stat.tcp.recv);
\r
1175 /* Start of TCP input header processing code. */
\r
1177 if(uip_tcpchksum() != 0xffff) { /* Compute and check the TCP
\r
1179 UIP_STAT(++uip_stat.tcp.drop);
\r
1180 UIP_STAT(++uip_stat.tcp.chkerr);
\r
1181 UIP_LOG("tcp: bad checksum.");
\r
1186 /* Demultiplex this segment. */
\r
1187 /* First check any active connections. */
\r
1188 for(uip_connr = &uip_conns[0]; uip_connr <= &uip_conns[UIP_CONNS - 1];
\r
1190 if(uip_connr->tcpstateflags != UIP_CLOSED &&
\r
1191 BUF->destport == uip_connr->lport &&
\r
1192 BUF->srcport == uip_connr->rport &&
\r
1193 uip_ipaddr_cmp(BUF->srcipaddr, uip_connr->ripaddr)) {
\r
1198 /* If we didn't find and active connection that expected the packet,
\r
1199 either this packet is an old duplicate, or this is a SYN packet
\r
1200 destined for a connection in LISTEN. If the SYN flag isn't set,
\r
1201 it is an old packet and we send a RST. */
\r
1202 if((BUF->flags & TCP_CTL) != TCP_SYN) {
\r
1206 tmp16 = BUF->destport;
\r
1207 /* Next, check listening connections. */
\r
1208 for(c = 0; c < UIP_LISTENPORTS; ++c) {
\r
1209 if(tmp16 == uip_listenports[c])
\r
1210 goto found_listen;
\r
1213 /* No matching connection found, so we send a RST packet. */
\r
1214 UIP_STAT(++uip_stat.tcp.synrst);
\r
1217 /* We do not send resets in response to resets. */
\r
1218 if(BUF->flags & TCP_RST) {
\r
1222 UIP_STAT(++uip_stat.tcp.rst);
\r
1224 BUF->flags = TCP_RST | TCP_ACK;
\r
1225 uip_len = UIP_IPTCPH_LEN;
\r
1226 BUF->tcpoffset = 5 << 4;
\r
1228 /* Flip the seqno and ackno fields in the TCP header. */
\r
1229 c = BUF->seqno[3];
\r
1230 BUF->seqno[3] = BUF->ackno[3];
\r
1231 BUF->ackno[3] = c;
\r
1233 c = BUF->seqno[2];
\r
1234 BUF->seqno[2] = BUF->ackno[2];
\r
1235 BUF->ackno[2] = c;
\r
1237 c = BUF->seqno[1];
\r
1238 BUF->seqno[1] = BUF->ackno[1];
\r
1239 BUF->ackno[1] = c;
\r
1241 c = BUF->seqno[0];
\r
1242 BUF->seqno[0] = BUF->ackno[0];
\r
1243 BUF->ackno[0] = c;
\r
1245 /* We also have to increase the sequence number we are
\r
1246 acknowledging. If the least significant byte overflowed, we need
\r
1247 to propagate the carry to the other bytes as well. */
\r
1248 if(++BUF->ackno[3] == 0) {
\r
1249 if(++BUF->ackno[2] == 0) {
\r
1250 if(++BUF->ackno[1] == 0) {
\r
1256 /* Swap port numbers. */
\r
1257 tmp16 = BUF->srcport;
\r
1258 BUF->srcport = BUF->destport;
\r
1259 BUF->destport = tmp16;
\r
1261 /* Swap IP addresses. */
\r
1262 uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
\r
1263 uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
\r
1265 /* And send out the RST packet! */
\r
1266 goto tcp_send_noconn;
\r
1268 /* This label will be jumped to if we matched the incoming packet
\r
1269 with a connection in LISTEN. In that case, we should create a new
\r
1270 connection and send a SYNACK in return. */
\r
1272 /* First we check if there are any connections avaliable. Unused
\r
1273 connections are kept in the same table as used connections, but
\r
1274 unused ones have the tcpstate set to CLOSED. Also, connections in
\r
1275 TIME_WAIT are kept track of and we'll use the oldest one if no
\r
1276 CLOSED connections are found. Thanks to Eddie C. Dost for a very
\r
1277 nice algorithm for the TIME_WAIT search. */
\r
1279 for(c = 0; c < UIP_CONNS; ++c) {
\r
1280 if(uip_conns[c].tcpstateflags == UIP_CLOSED) {
\r
1281 uip_connr = &uip_conns[c];
\r
1284 if(uip_conns[c].tcpstateflags == UIP_TIME_WAIT) {
\r
1285 if(uip_connr == 0 ||
\r
1286 uip_conns[c].timer > uip_connr->timer) {
\r
1287 uip_connr = &uip_conns[c];
\r
1292 if(uip_connr == 0) {
\r
1293 /* All connections are used already, we drop packet and hope that
\r
1294 the remote end will retransmit the packet at a time when we
\r
1295 have more spare connections. */
\r
1296 UIP_STAT(++uip_stat.tcp.syndrop);
\r
1297 UIP_LOG("tcp: found no unused connections.");
\r
1300 uip_conn = uip_connr;
\r
1302 /* Fill in the necessary fields for the new connection. */
\r
1303 uip_connr->rto = uip_connr->timer = UIP_RTO;
\r
1304 uip_connr->sa = 0;
\r
1305 uip_connr->sv = 4;
\r
1306 uip_connr->nrtx = 0;
\r
1307 uip_connr->lport = BUF->destport;
\r
1308 uip_connr->rport = BUF->srcport;
\r
1309 uip_ipaddr_copy(uip_connr->ripaddr, BUF->srcipaddr);
\r
1310 uip_connr->tcpstateflags = UIP_SYN_RCVD;
\r
1312 uip_connr->snd_nxt[0] = iss[0];
\r
1313 uip_connr->snd_nxt[1] = iss[1];
\r
1314 uip_connr->snd_nxt[2] = iss[2];
\r
1315 uip_connr->snd_nxt[3] = iss[3];
\r
1316 uip_connr->len = 1;
\r
1318 /* rcv_nxt should be the seqno from the incoming packet + 1. */
\r
1319 uip_connr->rcv_nxt[3] = BUF->seqno[3];
\r
1320 uip_connr->rcv_nxt[2] = BUF->seqno[2];
\r
1321 uip_connr->rcv_nxt[1] = BUF->seqno[1];
\r
1322 uip_connr->rcv_nxt[0] = BUF->seqno[0];
\r
1323 uip_add_rcv_nxt(1);
\r
1325 /* Parse the TCP MSS option, if present. */
\r
1326 if((BUF->tcpoffset & 0xf0) > 0x50) {
\r
1327 for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
\r
1328 opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c];
\r
1329 if(opt == TCP_OPT_END) {
\r
1330 /* End of options. */
\r
1332 } else if(opt == TCP_OPT_NOOP) {
\r
1335 } else if(opt == TCP_OPT_MSS &&
\r
1336 uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
\r
1337 /* An MSS option with the right option length. */
\r
1338 tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
\r
1339 (u16_t)uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c];
\r
1340 uip_connr->initialmss = uip_connr->mss =
\r
1341 tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
\r
1343 /* And we are done processing options. */
\r
1346 /* All other options have a length field, so that we easily
\r
1347 can skip past them. */
\r
1348 if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
\r
1349 /* If the length field is zero, the options are malformed
\r
1350 and we don't process them further. */
\r
1353 c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
\r
1358 /* Our response will be a SYNACK. */
\r
1359 #if UIP_ACTIVE_OPEN
\r
1361 BUF->flags = TCP_ACK;
\r
1364 BUF->flags |= TCP_SYN;
\r
1365 #else /* UIP_ACTIVE_OPEN */
\r
1367 BUF->flags = TCP_SYN | TCP_ACK;
\r
1368 #endif /* UIP_ACTIVE_OPEN */
\r
1370 /* We send out the TCP Maximum Segment Size option with our
\r
1372 BUF->optdata[0] = TCP_OPT_MSS;
\r
1373 BUF->optdata[1] = TCP_OPT_MSS_LEN;
\r
1374 BUF->optdata[2] = (UIP_TCP_MSS) / 256;
\r
1375 BUF->optdata[3] = (UIP_TCP_MSS) & 255;
\r
1376 uip_len = UIP_IPTCPH_LEN + TCP_OPT_MSS_LEN;
\r
1377 BUF->tcpoffset = ((UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4) << 4;
\r
1380 /* This label will be jumped to if we found an active connection. */
\r
1382 uip_conn = uip_connr;
\r
1384 /* We do a very naive form of TCP reset processing; we just accept
\r
1385 any RST and kill our connection. We should in fact check if the
\r
1386 sequence number of this reset is wihtin our advertised window
\r
1387 before we accept the reset. */
\r
1388 if(BUF->flags & TCP_RST) {
\r
1389 uip_connr->tcpstateflags = UIP_CLOSED;
\r
1390 UIP_LOG("tcp: got reset, aborting connection.");
\r
1391 uip_flags = UIP_ABORT;
\r
1395 /* Calculated the length of the data, if the application has sent
\r
1396 any data to us. */
\r
1397 c = (BUF->tcpoffset >> 4) << 2;
\r
1398 /* uip_len will contain the length of the actual TCP data. This is
\r
1399 calculated by subtracing the length of the TCP header (in
\r
1400 c) and the length of the IP header (20 bytes). */
\r
1401 uip_len = uip_len - c - UIP_IPH_LEN;
\r
1403 /* First, check if the sequence number of the incoming packet is
\r
1404 what we're expecting next. If not, we send out an ACK with the
\r
1405 correct numbers in. */
\r
1406 if(!(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) &&
\r
1407 ((BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)))) {
\r
1408 if((uip_len > 0 || ((BUF->flags & (TCP_SYN | TCP_FIN)) != 0)) &&
\r
1409 (BUF->seqno[0] != uip_connr->rcv_nxt[0] ||
\r
1410 BUF->seqno[1] != uip_connr->rcv_nxt[1] ||
\r
1411 BUF->seqno[2] != uip_connr->rcv_nxt[2] ||
\r
1412 BUF->seqno[3] != uip_connr->rcv_nxt[3])) {
\r
1413 goto tcp_send_ack;
\r
1417 /* Next, check if the incoming segment acknowledges any outstanding
\r
1418 data. If so, we update the sequence number, reset the length of
\r
1419 the outstanding data, calculate RTT estimations, and reset the
\r
1420 retransmission timer. */
\r
1421 if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) {
\r
1422 uip_add32(uip_connr->snd_nxt, uip_connr->len);
\r
1424 if(BUF->ackno[0] == uip_acc32[0] &&
\r
1425 BUF->ackno[1] == uip_acc32[1] &&
\r
1426 BUF->ackno[2] == uip_acc32[2] &&
\r
1427 BUF->ackno[3] == uip_acc32[3]) {
\r
1428 /* Update sequence number. */
\r
1429 uip_connr->snd_nxt[0] = uip_acc32[0];
\r
1430 uip_connr->snd_nxt[1] = uip_acc32[1];
\r
1431 uip_connr->snd_nxt[2] = uip_acc32[2];
\r
1432 uip_connr->snd_nxt[3] = uip_acc32[3];
\r
1435 /* Do RTT estimation, unless we have done retransmissions. */
\r
1436 if(uip_connr->nrtx == 0) {
\r
1438 m = uip_connr->rto - uip_connr->timer;
\r
1439 /* This is taken directly from VJs original code in his paper */
\r
1440 m = m - (uip_connr->sa >> 3);
\r
1441 uip_connr->sa += m;
\r
1445 m = m - (uip_connr->sv >> 2);
\r
1446 uip_connr->sv += m;
\r
1447 uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv;
\r
1450 /* Set the acknowledged flag. */
\r
1451 uip_flags = UIP_ACKDATA;
\r
1452 /* Reset the retransmission timer. */
\r
1453 uip_connr->timer = uip_connr->rto;
\r
1455 /* Reset length of outstanding data. */
\r
1456 uip_connr->len = 0;
\r
1461 /* Do different things depending on in what state the connection is. */
\r
1462 switch(uip_connr->tcpstateflags & UIP_TS_MASK) {
\r
1463 /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not
\r
1464 implemented, since we force the application to close when the
\r
1465 peer sends a FIN (hence the application goes directly from
\r
1466 ESTABLISHED to LAST_ACK). */
\r
1467 case UIP_SYN_RCVD:
\r
1468 /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and
\r
1469 we are waiting for an ACK that acknowledges the data we sent
\r
1470 out the last time. Therefore, we want to have the UIP_ACKDATA
\r
1471 flag set. If so, we enter the ESTABLISHED state. */
\r
1472 if(uip_flags & UIP_ACKDATA) {
\r
1473 uip_connr->tcpstateflags = UIP_ESTABLISHED;
\r
1474 uip_flags = UIP_CONNECTED;
\r
1475 uip_connr->len = 0;
\r
1477 uip_flags |= UIP_NEWDATA;
\r
1478 uip_add_rcv_nxt(uip_len);
\r
1485 #if UIP_ACTIVE_OPEN
\r
1486 case UIP_SYN_SENT:
\r
1487 /* In SYN_SENT, we wait for a SYNACK that is sent in response to
\r
1488 our SYN. The rcv_nxt is set to sequence number in the SYNACK
\r
1489 plus one, and we send an ACK. We move into the ESTABLISHED
\r
1491 if((uip_flags & UIP_ACKDATA) &&
\r
1492 (BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)) {
\r
1494 /* Parse the TCP MSS option, if present. */
\r
1495 if((BUF->tcpoffset & 0xf0) > 0x50) {
\r
1496 for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
\r
1497 opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c];
\r
1498 if(opt == TCP_OPT_END) {
\r
1499 /* End of options. */
\r
1501 } else if(opt == TCP_OPT_NOOP) {
\r
1504 } else if(opt == TCP_OPT_MSS &&
\r
1505 uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
\r
1506 /* An MSS option with the right option length. */
\r
1507 tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
\r
1508 uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c];
\r
1509 uip_connr->initialmss =
\r
1510 uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
\r
1512 /* And we are done processing options. */
\r
1515 /* All other options have a length field, so that we easily
\r
1516 can skip past them. */
\r
1517 if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
\r
1518 /* If the length field is zero, the options are malformed
\r
1519 and we don't process them further. */
\r
1522 c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
\r
1526 uip_connr->tcpstateflags = UIP_ESTABLISHED;
\r
1527 uip_connr->rcv_nxt[0] = BUF->seqno[0];
\r
1528 uip_connr->rcv_nxt[1] = BUF->seqno[1];
\r
1529 uip_connr->rcv_nxt[2] = BUF->seqno[2];
\r
1530 uip_connr->rcv_nxt[3] = BUF->seqno[3];
\r
1531 uip_add_rcv_nxt(1);
\r
1532 uip_flags = UIP_CONNECTED | UIP_NEWDATA;
\r
1533 uip_connr->len = 0;
\r
1539 /* Inform the application that the connection failed */
\r
1540 uip_flags = UIP_ABORT;
\r
1542 /* The connection is closed after we send the RST */
\r
1543 uip_conn->tcpstateflags = UIP_CLOSED;
\r
1545 #endif /* UIP_ACTIVE_OPEN */
\r
1547 case UIP_ESTABLISHED:
\r
1548 /* In the ESTABLISHED state, we call upon the application to feed
\r
1549 data into the uip_buf. If the UIP_ACKDATA flag is set, the
\r
1550 application should put new data into the buffer, otherwise we are
\r
1551 retransmitting an old segment, and the application should put that
\r
1552 data into the buffer.
\r
1554 If the incoming packet is a FIN, we should close the connection on
\r
1555 this side as well, and we send out a FIN and enter the LAST_ACK
\r
1556 state. We require that there is no outstanding data; otherwise the
\r
1557 sequence numbers will be screwed up. */
\r
1559 if(BUF->flags & TCP_FIN && !(uip_connr->tcpstateflags & UIP_STOPPED)) {
\r
1560 if(uip_outstanding(uip_connr)) {
\r
1563 uip_add_rcv_nxt(1 + uip_len);
\r
1564 uip_flags |= UIP_CLOSE;
\r
1566 uip_flags |= UIP_NEWDATA;
\r
1569 uip_connr->len = 1;
\r
1570 uip_connr->tcpstateflags = UIP_LAST_ACK;
\r
1571 uip_connr->nrtx = 0;
\r
1573 BUF->flags = TCP_FIN | TCP_ACK;
\r
1574 goto tcp_send_nodata;
\r
1577 /* Check the URG flag. If this is set, the segment carries urgent
\r
1578 data that we must pass to the application. */
\r
1579 if((BUF->flags & TCP_URG) != 0) {
\r
1580 #if UIP_URGDATA > 0
\r
1581 uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1];
\r
1582 if(uip_urglen > uip_len) {
\r
1583 /* There is more urgent data in the next segment to come. */
\r
1584 uip_urglen = uip_len;
\r
1586 uip_add_rcv_nxt(uip_urglen);
\r
1587 uip_len -= uip_urglen;
\r
1588 uip_urgdata = uip_appdata;
\r
1589 uip_appdata += uip_urglen;
\r
1592 #else /* UIP_URGDATA > 0 */
\r
1593 uip_appdata = ((char *)uip_appdata) + ((BUF->urgp[0] << 8) | BUF->urgp[1]);
\r
1594 uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1];
\r
1595 #endif /* UIP_URGDATA > 0 */
\r
1598 /* If uip_len > 0 we have TCP data in the packet, and we flag this
\r
1599 by setting the UIP_NEWDATA flag and update the sequence number
\r
1600 we acknowledge. If the application has stopped the dataflow
\r
1601 using uip_stop(), we must not accept any data packets from the
\r
1603 if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) {
\r
1604 uip_flags |= UIP_NEWDATA;
\r
1605 uip_add_rcv_nxt(uip_len);
\r
1608 /* Check if the available buffer space advertised by the other end
\r
1609 is smaller than the initial MSS for this connection. If so, we
\r
1610 set the current MSS to the window size to ensure that the
\r
1611 application does not send more data than the other end can
\r
1614 If the remote host advertises a zero window, we set the MSS to
\r
1615 the initial MSS so that the application will send an entire MSS
\r
1616 of data. This data will not be acknowledged by the receiver,
\r
1617 and the application will retransmit it. This is called the
\r
1618 "persistent timer" and uses the retransmission mechanim.
\r
1620 tmp16 = ((u16_t)BUF->wnd[0] << 8) + (u16_t)BUF->wnd[1];
\r
1621 if(tmp16 > uip_connr->initialmss ||
\r
1623 tmp16 = uip_connr->initialmss;
\r
1625 uip_connr->mss = tmp16;
\r
1627 /* If this packet constitutes an ACK for outstanding data (flagged
\r
1628 by the UIP_ACKDATA flag, we should call the application since it
\r
1629 might want to send more data. If the incoming packet had data
\r
1630 from the peer (as flagged by the UIP_NEWDATA flag), the
\r
1631 application must also be notified.
\r
1633 When the application is called, the global variable uip_len
\r
1634 contains the length of the incoming data. The application can
\r
1635 access the incoming data through the global pointer
\r
1636 uip_appdata, which usually points UIP_IPTCPH_LEN + UIP_LLH_LEN
\r
1637 bytes into the uip_buf array.
\r
1639 If the application wishes to send any data, this data should be
\r
1640 put into the uip_appdata and the length of the data should be
\r
1641 put into uip_len. If the application don't have any data to
\r
1642 send, uip_len must be set to 0. */
\r
1643 if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) {
\r
1649 if(uip_flags & UIP_ABORT) {
\r
1651 uip_connr->tcpstateflags = UIP_CLOSED;
\r
1652 BUF->flags = TCP_RST | TCP_ACK;
\r
1653 goto tcp_send_nodata;
\r
1656 if(uip_flags & UIP_CLOSE) {
\r
1658 uip_connr->len = 1;
\r
1659 uip_connr->tcpstateflags = UIP_FIN_WAIT_1;
\r
1660 uip_connr->nrtx = 0;
\r
1661 BUF->flags = TCP_FIN | TCP_ACK;
\r
1662 goto tcp_send_nodata;
\r
1665 /* If uip_slen > 0, the application has data to be sent. */
\r
1666 if(uip_slen > 0) {
\r
1668 /* If the connection has acknowledged data, the contents of
\r
1669 the ->len variable should be discarded. */
\r
1670 if((uip_flags & UIP_ACKDATA) != 0) {
\r
1671 uip_connr->len = 0;
\r
1674 /* If the ->len variable is non-zero the connection has
\r
1675 already data in transit and cannot send anymore right
\r
1677 if(uip_connr->len == 0) {
\r
1679 /* The application cannot send more than what is allowed by
\r
1680 the mss (the minumum of the MSS and the available
\r
1682 if(uip_slen > uip_connr->mss) {
\r
1683 uip_slen = uip_connr->mss;
\r
1686 /* Remember how much data we send out now so that we know
\r
1687 when everything has been acknowledged. */
\r
1688 uip_connr->len = uip_slen;
\r
1691 /* If the application already had unacknowledged data, we
\r
1692 make sure that the application does not send (i.e.,
\r
1693 retransmit) out more than it previously sent out. */
\r
1694 uip_slen = uip_connr->len;
\r
1697 uip_connr->nrtx = 0;
\r
1699 uip_appdata = uip_sappdata;
\r
1701 /* If the application has data to be sent, or if the incoming
\r
1702 packet had new data in it, we must send out a packet. */
\r
1703 if(uip_slen > 0 && uip_connr->len > 0) {
\r
1704 /* Add the length of the IP and TCP headers. */
\r
1705 uip_len = uip_connr->len + UIP_TCPIP_HLEN;
\r
1706 /* We always set the ACK flag in response packets. */
\r
1707 BUF->flags = TCP_ACK | TCP_PSH;
\r
1708 /* Send the packet. */
\r
1709 goto tcp_send_noopts;
\r
1711 /* If there is no data to send, just send out a pure ACK if
\r
1712 there is newdata. */
\r
1713 if(uip_flags & UIP_NEWDATA) {
\r
1714 uip_len = UIP_TCPIP_HLEN;
\r
1715 BUF->flags = TCP_ACK;
\r
1716 goto tcp_send_noopts;
\r
1720 case UIP_LAST_ACK:
\r
1721 /* We can close this connection if the peer has acknowledged our
\r
1722 FIN. This is indicated by the UIP_ACKDATA flag. */
\r
1723 if(uip_flags & UIP_ACKDATA) {
\r
1724 uip_connr->tcpstateflags = UIP_CLOSED;
\r
1725 uip_flags = UIP_CLOSE;
\r
1730 case UIP_FIN_WAIT_1:
\r
1731 /* The application has closed the connection, but the remote host
\r
1732 hasn't closed its end yet. Thus we do nothing but wait for a
\r
1733 FIN from the other side. */
\r
1735 uip_add_rcv_nxt(uip_len);
\r
1737 if(BUF->flags & TCP_FIN) {
\r
1738 if(uip_flags & UIP_ACKDATA) {
\r
1739 uip_connr->tcpstateflags = UIP_TIME_WAIT;
\r
1740 uip_connr->timer = 0;
\r
1741 uip_connr->len = 0;
\r
1743 uip_connr->tcpstateflags = UIP_CLOSING;
\r
1745 uip_add_rcv_nxt(1);
\r
1746 uip_flags = UIP_CLOSE;
\r
1748 goto tcp_send_ack;
\r
1749 } else if(uip_flags & UIP_ACKDATA) {
\r
1750 uip_connr->tcpstateflags = UIP_FIN_WAIT_2;
\r
1751 uip_connr->len = 0;
\r
1755 goto tcp_send_ack;
\r
1759 case UIP_FIN_WAIT_2:
\r
1761 uip_add_rcv_nxt(uip_len);
\r
1763 if(BUF->flags & TCP_FIN) {
\r
1764 uip_connr->tcpstateflags = UIP_TIME_WAIT;
\r
1765 uip_connr->timer = 0;
\r
1766 uip_add_rcv_nxt(1);
\r
1767 uip_flags = UIP_CLOSE;
\r
1769 goto tcp_send_ack;
\r
1772 goto tcp_send_ack;
\r
1776 case UIP_TIME_WAIT:
\r
1777 goto tcp_send_ack;
\r
1780 if(uip_flags & UIP_ACKDATA) {
\r
1781 uip_connr->tcpstateflags = UIP_TIME_WAIT;
\r
1782 uip_connr->timer = 0;
\r
1788 /* We jump here when we are ready to send the packet, and just want
\r
1789 to set the appropriate TCP sequence numbers in the TCP header. */
\r
1791 BUF->flags = TCP_ACK;
\r
1793 uip_len = UIP_IPTCPH_LEN;
\r
1795 BUF->tcpoffset = (UIP_TCPH_LEN / 4) << 4;
\r
1797 /* We're done with the input processing. We are now ready to send a
\r
1798 reply. Our job is to fill in all the fields of the TCP and IP
\r
1799 headers before calculating the checksum and finally send the
\r
1801 BUF->ackno[0] = uip_connr->rcv_nxt[0];
\r
1802 BUF->ackno[1] = uip_connr->rcv_nxt[1];
\r
1803 BUF->ackno[2] = uip_connr->rcv_nxt[2];
\r
1804 BUF->ackno[3] = uip_connr->rcv_nxt[3];
\r
1806 BUF->seqno[0] = uip_connr->snd_nxt[0];
\r
1807 BUF->seqno[1] = uip_connr->snd_nxt[1];
\r
1808 BUF->seqno[2] = uip_connr->snd_nxt[2];
\r
1809 BUF->seqno[3] = uip_connr->snd_nxt[3];
\r
1811 BUF->proto = UIP_PROTO_TCP;
\r
1813 BUF->srcport = uip_connr->lport;
\r
1814 BUF->destport = uip_connr->rport;
\r
1816 uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
\r
1817 uip_ipaddr_copy(BUF->destipaddr, uip_connr->ripaddr);
\r
1819 if(uip_connr->tcpstateflags & UIP_STOPPED) {
\r
1820 /* If the connection has issued uip_stop(), we advertise a zero
\r
1821 window so that the remote host will stop sending data. */
\r
1822 BUF->wnd[0] = BUF->wnd[1] = 0;
\r
1824 BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8);
\r
1825 BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff);
\r
1829 BUF->ttl = UIP_TTL;
\r
1831 /* For IPv6, the IP length field does not include the IPv6 IP header
\r
1833 BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
\r
1834 BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
\r
1835 #else /* UIP_CONF_IPV6 */
\r
1836 BUF->len[0] = (uip_len >> 8);
\r
1837 BUF->len[1] = (uip_len & 0xff);
\r
1838 #endif /* UIP_CONF_IPV6 */
\r
1840 BUF->urgp[0] = BUF->urgp[1] = 0;
\r
1842 /* Calculate TCP checksum. */
\r
1843 BUF->tcpchksum = 0;
\r
1844 BUF->tcpchksum = ~(uip_tcpchksum());
\r
1850 BUF->tcflow = 0x00;
\r
1852 #else /* UIP_CONF_IPV6 */
\r
1855 BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
\r
1857 BUF->ipid[0] = ipid >> 8;
\r
1858 BUF->ipid[1] = ipid & 0xff;
\r
1859 /* Calculate IP checksum. */
\r
1860 BUF->ipchksum = 0;
\r
1861 BUF->ipchksum = ~(uip_ipchksum());
\r
1862 DEBUG_PRINTF("uip ip_send_nolen: chkecum 0x%04x\n", uip_ipchksum());
\r
1863 #endif /* UIP_CONF_IPV6 */
\r
1865 UIP_STAT(++uip_stat.tcp.sent);
\r
1867 DEBUG_PRINTF("Sending packet with length %d (%d)\n", uip_len,
\r
1868 (BUF->len[0] << 8) | BUF->len[1]);
\r
1870 UIP_STAT(++uip_stat.ip.sent);
\r
1871 /* Return and let the caller do the actual transmission. */
\r
1879 /*---------------------------------------------------------------------------*/
\r
1883 return HTONS(val);
\r
1885 /*---------------------------------------------------------------------------*/
\r
1887 uip_send(const void *data, int len)
\r
1891 if(data != uip_sappdata) {
\r
1892 memcpy(uip_sappdata, (data), uip_slen);
\r