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
140 #pragma data_alignment=4
\r
141 u8_t uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains incoming packets. */
\r
143 u8_t uip_buf[UIP_BUFSIZE + 2] ALIGN_STRUCT_END; /* The packet buffer that contains incoming packets. */
\r
146 #endif /* UIP_CONF_EXTERNAL_BUFFER */
\r
148 void *uip_appdata; /* The uip_appdata pointer points to
\r
149 application data. */
\r
150 void *uip_sappdata; /* The uip_appdata pointer points to
\r
151 the application data which is to
\r
153 #if UIP_URGDATA > 0
\r
154 void *uip_urgdata; /* The uip_urgdata pointer points to
\r
155 urgent data (out-of-band data), if
\r
157 u16_t uip_urglen, uip_surglen;
\r
158 #endif /* UIP_URGDATA > 0 */
\r
160 u16_t uip_len, uip_slen;
\r
161 /* The uip_len is either 8 or 16 bits,
\r
162 depending on the maximum packet
\r
165 u8_t uip_flags; /* The uip_flags variable is used for
\r
166 communication between the TCP/IP stack
\r
167 and the application program. */
\r
168 struct uip_conn *uip_conn; /* uip_conn always points to the current
\r
171 struct uip_conn uip_conns[UIP_CONNS];
\r
172 /* The uip_conns array holds all TCP
\r
174 u16_t uip_listenports[UIP_LISTENPORTS];
\r
175 /* The uip_listenports list all currently
\r
178 struct uip_udp_conn *uip_udp_conn;
\r
179 struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
\r
180 #endif /* UIP_UDP */
\r
182 static u16_t ipid; /* Ths ipid variable is an increasing
\r
183 number that is used for the IP ID
\r
186 void uip_setipid(u16_t id) { ipid = id; }
\r
188 static u8_t iss[4]; /* The iss variable is used for the TCP
\r
189 initial sequence number. */
\r
191 #if UIP_ACTIVE_OPEN
\r
192 static u16_t lastport; /* Keeps track of the last port used for
\r
193 a new connection. */
\r
194 #endif /* UIP_ACTIVE_OPEN */
\r
196 /* Temporary variables. */
\r
198 static u8_t c, opt;
\r
199 static u16_t tmp16;
\r
201 /* Structures and definitions. */
\r
202 #define TCP_FIN 0x01
\r
203 #define TCP_SYN 0x02
\r
204 #define TCP_RST 0x04
\r
205 #define TCP_PSH 0x08
\r
206 #define TCP_ACK 0x10
\r
207 #define TCP_URG 0x20
\r
208 #define TCP_CTL 0x3f
\r
210 #define TCP_OPT_END 0 /* End of TCP options list */
\r
211 #define TCP_OPT_NOOP 1 /* "No-operation" TCP option */
\r
212 #define TCP_OPT_MSS 2 /* Maximum segment size TCP option */
\r
214 #define TCP_OPT_MSS_LEN 4 /* Length of TCP MSS option. */
\r
216 #define ICMP_ECHO_REPLY 0
\r
217 #define ICMP_ECHO 8
\r
219 #define ICMP6_ECHO_REPLY 129
\r
220 #define ICMP6_ECHO 128
\r
221 #define ICMP6_NEIGHBOR_SOLICITATION 135
\r
222 #define ICMP6_NEIGHBOR_ADVERTISEMENT 136
\r
224 #define ICMP6_FLAG_S (1 << 6)
\r
226 #define ICMP6_OPTION_SOURCE_LINK_ADDRESS 1
\r
227 #define ICMP6_OPTION_TARGET_LINK_ADDRESS 2
\r
231 #define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
\r
232 #define FBUF ((struct uip_tcpip_hdr *)&uip_reassbuf[0])
\r
233 #define ICMPBUF ((struct uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN])
\r
234 #define UDPBUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])
\r
237 #if UIP_STATISTICS == 1
\r
238 struct uip_stats uip_stat;
\r
239 #define UIP_STAT(s) s
\r
241 #define UIP_STAT(s)
\r
242 #endif /* UIP_STATISTICS == 1 */
\r
244 #if UIP_LOGGING == 1
\r
246 void uip_log(char *msg);
\r
247 #define UIP_LOG(m) uip_log(m)
\r
250 #endif /* UIP_LOGGING == 1 */
\r
252 #if ! UIP_ARCH_ADD32
\r
254 uip_add32(u8_t *op32, u16_t op16)
\r
256 uip_acc32[3] = op32[3] + (op16 & 0xff);
\r
257 uip_acc32[2] = op32[2] + (op16 >> 8);
\r
258 uip_acc32[1] = op32[1];
\r
259 uip_acc32[0] = op32[0];
\r
261 if(uip_acc32[2] < (op16 >> 8)) {
\r
263 if(uip_acc32[1] == 0) {
\r
269 if(uip_acc32[3] < (op16 & 0xff)) {
\r
271 if(uip_acc32[2] == 0) {
\r
273 if(uip_acc32[1] == 0) {
\r
280 #endif /* UIP_ARCH_ADD32 */
\r
282 #if ! UIP_ARCH_CHKSUM
\r
283 /*---------------------------------------------------------------------------*/
\r
285 chksum(u16_t sum, const u8_t *data, u16_t len)
\r
288 const u8_t *dataptr;
\r
289 const u8_t *last_byte;
\r
292 last_byte = data + len - 1;
\r
294 while(dataptr < last_byte) { /* At least two more bytes */
\r
295 t = (dataptr[0] << 8) + dataptr[1];
\r
303 if(dataptr == last_byte) {
\r
304 t = (dataptr[0] << 8) + 0;
\r
311 /* Return sum in host byte order. */
\r
314 /*---------------------------------------------------------------------------*/
\r
316 uip_chksum(u16_t *data, u16_t len)
\r
318 return htons(chksum(0, (u8_t *)data, len));
\r
320 /*---------------------------------------------------------------------------*/
\r
321 #ifndef UIP_ARCH_IPCHKSUM
\r
327 sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN);
\r
328 DEBUG_PRINTF("uip_ipchksum: sum 0x%04x\n", sum);
\r
329 return (sum == 0) ? 0xffff : htons(sum);
\r
332 /*---------------------------------------------------------------------------*/
\r
334 upper_layer_chksum(u8_t proto)
\r
336 u16_t upper_layer_len;
\r
340 upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]);
\r
341 #else /* UIP_CONF_IPV6 */
\r
342 upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN;
\r
343 #endif /* UIP_CONF_IPV6 */
\r
345 /* First sum pseudoheader. */
\r
347 /* IP protocol and length fields. This addition cannot carry. */
\r
348 sum = upper_layer_len + proto;
\r
349 /* Sum IP source and destination addresses. */
\r
350 sum = chksum(sum, (u8_t *)&BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t));
\r
352 /* Sum TCP header and data. */
\r
353 sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN],
\r
356 return (sum == 0) ? 0xffff : htons(sum);
\r
358 /*---------------------------------------------------------------------------*/
\r
361 uip_icmp6chksum(void)
\r
363 return upper_layer_chksum(UIP_PROTO_ICMP6);
\r
366 #endif /* UIP_CONF_IPV6 */
\r
367 /*---------------------------------------------------------------------------*/
\r
369 uip_tcpchksum(void)
\r
371 return upper_layer_chksum(UIP_PROTO_TCP);
\r
373 /*---------------------------------------------------------------------------*/
\r
374 #if UIP_UDP_CHECKSUMS
\r
376 uip_udpchksum(void)
\r
378 return upper_layer_chksum(UIP_PROTO_UDP);
\r
380 #endif /* UIP_UDP_CHECKSUMS */
\r
381 #endif /* UIP_ARCH_CHKSUM */
\r
382 /*---------------------------------------------------------------------------*/
\r
386 for(c = 0; c < UIP_LISTENPORTS; ++c) {
\r
387 uip_listenports[c] = 0;
\r
389 for(c = 0; c < UIP_CONNS; ++c) {
\r
390 uip_conns[c].tcpstateflags = UIP_CLOSED;
\r
392 #if UIP_ACTIVE_OPEN
\r
394 #endif /* UIP_ACTIVE_OPEN */
\r
397 for(c = 0; c < UIP_UDP_CONNS; ++c) {
\r
398 uip_udp_conns[c].lport = 0;
\r
400 #endif /* UIP_UDP */
\r
403 /* IPv4 initialization. */
\r
404 #if UIP_FIXEDADDR == 0
\r
405 /* uip_hostaddr[0] = uip_hostaddr[1] = 0;*/
\r
406 #endif /* UIP_FIXEDADDR */
\r
409 /*---------------------------------------------------------------------------*/
\r
410 #if UIP_ACTIVE_OPEN
\r
412 uip_connect(uip_ipaddr_t *ripaddr, u16_t rport)
\r
414 register struct uip_conn *conn, *cconn;
\r
416 /* Find an unused local port. */
\r
420 if(lastport >= 32000) {
\r
424 /* Check if this port is already in use, and if so try to find
\r
426 for(c = 0; c < UIP_CONNS; ++c) {
\r
427 conn = &uip_conns[c];
\r
428 if(conn->tcpstateflags != UIP_CLOSED &&
\r
429 conn->lport == htons(lastport)) {
\r
435 for(c = 0; c < UIP_CONNS; ++c) {
\r
436 cconn = &uip_conns[c];
\r
437 if(cconn->tcpstateflags == UIP_CLOSED) {
\r
441 if(cconn->tcpstateflags == UIP_TIME_WAIT) {
\r
443 cconn->timer > conn->timer) {
\r
453 conn->tcpstateflags = UIP_SYN_SENT;
\r
455 conn->snd_nxt[0] = iss[0];
\r
456 conn->snd_nxt[1] = iss[1];
\r
457 conn->snd_nxt[2] = iss[2];
\r
458 conn->snd_nxt[3] = iss[3];
\r
460 conn->initialmss = conn->mss = UIP_TCP_MSS;
\r
462 conn->len = 1; /* TCP length of the SYN is one. */
\r
464 conn->timer = 1; /* Send the SYN next time around. */
\r
465 conn->rto = UIP_RTO;
\r
467 conn->sv = 16; /* Initial value of the RTT variance. */
\r
468 conn->lport = htons(lastport);
\r
469 conn->rport = rport;
\r
470 uip_ipaddr_copy(&conn->ripaddr, ripaddr);
\r
474 #endif /* UIP_ACTIVE_OPEN */
\r
475 /*---------------------------------------------------------------------------*/
\r
477 struct uip_udp_conn *
\r
478 uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport)
\r
480 register struct uip_udp_conn *conn;
\r
482 /* Find an unused local port. */
\r
486 if(lastport >= 32000) {
\r
490 for(c = 0; c < UIP_UDP_CONNS; ++c) {
\r
491 if(uip_udp_conns[c].lport == htons(lastport)) {
\r
498 for(c = 0; c < UIP_UDP_CONNS; ++c) {
\r
499 if(uip_udp_conns[c].lport == 0) {
\r
500 conn = &uip_udp_conns[c];
\r
509 conn->lport = HTONS(lastport);
\r
510 conn->rport = rport;
\r
511 if(ripaddr == NULL) {
\r
512 memset(conn->ripaddr, 0, sizeof(uip_ipaddr_t));
\r
514 uip_ipaddr_copy(&conn->ripaddr, ripaddr);
\r
516 conn->ttl = UIP_TTL;
\r
520 #endif /* UIP_UDP */
\r
521 /*---------------------------------------------------------------------------*/
\r
523 uip_unlisten(u16_t port)
\r
525 for(c = 0; c < UIP_LISTENPORTS; ++c) {
\r
526 if(uip_listenports[c] == port) {
\r
527 uip_listenports[c] = 0;
\r
532 /*---------------------------------------------------------------------------*/
\r
534 uip_listen(u16_t port)
\r
536 for(c = 0; c < UIP_LISTENPORTS; ++c) {
\r
537 if(uip_listenports[c] == 0) {
\r
538 uip_listenports[c] = port;
\r
543 /*---------------------------------------------------------------------------*/
\r
544 /* XXX: IP fragment reassembly: not well-tested. */
\r
546 #if UIP_REASSEMBLY && !UIP_CONF_IPV6
\r
547 #define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN)
\r
548 static u8_t uip_reassbuf[UIP_REASS_BUFSIZE];
\r
549 static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)];
\r
550 static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f,
\r
551 0x0f, 0x07, 0x03, 0x01};
\r
552 static u16_t uip_reasslen;
\r
553 static u8_t uip_reassflags;
\r
554 #define UIP_REASS_FLAG_LASTFRAG 0x01
\r
555 static u8_t uip_reasstmr;
\r
565 /* If ip_reasstmr is zero, no packet is present in the buffer, so we
\r
566 write the IP header of the fragment into the reassembly
\r
567 buffer. The timer is updated with the maximum age. */
\r
568 if(uip_reasstmr == 0) {
\r
569 memcpy(uip_reassbuf, &BUF->vhl, UIP_IPH_LEN);
\r
570 uip_reasstmr = UIP_REASS_MAXAGE;
\r
571 uip_reassflags = 0;
\r
572 /* Clear the bitmap. */
\r
573 memset(uip_reassbitmap, 0, sizeof(uip_reassbitmap));
\r
576 /* Check if the incoming fragment matches the one currently present
\r
577 in the reasembly buffer. If so, we proceed with copying the
\r
578 fragment into the buffer. */
\r
579 if(BUF->srcipaddr[0] == FBUF->srcipaddr[0] &&
\r
580 BUF->srcipaddr[1] == FBUF->srcipaddr[1] &&
\r
581 BUF->destipaddr[0] == FBUF->destipaddr[0] &&
\r
582 BUF->destipaddr[1] == FBUF->destipaddr[1] &&
\r
583 BUF->ipid[0] == FBUF->ipid[0] &&
\r
584 BUF->ipid[1] == FBUF->ipid[1]) {
\r
586 len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4;
\r
587 offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8;
\r
589 /* If the offset or the offset + fragment length overflows the
\r
590 reassembly buffer, we discard the entire packet. */
\r
591 if(offset > UIP_REASS_BUFSIZE ||
\r
592 offset + len > UIP_REASS_BUFSIZE) {
\r
597 /* Copy the fragment into the reassembly buffer, at the right
\r
599 memcpy(&uip_reassbuf[UIP_IPH_LEN + offset],
\r
600 (char *)BUF + (int)((BUF->vhl & 0x0f) * 4),
\r
603 /* Update the bitmap. */
\r
604 if(offset / (8 * 8) == (offset + len) / (8 * 8)) {
\r
605 /* If the two endpoints are in the same byte, we only update
\r
608 uip_reassbitmap[offset / (8 * 8)] |=
\r
609 bitmap_bits[(offset / 8 ) & 7] &
\r
610 ~bitmap_bits[((offset + len) / 8 ) & 7];
\r
612 /* If the two endpoints are in different bytes, we update the
\r
613 bytes in the endpoints and fill the stuff inbetween with
\r
615 uip_reassbitmap[offset / (8 * 8)] |=
\r
616 bitmap_bits[(offset / 8 ) & 7];
\r
617 for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) {
\r
618 uip_reassbitmap[i] = 0xff;
\r
620 uip_reassbitmap[(offset + len) / (8 * 8)] |=
\r
621 ~bitmap_bits[((offset + len) / 8 ) & 7];
\r
624 /* If this fragment has the More Fragments flag set to zero, we
\r
625 know that this is the last fragment, so we can calculate the
\r
626 size of the entire packet. We also set the
\r
627 IP_REASS_FLAG_LASTFRAG flag to indicate that we have received
\r
628 the final fragment. */
\r
630 if((BUF->ipoffset[0] & IP_MF) == 0) {
\r
631 uip_reassflags |= UIP_REASS_FLAG_LASTFRAG;
\r
632 uip_reasslen = offset + len;
\r
635 /* Finally, we check if we have a full packet in the buffer. We do
\r
636 this by checking if we have the last fragment and if all bits
\r
637 in the bitmap are set. */
\r
638 if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) {
\r
639 /* Check all bytes up to and including all but the last byte in
\r
641 for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) {
\r
642 if(uip_reassbitmap[i] != 0xff) {
\r
646 /* Check the last byte in the bitmap. It should contain just the
\r
647 right amount of bits. */
\r
648 if(uip_reassbitmap[uip_reasslen / (8 * 8)] !=
\r
649 (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) {
\r
653 /* If we have come this far, we have a full packet in the
\r
654 buffer, so we allocate a pbuf and copy the packet into it. We
\r
655 also reset the timer. */
\r
657 memcpy(BUF, FBUF, uip_reasslen);
\r
659 /* Pretend to be a "normal" (i.e., not fragmented) IP packet
\r
661 BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
\r
662 BUF->len[0] = uip_reasslen >> 8;
\r
663 BUF->len[1] = uip_reasslen & 0xff;
\r
665 BUF->ipchksum = ~(uip_ipchksum());
\r
667 return uip_reasslen;
\r
674 #endif /* UIP_REASSEMBLY */
\r
675 /*---------------------------------------------------------------------------*/
\r
677 uip_add_rcv_nxt(u16_t n)
\r
679 uip_add32(uip_conn->rcv_nxt, n);
\r
680 uip_conn->rcv_nxt[0] = uip_acc32[0];
\r
681 uip_conn->rcv_nxt[1] = uip_acc32[1];
\r
682 uip_conn->rcv_nxt[2] = uip_acc32[2];
\r
683 uip_conn->rcv_nxt[3] = uip_acc32[3];
\r
685 /*---------------------------------------------------------------------------*/
\r
687 uip_process(u8_t flag)
\r
689 register struct uip_conn *uip_connr = uip_conn;
\r
692 if(flag == UIP_UDP_SEND_CONN) {
\r
695 #endif /* UIP_UDP */
\r
697 uip_sappdata = uip_appdata = &uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN];
\r
699 /* Check if we were invoked because of a poll request for a
\r
700 particular connection. */
\r
701 if(flag == UIP_POLL_REQUEST) {
\r
702 if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED &&
\r
703 !uip_outstanding(uip_connr)) {
\r
704 uip_flags = UIP_POLL;
\r
710 /* Check if we were invoked because of the perodic timer fireing. */
\r
711 } else if(flag == UIP_TIMER) {
\r
713 if(uip_reasstmr != 0) {
\r
716 #endif /* UIP_REASSEMBLY */
\r
717 /* Increase the initial sequence number. */
\r
718 if(++iss[3] == 0) {
\r
719 if(++iss[2] == 0) {
\r
720 if(++iss[1] == 0) {
\r
726 /* Reset the length variables. */
\r
730 /* Check if the connection is in a state in which we simply wait
\r
731 for the connection to time out. If so, we increase the
\r
732 connection's timer and remove the connection if it times
\r
734 if(uip_connr->tcpstateflags == UIP_TIME_WAIT ||
\r
735 uip_connr->tcpstateflags == UIP_FIN_WAIT_2) {
\r
736 ++(uip_connr->timer);
\r
737 if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) {
\r
738 uip_connr->tcpstateflags = UIP_CLOSED;
\r
740 } else if(uip_connr->tcpstateflags != UIP_CLOSED) {
\r
741 /* If the connection has outstanding data, we increase the
\r
742 connection's timer and see if it has reached the RTO value
\r
743 in which case we retransmit. */
\r
744 if(uip_outstanding(uip_connr)) {
\r
745 uip_connr->timer = uip_connr->timer - 1;
\r
746 if(uip_connr->timer == 0) {
\r
747 if(uip_connr->nrtx == UIP_MAXRTX ||
\r
748 ((uip_connr->tcpstateflags == UIP_SYN_SENT ||
\r
749 uip_connr->tcpstateflags == UIP_SYN_RCVD) &&
\r
750 uip_connr->nrtx == UIP_MAXSYNRTX)) {
\r
751 uip_connr->tcpstateflags = UIP_CLOSED;
\r
753 /* We call UIP_APPCALL() with uip_flags set to
\r
754 UIP_TIMEDOUT to inform the application that the
\r
755 connection has timed out. */
\r
756 uip_flags = UIP_TIMEDOUT;
\r
759 /* We also send a reset packet to the remote host. */
\r
760 BUF->flags = TCP_RST | TCP_ACK;
\r
761 goto tcp_send_nodata;
\r
764 /* Exponential backoff. */
\r
765 uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4?
\r
768 ++(uip_connr->nrtx);
\r
770 /* Ok, so we need to retransmit. We do this differently
\r
771 depending on which state we are in. In ESTABLISHED, we
\r
772 call upon the application so that it may prepare the
\r
773 data for the retransmit. In SYN_RCVD, we resend the
\r
774 SYNACK that we sent earlier and in LAST_ACK we have to
\r
775 retransmit our FINACK. */
\r
776 UIP_STAT(++uip_stat.tcp.rexmit);
\r
777 switch(uip_connr->tcpstateflags & UIP_TS_MASK) {
\r
779 /* In the SYN_RCVD state, we should retransmit our
\r
781 goto tcp_send_synack;
\r
783 #if UIP_ACTIVE_OPEN
\r
785 /* In the SYN_SENT state, we retransmit out SYN. */
\r
788 #endif /* UIP_ACTIVE_OPEN */
\r
790 case UIP_ESTABLISHED:
\r
791 /* In the ESTABLISHED state, we call upon the application
\r
792 to do the actual retransmit after which we jump into
\r
793 the code for sending out the packet (the apprexmit
\r
795 uip_flags = UIP_REXMIT;
\r
799 case UIP_FIN_WAIT_1:
\r
802 /* In all these states we should retransmit a FINACK. */
\r
803 goto tcp_send_finack;
\r
807 } else if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) {
\r
808 /* If there was no need for a retransmission, we poll the
\r
809 application for new data. */
\r
810 uip_flags = UIP_POLL;
\r
818 if(flag == UIP_UDP_TIMER) {
\r
819 if(uip_udp_conn->lport != 0) {
\r
821 uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
\r
822 uip_len = uip_slen = 0;
\r
823 uip_flags = UIP_POLL;
\r
832 /* This is where the input processing starts. */
\r
833 UIP_STAT(++uip_stat.ip.recv);
\r
835 /* Start of IP input header processing code. */
\r
838 /* Check validity of the IP header. */
\r
839 if((BUF->vtc & 0xf0) != 0x60) { /* IP version and header length. */
\r
840 UIP_STAT(++uip_stat.ip.drop);
\r
841 UIP_STAT(++uip_stat.ip.vhlerr);
\r
842 UIP_LOG("ipv6: invalid version.");
\r
845 #else /* UIP_CONF_IPV6 */
\r
846 /* Check validity of the IP header. */
\r
847 if(BUF->vhl != 0x45) { /* IP version and header length. */
\r
848 UIP_STAT(++uip_stat.ip.drop);
\r
849 UIP_STAT(++uip_stat.ip.vhlerr);
\r
850 UIP_LOG("ip: invalid version or header length.");
\r
853 #endif /* UIP_CONF_IPV6 */
\r
855 /* Check the size of the packet. If the size reported to us in
\r
856 uip_len is smaller the size reported in the IP header, we assume
\r
857 that the packet has been corrupted in transit. If the size of
\r
858 uip_len is larger than the size reported in the IP packet header,
\r
859 the packet has been padded and we set uip_len to the correct
\r
862 if((BUF->len[0] << 8) + BUF->len[1] <= uip_len) {
\r
863 uip_len = (BUF->len[0] << 8) + BUF->len[1];
\r
865 uip_len += 40; /* The length reported in the IPv6 header is the
\r
866 length of the payload that follows the
\r
867 header. However, uIP uses the uip_len variable
\r
868 for holding the size of the entire packet,
\r
869 including the IP header. For IPv4 this is not a
\r
870 problem as the length field in the IPv4 header
\r
871 contains the length of the entire packet. But
\r
872 for IPv6 we need to add the size of the IPv6
\r
873 header (40 bytes). */
\r
874 #endif /* UIP_CONF_IPV6 */
\r
876 UIP_LOG("ip: packet shorter than reported in IP header.");
\r
881 /* Check the fragment flag. */
\r
882 if((BUF->ipoffset[0] & 0x3f) != 0 ||
\r
883 BUF->ipoffset[1] != 0) {
\r
885 uip_len = uip_reass();
\r
889 #else /* UIP_REASSEMBLY */
\r
890 UIP_STAT(++uip_stat.ip.drop);
\r
891 UIP_STAT(++uip_stat.ip.fragerr);
\r
892 UIP_LOG("ip: fragment dropped.");
\r
894 #endif /* UIP_REASSEMBLY */
\r
896 #endif /* UIP_CONF_IPV6 */
\r
898 if(uip_ipaddr_cmp(uip_hostaddr, all_zeroes_addr)) {
\r
899 /* If we are configured to use ping IP address configuration and
\r
900 hasn't been assigned an IP address yet, we accept all ICMP
\r
902 #if UIP_PINGADDRCONF && !UIP_CONF_IPV6
\r
903 if(BUF->proto == UIP_PROTO_ICMP) {
\r
904 UIP_LOG("ip: possible ping config packet received.");
\r
907 UIP_LOG("ip: packet dropped since no address assigned.");
\r
910 #endif /* UIP_PINGADDRCONF */
\r
913 /* If IP broadcast support is configured, we check for a broadcast
\r
914 UDP packet, which may be destined to us. */
\r
916 DEBUG_PRINTF("UDP IP checksum 0x%04x\n", uip_ipchksum());
\r
917 if(BUF->proto == UIP_PROTO_UDP &&
\r
918 uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr)
\r
920 uip_ipchksum() == 0xffff*/) {
\r
923 #endif /* UIP_BROADCAST */
\r
925 /* Check if the packet is destined for our IP address. */
\r
927 if(!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr)) {
\r
928 UIP_STAT(++uip_stat.ip.drop);
\r
931 #else /* UIP_CONF_IPV6 */
\r
932 /* For IPv6, packet reception is a little trickier as we need to
\r
933 make sure that we listen to certain multicast addresses (all
\r
934 hosts multicast address, and the solicited-node multicast
\r
935 address) as well. However, we will cheat here and accept all
\r
936 multicast packets that are sent to the ff02::/16 addresses. */
\r
937 if(!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr) &&
\r
938 BUF->destipaddr[0] != HTONS(0xff02)) {
\r
939 UIP_STAT(++uip_stat.ip.drop);
\r
942 #endif /* UIP_CONF_IPV6 */
\r
946 if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header
\r
948 UIP_STAT(++uip_stat.ip.drop);
\r
949 UIP_STAT(++uip_stat.ip.chkerr);
\r
950 UIP_LOG("ip: bad checksum.");
\r
953 #endif /* UIP_CONF_IPV6 */
\r
955 if(BUF->proto == UIP_PROTO_TCP) { /* Check for TCP packet. If so,
\r
956 proceed with TCP input
\r
962 if(BUF->proto == UIP_PROTO_UDP) {
\r
965 #endif /* UIP_UDP */
\r
968 /* ICMPv4 processing code follows. */
\r
969 if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from
\r
971 UIP_STAT(++uip_stat.ip.drop);
\r
972 UIP_STAT(++uip_stat.ip.protoerr);
\r
973 UIP_LOG("ip: neither tcp nor icmp.");
\r
977 #if UIP_PINGADDRCONF
\r
979 #endif /* UIP_PINGADDRCONF */
\r
980 UIP_STAT(++uip_stat.icmp.recv);
\r
982 /* ICMP echo (i.e., ping) processing. This is simple, we only change
\r
983 the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP
\r
984 checksum before we return the packet. */
\r
985 if(ICMPBUF->type != ICMP_ECHO) {
\r
986 UIP_STAT(++uip_stat.icmp.drop);
\r
987 UIP_STAT(++uip_stat.icmp.typeerr);
\r
988 UIP_LOG("icmp: not icmp echo.");
\r
992 /* If we are configured to use ping IP address assignment, we use
\r
993 the destination IP address of this ping packet and assign it to
\r
995 #if UIP_PINGADDRCONF
\r
996 if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) {
\r
997 uip_hostaddr[0] = BUF->destipaddr[0];
\r
998 uip_hostaddr[1] = BUF->destipaddr[1];
\r
1000 #endif /* UIP_PINGADDRCONF */
\r
1002 ICMPBUF->type = ICMP_ECHO_REPLY;
\r
1004 if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) {
\r
1005 ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1;
\r
1007 ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8);
\r
1010 /* Swap IP addresses. */
\r
1011 uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
\r
1012 uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
\r
1014 UIP_STAT(++uip_stat.icmp.sent);
\r
1017 /* End of IPv4 input header processing code. */
\r
1018 #else /* !UIP_CONF_IPV6 */
\r
1020 /* This is IPv6 ICMPv6 processing code. */
\r
1021 DEBUG_PRINTF("icmp6_input: length %d\n", uip_len);
\r
1023 if(BUF->proto != UIP_PROTO_ICMP6) { /* We only allow ICMPv6 packets from
\r
1025 UIP_STAT(++uip_stat.ip.drop);
\r
1026 UIP_STAT(++uip_stat.ip.protoerr);
\r
1027 UIP_LOG("ip: neither tcp nor icmp6.");
\r
1031 UIP_STAT(++uip_stat.icmp.recv);
\r
1033 /* If we get a neighbor solicitation for our address we should send
\r
1034 a neighbor advertisement message back. */
\r
1035 if(ICMPBUF->type == ICMP6_NEIGHBOR_SOLICITATION) {
\r
1036 if(uip_ipaddr_cmp(ICMPBUF->icmp6data, uip_hostaddr)) {
\r
1038 if(ICMPBUF->options[0] == ICMP6_OPTION_SOURCE_LINK_ADDRESS) {
\r
1039 /* Save the sender's address in our neighbor list. */
\r
1040 uip_neighbor_add(ICMPBUF->srcipaddr, &(ICMPBUF->options[2]));
\r
1043 /* We should now send a neighbor advertisement back to where the
\r
1044 neighbor solicication came from. */
\r
1045 ICMPBUF->type = ICMP6_NEIGHBOR_ADVERTISEMENT;
\r
1046 ICMPBUF->flags = ICMP6_FLAG_S; /* Solicited flag. */
\r
1048 ICMPBUF->reserved1 = ICMPBUF->reserved2 = ICMPBUF->reserved3 = 0;
\r
1050 uip_ipaddr_copy(ICMPBUF->destipaddr, ICMPBUF->srcipaddr);
\r
1051 uip_ipaddr_copy(ICMPBUF->srcipaddr, uip_hostaddr);
\r
1052 ICMPBUF->options[0] = ICMP6_OPTION_TARGET_LINK_ADDRESS;
\r
1053 ICMPBUF->options[1] = 1; /* Options length, 1 = 8 bytes. */
\r
1054 memcpy(&(ICMPBUF->options[2]), &uip_ethaddr, sizeof(uip_ethaddr));
\r
1055 ICMPBUF->icmpchksum = 0;
\r
1056 ICMPBUF->icmpchksum = ~uip_icmp6chksum();
\r
1061 } else if(ICMPBUF->type == ICMP6_ECHO) {
\r
1062 /* ICMP echo (i.e., ping) processing. This is simple, we only
\r
1063 change the ICMP type from ECHO to ECHO_REPLY and update the
\r
1064 ICMP checksum before we return the packet. */
\r
1066 ICMPBUF->type = ICMP6_ECHO_REPLY;
\r
1068 uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
\r
1069 uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
\r
1070 ICMPBUF->icmpchksum = 0;
\r
1071 ICMPBUF->icmpchksum = ~uip_icmp6chksum();
\r
1073 UIP_STAT(++uip_stat.icmp.sent);
\r
1076 DEBUG_PRINTF("Unknown icmp6 message type %d\n", ICMPBUF->type);
\r
1077 UIP_STAT(++uip_stat.icmp.drop);
\r
1078 UIP_STAT(++uip_stat.icmp.typeerr);
\r
1079 UIP_LOG("icmp: unknown ICMP message.");
\r
1083 /* End of IPv6 ICMP processing. */
\r
1085 #endif /* !UIP_CONF_IPV6 */
\r
1088 /* UDP input processing. */
\r
1090 /* UDP processing is really just a hack. We don't do anything to the
\r
1091 UDP/IP headers, but let the UDP application do all the hard
\r
1092 work. If the application sets uip_slen, it has a packet to
\r
1094 #if UIP_UDP_CHECKSUMS
\r
1095 uip_len = uip_len - UIP_IPUDPH_LEN;
\r
1096 uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
\r
1097 if(UDPBUF->udpchksum != 0 && uip_udpchksum() != 0xffff) {
\r
1098 UIP_STAT(++uip_stat.udp.drop);
\r
1099 UIP_STAT(++uip_stat.udp.chkerr);
\r
1100 UIP_LOG("udp: bad checksum.");
\r
1103 #else /* UIP_UDP_CHECKSUMS */
\r
1104 uip_len = uip_len - UIP_IPUDPH_LEN;
\r
1105 #endif /* UIP_UDP_CHECKSUMS */
\r
1107 /* Demultiplex this UDP packet between the UDP "connections". */
\r
1108 for(uip_udp_conn = &uip_udp_conns[0];
\r
1109 uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS];
\r
1111 /* If the local UDP port is non-zero, the connection is considered
\r
1112 to be used. If so, the local port number is checked against the
\r
1113 destination port number in the received packet. If the two port
\r
1114 numbers match, the remote port number is checked if the
\r
1115 connection is bound to a remote port. Finally, if the
\r
1116 connection is bound to a remote IP address, the source IP
\r
1117 address of the packet is checked. */
\r
1118 if(uip_udp_conn->lport != 0 &&
\r
1119 UDPBUF->destport == uip_udp_conn->lport &&
\r
1120 (uip_udp_conn->rport == 0 ||
\r
1121 UDPBUF->srcport == uip_udp_conn->rport) &&
\r
1122 (uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) ||
\r
1123 uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) ||
\r
1124 uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr))) {
\r
1128 UIP_LOG("udp: no matching connection found");
\r
1132 UIP_STAT(++uip_stat.udp.recv);
\r
1134 uip_flags = UIP_NEWDATA;
\r
1135 uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
\r
1137 UIP_UDP_APPCALL();
\r
1139 if(uip_slen == 0) {
\r
1142 uip_len = uip_slen + UIP_IPUDPH_LEN;
\r
1145 /* For IPv6, the IP length field does not include the IPv6 IP header
\r
1147 BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
\r
1148 BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
\r
1149 #else /* UIP_CONF_IPV6 */
\r
1150 BUF->len[0] = (uip_len >> 8);
\r
1151 BUF->len[1] = (uip_len & 0xff);
\r
1152 #endif /* UIP_CONF_IPV6 */
\r
1154 BUF->ttl = uip_udp_conn->ttl;
\r
1155 BUF->proto = UIP_PROTO_UDP;
\r
1157 UDPBUF->udplen = HTONS(uip_slen + UIP_UDPH_LEN);
\r
1158 UDPBUF->udpchksum = 0;
\r
1160 BUF->srcport = uip_udp_conn->lport;
\r
1161 BUF->destport = uip_udp_conn->rport;
\r
1163 uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
\r
1164 uip_ipaddr_copy(BUF->destipaddr, uip_udp_conn->ripaddr);
\r
1166 uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN];
\r
1168 #if UIP_UDP_CHECKSUMS
\r
1169 /* Calculate UDP checksum. */
\r
1170 UDPBUF->udpchksum = ~(uip_udpchksum());
\r
1171 if(UDPBUF->udpchksum == 0) {
\r
1172 UDPBUF->udpchksum = 0xffff;
\r
1174 #endif /* UIP_UDP_CHECKSUMS */
\r
1175 UIP_STAT(++uip_stat.udp.sent);
\r
1176 goto ip_send_nolen;
\r
1177 #endif /* UIP_UDP */
\r
1179 /* TCP input processing. */
\r
1181 UIP_STAT(++uip_stat.tcp.recv);
\r
1183 /* Start of TCP input header processing code. */
\r
1185 if(uip_tcpchksum() != 0xffff) { /* Compute and check the TCP
\r
1187 UIP_STAT(++uip_stat.tcp.drop);
\r
1188 UIP_STAT(++uip_stat.tcp.chkerr);
\r
1189 UIP_LOG("tcp: bad checksum.");
\r
1194 /* Demultiplex this segment. */
\r
1195 /* First check any active connections. */
\r
1196 for(uip_connr = &uip_conns[0]; uip_connr <= &uip_conns[UIP_CONNS - 1];
\r
1198 if(uip_connr->tcpstateflags != UIP_CLOSED &&
\r
1199 BUF->destport == uip_connr->lport &&
\r
1200 BUF->srcport == uip_connr->rport &&
\r
1201 uip_ipaddr_cmp(BUF->srcipaddr, uip_connr->ripaddr)) {
\r
1206 /* If we didn't find and active connection that expected the packet,
\r
1207 either this packet is an old duplicate, or this is a SYN packet
\r
1208 destined for a connection in LISTEN. If the SYN flag isn't set,
\r
1209 it is an old packet and we send a RST. */
\r
1210 if((BUF->flags & TCP_CTL) != TCP_SYN) {
\r
1214 tmp16 = BUF->destport;
\r
1215 /* Next, check listening connections. */
\r
1216 for(c = 0; c < UIP_LISTENPORTS; ++c) {
\r
1217 if(tmp16 == uip_listenports[c])
\r
1218 goto found_listen;
\r
1221 /* No matching connection found, so we send a RST packet. */
\r
1222 UIP_STAT(++uip_stat.tcp.synrst);
\r
1225 /* We do not send resets in response to resets. */
\r
1226 if(BUF->flags & TCP_RST) {
\r
1230 UIP_STAT(++uip_stat.tcp.rst);
\r
1232 BUF->flags = TCP_RST | TCP_ACK;
\r
1233 uip_len = UIP_IPTCPH_LEN;
\r
1234 BUF->tcpoffset = 5 << 4;
\r
1236 /* Flip the seqno and ackno fields in the TCP header. */
\r
1237 c = BUF->seqno[3];
\r
1238 BUF->seqno[3] = BUF->ackno[3];
\r
1239 BUF->ackno[3] = c;
\r
1241 c = BUF->seqno[2];
\r
1242 BUF->seqno[2] = BUF->ackno[2];
\r
1243 BUF->ackno[2] = c;
\r
1245 c = BUF->seqno[1];
\r
1246 BUF->seqno[1] = BUF->ackno[1];
\r
1247 BUF->ackno[1] = c;
\r
1249 c = BUF->seqno[0];
\r
1250 BUF->seqno[0] = BUF->ackno[0];
\r
1251 BUF->ackno[0] = c;
\r
1253 /* We also have to increase the sequence number we are
\r
1254 acknowledging. If the least significant byte overflowed, we need
\r
1255 to propagate the carry to the other bytes as well. */
\r
1256 if(++BUF->ackno[3] == 0) {
\r
1257 if(++BUF->ackno[2] == 0) {
\r
1258 if(++BUF->ackno[1] == 0) {
\r
1264 /* Swap port numbers. */
\r
1265 tmp16 = BUF->srcport;
\r
1266 BUF->srcport = BUF->destport;
\r
1267 BUF->destport = tmp16;
\r
1269 /* Swap IP addresses. */
\r
1270 uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
\r
1271 uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
\r
1273 /* And send out the RST packet! */
\r
1274 goto tcp_send_noconn;
\r
1276 /* This label will be jumped to if we matched the incoming packet
\r
1277 with a connection in LISTEN. In that case, we should create a new
\r
1278 connection and send a SYNACK in return. */
\r
1280 /* First we check if there are any connections avaliable. Unused
\r
1281 connections are kept in the same table as used connections, but
\r
1282 unused ones have the tcpstate set to CLOSED. Also, connections in
\r
1283 TIME_WAIT are kept track of and we'll use the oldest one if no
\r
1284 CLOSED connections are found. Thanks to Eddie C. Dost for a very
\r
1285 nice algorithm for the TIME_WAIT search. */
\r
1287 for(c = 0; c < UIP_CONNS; ++c) {
\r
1288 if(uip_conns[c].tcpstateflags == UIP_CLOSED) {
\r
1289 uip_connr = &uip_conns[c];
\r
1292 if(uip_conns[c].tcpstateflags == UIP_TIME_WAIT) {
\r
1293 if(uip_connr == 0 ||
\r
1294 uip_conns[c].timer > uip_connr->timer) {
\r
1295 uip_connr = &uip_conns[c];
\r
1300 if(uip_connr == 0) {
\r
1301 /* All connections are used already, we drop packet and hope that
\r
1302 the remote end will retransmit the packet at a time when we
\r
1303 have more spare connections. */
\r
1304 UIP_STAT(++uip_stat.tcp.syndrop);
\r
1305 UIP_LOG("tcp: found no unused connections.");
\r
1308 uip_conn = uip_connr;
\r
1310 /* Fill in the necessary fields for the new connection. */
\r
1311 uip_connr->rto = uip_connr->timer = UIP_RTO;
\r
1312 uip_connr->sa = 0;
\r
1313 uip_connr->sv = 4;
\r
1314 uip_connr->nrtx = 0;
\r
1315 uip_connr->lport = BUF->destport;
\r
1316 uip_connr->rport = BUF->srcport;
\r
1317 uip_ipaddr_copy(uip_connr->ripaddr, BUF->srcipaddr);
\r
1318 uip_connr->tcpstateflags = UIP_SYN_RCVD;
\r
1320 uip_connr->snd_nxt[0] = iss[0];
\r
1321 uip_connr->snd_nxt[1] = iss[1];
\r
1322 uip_connr->snd_nxt[2] = iss[2];
\r
1323 uip_connr->snd_nxt[3] = iss[3];
\r
1324 uip_connr->len = 1;
\r
1326 /* rcv_nxt should be the seqno from the incoming packet + 1. */
\r
1327 uip_connr->rcv_nxt[3] = BUF->seqno[3];
\r
1328 uip_connr->rcv_nxt[2] = BUF->seqno[2];
\r
1329 uip_connr->rcv_nxt[1] = BUF->seqno[1];
\r
1330 uip_connr->rcv_nxt[0] = BUF->seqno[0];
\r
1331 uip_add_rcv_nxt(1);
\r
1333 /* Parse the TCP MSS option, if present. */
\r
1334 if((BUF->tcpoffset & 0xf0) > 0x50) {
\r
1335 for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
\r
1336 opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c];
\r
1337 if(opt == TCP_OPT_END) {
\r
1338 /* End of options. */
\r
1340 } else if(opt == TCP_OPT_NOOP) {
\r
1343 } else if(opt == TCP_OPT_MSS &&
\r
1344 uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
\r
1345 /* An MSS option with the right option length. */
\r
1346 tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
\r
1347 (u16_t)uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c];
\r
1348 uip_connr->initialmss = uip_connr->mss =
\r
1349 tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
\r
1351 /* And we are done processing options. */
\r
1354 /* All other options have a length field, so that we easily
\r
1355 can skip past them. */
\r
1356 if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
\r
1357 /* If the length field is zero, the options are malformed
\r
1358 and we don't process them further. */
\r
1361 c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
\r
1366 /* Our response will be a SYNACK. */
\r
1367 #if UIP_ACTIVE_OPEN
\r
1369 BUF->flags = TCP_ACK;
\r
1372 BUF->flags |= TCP_SYN;
\r
1373 #else /* UIP_ACTIVE_OPEN */
\r
1375 BUF->flags = TCP_SYN | TCP_ACK;
\r
1376 #endif /* UIP_ACTIVE_OPEN */
\r
1378 /* We send out the TCP Maximum Segment Size option with our
\r
1380 BUF->optdata[0] = TCP_OPT_MSS;
\r
1381 BUF->optdata[1] = TCP_OPT_MSS_LEN;
\r
1382 BUF->optdata[2] = (UIP_TCP_MSS) / 256;
\r
1383 BUF->optdata[3] = (UIP_TCP_MSS) & 255;
\r
1384 uip_len = UIP_IPTCPH_LEN + TCP_OPT_MSS_LEN;
\r
1385 BUF->tcpoffset = ((UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4) << 4;
\r
1388 /* This label will be jumped to if we found an active connection. */
\r
1390 uip_conn = uip_connr;
\r
1392 /* We do a very naive form of TCP reset processing; we just accept
\r
1393 any RST and kill our connection. We should in fact check if the
\r
1394 sequence number of this reset is wihtin our advertised window
\r
1395 before we accept the reset. */
\r
1396 if(BUF->flags & TCP_RST) {
\r
1397 uip_connr->tcpstateflags = UIP_CLOSED;
\r
1398 UIP_LOG("tcp: got reset, aborting connection.");
\r
1399 uip_flags = UIP_ABORT;
\r
1403 /* Calculated the length of the data, if the application has sent
\r
1404 any data to us. */
\r
1405 c = (BUF->tcpoffset >> 4) << 2;
\r
1406 /* uip_len will contain the length of the actual TCP data. This is
\r
1407 calculated by subtracing the length of the TCP header (in
\r
1408 c) and the length of the IP header (20 bytes). */
\r
1409 uip_len = uip_len - c - UIP_IPH_LEN;
\r
1411 /* First, check if the sequence number of the incoming packet is
\r
1412 what we're expecting next. If not, we send out an ACK with the
\r
1413 correct numbers in. */
\r
1414 if(!(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) &&
\r
1415 ((BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)))) {
\r
1416 if((uip_len > 0 || ((BUF->flags & (TCP_SYN | TCP_FIN)) != 0)) &&
\r
1417 (BUF->seqno[0] != uip_connr->rcv_nxt[0] ||
\r
1418 BUF->seqno[1] != uip_connr->rcv_nxt[1] ||
\r
1419 BUF->seqno[2] != uip_connr->rcv_nxt[2] ||
\r
1420 BUF->seqno[3] != uip_connr->rcv_nxt[3])) {
\r
1421 goto tcp_send_ack;
\r
1425 /* Next, check if the incoming segment acknowledges any outstanding
\r
1426 data. If so, we update the sequence number, reset the length of
\r
1427 the outstanding data, calculate RTT estimations, and reset the
\r
1428 retransmission timer. */
\r
1429 if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) {
\r
1430 uip_add32(uip_connr->snd_nxt, uip_connr->len);
\r
1432 if(BUF->ackno[0] == uip_acc32[0] &&
\r
1433 BUF->ackno[1] == uip_acc32[1] &&
\r
1434 BUF->ackno[2] == uip_acc32[2] &&
\r
1435 BUF->ackno[3] == uip_acc32[3]) {
\r
1436 /* Update sequence number. */
\r
1437 uip_connr->snd_nxt[0] = uip_acc32[0];
\r
1438 uip_connr->snd_nxt[1] = uip_acc32[1];
\r
1439 uip_connr->snd_nxt[2] = uip_acc32[2];
\r
1440 uip_connr->snd_nxt[3] = uip_acc32[3];
\r
1443 /* Do RTT estimation, unless we have done retransmissions. */
\r
1444 if(uip_connr->nrtx == 0) {
\r
1446 m = uip_connr->rto - uip_connr->timer;
\r
1447 /* This is taken directly from VJs original code in his paper */
\r
1448 m = m - (uip_connr->sa >> 3);
\r
1449 uip_connr->sa += m;
\r
1453 m = m - (uip_connr->sv >> 2);
\r
1454 uip_connr->sv += m;
\r
1455 uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv;
\r
1458 /* Set the acknowledged flag. */
\r
1459 uip_flags = UIP_ACKDATA;
\r
1460 /* Reset the retransmission timer. */
\r
1461 uip_connr->timer = uip_connr->rto;
\r
1463 /* Reset length of outstanding data. */
\r
1464 uip_connr->len = 0;
\r
1469 /* Do different things depending on in what state the connection is. */
\r
1470 switch(uip_connr->tcpstateflags & UIP_TS_MASK) {
\r
1471 /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not
\r
1472 implemented, since we force the application to close when the
\r
1473 peer sends a FIN (hence the application goes directly from
\r
1474 ESTABLISHED to LAST_ACK). */
\r
1475 case UIP_SYN_RCVD:
\r
1476 /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and
\r
1477 we are waiting for an ACK that acknowledges the data we sent
\r
1478 out the last time. Therefore, we want to have the UIP_ACKDATA
\r
1479 flag set. If so, we enter the ESTABLISHED state. */
\r
1480 if(uip_flags & UIP_ACKDATA) {
\r
1481 uip_connr->tcpstateflags = UIP_ESTABLISHED;
\r
1482 uip_flags = UIP_CONNECTED;
\r
1483 uip_connr->len = 0;
\r
1485 uip_flags |= UIP_NEWDATA;
\r
1486 uip_add_rcv_nxt(uip_len);
\r
1493 #if UIP_ACTIVE_OPEN
\r
1494 case UIP_SYN_SENT:
\r
1495 /* In SYN_SENT, we wait for a SYNACK that is sent in response to
\r
1496 our SYN. The rcv_nxt is set to sequence number in the SYNACK
\r
1497 plus one, and we send an ACK. We move into the ESTABLISHED
\r
1499 if((uip_flags & UIP_ACKDATA) &&
\r
1500 (BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)) {
\r
1502 /* Parse the TCP MSS option, if present. */
\r
1503 if((BUF->tcpoffset & 0xf0) > 0x50) {
\r
1504 for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
\r
1505 opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c];
\r
1506 if(opt == TCP_OPT_END) {
\r
1507 /* End of options. */
\r
1509 } else if(opt == TCP_OPT_NOOP) {
\r
1512 } else if(opt == TCP_OPT_MSS &&
\r
1513 uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
\r
1514 /* An MSS option with the right option length. */
\r
1515 tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
\r
1516 uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c];
\r
1517 uip_connr->initialmss =
\r
1518 uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
\r
1520 /* And we are done processing options. */
\r
1523 /* All other options have a length field, so that we easily
\r
1524 can skip past them. */
\r
1525 if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
\r
1526 /* If the length field is zero, the options are malformed
\r
1527 and we don't process them further. */
\r
1530 c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
\r
1534 uip_connr->tcpstateflags = UIP_ESTABLISHED;
\r
1535 uip_connr->rcv_nxt[0] = BUF->seqno[0];
\r
1536 uip_connr->rcv_nxt[1] = BUF->seqno[1];
\r
1537 uip_connr->rcv_nxt[2] = BUF->seqno[2];
\r
1538 uip_connr->rcv_nxt[3] = BUF->seqno[3];
\r
1539 uip_add_rcv_nxt(1);
\r
1540 uip_flags = UIP_CONNECTED | UIP_NEWDATA;
\r
1541 uip_connr->len = 0;
\r
1547 /* Inform the application that the connection failed */
\r
1548 uip_flags = UIP_ABORT;
\r
1550 /* The connection is closed after we send the RST */
\r
1551 uip_conn->tcpstateflags = UIP_CLOSED;
\r
1553 #endif /* UIP_ACTIVE_OPEN */
\r
1555 case UIP_ESTABLISHED:
\r
1556 /* In the ESTABLISHED state, we call upon the application to feed
\r
1557 data into the uip_buf. If the UIP_ACKDATA flag is set, the
\r
1558 application should put new data into the buffer, otherwise we are
\r
1559 retransmitting an old segment, and the application should put that
\r
1560 data into the buffer.
\r
1562 If the incoming packet is a FIN, we should close the connection on
\r
1563 this side as well, and we send out a FIN and enter the LAST_ACK
\r
1564 state. We require that there is no outstanding data; otherwise the
\r
1565 sequence numbers will be screwed up. */
\r
1567 if(BUF->flags & TCP_FIN && !(uip_connr->tcpstateflags & UIP_STOPPED)) {
\r
1568 if(uip_outstanding(uip_connr)) {
\r
1571 uip_add_rcv_nxt(1 + uip_len);
\r
1572 uip_flags |= UIP_CLOSE;
\r
1574 uip_flags |= UIP_NEWDATA;
\r
1577 uip_connr->len = 1;
\r
1578 uip_connr->tcpstateflags = UIP_LAST_ACK;
\r
1579 uip_connr->nrtx = 0;
\r
1581 BUF->flags = TCP_FIN | TCP_ACK;
\r
1582 goto tcp_send_nodata;
\r
1585 /* Check the URG flag. If this is set, the segment carries urgent
\r
1586 data that we must pass to the application. */
\r
1587 if((BUF->flags & TCP_URG) != 0) {
\r
1588 #if UIP_URGDATA > 0
\r
1589 uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1];
\r
1590 if(uip_urglen > uip_len) {
\r
1591 /* There is more urgent data in the next segment to come. */
\r
1592 uip_urglen = uip_len;
\r
1594 uip_add_rcv_nxt(uip_urglen);
\r
1595 uip_len -= uip_urglen;
\r
1596 uip_urgdata = uip_appdata;
\r
1597 uip_appdata += uip_urglen;
\r
1600 #else /* UIP_URGDATA > 0 */
\r
1601 uip_appdata = ((char *)uip_appdata) + ((BUF->urgp[0] << 8) | BUF->urgp[1]);
\r
1602 uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1];
\r
1603 #endif /* UIP_URGDATA > 0 */
\r
1606 /* If uip_len > 0 we have TCP data in the packet, and we flag this
\r
1607 by setting the UIP_NEWDATA flag and update the sequence number
\r
1608 we acknowledge. If the application has stopped the dataflow
\r
1609 using uip_stop(), we must not accept any data packets from the
\r
1611 if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) {
\r
1612 uip_flags |= UIP_NEWDATA;
\r
1613 uip_add_rcv_nxt(uip_len);
\r
1616 /* Check if the available buffer space advertised by the other end
\r
1617 is smaller than the initial MSS for this connection. If so, we
\r
1618 set the current MSS to the window size to ensure that the
\r
1619 application does not send more data than the other end can
\r
1622 If the remote host advertises a zero window, we set the MSS to
\r
1623 the initial MSS so that the application will send an entire MSS
\r
1624 of data. This data will not be acknowledged by the receiver,
\r
1625 and the application will retransmit it. This is called the
\r
1626 "persistent timer" and uses the retransmission mechanim.
\r
1628 tmp16 = ((u16_t)BUF->wnd[0] << 8) + (u16_t)BUF->wnd[1];
\r
1629 if(tmp16 > uip_connr->initialmss ||
\r
1631 tmp16 = uip_connr->initialmss;
\r
1633 uip_connr->mss = tmp16;
\r
1635 /* If this packet constitutes an ACK for outstanding data (flagged
\r
1636 by the UIP_ACKDATA flag, we should call the application since it
\r
1637 might want to send more data. If the incoming packet had data
\r
1638 from the peer (as flagged by the UIP_NEWDATA flag), the
\r
1639 application must also be notified.
\r
1641 When the application is called, the global variable uip_len
\r
1642 contains the length of the incoming data. The application can
\r
1643 access the incoming data through the global pointer
\r
1644 uip_appdata, which usually points UIP_IPTCPH_LEN + UIP_LLH_LEN
\r
1645 bytes into the uip_buf array.
\r
1647 If the application wishes to send any data, this data should be
\r
1648 put into the uip_appdata and the length of the data should be
\r
1649 put into uip_len. If the application don't have any data to
\r
1650 send, uip_len must be set to 0. */
\r
1651 if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) {
\r
1657 if(uip_flags & UIP_ABORT) {
\r
1659 uip_connr->tcpstateflags = UIP_CLOSED;
\r
1660 BUF->flags = TCP_RST | TCP_ACK;
\r
1661 goto tcp_send_nodata;
\r
1664 if(uip_flags & UIP_CLOSE) {
\r
1666 uip_connr->len = 1;
\r
1667 uip_connr->tcpstateflags = UIP_FIN_WAIT_1;
\r
1668 uip_connr->nrtx = 0;
\r
1669 BUF->flags = TCP_FIN | TCP_ACK;
\r
1670 goto tcp_send_nodata;
\r
1673 /* If uip_slen > 0, the application has data to be sent. */
\r
1674 if(uip_slen > 0) {
\r
1676 /* If the connection has acknowledged data, the contents of
\r
1677 the ->len variable should be discarded. */
\r
1678 if((uip_flags & UIP_ACKDATA) != 0) {
\r
1679 uip_connr->len = 0;
\r
1682 /* If the ->len variable is non-zero the connection has
\r
1683 already data in transit and cannot send anymore right
\r
1685 if(uip_connr->len == 0) {
\r
1687 /* The application cannot send more than what is allowed by
\r
1688 the mss (the minumum of the MSS and the available
\r
1690 if(uip_slen > uip_connr->mss) {
\r
1691 uip_slen = uip_connr->mss;
\r
1694 /* Remember how much data we send out now so that we know
\r
1695 when everything has been acknowledged. */
\r
1696 uip_connr->len = uip_slen;
\r
1699 /* If the application already had unacknowledged data, we
\r
1700 make sure that the application does not send (i.e.,
\r
1701 retransmit) out more than it previously sent out. */
\r
1702 uip_slen = uip_connr->len;
\r
1705 uip_connr->nrtx = 0;
\r
1707 uip_appdata = uip_sappdata;
\r
1709 /* If the application has data to be sent, or if the incoming
\r
1710 packet had new data in it, we must send out a packet. */
\r
1711 if(uip_slen > 0 && uip_connr->len > 0) {
\r
1712 /* Add the length of the IP and TCP headers. */
\r
1713 uip_len = uip_connr->len + UIP_TCPIP_HLEN;
\r
1714 /* We always set the ACK flag in response packets. */
\r
1715 BUF->flags = TCP_ACK | TCP_PSH;
\r
1716 /* Send the packet. */
\r
1717 goto tcp_send_noopts;
\r
1719 /* If there is no data to send, just send out a pure ACK if
\r
1720 there is newdata. */
\r
1721 if(uip_flags & UIP_NEWDATA) {
\r
1722 uip_len = UIP_TCPIP_HLEN;
\r
1723 BUF->flags = TCP_ACK;
\r
1724 goto tcp_send_noopts;
\r
1728 case UIP_LAST_ACK:
\r
1729 /* We can close this connection if the peer has acknowledged our
\r
1730 FIN. This is indicated by the UIP_ACKDATA flag. */
\r
1731 if(uip_flags & UIP_ACKDATA) {
\r
1732 uip_connr->tcpstateflags = UIP_CLOSED;
\r
1733 uip_flags = UIP_CLOSE;
\r
1738 case UIP_FIN_WAIT_1:
\r
1739 /* The application has closed the connection, but the remote host
\r
1740 hasn't closed its end yet. Thus we do nothing but wait for a
\r
1741 FIN from the other side. */
\r
1743 uip_add_rcv_nxt(uip_len);
\r
1745 if(BUF->flags & TCP_FIN) {
\r
1746 if(uip_flags & UIP_ACKDATA) {
\r
1747 uip_connr->tcpstateflags = UIP_TIME_WAIT;
\r
1748 uip_connr->timer = 0;
\r
1749 uip_connr->len = 0;
\r
1751 uip_connr->tcpstateflags = UIP_CLOSING;
\r
1753 uip_add_rcv_nxt(1);
\r
1754 uip_flags = UIP_CLOSE;
\r
1756 goto tcp_send_ack;
\r
1757 } else if(uip_flags & UIP_ACKDATA) {
\r
1758 uip_connr->tcpstateflags = UIP_FIN_WAIT_2;
\r
1759 uip_connr->len = 0;
\r
1763 goto tcp_send_ack;
\r
1767 case UIP_FIN_WAIT_2:
\r
1769 uip_add_rcv_nxt(uip_len);
\r
1771 if(BUF->flags & TCP_FIN) {
\r
1772 uip_connr->tcpstateflags = UIP_TIME_WAIT;
\r
1773 uip_connr->timer = 0;
\r
1774 uip_add_rcv_nxt(1);
\r
1775 uip_flags = UIP_CLOSE;
\r
1777 goto tcp_send_ack;
\r
1780 goto tcp_send_ack;
\r
1784 case UIP_TIME_WAIT:
\r
1785 goto tcp_send_ack;
\r
1788 if(uip_flags & UIP_ACKDATA) {
\r
1789 uip_connr->tcpstateflags = UIP_TIME_WAIT;
\r
1790 uip_connr->timer = 0;
\r
1796 /* We jump here when we are ready to send the packet, and just want
\r
1797 to set the appropriate TCP sequence numbers in the TCP header. */
\r
1799 BUF->flags = TCP_ACK;
\r
1801 uip_len = UIP_IPTCPH_LEN;
\r
1803 BUF->tcpoffset = (UIP_TCPH_LEN / 4) << 4;
\r
1805 /* We're done with the input processing. We are now ready to send a
\r
1806 reply. Our job is to fill in all the fields of the TCP and IP
\r
1807 headers before calculating the checksum and finally send the
\r
1809 BUF->ackno[0] = uip_connr->rcv_nxt[0];
\r
1810 BUF->ackno[1] = uip_connr->rcv_nxt[1];
\r
1811 BUF->ackno[2] = uip_connr->rcv_nxt[2];
\r
1812 BUF->ackno[3] = uip_connr->rcv_nxt[3];
\r
1814 BUF->seqno[0] = uip_connr->snd_nxt[0];
\r
1815 BUF->seqno[1] = uip_connr->snd_nxt[1];
\r
1816 BUF->seqno[2] = uip_connr->snd_nxt[2];
\r
1817 BUF->seqno[3] = uip_connr->snd_nxt[3];
\r
1819 BUF->proto = UIP_PROTO_TCP;
\r
1821 BUF->srcport = uip_connr->lport;
\r
1822 BUF->destport = uip_connr->rport;
\r
1824 uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
\r
1825 uip_ipaddr_copy(BUF->destipaddr, uip_connr->ripaddr);
\r
1827 if(uip_connr->tcpstateflags & UIP_STOPPED) {
\r
1828 /* If the connection has issued uip_stop(), we advertise a zero
\r
1829 window so that the remote host will stop sending data. */
\r
1830 BUF->wnd[0] = BUF->wnd[1] = 0;
\r
1832 BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8);
\r
1833 BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff);
\r
1837 BUF->ttl = UIP_TTL;
\r
1839 /* For IPv6, the IP length field does not include the IPv6 IP header
\r
1841 BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
\r
1842 BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
\r
1843 #else /* UIP_CONF_IPV6 */
\r
1844 BUF->len[0] = (uip_len >> 8);
\r
1845 BUF->len[1] = (uip_len & 0xff);
\r
1846 #endif /* UIP_CONF_IPV6 */
\r
1848 BUF->urgp[0] = BUF->urgp[1] = 0;
\r
1850 /* Calculate TCP checksum. */
\r
1851 BUF->tcpchksum = 0;
\r
1852 BUF->tcpchksum = ~(uip_tcpchksum());
\r
1856 #endif /* UIP_UDP */
\r
1860 BUF->tcflow = 0x00;
\r
1862 #else /* UIP_CONF_IPV6 */
\r
1865 BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
\r
1867 BUF->ipid[0] = ipid >> 8;
\r
1868 BUF->ipid[1] = ipid & 0xff;
\r
1869 /* Calculate IP checksum. */
\r
1870 BUF->ipchksum = 0;
\r
1871 BUF->ipchksum = ~(uip_ipchksum());
\r
1872 DEBUG_PRINTF("uip ip_send_nolen: chkecum 0x%04x\n", uip_ipchksum());
\r
1873 #endif /* UIP_CONF_IPV6 */
\r
1875 UIP_STAT(++uip_stat.tcp.sent);
\r
1877 DEBUG_PRINTF("Sending packet with length %d (%d)\n", uip_len,
\r
1878 (BUF->len[0] << 8) | BUF->len[1]);
\r
1880 UIP_STAT(++uip_stat.ip.sent);
\r
1881 /* Return and let the caller do the actual transmission. */
\r
1889 /*---------------------------------------------------------------------------*/
\r
1893 return HTONS(val);
\r
1895 /*---------------------------------------------------------------------------*/
\r
1897 uip_send(const void *data, int len)
\r
1901 if(data != uip_sappdata) {
\r
1902 memcpy(uip_sappdata, (data), uip_slen);
\r