OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [uIP_Demo_IAR_ARM7/] [uip/] [uip.c] - Blame information for rev 712

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.