blob: 4e306e106e7954d12ecb99719251e6f014c35c1f [file] [log] [blame]
adamdunkelsca9ddcb2003-03-19 14:13:31 +00001/*
2 * Copyright (c) 2001-2002, Adam Dunkels.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Adam Dunkels.
16 * 4. The name of the author may not be used to endorse or promote
17 * products derived from this software without specific prior
18 * written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
21 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
24 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
26 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 * This file is part of the uIP TCP/IP stack.
33 *
adamdunkelsd962db42003-08-21 18:10:21 +000034 * $Id: uip.c,v 1.8 2003/08/21 18:10:21 adamdunkels Exp $
adamdunkelsca9ddcb2003-03-19 14:13:31 +000035 *
36 */
37
38/*
39This is a small implementation of the IP and TCP protocols (as well as
40some basic ICMP stuff). The implementation couples the IP, TCP and the
41application layers very tightly. To keep the size of the compiled code
42down, this code also features heavy usage of the goto statement.
43
44The principle is that we have a small buffer, called the uip_buf, in
45which the device driver puts an incoming packet. The TCP/IP stack
46parses the headers in the packet, and calls upon the application. If
47the remote host has sent data to the application, this data is present
48in the uip_buf and the application read the data from there. It is up
49to the application to put this data into a byte stream if needed. The
50application will not be fed with data that is out of sequence.
51
52If the application whishes to send data to the peer, it should put its
53data into the uip_buf, 40 bytes from the start of the buffer. The
54TCP/IP stack will calculate the checksums, and fill in the necessary
55header fields and finally send the packet back to the peer.
56*/
57
58#include "uip.h"
59#include "uipopt.h"
60#include "uip_arch.h"
61
62/*-----------------------------------------------------------------------------------*/
63/* Variable definitions. */
64
65
66/* The IP address of this host. If it is defined to be fixed (by setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set here. Otherwise, the address */
67#if UIP_FIXEDADDR > 0
adamdunkelsca9ddcb2003-03-19 14:13:31 +000068const u16_t uip_hostaddr[2] =
adamdunkels47ec7fa2003-03-28 12:11:17 +000069 {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1),
70 HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)};
adamdunkelsca9ddcb2003-03-19 14:13:31 +000071#else
adamdunkelsca9ddcb2003-03-19 14:13:31 +000072u16_t uip_hostaddr[2];
adamdunkelsca9ddcb2003-03-19 14:13:31 +000073#endif /* UIP_FIXEDADDR */
74
75u8_t uip_buf[UIP_BUFSIZE]; /* The packet buffer that contains
76 incoming packets. */
77volatile u8_t *uip_appdata; /* The uip_appdata pointer points to
78 application data. */
79#if UIP_URGDATA > 0
80volatile u8_t *uip_urgdata; /* The uip_urgdata pointer points to
81 urgent data (out-of-band data), if
82 present. */
83volatile u8_t uip_urglen, uip_surglen;
84#endif /* UIP_URGDATA > 0 */
85
86#if UIP_BUFSIZE > 255
87volatile u16_t uip_len, uip_slen;
88 /* The uip_len is either 8 or 16 bits,
89 depending on the maximum packet
90 size. */
91#else
92volatile u8_t uip_len, uip_slen;
93#endif /* UIP_BUFSIZE > 255 */
94
95volatile u8_t uip_flags; /* The uip_flags variable is used for
96 communication between the TCP/IP stack
97 and the application program. */
98struct uip_conn *uip_conn; /* uip_conn always points to the current
99 connection. */
100
101struct uip_conn uip_conns[UIP_CONNS];
102 /* The uip_conns array holds all TCP
103 connections. */
104u16_t uip_listenports[UIP_LISTENPORTS];
105 /* The uip_listenports list all currently
106 listning ports. */
107#if UIP_UDP
108struct uip_udp_conn *uip_udp_conn;
109struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
110#endif /* UIP_UDP */
111
112
113static u16_t ipid; /* Ths ipid variable is an increasing
114 number that is used for the IP ID
115 field. */
116
117static u8_t iss[4]; /* The iss variable is used for the TCP
118 initial sequence number. */
119
120#if UIP_ACTIVE_OPEN
121/* XXX static */ u16_t lastport; /* Keeps track of the last port used for
122 a new connection. */
123#endif /* UIP_ACTIVE_OPEN */
124
125/* Temporary variables. */
126volatile u8_t uip_acc32[4];
127static u8_t c, opt;
128static u16_t tmpport;
129
130/* Structures and definitions. */
131#define TCP_FIN 0x01
132#define TCP_SYN 0x02
133#define TCP_RST 0x04
134#define TCP_PSH 0x08
135#define TCP_ACK 0x10
136#define TCP_URG 0x20
137#define TCP_CTL 0x3f
138
139#define ICMP_ECHO_REPLY 0
140#define ICMP_ECHO 8
141
142/* Macros. */
143#define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
144#define FBUF ((uip_tcpip_hdr *)&uip_reassbuf[0])
145#define ICMPBUF ((uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN])
146#define UDPBUF ((uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])
147
148#if UIP_STATISTICS == 1
149struct uip_stats uip_stat;
150#define UIP_STAT(s) s
151#else
152#define UIP_STAT(s)
153#endif /* UIP_STATISTICS == 1 */
154
155#if UIP_LOGGING == 1
156#include <stdio.h>
157void uip_log(char *msg);
158#define UIP_LOG(m) uip_log(m)
159#else
160#define UIP_LOG(m)
161#endif /* UIP_LOGGING == 1 */
162
163/*-----------------------------------------------------------------------------------*/
164void
165uip_init(void)
166{
167 for(c = 0; c < UIP_LISTENPORTS; ++c) {
168 uip_listenports[c] = 0;
169 }
170 for(c = 0; c < UIP_CONNS; ++c) {
171 uip_conns[c].tcpstateflags = CLOSED;
172 }
173#if UIP_ACTIVE_OPEN
174 lastport = 1024;
175#endif /* UIP_ACTIVE_OPEN */
176
177#if UIP_UDP
178 for(c = 0; c < UIP_UDP_CONNS; ++c) {
179 uip_udp_conns[c].lport = 0;
180 }
181#endif /* UIP_UDP */
182
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000183
184 /* IPv4 initialization. */
185#if UIP_FIXEDADDR == 0
186 uip_hostaddr[0] = uip_hostaddr[1] = 0;
187#endif /* UIP_FIXEDADDR */
adamdunkelsa38da252003-08-20 20:56:54 +0000188
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000189}
190/*-----------------------------------------------------------------------------------*/
191#if UIP_ACTIVE_OPEN
192struct uip_conn *
193uip_connect(u16_t *ripaddr, u16_t rport)
194{
adamdunkelsa38da252003-08-20 20:56:54 +0000195 register struct uip_conn *conn, *cconn;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000196
197 /* Find an unused local port. */
198 again:
199 ++lastport;
200
201 if(lastport >= 32000) {
202 lastport = 4096;
203 }
204
205 for(c = 0; c < UIP_CONNS; ++c) {
adamdunkels23664022003-08-05 13:51:50 +0000206 conn = &uip_conns[c];
207 if(conn->tcpstateflags != CLOSED &&
adamdunkelsa38da252003-08-20 20:56:54 +0000208 conn->lport == lastport) {
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000209 goto again;
adamdunkelsa38da252003-08-20 20:56:54 +0000210 }
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000211 }
212
213
214 conn = 0;
215 for(c = 0; c < UIP_CONNS; ++c) {
adamdunkelsa38da252003-08-20 20:56:54 +0000216 cconn = &uip_conns[c];
217 if(cconn->tcpstateflags == CLOSED) {
218 conn = cconn;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000219 break;
220 }
adamdunkelsa38da252003-08-20 20:56:54 +0000221 if(cconn->tcpstateflags == TIME_WAIT) {
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000222 if(conn == 0 ||
adamdunkelsa38da252003-08-20 20:56:54 +0000223 cconn->timer > uip_conn->timer) {
224 conn = cconn;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000225 }
226 }
227 }
228
229 if(conn == 0) {
230 return 0;
231 }
232
233 conn->tcpstateflags = SYN_SENT;
234
235 conn->snd_nxt[0] = iss[0];
236 conn->snd_nxt[1] = iss[1];
237 conn->snd_nxt[2] = iss[2];
238 conn->snd_nxt[3] = iss[3];
239
adamdunkelsd962db42003-08-21 18:10:21 +0000240 conn->mss = UIP_TCP_MSS;
241
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000242 conn->len = 1; /* TCP length of the SYN is one. */
243 conn->nrtx = 0;
244 conn->timer = 1; /* Send the SYN next time around. */
adamdunkels47ec7fa2003-03-28 12:11:17 +0000245 conn->lport = HTONS(lastport);
246 conn->rport = HTONS(rport);
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000247 conn->ripaddr[0] = ripaddr[0];
248 conn->ripaddr[1] = ripaddr[1];
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000249
250 return conn;
251}
252#endif /* UIP_ACTIVE_OPEN */
253/*-----------------------------------------------------------------------------------*/
254#if UIP_UDP
255struct uip_udp_conn *
256uip_udp_new(u16_t *ripaddr, u16_t rport)
257{
adamdunkels23664022003-08-05 13:51:50 +0000258 register struct uip_udp_conn *conn;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000259
260 /* Find an unused local port. */
261 again:
262 ++lastport;
263
264 if(lastport >= 32000) {
265 lastport = 4096;
266 }
267
268 for(c = 0; c < UIP_UDP_CONNS; ++c) {
269 if(uip_udp_conns[c].lport == lastport)
270 goto again;
271 }
272
273
274 conn = 0;
275 for(c = 0; c < UIP_UDP_CONNS; ++c) {
276 if(uip_udp_conns[c].lport == 0) {
277 conn = &uip_udp_conns[c];
278 break;
279 }
280 }
281
282 if(conn == 0) {
283 return 0;
284 }
285
adamdunkels47ec7fa2003-03-28 12:11:17 +0000286 conn->lport = HTONS(lastport);
287 conn->rport = HTONS(rport);
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000288 conn->ripaddr[0] = ripaddr[0];
289 conn->ripaddr[1] = ripaddr[1];
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000290
291 return conn;
292}
293#endif /* UIP_UDP */
294/*-----------------------------------------------------------------------------------*/
295void
adamdunkelscd8c3a22003-08-13 22:52:48 +0000296uip_unlisten(u16_t port)
297{
298 for(c = 0; c < UIP_LISTENPORTS; ++c) {
299 if(uip_listenports[c] == port) {
300 uip_listenports[c] = 0;
301 return;
302 }
303 }
304}
305/*-----------------------------------------------------------------------------------*/
306void
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000307uip_listen(u16_t port)
308{
309 for(c = 0; c < UIP_LISTENPORTS; ++c) {
310 if(uip_listenports[c] == 0) {
adamdunkelscd8c3a22003-08-13 22:52:48 +0000311 uip_listenports[c] = htons(port);
312 return;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000313 }
314 }
315}
316/*-----------------------------------------------------------------------------------*/
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000317#define UIP_REASSEMBLY 0
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000318
319#define UIP_REASS_MAXAGE 10
320
321#if UIP_REASSEMBLY
322#define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN)
323static u8_t uip_reassbuf[UIP_REASS_BUFSIZE];
324static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)];
325static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f,
326 0x0f, 0x07, 0x03, 0x01};
327static u16_t uip_reasslen;
328static u8_t uip_reassflags;
329#define UIP_REASS_FLAG_LASTFRAG 0x01
330static u8_t uip_reasstmr;
331
332#define IP_HLEN 20
333#define IP_MF 0x20
334
335static u8_t
336uip_reass(void)
337{
338 u16_t offset, len;
339 u16_t i;
340
341 /* If ip_reasstmr is zero, no packet is present in the buffer, so we
342 write the IP header of the fragment into the reassembly
343 buffer. The timer is updated with the maximum age. */
344 if(uip_reasstmr == 0) {
345 bcopy(&BUF->vhl, uip_reassbuf, IP_HLEN);
346 uip_reasstmr = UIP_REASS_MAXAGE;
347 uip_reassflags = 0;
348 /* Clear the bitmap. */
349 bzero(uip_reassbitmap, sizeof(uip_reassbitmap));
350 }
351
352 /* Check if the incoming fragment matches the one currently present
353 in the reasembly buffer. If so, we proceed with copying the
354 fragment into the buffer. */
355 if(BUF->srcipaddr[0] == FBUF->srcipaddr[0] &&
356 BUF->destipaddr[1] == FBUF->destipaddr[1] &&
357 BUF->srcipaddr[0] == FBUF->srcipaddr[0] &&
358 BUF->destipaddr[1] == FBUF->destipaddr[1] &&
359 BUF->ipid == FBUF->ipid) {
360
361 len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4;
362 offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8;
363
364 /* If the offset or the offset + fragment length overflows the
365 reassembly buffer, we discard the entire packet. */
366 if(offset > UIP_REASS_BUFSIZE ||
367 offset + len > UIP_REASS_BUFSIZE) {
368 uip_reasstmr = 0;
369 goto nullreturn;
370 }
371
372 /* Copy the fragment into the reassembly buffer, at the right
373 offset. */
374 bcopy(BUF + (BUF->vhl & 0x0f) * 4,
375 &uip_reassbuf[IP_HLEN + offset], len);
376
377 /* Update the bitmap. */
378 if(offset / (8 * 8) == (offset + len) / (8 * 8)) {
379 /* If the two endpoints are in the same byte, we only update
380 that byte. */
381 uip_reassbitmap[offset / (8 * 8)] |=
382 bitmap_bits[(offset / 8 ) & 7] &
383 ~bitmap_bits[((offset + len) / 8 ) & 7];
384 } else {
385 /* If the two endpoints are in different bytes, we update the
386 bytes in the endpoints and fill the stuff inbetween with
387 0xff. */
388 uip_reassbitmap[offset / (8 * 8)] |=
389 bitmap_bits[(offset / 8 ) & 7];
390 for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) {
391 uip_reassbitmap[i] = 0xff;
392 }
393 uip_reassbitmap[(offset + len) / (8 * 8)] |=
394 ~bitmap_bits[((offset + len) / 8 ) & 7];
395 }
396
397 /* If this fragment has the More Fragments flag set to zero, we
398 know that this is the last fragment, so we can calculate the
399 size of the entire packet. We also set the
400 IP_REASS_FLAG_LASTFRAG flag to indicate that we have received
401 the final fragment. */
402
403 if((BUF->ipoffset[0] & IP_MF) == 0) {
404 uip_reassflags |= UIP_REASS_FLAG_LASTFRAG;
405 uip_reasslen = offset + len;
406 }
407
408 /* Finally, we check if we have a full packet in the buffer. We do
409 this by checking if we have the last fragment and if all bits
410 in the bitmap are set. */
411 if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) {
412 /* Check all bytes up to and including all but the last byte in
413 the bitmap. */
414 for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) {
415 if(uip_reassbitmap[i] != 0xff) {
416 goto nullreturn;
417 }
418 }
419 /* Check the last byte in the bitmap. It should contain just the
420 right amount of bits. */
421 if(uip_reassbitmap[uip_reasslen / (8 * 8)] !=
422 (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) {
423 goto nullreturn;
424 }
425
426 /* If we have come this far, we have a full packet in the
427 buffer, so we allocate a pbuf and copy the packet into it. We
428 also reset the timer. */
429 uip_reasstmr = 0;
430 bcopy(FBUF, BUF, uip_reasslen);
431
432 /* Pretend to be a "normal" (i.e., not fragmented) IP packet
433 from now on. */
434 BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
435 BUF->ipchksum = 0;
436 BUF->ipchksum = ~(uip_ipchksum());
437
438
439
440 return uip_reasslen;
441 }
442 }
443
444 nullreturn:
445 return 0;
446}
447#endif /* IP_REASSEMBLY */
448/*-----------------------------------------------------------------------------------*/
449void
450uip_process(u8_t flag)
451{
452 register struct uip_conn *uip_connr = uip_conn;
453 /*#define uip_connr uip_conn*/
454
455 uip_appdata = &uip_buf[40 + UIP_LLH_LEN];
456
457
458 /* Check if we were invoked because of the perodic timer fireing. */
459 if(flag == UIP_TIMER) {
460 /* Increase the initial sequence number. */
461 if(++iss[3] == 0) {
462 if(++iss[2] == 0) {
463 if(++iss[1] == 0) {
464 ++iss[0];
465 }
466 }
467 }
468 uip_len = 0;
469 if(uip_connr->tcpstateflags == TIME_WAIT ||
470 uip_connr->tcpstateflags == FIN_WAIT_2) {
471 ++(uip_connr->timer);
472 if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) {
473 uip_connr->tcpstateflags = CLOSED;
474 }
475 } else if(uip_connr->tcpstateflags != CLOSED) {
476 /* If the connection has outstanding data, we increase the
477 connection's timer and see if it has reached the RTO value
478 in which case we retransmit. */
479 if(uip_outstanding(uip_connr)) {
480 --(uip_connr->timer);
481 if(uip_connr->timer == 0) {
482 if(uip_connr->nrtx == UIP_MAXRTX ||
483 ((uip_connr->tcpstateflags == SYN_SENT ||
484 uip_connr->tcpstateflags == SYN_RCVD) &&
485 uip_connr->nrtx == UIP_MAXSYNRTX)) {
486 uip_connr->tcpstateflags = CLOSED;
487
488 /* We call UIP_APPCALL() with uip_flags set to
489 UIP_TIMEDOUT to inform the application that the
490 connection has timed out. */
491 uip_flags = UIP_TIMEDOUT;
492 UIP_APPCALL();
493
494 /* We also send a reset packet to the remote host. */
495 BUF->flags = TCP_RST | TCP_ACK;
496 goto tcp_send_nodata;
497 }
498
499 /* Exponential backoff. */
adamdunkels47ec7fa2003-03-28 12:11:17 +0000500 uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4?
501 4:
502 uip_connr->nrtx);
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000503 ++(uip_connr->nrtx);
504
505 /* Ok, so we need to retransmit. We do this differently
506 depending on which state we are in. In ESTABLISHED, we
507 call upon the application so that it may prepare the
508 data for the retransmit. In SYN_RCVD, we resend the
509 SYNACK that we sent earlier and in LAST_ACK we have to
510 retransmit our FINACK. */
511 UIP_STAT(++uip_stat.tcp.rexmit);
512 switch(uip_connr->tcpstateflags & TS_MASK) {
513 case SYN_RCVD:
514 /* In the SYN_RCVD state, we should retransmit our
515 SYNACK. */
516 goto tcp_send_synack;
517
518#if UIP_ACTIVE_OPEN
519 case SYN_SENT:
520 /* In the SYN_SENT state, we retransmit out SYN. */
521 BUF->flags = 0;
522 goto tcp_send_syn;
523#endif /* UIP_ACTIVE_OPEN */
524
525 case ESTABLISHED:
526 /* In the ESTABLISHED state, we call upon the application
527 to do the actual retransmit after which we jump into
528 the code for sending out the packet (the apprexmit
529 label). */
530 uip_len = 0;
531 uip_slen = 0;
532 uip_flags = UIP_REXMIT;
533 UIP_APPCALL();
534 goto apprexmit;
535
536 case FIN_WAIT_1:
537 case CLOSING:
538 case LAST_ACK:
539 /* In all these states we should retransmit a FINACK. */
540 goto tcp_send_finack;
541
542 }
543 }
544 } else if((uip_connr->tcpstateflags & TS_MASK) == ESTABLISHED) {
545 /* If there was no need for a retransmission, we poll the
546 application for new data. */
547 uip_len = 0;
548 uip_slen = 0;
549 uip_flags = UIP_POLL;
550 UIP_APPCALL();
551 goto appsend;
552 }
553 }
554 goto drop;
555 }
556#if UIP_UDP
557 if(flag == UIP_UDP_TIMER) {
558 if(uip_udp_conn->lport != 0) {
559 uip_appdata = &uip_buf[UIP_LLH_LEN + 28];
560 uip_len = uip_slen = 0;
561 uip_flags = UIP_POLL;
562 UIP_UDP_APPCALL();
563 goto udp_send;
564 } else {
565 goto drop;
566 }
567 }
568#endif
569
570 /* This is where the input processing starts. */
571 UIP_STAT(++uip_stat.ip.recv);
572
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000573
574 /* Start of IPv4 input header processing code. */
575
576 /* Check validity of the IP header. */
577 if(BUF->vhl != 0x45) { /* IP version and header length. */
578 UIP_STAT(++uip_stat.ip.drop);
579 UIP_STAT(++uip_stat.ip.vhlerr);
580 UIP_LOG("ip: invalid version or header length.");
581 goto drop;
582 }
583
584 /* Check the size of the packet. If the size reported to us in
585 uip_len doesn't match the size reported in the IP header, there
586 has been a transmission error and we drop the packet. */
587
588#if UIP_BUFSIZE > 255
589 if(BUF->len[0] != (uip_len >> 8)) { /* IP length, high byte. */
590 uip_len = (uip_len & 0xff) | (BUF->len[0] << 8);
591 }
592 if(BUF->len[1] != (uip_len & 0xff)) { /* IP length, low byte. */
593 uip_len = (uip_len & 0xff00) | BUF->len[1];
594 }
595#else
596 if(BUF->len[0] != 0) { /* IP length, high byte. */
597 UIP_STAT(++uip_stat.ip.drop);
598 UIP_STAT(++uip_stat.ip.hblenerr);
599 UIP_LOG("ip: invalid length, high byte.");
600 goto drop;
601 }
602 if(BUF->len[1] != uip_len) { /* IP length, low byte. */
603 uip_len = BUF->len[1];
604 }
605#endif /* UIP_BUFSIZE > 255 */
606
607 if(BUF->ipoffset[0] & 0x3f) { /* We don't allow IP fragments. */
608 UIP_STAT(++uip_stat.ip.drop);
609 UIP_STAT(++uip_stat.ip.fragerr);
610 UIP_LOG("ip: fragment dropped.");
611 goto drop;
612 }
613
614 /* If we are configured to use ping IP address configuration and
615 hasn't been assigned an IP address yet, we accept all ICMP
616 packets. */
617#if UIP_PINGADDRCONF
618 if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) {
619 if(BUF->proto == UIP_PROTO_ICMP) {
620 UIP_LOG("ip: possible ping config packet received.");
621 goto icmp_input;
622 } else {
623 UIP_LOG("ip: packet dropped since no address assigned..");
624 goto drop;
625 }
626 }
627#endif /* UIP_PINGADDRCONF */
628
629 /* Check if the packet is destined for our IP address. */
630 if(BUF->destipaddr[0] != uip_hostaddr[0]) {
631 UIP_STAT(++uip_stat.ip.drop);
632 UIP_LOG("ip: packet not for us.");
633 goto drop;
634 }
635 if(BUF->destipaddr[1] != uip_hostaddr[1]) {
636 UIP_STAT(++uip_stat.ip.drop);
637 UIP_LOG("ip: packet not for us.");
638 goto drop;
639 }
640
641 if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header
642 checksum. */
643 UIP_STAT(++uip_stat.ip.drop);
644 UIP_STAT(++uip_stat.ip.chkerr);
645 UIP_LOG("ip: bad checksum.");
646 goto drop;
647 }
648
649 if(BUF->proto == UIP_PROTO_TCP) /* Check for TCP packet. If so, jump
650 to the tcp_input label. */
651 goto tcp_input;
652
653#if UIP_UDP
654 if(BUF->proto == UIP_PROTO_UDP)
655 goto udp_input;
656#endif /* UIP_UDP */
657
658 if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from
659 here. */
660 UIP_STAT(++uip_stat.ip.drop);
661 UIP_STAT(++uip_stat.ip.protoerr);
662 UIP_LOG("ip: neither tcp nor icmp.");
663 goto drop;
664 }
665
666 icmp_input:
667 UIP_STAT(++uip_stat.icmp.recv);
668
669 /* ICMP echo (i.e., ping) processing. This is simple, we only change
670 the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP
671 checksum before we return the packet. */
672 if(ICMPBUF->type != ICMP_ECHO) {
673 UIP_STAT(++uip_stat.icmp.drop);
674 UIP_STAT(++uip_stat.icmp.typeerr);
675 UIP_LOG("icmp: not icmp echo.");
676 goto drop;
677 }
678
679 /* If we are configured to use ping IP address assignment, we use
680 the destination IP address of this ping packet and assign it to
681 ourself. */
682#if UIP_PINGADDRCONF
683 if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) {
684 uip_hostaddr[0] = BUF->destipaddr[0];
685 uip_hostaddr[1] = BUF->destipaddr[1];
686 }
687#endif /* UIP_PINGADDRCONF */
688
689 ICMPBUF->type = ICMP_ECHO_REPLY;
690
adamdunkels47ec7fa2003-03-28 12:11:17 +0000691 if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) {
692 ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000693 } else {
adamdunkels47ec7fa2003-03-28 12:11:17 +0000694 ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8);
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000695 }
696
697 /* Swap IP addresses. */
698 tmpport = BUF->destipaddr[0];
699 BUF->destipaddr[0] = BUF->srcipaddr[0];
700 BUF->srcipaddr[0] = tmpport;
701 tmpport = BUF->destipaddr[1];
702 BUF->destipaddr[1] = BUF->srcipaddr[1];
703 BUF->srcipaddr[1] = tmpport;
704
705 UIP_STAT(++uip_stat.icmp.sent);
706 goto send;
707
708 /* End of IPv4 input header processing code. */
709
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000710
711#if UIP_UDP
712 /* UDP input processing. */
713 udp_input:
714 /* UDP processing is really just a hack. We don't do anything to the
715 UDP/IP headers, but let the UDP application do all the hard
716 work. If the application sets uip_slen, it has a packet to
717 send. */
718#if UIP_UDP_CHECKSUMS
719 if(uip_udpchksum() != 0xffff) {
720 UIP_STAT(++uip_stat.udp.drop);
721 UIP_STAT(++uip_stat.udp.chkerr);
722 UIP_LOG("udp: bad checksum.");
723 goto drop;
724 }
725#endif /* UIP_UDP_CHECKSUMS */
726
727 /* Demultiplex this UDP packet between the UDP "connections". */
728 for(uip_udp_conn = &uip_udp_conns[0];
729 uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS];
730 ++uip_udp_conn) {
731 if(uip_udp_conn->lport != 0 &&
732 UDPBUF->destport == uip_udp_conn->lport &&
733 (uip_udp_conn->rport == 0 ||
734 UDPBUF->srcport == uip_udp_conn->rport) &&
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000735 BUF->srcipaddr[0] == uip_udp_conn->ripaddr[0] &&
736 BUF->srcipaddr[1] == uip_udp_conn->ripaddr[1]) {
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000737 goto udp_found;
738 }
739 }
740 goto drop;
741
742 udp_found:
743 uip_len = uip_len - 28;
744 uip_appdata = &uip_buf[UIP_LLH_LEN + 28];
745 uip_flags = UIP_NEWDATA;
746 uip_slen = 0;
747 UIP_UDP_APPCALL();
748 udp_send:
749 if(uip_slen == 0) {
750 goto drop;
751 }
752 uip_len = uip_slen + 28;
753
754#if UIP_BUFSIZE > 255
755 BUF->len[0] = (uip_len >> 8);
756 BUF->len[1] = (uip_len & 0xff);
757#else
758 BUF->len[0] = 0;
759 BUF->len[1] = uip_len;
760#endif /* UIP_BUFSIZE > 255 */
761 BUF->proto = UIP_PROTO_UDP;
762
adamdunkels47ec7fa2003-03-28 12:11:17 +0000763 UDPBUF->udplen = HTONS(uip_slen + 8);
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000764 UDPBUF->udpchksum = 0;
765#if UIP_UDP_CHECKSUMS
766 /* Calculate UDP checksum. */
767 UDPBUF->udpchksum = ~(uip_udpchksum());
768 if(UDPBUF->udpchksum == 0) {
769 UDPBUF->udpchksum = 0xffff;
770 }
771#endif /* UIP_UDP_CHECKSUMS */
772
773 BUF->srcport = uip_udp_conn->lport;
774 BUF->destport = uip_udp_conn->rport;
775
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000776 BUF->srcipaddr[0] = uip_hostaddr[0];
777 BUF->srcipaddr[1] = uip_hostaddr[1];
778 BUF->destipaddr[0] = uip_udp_conn->ripaddr[0];
779 BUF->destipaddr[1] = uip_udp_conn->ripaddr[1];
780
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000781 uip_appdata = &uip_buf[UIP_LLH_LEN + 40];
782 goto ip_send_nolen;
783#endif /* UIP_UDP */
784
785 /* TCP input processing. */
786 tcp_input:
787 UIP_STAT(++uip_stat.tcp.recv);
788
789 /* Start of TCP input header processing code. */
790
791 if(uip_tcpchksum() != 0xffff) { /* Compute and check the TCP
792 checksum. */
793 UIP_STAT(++uip_stat.tcp.drop);
794 UIP_STAT(++uip_stat.tcp.chkerr);
795 UIP_LOG("tcp: bad checksum.");
796 goto drop;
797 }
798
799 /* Demultiplex this segment. */
800 /* First check any active connections. */
801 for(uip_connr = &uip_conns[0]; uip_connr < &uip_conns[UIP_CONNS]; ++uip_connr) {
802 if(uip_connr->tcpstateflags != CLOSED &&
803 BUF->destport == uip_connr->lport &&
804 BUF->srcport == uip_connr->rport &&
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000805 BUF->srcipaddr[0] == uip_connr->ripaddr[0] &&
806 BUF->srcipaddr[1] == uip_connr->ripaddr[1]) {
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000807 goto found;
808 }
809 }
810
811 /* If we didn't find and active connection that expected the packet,
812 either this packet is an old duplicate, or this is a SYN packet
813 destined for a connection in LISTEN. If the SYN flag isn't set,
814 it is an old packet and we send a RST. */
815 if((BUF->flags & TCP_CTL) != TCP_SYN)
816 goto reset;
817
818 tmpport = BUF->destport;
819 /* Next, check listening connections. */
adamdunkelscd8c3a22003-08-13 22:52:48 +0000820 for(c = 0; c < UIP_LISTENPORTS; ++c) {
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000821 if(tmpport == uip_listenports[c])
822 goto found_listen;
823 }
824
825 /* No matching connection found, so we send a RST packet. */
826 UIP_STAT(++uip_stat.tcp.synrst);
827 reset:
828
829 /* We do not send resets in response to resets. */
830 if(BUF->flags & TCP_RST)
831 goto drop;
832
833 UIP_STAT(++uip_stat.tcp.rst);
834
835 BUF->flags = TCP_RST | TCP_ACK;
836 uip_len = 40;
837 BUF->tcpoffset = 5 << 4;
838
839 /* Flip the seqno and ackno fields in the TCP header. */
840 c = BUF->seqno[3];
841 BUF->seqno[3] = BUF->ackno[3];
842 BUF->ackno[3] = c;
843
844 c = BUF->seqno[2];
845 BUF->seqno[2] = BUF->ackno[2];
846 BUF->ackno[2] = c;
847
848 c = BUF->seqno[1];
849 BUF->seqno[1] = BUF->ackno[1];
850 BUF->ackno[1] = c;
851
852 c = BUF->seqno[0];
853 BUF->seqno[0] = BUF->ackno[0];
854 BUF->ackno[0] = c;
855
856 /* We also have to increase the sequence number we are
857 acknowledging. If the least significant byte overflowed, we need
858 to propagate the carry to the other bytes as well. */
859 if(++BUF->ackno[3] == 0) {
860 if(++BUF->ackno[2] == 0) {
861 if(++BUF->ackno[1] == 0) {
862 ++BUF->ackno[0];
863 }
864 }
865 }
866
867 /* Swap port numbers. */
868 tmpport = BUF->srcport;
869 BUF->srcport = BUF->destport;
870 BUF->destport = tmpport;
871
872 /* Swap IP addresses. */
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000873 tmpport = BUF->destipaddr[0];
874 BUF->destipaddr[0] = BUF->srcipaddr[0];
875 BUF->srcipaddr[0] = tmpport;
876 tmpport = BUF->destipaddr[1];
877 BUF->destipaddr[1] = BUF->srcipaddr[1];
878 BUF->srcipaddr[1] = tmpport;
adamdunkelsa38da252003-08-20 20:56:54 +0000879
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000880
881 /* And send out the RST packet! */
882 goto tcp_send_noconn;
883
884 /* This label will be jumped to if we matched the incoming packet
885 with a connection in LISTEN. In that case, we should create a new
886 connection and send a SYNACK in return. */
887 found_listen:
888 /* First we check if there are any connections avaliable. Unused
889 connections are kept in the same table as used connections, but
890 unused ones have the tcpstate set to CLOSED. Also, connections in
891 TIME_WAIT are kept track of and we'll use the oldest one if no
892 CLOSED connections are found. Thanks to Eddie C. Dost for a very
893 nice algorithm for the TIME_WAIT search. */
894 uip_connr = 0;
895 for(c = 0; c < UIP_CONNS; ++c) {
896 if(uip_conns[c].tcpstateflags == CLOSED) {
897 uip_connr = &uip_conns[c];
898 break;
899 }
900 if(uip_conns[c].tcpstateflags == TIME_WAIT) {
901 if(uip_connr == 0 ||
902 uip_conns[c].timer > uip_connr->timer) {
903 uip_connr = &uip_conns[c];
904 }
905 }
906 }
907
908 if(uip_connr == 0) {
909 /* All connections are used already, we drop packet and hope that
910 the remote end will retransmit the packet at a time when we
911 have more spare connections. */
912 UIP_STAT(++uip_stat.tcp.syndrop);
913 UIP_LOG("tcp: found no unused connections.");
914 goto drop;
915 }
916 uip_conn = uip_connr;
917
918 /* Fill in the necessary fields for the new connection. */
919 uip_connr->timer = UIP_RTO;
920 uip_connr->nrtx = 0;
921 uip_connr->lport = BUF->destport;
922 uip_connr->rport = BUF->srcport;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000923 uip_connr->ripaddr[0] = BUF->srcipaddr[0];
924 uip_connr->ripaddr[1] = BUF->srcipaddr[1];
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000925 uip_connr->tcpstateflags = SYN_RCVD;
926
927 uip_connr->snd_nxt[0] = iss[0];
928 uip_connr->snd_nxt[1] = iss[1];
929 uip_connr->snd_nxt[2] = iss[2];
930 uip_connr->snd_nxt[3] = iss[3];
931 uip_connr->len = 1;
932
933 /* rcv_nxt should be the seqno from the incoming packet + 1. */
934 uip_connr->rcv_nxt[3] = BUF->seqno[3];
935 uip_connr->rcv_nxt[2] = BUF->seqno[2];
936 uip_connr->rcv_nxt[1] = BUF->seqno[1];
937 uip_connr->rcv_nxt[0] = BUF->seqno[0];
938 uip_add_rcv_nxt(1);
939
940 /* Parse the TCP MSS option, if present. */
941 if((BUF->tcpoffset & 0xf0) > 0x50) {
942 for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
943 opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c];
944 if(opt == 0x00) {
945 /* End of options. */
946 break;
947 } else if(opt == 0x01) {
948 ++c;
949 /* NOP option. */
950 } else if(opt == 0x02 &&
951 uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) {
952 /* An MSS option with the right option length. */
953 tmpport = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
954 uip_buf[40 + UIP_LLH_LEN + 3 + c];
955 uip_connr->mss = tmpport > UIP_TCP_MSS? UIP_TCP_MSS: tmpport;
956
957 /* And we are done processing options. */
958 break;
959 } else {
960 /* All other options have a length field, so that we easily
961 can skip past them. */
962 if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
963 /* If the length field is zero, the options are malformed
964 and we don't process them further. */
965 break;
966 }
967 c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
968 }
969 }
970 }
971
972 /* Our response will be a SYNACK. */
973#if UIP_ACTIVE_OPEN
974 tcp_send_synack:
975 BUF->flags = TCP_ACK;
976
977 tcp_send_syn:
978 BUF->flags |= TCP_SYN;
979#else /* UIP_ACTIVE_OPEN */
980 tcp_send_synack:
981 BUF->flags = TCP_SYN | TCP_ACK;
982#endif /* UIP_ACTIVE_OPEN */
983
984 /* We send out the TCP Maximum Segment Size option with our
985 SYNACK. */
986 BUF->optdata[0] = 2;
987 BUF->optdata[1] = 4;
988 BUF->optdata[2] = (UIP_TCP_MSS) / 256;
989 BUF->optdata[3] = (UIP_TCP_MSS) & 255;
990 uip_len = 44;
991 BUF->tcpoffset = 6 << 4;
992 goto tcp_send;
993
994 /* This label will be jumped to if we found an active connection. */
995 found:
996 uip_conn = uip_connr;
997 uip_flags = 0;
998
999 /* We do a very naive form of TCP reset processing; we just accept
1000 any RST and kill our connection. We should in fact check if the
1001 sequence number of this reset is wihtin our advertised window
1002 before we accept the reset. */
1003 if(BUF->flags & TCP_RST) {
1004 uip_connr->tcpstateflags = CLOSED;
1005 UIP_LOG("tcp: got reset, aborting connection.");
1006 uip_flags = UIP_ABORT;
1007 UIP_APPCALL();
1008 goto drop;
adamdunkels47ec7fa2003-03-28 12:11:17 +00001009 }
adamdunkelsca9ddcb2003-03-19 14:13:31 +00001010 /* Calculated the length of the data, if the application has sent
1011 any data to us. */
1012 c = (BUF->tcpoffset >> 4) << 2;
1013 /* uip_len will contain the length of the actual TCP data. This is
1014 calculated by subtracing the length of the TCP header (in
1015 c) and the length of the IP header (20 bytes). */
1016 uip_len = uip_len - c - 20;
1017
1018 /* First, check if the sequence number of the incoming packet is
1019 what we're expecting next. If not, we send out an ACK with the
1020 correct numbers in. */
1021 if(uip_len > 0 &&
1022 (BUF->seqno[0] != uip_connr->rcv_nxt[0] ||
1023 BUF->seqno[1] != uip_connr->rcv_nxt[1] ||
1024 BUF->seqno[2] != uip_connr->rcv_nxt[2] ||
1025 BUF->seqno[3] != uip_connr->rcv_nxt[3])) {
1026 goto tcp_send_ack;
1027 }
1028
1029 /* Next, check if the incoming segment acknowledges any outstanding
1030 data. If so, we update the sequence number, reset the length of
1031 the outstanding data, calculate RTT estimations, and reset the
1032 retransmission timer. */
adamdunkels47ec7fa2003-03-28 12:11:17 +00001033 if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) {
adamdunkelsca9ddcb2003-03-19 14:13:31 +00001034 uip_add32(uip_connr->snd_nxt, uip_connr->len);
1035 if(BUF->ackno[0] == uip_acc32[0] &&
1036 BUF->ackno[1] == uip_acc32[1] &&
1037 BUF->ackno[2] == uip_acc32[2] &&
1038 BUF->ackno[3] == uip_acc32[3]) {
1039 /* Update sequence number. */
1040 uip_connr->snd_nxt[0] = uip_acc32[0];
1041 uip_connr->snd_nxt[1] = uip_acc32[1];
1042 uip_connr->snd_nxt[2] = uip_acc32[2];
1043 uip_connr->snd_nxt[3] = uip_acc32[3];
adamdunkelsa38da252003-08-20 20:56:54 +00001044
adamdunkelsca9ddcb2003-03-19 14:13:31 +00001045
1046 /* Do RTT estimation, unless we have done retransmissions. */
1047 if(uip_connr->nrtx == 0) {
1048 signed char m;
1049 m = (UIP_RTO << (uip_connr->nrtx > 4? 4: uip_connr->nrtx)) - uip_connr->timer;
1050 /* This is taken directly from VJs original code in his paper */
1051 m = m - (uip_connr->sa >> 3);
1052 uip_connr->sa += m;
1053 if(m < 0) {
1054 m = -m;
1055 }
1056 m = m - (uip_connr->sv >> 2);
1057 uip_connr->sv += m;
1058 uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv;
1059
1060 }
adamdunkelsca9ddcb2003-03-19 14:13:31 +00001061 /* Set the acknowledged flag. */
1062 uip_flags = UIP_ACKDATA;
1063 /* Reset the length of the outstanding data. */
1064 uip_connr->len = 0;
1065 /* Reset the retransmission timer. */
1066 uip_connr->timer = UIP_RTO;
1067 }
adamdunkelsab4b0822003-07-30 23:31:40 +00001068
adamdunkelsca9ddcb2003-03-19 14:13:31 +00001069 }
1070
1071 /* Do different things depending on in what state the connection is. */
1072 switch(uip_connr->tcpstateflags & TS_MASK) {
1073 /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not
1074 implemented, since we force the application to close when the
1075 peer sends a FIN (hence the application goes directly from
1076 ESTABLISHED to LAST_ACK). */
1077 case SYN_RCVD:
1078 /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and
1079 we are waiting for an ACK that acknowledges the data we sent
1080 out the last time. Therefore, we want to have the UIP_ACKDATA
1081 flag set. If so, we enter the ESTABLISHED state. */
1082 if(uip_flags & UIP_ACKDATA) {
1083 uip_connr->tcpstateflags = ESTABLISHED;
1084 uip_flags = UIP_CONNECTED;
1085 if(uip_len > 0) {
1086 uip_flags |= UIP_NEWDATA;
1087 uip_add_rcv_nxt(uip_len);
1088 }
1089 uip_slen = 0;
1090 UIP_APPCALL();
1091 goto appsend;
1092 }
1093 goto drop;
1094#if UIP_ACTIVE_OPEN
1095 case SYN_SENT:
1096 /* In SYN_SENT, we wait for a SYNACK that is sent in response to
1097 our SYN. The rcv_nxt is set to sequence number in the SYNACK
1098 plus one, and we send an ACK. We move into the ESTABLISHED
1099 state. */
1100 if((uip_flags & UIP_ACKDATA) &&
1101 BUF->flags == (TCP_SYN | TCP_ACK)) {
1102
1103 /* Parse the TCP MSS option, if present. */
1104 if((BUF->tcpoffset & 0xf0) > 0x50) {
1105 for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
1106 opt = uip_buf[40 + UIP_LLH_LEN + c];
1107 if(opt == 0x00) {
1108 /* End of options. */
1109 break;
1110 } else if(opt == 0x01) {
1111 ++c;
1112 /* NOP option. */
1113 } else if(opt == 0x02 &&
1114 uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) {
1115 /* An MSS option with the right option length. */
1116 tmpport = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
1117 uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c];
1118 uip_connr->mss = tmpport > UIP_TCP_MSS? UIP_TCP_MSS: tmpport;
1119
1120 /* And we are done processing options. */
1121 break;
1122 } else {
1123 /* All other options have a length field, so that we easily
1124 can skip past them. */
1125 if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
1126 /* If the length field is zero, the options are malformed
1127 and we don't process them further. */
1128 break;
1129 }
1130 c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
1131 }
1132 }
1133 }
1134 uip_connr->tcpstateflags = ESTABLISHED;
1135 uip_connr->rcv_nxt[0] = BUF->seqno[0];
1136 uip_connr->rcv_nxt[1] = BUF->seqno[1];
1137 uip_connr->rcv_nxt[2] = BUF->seqno[2];
1138 uip_connr->rcv_nxt[3] = BUF->seqno[3];
1139 uip_add_rcv_nxt(1);
1140 uip_flags = UIP_CONNECTED | UIP_NEWDATA;
1141 uip_len = 0;
1142 uip_slen = 0;
1143 UIP_APPCALL();
1144 goto appsend;
1145 }
1146 goto reset;
1147#endif /* UIP_ACTIVE_OPEN */
1148
1149 case ESTABLISHED:
1150 /* In the ESTABLISHED state, we call upon the application to feed
1151 data into the uip_buf. If the UIP_ACKDATA flag is set, the
1152 application should put new data into the buffer, otherwise we are
1153 retransmitting an old segment, and the application should put that
1154 data into the buffer.
1155
1156 If the incoming packet is a FIN, we should close the connection on
1157 this side as well, and we send out a FIN and enter the LAST_ACK
1158 state. We require that there is no outstanding data; otherwise the
1159 sequence numbers will be screwed up. */
1160
1161 if(BUF->flags & TCP_FIN) {
1162 if(uip_outstanding(uip_connr)) {
1163 goto drop;
1164 }
1165 uip_add_rcv_nxt(1 + uip_len);
1166 uip_flags = UIP_CLOSE;
1167 if(uip_len > 0) {
1168 uip_flags |= UIP_NEWDATA;
1169 }
1170 UIP_APPCALL();
1171 uip_connr->len = 1;
1172 uip_connr->tcpstateflags = LAST_ACK;
1173 uip_connr->nrtx = 0;
1174 tcp_send_finack:
1175 BUF->flags = TCP_FIN | TCP_ACK;
1176 goto tcp_send_nodata;
1177 }
1178
1179 /* Check the URG flag. If this is set, the segment carries urgent
1180 data that we must pass to the application. */
1181 if(BUF->flags & TCP_URG) {
1182#if UIP_URGDATA > 0
1183 uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1];
1184 if(uip_urglen > uip_len) {
1185 /* There is more urgent data in the next segment to come. */
1186 uip_urglen = uip_len;
1187 }
1188 uip_add_rcv_nxt(uip_urglen);
1189 uip_len -= uip_urglen;
1190 uip_urgdata = uip_appdata;
1191 uip_appdata += uip_urglen;
1192 } else {
1193 uip_urglen = 0;
1194#endif /* UIP_URGDATA > 0 */
1195 uip_appdata += (BUF->urgp[0] << 8) | BUF->urgp[1];
1196 uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1];
1197 }
1198
1199
1200 /* If uip_len > 0 we have TCP data in the packet, and we flag this
1201 by setting the UIP_NEWDATA flag and update the sequence number
1202 we acknowledge. If the application has stopped the dataflow
1203 using uip_stop(), we must not accept any data packets from the
1204 remote host. */
1205 if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) {
1206 uip_flags |= UIP_NEWDATA;
1207 uip_add_rcv_nxt(uip_len);
1208 }
1209
1210
1211 /* If this packet constitutes an ACK for outstanding data (flagged
1212 by the UIP_ACKDATA flag, we should call the application since it
1213 might want to send more data. If the incoming packet had data
1214 from the peer (as flagged by the UIP_NEWDATA flag), the
1215 application must also be notified.
1216
1217 When the application is called, the global variable uip_len
1218 contains the length of the incoming data. The application can
1219 access the incoming data through the global pointer
1220 uip_appdata, which usually points 40 bytes into the uip_buf
1221 array.
1222
1223 If the application wishes to send any data, this data should be
1224 put into the uip_appdata and the length of the data should be
1225 put into uip_len. If the application don't have any data to
1226 send, uip_len must be set to 0. */
1227 if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) {
1228 uip_slen = 0;
1229 UIP_APPCALL();
1230
1231 appsend:
1232 if(uip_flags & UIP_ABORT) {
1233 uip_slen = 0;
1234 uip_connr->tcpstateflags = CLOSED;
1235 BUF->flags = TCP_RST | TCP_ACK;
1236 goto tcp_send_nodata;
1237 }
1238
1239 if(uip_flags & UIP_CLOSE) {
1240 uip_slen = 0;
1241 uip_connr->len = 1;
1242 uip_connr->tcpstateflags = FIN_WAIT_1;
1243 uip_connr->nrtx = 0;
1244 BUF->flags = TCP_FIN | TCP_ACK;
1245 goto tcp_send_nodata;
1246 }
1247
1248 /* If uip_slen > 0, the application has data to be sent. We
1249 cannot send data if the application already has outstanding
1250 data. */
1251 if(uip_slen > 0 &&
1252 !uip_outstanding(uip_connr)) {
1253 uip_connr->nrtx = 0;
1254 uip_connr->len = uip_slen;
adamdunkelsab4b0822003-07-30 23:31:40 +00001255 } else {
1256 uip_connr->nrtx = 0;
1257 uip_slen = uip_connr->len;
adamdunkelsca9ddcb2003-03-19 14:13:31 +00001258 }
1259 apprexmit:
1260 /* If the application has data to be sent, or if the incoming
1261 packet had new data in it, we must send out a packet. */
adamdunkels759185d2003-06-30 20:35:41 +00001262 if(uip_slen > 0 && uip_connr->len > 0) {
adamdunkelsca9ddcb2003-03-19 14:13:31 +00001263 /* Add the length of the IP and TCP headers. */
1264 uip_len = uip_connr->len + UIP_TCPIP_HLEN;
1265 /* We always set the ACK flag in response packets. */
adamdunkels759185d2003-06-30 20:35:41 +00001266 BUF->flags = TCP_ACK | TCP_PSH;
adamdunkelsca9ddcb2003-03-19 14:13:31 +00001267 /* Send the packet. */
1268 goto tcp_send_noopts;
1269 }
adamdunkels759185d2003-06-30 20:35:41 +00001270 /* If there is no data to send, just send out a pure ACK if
1271 there is newdata. */
1272 if(uip_flags & UIP_NEWDATA) {
1273 uip_len = UIP_TCPIP_HLEN;
1274 BUF->flags = TCP_ACK;
1275 goto tcp_send_noopts;
1276 }
adamdunkelsca9ddcb2003-03-19 14:13:31 +00001277 }
1278 goto drop;
1279 case LAST_ACK:
1280 /* We can close this connection if the peer has acknowledged our
1281 FIN. This is indicated by the UIP_ACKDATA flag. */
1282 if(uip_flags & UIP_ACKDATA) {
1283 uip_connr->tcpstateflags = CLOSED;
1284 uip_flags = UIP_CLOSE;
1285 UIP_APPCALL();
1286 }
1287 break;
1288
1289 case FIN_WAIT_1:
1290 /* The application has closed the connection, but the remote host
1291 hasn't closed its end yet. Thus we do nothing but wait for a
1292 FIN from the other side. */
1293 if(uip_len > 0) {
1294 uip_add_rcv_nxt(uip_len);
1295 }
1296 if(BUF->flags & TCP_FIN) {
1297 if(uip_flags & UIP_ACKDATA) {
1298 uip_connr->tcpstateflags = TIME_WAIT;
1299 uip_connr->timer = 0;
1300 uip_connr->len = 0;
1301 } else {
1302 uip_connr->tcpstateflags = CLOSING;
1303 }
1304 uip_add_rcv_nxt(1);
1305 uip_flags = UIP_CLOSE;
1306 UIP_APPCALL();
1307 goto tcp_send_ack;
1308 } else if(uip_flags & UIP_ACKDATA) {
1309 uip_connr->tcpstateflags = FIN_WAIT_2;
1310 uip_connr->len = 0;
1311 goto drop;
1312 }
1313 if(uip_len > 0) {
1314 goto tcp_send_ack;
1315 }
1316 goto drop;
1317
1318 case FIN_WAIT_2:
1319 if(uip_len > 0) {
1320 uip_add_rcv_nxt(uip_len);
1321 }
1322 if(BUF->flags & TCP_FIN) {
1323 uip_connr->tcpstateflags = TIME_WAIT;
1324 uip_connr->timer = 0;
1325 uip_add_rcv_nxt(1);
1326 uip_flags = UIP_CLOSE;
1327 UIP_APPCALL();
1328 goto tcp_send_ack;
1329 }
1330 if(uip_len > 0) {
1331 goto tcp_send_ack;
1332 }
1333 goto drop;
1334
1335 case TIME_WAIT:
1336 goto tcp_send_ack;
1337
1338 case CLOSING:
1339 if(uip_flags & UIP_ACKDATA) {
1340 uip_connr->tcpstateflags = TIME_WAIT;
1341 uip_connr->timer = 0;
1342 }
1343 }
1344 goto drop;
1345
1346
1347 /* We jump here when we are ready to send the packet, and just want
1348 to set the appropriate TCP sequence numbers in the TCP header. */
1349 tcp_send_ack:
1350 BUF->flags = TCP_ACK;
1351 tcp_send_nodata:
1352 uip_len = 40;
1353 tcp_send_noopts:
1354 BUF->tcpoffset = 5 << 4;
1355 tcp_send:
1356 /* We're done with the input processing. We are now ready to send a
1357 reply. Our job is to fill in all the fields of the TCP and IP
1358 headers before calculating the checksum and finally send the
1359 packet. */
1360 BUF->ackno[0] = uip_connr->rcv_nxt[0];
1361 BUF->ackno[1] = uip_connr->rcv_nxt[1];
1362 BUF->ackno[2] = uip_connr->rcv_nxt[2];
1363 BUF->ackno[3] = uip_connr->rcv_nxt[3];
1364
1365 BUF->seqno[0] = uip_connr->snd_nxt[0];
1366 BUF->seqno[1] = uip_connr->snd_nxt[1];
1367 BUF->seqno[2] = uip_connr->snd_nxt[2];
1368 BUF->seqno[3] = uip_connr->snd_nxt[3];
1369
1370 BUF->proto = UIP_PROTO_TCP;
1371
1372 BUF->srcport = uip_connr->lport;
1373 BUF->destport = uip_connr->rport;
1374
adamdunkelsca9ddcb2003-03-19 14:13:31 +00001375 BUF->srcipaddr[0] = uip_hostaddr[0];
1376 BUF->srcipaddr[1] = uip_hostaddr[1];
1377 BUF->destipaddr[0] = uip_connr->ripaddr[0];
1378 BUF->destipaddr[1] = uip_connr->ripaddr[1];
1379
adamdunkelsca9ddcb2003-03-19 14:13:31 +00001380
1381 if(uip_connr->tcpstateflags & UIP_STOPPED) {
1382 /* If the connection has issued uip_stop(), we advertise a zero
1383 window so that the remote host will stop sending data. */
1384 BUF->wnd[0] = BUF->wnd[1] = 0;
1385 } else {
1386#if (UIP_TCP_MSS) > 255
1387 BUF->wnd[0] = (uip_connr->mss >> 8);
1388#else
1389 BUF->wnd[0] = 0;
1390#endif /* UIP_MSS */
1391 BUF->wnd[1] = (uip_connr->mss & 0xff);
1392 }
1393
1394 tcp_send_noconn:
1395
1396#if UIP_BUFSIZE > 255
1397 BUF->len[0] = (uip_len >> 8);
1398 BUF->len[1] = (uip_len & 0xff);
1399#else
1400 BUF->len[0] = 0;
1401 BUF->len[1] = uip_len;
1402#endif /* UIP_BUFSIZE > 255 */
1403
1404 /* Calculate TCP checksum. */
1405 BUF->tcpchksum = 0;
1406 BUF->tcpchksum = ~(uip_tcpchksum());
1407
1408 ip_send_nolen:
1409
adamdunkelsca9ddcb2003-03-19 14:13:31 +00001410 BUF->vhl = 0x45;
1411 BUF->tos = 0;
1412 BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
1413 BUF->ttl = UIP_TTL;
1414 ++ipid;
1415 BUF->ipid[0] = ipid >> 8;
1416 BUF->ipid[1] = ipid & 0xff;
1417
1418 /* Calculate IP checksum. */
1419 BUF->ipchksum = 0;
1420 BUF->ipchksum = ~(uip_ipchksum());
adamdunkelsca9ddcb2003-03-19 14:13:31 +00001421
1422 UIP_STAT(++uip_stat.tcp.sent);
1423 send:
1424 UIP_STAT(++uip_stat.ip.sent);
1425 /* Return and let the caller do the actual transmission. */
1426 return;
1427 drop:
1428 uip_len = 0;
1429 return;
1430}
1431/*-----------------------------------------------------------------------------------*/
adamdunkels47ec7fa2003-03-28 12:11:17 +00001432u16_t
1433htons(u16_t val)
1434{
1435 return HTONS(val);
1436}
1437/*-----------------------------------------------------------------------------------*/