OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [Common/] [ethernet/] [FreeRTOS-uIP/] [uip.c] - Blame information for rev 615

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

Line No. Rev Author Line
1 606 jeremybenn
#define DEBUG_PRINTF( ... )             /*printf(__VA_ARGS__)*/
2
 
3
/**
4
 * \defgroup uip The uIP TCP/IP stack
5
 * @{
6
 *
7
 * uIP is an implementation of the TCP/IP protocol stack intended for
8
 * small 8-bit and 16-bit microcontrollers.
9
 *
10
 * uIP provides the necessary protocols for Internet communication,
11
 * with a very small code footprint and RAM requirements - the uIP
12
 * code size is on the order of a few kilobytes and RAM usage is on
13
 * the order of a few hundred bytes.
14
 */
15
 
16
/**
17
 * \file
18
 * The uIP TCP/IP stack code.
19
 * \author Adam Dunkels <adam@dunkels.com>
20
 */
21
 
22
/*
23
 * Copyright (c) 2001-2003, Adam Dunkels.
24
 * All rights reserved.
25
 *
26
 * Redistribution and use in source and binary forms, with or without
27
 * modification, are permitted provided that the following conditions
28
 * are met:
29
 * 1. Redistributions of source code must retain the above copyright
30
 *    notice, this list of conditions and the following disclaimer.
31
 * 2. Redistributions in binary form must reproduce the above copyright
32
 *    notice, this list of conditions and the following disclaimer in the
33
 *    documentation and/or other materials provided with the distribution.
34
 * 3. The name of the author may not be used to endorse or promote
35
 *    products derived from this software without specific prior
36
 *    written permission.
37
 *
38
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
39
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
40
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
42
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
43
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
44
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
45
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
46
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
47
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
48
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
49
 *
50
 * This file is part of the uIP TCP/IP stack.
51
 *
52
 * $Id: uip.c 2 2011-07-17 20:13:17Z filepang@gmail.com $
53
 *
54
 */
55
 
56
/*
57
 * uIP is a small implementation of the IP, UDP and TCP protocols (as
58
 * well as some basic ICMP stuff). The implementation couples the IP,
59
 * UDP, TCP and the application layers very tightly. To keep the size
60
 * of the compiled code down, this code frequently uses the goto
61
 * statement. While it would be possible to break the uip_process()
62
 * function into many smaller functions, this would increase the code
63
 * size because of the overhead of parameter passing and the fact that
64
 * the optimier would not be as efficient.
65
 *
66
 * The principle is that we have a small buffer, called the uip_buf,
67
 * in which the device driver puts an incoming packet. The TCP/IP
68
 * stack parses the headers in the packet, and calls the
69
 * application. If the remote host has sent data to the application,
70
 * this data is present in the uip_buf and the application read the
71
 * data from there. It is up to the application to put this data into
72
 * a byte stream if needed. The application will not be fed with data
73
 * that is out of sequence.
74
 *
75
 * If the application whishes to send data to the peer, it should put
76
 * its data into the uip_buf. The uip_appdata pointer points to the
77
 * first available byte. The TCP/IP stack will calculate the
78
 * checksums, and fill in the necessary header fields and finally send
79
 * the packet back to the peer.
80
*/
81
#include "uip.h"
82
#include "uipopt.h"
83
#include "uip_arch.h"
84
#include "uip_arp.h"
85
#include "FreeRTOS.h"
86
 
87
#if UIP_CONF_IPV6
88
        #include "uip-neighbor.h"
89
#endif /* UIP_CONF_IPV6 */
90
 
91
#include <string.h>
92
 
93
/*---------------------------------------------------------------------------*/
94
 
95
/* Variable definitions. */
96
 
97
/* The IP address of this host. If it is defined to be fixed (by
98
   setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set
99
   here. Otherwise, the address */
100
#if UIP_FIXEDADDR > 0
101
const uip_ipaddr_t                      uip_hostaddr = { HTONS( (UIP_IPADDR0 << 8) | UIP_IPADDR1 ), HTONS( (UIP_IPADDR2 << 8) | UIP_IPADDR3 ) };
102
const uip_ipaddr_t                      uip_draddr = { HTONS( (UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1 ), HTONS( (UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3 ) };
103
const uip_ipaddr_t                      uip_netmask = { HTONS( (UIP_NETMASK0 << 8) | UIP_NETMASK1 ), HTONS( (UIP_NETMASK2 << 8) | UIP_NETMASK3 ) };
104
#else
105
uip_ipaddr_t                            uip_hostaddr, uip_draddr, uip_netmask;
106
#endif /* UIP_FIXEDADDR */
107
 
108
static const uip_ipaddr_t       all_ones_addr =
109
#if UIP_CONF_IPV6
110
{ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff };
111
#else /* UIP_CONF_IPV6 */
112
{
113
        0xffff, 0xffff
114
};
115
#endif /* UIP_CONF_IPV6 */
116
static const uip_ipaddr_t       all_zeroes_addr =
117
#if UIP_CONF_IPV6
118
{ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 };
119
#else /* UIP_CONF_IPV6 */
120
{
121
        0x0000, 0x0000
122
};
123
#endif /* UIP_CONF_IPV6 */
124
 
125
#if UIP_FIXEDETHADDR
126
const struct uip_eth_addr       uip_ethaddr = { { UIP_ETHADDR0, UIP_ETHADDR1, UIP_ETHADDR2, UIP_ETHADDR3, UIP_ETHADDR4, UIP_ETHADDR5 } };
127
#else
128
struct uip_eth_addr                     uip_ethaddr = { { 0, 0, 0, 0, 0, 0 } };
129
#endif
130
#ifndef UIP_CONF_EXTERNAL_BUFFER
131
        #ifdef __ICCARM__
132
                #pragma data_alignment = 4
133
u8_t uip_buf[UIP_BUFSIZE + 2];  /* The packet buffer that contains incoming packets. */
134
        #else
135
u8_t                            uip_buf[UIP_BUFSIZE + 2] ALIGN_STRUCT_END;      /* The packet buffer that contains incoming packets. */
136
        #endif
137
#endif /* UIP_CONF_EXTERNAL_BUFFER */
138
 
139
void                            *uip_appdata;                           /* The uip_appdata pointer points to
140
                                    application data. */
141
void                            *uip_sappdata;                          /* The uip_appdata pointer points to
142
                                    the application data which is to
143
                                    be sent. */
144
#if UIP_URGDATA > 0
145
void                            *uip_urgdata;                           /* The uip_urgdata pointer points to
146
                                    urgent data (out-of-band data), if
147
                                    present. */
148
u16_t                           uip_urglen, uip_surglen;
149
#endif /* UIP_URGDATA > 0 */
150
 
151
u16_t                           uip_len, uip_slen;
152
 
153
/* The uip_len is either 8 or 16 bits,
154
                                depending on the maximum packet
155
                                size. */
156
u8_t                            uip_flags;                                      /* The uip_flags variable is used for
157
                                communication between the TCP/IP stack
158
                                and the application program. */
159
struct uip_conn         *uip_conn;                                      /* uip_conn always points to the current
160
                                connection. */
161
 
162
struct uip_conn         uip_conns[UIP_CONNS];
163
 
164
/* The uip_conns array holds all TCP
165
                                connections. */
166
u16_t                           uip_listenports[UIP_LISTENPORTS];
167
 
168
/* The uip_listenports list all currently
169
                                listning ports. */
170
#if UIP_UDP
171
struct uip_udp_conn *uip_udp_conn;
172
struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
173
#endif /* UIP_UDP */
174
 
175
static u16_t            ipid;                                           /* Ths ipid variable is an increasing
176
                                number that is used for the IP ID
177
                                field. */
178
 
179
void uip_setipid( u16_t id )
180
{
181
        ipid = id;
182
}
183
 
184
static u8_t             iss[4];                                                 /* The iss variable is used for the TCP
185
                                initial sequence number. */
186
 
187
#if UIP_ACTIVE_OPEN
188
static u16_t    lastport;                                               /* Keeps track of the last port used for
189
                                a new connection. */
190
#endif /* UIP_ACTIVE_OPEN */
191
 
192
/* Temporary variables. */
193
u8_t                    uip_acc32[4];
194
static u8_t             c, opt;
195
static u16_t    tmp16;
196
 
197
/* Structures and definitions. */
198
#define TCP_FIN                                                         0x01
199
#define TCP_SYN                                                         0x02
200
#define TCP_RST                                                         0x04
201
#define TCP_PSH                                                         0x08
202
#define TCP_ACK                                                         0x10
203
#define TCP_URG                                                         0x20
204
#define TCP_CTL                                                         0x3f
205
 
206
#define TCP_OPT_END                                                     0        /* End of TCP options list */
207
#define TCP_OPT_NOOP                                            1       /* "No-operation" TCP option */
208
#define TCP_OPT_MSS                                                     2       /* Maximum segment size TCP option */
209
 
210
#define TCP_OPT_MSS_LEN                                         4       /* Length of TCP MSS option. */
211
 
212
#define ICMP_ECHO_REPLY                                         0
213
#define ICMP_ECHO                                                       8
214
 
215
#define ICMP6_ECHO_REPLY                                        129
216
#define ICMP6_ECHO                                                      128
217
#define ICMP6_NEIGHBOR_SOLICITATION                     135
218
#define ICMP6_NEIGHBOR_ADVERTISEMENT            136
219
 
220
#define ICMP6_FLAG_S                                            ( 1 << 6 )
221
#define ICMP6_OPTION_SOURCE_LINK_ADDRESS        1
222
#define ICMP6_OPTION_TARGET_LINK_ADDRESS        2
223
 
224
/* Macros. */
225
#define BUF             ( ( struct uip_tcpip_hdr * ) &uip_buf[UIP_LLH_LEN] )
226
#define FBUF    ( ( struct uip_tcpip_hdr * ) &uip_reassbuf[0] )
227
#define ICMPBUF ( ( struct uip_icmpip_hdr * ) &uip_buf[UIP_LLH_LEN] )
228
#define UDPBUF  ( ( struct uip_udpip_hdr * ) &uip_buf[UIP_LLH_LEN] )
229
#if UIP_STATISTICS == 1
230
struct uip_stats        uip_stat;
231
        #define UIP_STAT( s )   s
232
#else
233
        #define UIP_STAT( s )
234
#endif /* UIP_STATISTICS == 1 */
235
 
236
#if UIP_LOGGING == 1
237
        #include <stdio.h>
238
void    uip_log( char *msg );
239
        #define UIP_LOG( m )    uip_log( m )
240
#else
241
        #define UIP_LOG( m )
242
#endif /* UIP_LOGGING == 1 */
243
 
244
#if !UIP_ARCH_ADD32
245
void uip_add32( u8_t *op32, u16_t op16 )
246
{
247
        uip_acc32[3] = op32[3] + ( op16 & 0xff );
248
        uip_acc32[2] = op32[2] + ( op16 >> 8 );
249
        uip_acc32[1] = op32[1];
250
        uip_acc32[0] = op32[0];
251
 
252
        if( uip_acc32[2] < (op16 >> 8) )
253
        {
254
                ++uip_acc32[1];
255
                if( uip_acc32[1] == 0 )
256
                {
257
                        ++uip_acc32[0];
258
                }
259
        }
260
 
261
        if( uip_acc32[3] < (op16 & 0xff) )
262
        {
263
                ++uip_acc32[2];
264
                if( uip_acc32[2] == 0 )
265
                {
266
                        ++uip_acc32[1];
267
                        if( uip_acc32[1] == 0 )
268
                        {
269
                                ++uip_acc32[0];
270
                        }
271
                }
272
        }
273
}
274
 
275
#endif /* UIP_ARCH_ADD32 */
276
 
277
#if !UIP_ARCH_CHKSUM
278
 
279
/*---------------------------------------------------------------------------*/
280
static u16_t chksum( u16_t sum, const u8_t *data, u16_t len )
281
{
282
        u16_t           t;
283
        const u8_t      *dataptr;
284
        const u8_t      *last_byte;
285
 
286
        dataptr = data;
287
        last_byte = data + len - 1;
288
 
289
        while( dataptr < last_byte )
290
        {                               /* At least two more bytes */
291
                t = ( dataptr[0] << 8 ) + dataptr[1];
292
                sum += t;
293
                if( sum < t )
294
                {
295
                        sum++;  /* carry */
296
                }
297
 
298
                dataptr += 2;
299
        }
300
 
301
        if( dataptr == last_byte )
302
        {
303
                t = ( dataptr[0] << 8 ) + 0;
304
                sum += t;
305
                if( sum < t )
306
                {
307
                        sum++;  /* carry */
308
                }
309
        }
310
 
311
        /* Return sum in host byte order. */
312
        return sum;
313
}
314
 
315
/*---------------------------------------------------------------------------*/
316
u16_t uip_chksum( u16_t *data, u16_t len )
317
{
318
        return htons( chksum(0, ( u8_t * ) data, len) );
319
}
320
 
321
/*---------------------------------------------------------------------------*/
322
        #ifndef UIP_ARCH_IPCHKSUM
323
u16_t uip_ipchksum( void )
324
{
325
        u16_t   sum;
326
 
327
        sum = chksum( 0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN );
328
        DEBUG_PRINTF( "uip_ipchksum: sum 0x%04x\n", sum );
329
        return( sum == 0 ) ? 0xffff : htons( sum );
330
}
331
 
332
        #endif
333
 
334
/*---------------------------------------------------------------------------*/
335
static u16_t upper_layer_chksum( u8_t proto )
336
{
337
        u16_t   upper_layer_len;
338
        u16_t   sum;
339
 
340
                #if UIP_CONF_IPV6
341
        upper_layer_len = ( ((u16_t) (BUF->len[0]) << 8) + BUF->len[1] );
342
                #else /* UIP_CONF_IPV6 */
343
        upper_layer_len = ( ((u16_t) (BUF->len[0]) << 8) + BUF->len[1] ) - UIP_IPH_LEN;
344
                #endif /* UIP_CONF_IPV6 */
345
 
346
        /* First sum pseudoheader. */
347
 
348
        /* IP protocol and length fields. This addition cannot carry. */
349
        sum = upper_layer_len + proto;
350
 
351
        /* Sum IP source and destination addresses. */
352
        sum = chksum( sum, ( u8_t * ) &BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t) );
353
 
354
        /* Sum TCP header and data. */
355
        sum = chksum( sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], upper_layer_len );
356
 
357
        return( sum == 0 ) ? 0xffff : htons( sum );
358
}
359
 
360
/*---------------------------------------------------------------------------*/
361
        #if UIP_CONF_IPV6
362
u16_t uip_icmp6chksum( void )
363
{
364
        return upper_layer_chksum( UIP_PROTO_ICMP6 );
365
}
366
 
367
        #endif /* UIP_CONF_IPV6 */
368
 
369
/*---------------------------------------------------------------------------*/
370
u16_t uip_tcpchksum( void )
371
{
372
        return upper_layer_chksum( UIP_PROTO_TCP );
373
}
374
 
375
/*---------------------------------------------------------------------------*/
376
        #if UIP_UDP_CHECKSUMS
377
u16_t uip_udpchksum( void )
378
{
379
        return upper_layer_chksum( UIP_PROTO_UDP );
380
}
381
 
382
        #endif /* UIP_UDP_CHECKSUMS */
383
#endif /* UIP_ARCH_CHKSUM */
384
 
385
/*---------------------------------------------------------------------------*/
386
void uip_init( void )
387
{
388
        for( c = 0; c < UIP_LISTENPORTS; ++c )
389
        {
390
                uip_listenports[c] = 0;
391
        }
392
 
393
        for( c = 0; c < UIP_CONNS; ++c )
394
        {
395
                uip_conns[c].tcpstateflags = UIP_CLOSED;
396
        }
397
 
398
        #if UIP_ACTIVE_OPEN
399
        lastport = 1024;
400
        #endif /* UIP_ACTIVE_OPEN */
401
 
402
        #if UIP_UDP
403
        for( c = 0; c < UIP_UDP_CONNS; ++c )
404
        {
405
                uip_udp_conns[c].lport = 0;
406
        }
407
 
408
        #endif /* UIP_UDP */
409
 
410
        /* IPv4 initialization. */
411
        #if UIP_FIXEDADDR == 0
412
 
413
        /*  uip_hostaddr[0] = uip_hostaddr[1] = 0;*/
414
        #endif /* UIP_FIXEDADDR */
415
}
416
 
417
/*---------------------------------------------------------------------------*/
418
#if UIP_ACTIVE_OPEN
419
struct uip_conn *uip_connect( uip_ipaddr_t *ripaddr, u16_t rport )
420
{
421
        register struct uip_conn        *conn, *cconn;
422
 
423
        /* Find an unused local port. */
424
again:
425
        ++lastport;
426
 
427
        if( lastport >= 32000 )
428
        {
429
                lastport = 4096;
430
        }
431
 
432
        /* Check if this port is already in use, and if so try to find
433
     another one. */
434
        for( c = 0; c < UIP_CONNS; ++c )
435
        {
436
                conn = &uip_conns[c];
437
                if( conn->tcpstateflags != UIP_CLOSED && conn->lport == htons(lastport) )
438
                {
439
                        goto again;
440
                }
441
        }
442
 
443
        conn = 0;
444
        for( c = 0; c < UIP_CONNS; ++c )
445
        {
446
                cconn = &uip_conns[c];
447
                if( cconn->tcpstateflags == UIP_CLOSED )
448
                {
449
                        conn = cconn;
450
                        break;
451
                }
452
 
453
                if( cconn->tcpstateflags == UIP_TIME_WAIT )
454
                {
455
                        if( conn == 0 || cconn->timer > conn->timer )
456
                        {
457
                                conn = cconn;
458
                        }
459
                }
460
        }
461
 
462
        if( conn == 0 )
463
        {
464
                return 0;
465
        }
466
 
467
        conn->tcpstateflags = UIP_SYN_SENT;
468
 
469
        conn->snd_nxt[0] = iss[0];
470
        conn->snd_nxt[1] = iss[1];
471
        conn->snd_nxt[2] = iss[2];
472
        conn->snd_nxt[3] = iss[3];
473
 
474
        conn->initialmss = conn->mss = UIP_TCP_MSS;
475
 
476
        conn->len = 1;          /* TCP length of the SYN is one. */
477
        conn->nrtx = 0;
478
        conn->timer = 1;        /* Send the SYN next time around. */
479
        conn->rto = UIP_RTO;
480
        conn->sa = 0;
481
        conn->sv = 16;          /* Initial value of the RTT variance. */
482
        conn->lport = htons( lastport );
483
        conn->rport = rport;
484
        uip_ipaddr_copy( &conn->ripaddr, ripaddr );
485
 
486
        return conn;
487
}
488
 
489
#endif /* UIP_ACTIVE_OPEN */
490
 
491
/*---------------------------------------------------------------------------*/
492
#if UIP_UDP
493
struct uip_udp_conn *uip_udp_new( uip_ipaddr_t *ripaddr, u16_t rport )
494
{
495
        register struct uip_udp_conn    *conn;
496
 
497
        /* Find an unused local port. */
498
again:
499
        ++lastport;
500
 
501
        if( lastport >= 32000 )
502
        {
503
                lastport = 4096;
504
        }
505
 
506
        for( c = 0; c < UIP_UDP_CONNS; ++c )
507
        {
508
                if( uip_udp_conns[c].lport == htons(lastport) )
509
                {
510
                        goto again;
511
                }
512
        }
513
 
514
        conn = 0;
515
        for( c = 0; c < UIP_UDP_CONNS; ++c )
516
        {
517
                if( uip_udp_conns[c].lport == 0 )
518
                {
519
                        conn = &uip_udp_conns[c];
520
                        break;
521
                }
522
        }
523
 
524
        if( conn == 0 )
525
        {
526
                return 0;
527
        }
528
 
529
        conn->lport = HTONS( lastport );
530
        conn->rport = rport;
531
        if( ripaddr == NULL )
532
        {
533
                memset( conn->ripaddr, 0, sizeof(uip_ipaddr_t) );
534
        }
535
        else
536
        {
537
                uip_ipaddr_copy( &conn->ripaddr, ripaddr );
538
        }
539
 
540
        conn->ttl = UIP_TTL;
541
 
542
        return conn;
543
}
544
 
545
#endif /* UIP_UDP */
546
 
547
/*---------------------------------------------------------------------------*/
548
void uip_unlisten( u16_t port )
549
{
550
        for( c = 0; c < UIP_LISTENPORTS; ++c )
551
        {
552
                if( uip_listenports[c] == port )
553
                {
554
                        uip_listenports[c] = 0;
555
                        return;
556
                }
557
        }
558
}
559
 
560
/*---------------------------------------------------------------------------*/
561
void uip_listen( u16_t port )
562
{
563
        for( c = 0; c < UIP_LISTENPORTS; ++c )
564
        {
565
                if( uip_listenports[c] == 0 )
566
                {
567
                        uip_listenports[c] = port;
568
                        return;
569
                }
570
        }
571
}
572
 
573
/*---------------------------------------------------------------------------*/
574
 
575
/* XXX: IP fragment reassembly: not well-tested. */
576
#if UIP_REASSEMBLY && !UIP_CONF_IPV6
577
        #define UIP_REASS_BUFSIZE       ( UIP_BUFSIZE - UIP_LLH_LEN )
578
static u8_t                     uip_reassbuf[UIP_REASS_BUFSIZE];
579
static u8_t                     uip_reassbitmap[UIP_REASS_BUFSIZE / ( 8 * 8 )];
580
static const u8_t       bitmap_bits[8] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
581
static u16_t            uip_reasslen;
582
static u8_t                     uip_reassflags;
583
        #define UIP_REASS_FLAG_LASTFRAG 0x01
584
static u8_t                     uip_reasstmr;
585
 
586
        #define IP_MF   0x20
587
 
588
static u8_t uip_reass( void )
589
{
590
        u16_t   offset, len;
591
        u16_t   i;
592
 
593
        /* If ip_reasstmr is zero, no packet is present in the buffer, so we
594
     write the IP header of the fragment into the reassembly
595
     buffer. The timer is updated with the maximum age. */
596
        if( uip_reasstmr == 0 )
597
        {
598
                memcpy( uip_reassbuf, &BUF->vhl, UIP_IPH_LEN );
599
                uip_reasstmr = UIP_REASS_MAXAGE;
600
                uip_reassflags = 0;
601
 
602
                /* Clear the bitmap. */
603
                memset( uip_reassbitmap, 0, sizeof(uip_reassbitmap) );
604
        }
605
 
606
        /* Check if the incoming fragment matches the one currently present
607
     in the reasembly buffer. If so, we proceed with copying the
608
     fragment into the buffer. */
609
        if
610
        (
611
                BUF->srcipaddr[0] == FBUF->srcipaddr[0] &&
612
                BUF->srcipaddr[1] == FBUF->srcipaddr[1] &&
613
                BUF->destipaddr[0] == FBUF->destipaddr[0] &&
614
                BUF->destipaddr[1] == FBUF->destipaddr[1] &&
615
                BUF->ipid[0] == FBUF->ipid[0] &&
616
                BUF->ipid[1] == FBUF->ipid[1]
617
        )
618
        {
619
                len = ( BUF->len[0] << 8 ) + BUF->len[1] - ( BUF->vhl & 0x0f ) * 4;
620
                offset = ( ((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1] ) * 8;
621
 
622
                /* If the offset or the offset + fragment length overflows the
623
       reassembly buffer, we discard the entire packet. */
624
                if( offset > UIP_REASS_BUFSIZE || offset + len > UIP_REASS_BUFSIZE )
625
                {
626
                        uip_reasstmr = 0;
627
                        goto nullreturn;
628
                }
629
 
630
                /* Copy the fragment into the reassembly buffer, at the right
631
       offset. */
632
                memcpy( &uip_reassbuf[UIP_IPH_LEN + offset], ( char * ) BUF + ( int ) ((BUF->vhl & 0x0f) * 4), len );
633
 
634
                /* Update the bitmap. */
635
                if( offset / (8 * 8) == (offset + len) / (8 * 8) )
636
                {
637
                        /* If the two endpoints are in the same byte, we only update
638
         that byte. */
639
                        uip_reassbitmap[offset / ( 8 * 8 )] |= bitmap_bits[( offset / 8 ) & 7] &~bitmap_bits[( (offset + len) / 8 ) & 7];
640
                }
641
                else
642
                {
643
                        /* If the two endpoints are in different bytes, we update the
644
         bytes in the endpoints and fill the stuff inbetween with
645
         0xff. */
646
                        uip_reassbitmap[offset / ( 8 * 8 )] |= bitmap_bits[( offset / 8 ) & 7];
647
                        for( i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i )
648
                        {
649
                                uip_reassbitmap[i] = 0xff;
650
                        }
651
 
652
                        uip_reassbitmap[( offset + len ) / ( 8 * 8 )] |= ~bitmap_bits[( (offset + len) / 8 ) & 7];
653
                }
654
 
655
                /* If this fragment has the More Fragments flag set to zero, we
656
       know that this is the last fragment, so we can calculate the
657
       size of the entire packet. We also set the
658
       IP_REASS_FLAG_LASTFRAG flag to indicate that we have received
659
       the final fragment. */
660
                if( (BUF->ipoffset[0] & IP_MF) == 0 )
661
                {
662
                        uip_reassflags |= UIP_REASS_FLAG_LASTFRAG;
663
                        uip_reasslen = offset + len;
664
                }
665
 
666
                /* Finally, we check if we have a full packet in the buffer. We do
667
       this by checking if we have the last fragment and if all bits
668
       in the bitmap are set. */
669
                if( uip_reassflags & UIP_REASS_FLAG_LASTFRAG )
670
                {
671
                        /* Check all bytes up to and including all but the last byte in
672
         the bitmap. */
673
                        for( i = 0; i < uip_reasslen / (8 * 8) - 1; ++i )
674
                        {
675
                                if( uip_reassbitmap[i] != 0xff )
676
                                {
677
                                        goto nullreturn;
678
                                }
679
                        }
680
 
681
                        /* Check the last byte in the bitmap. It should contain just the
682
         right amount of bits. */
683
                        if( uip_reassbitmap[uip_reasslen / (8 * 8)] != (u8_t)~bitmap_bits[uip_reasslen / 8 & 7] )
684
                        {
685
                                goto nullreturn;
686
                        }
687
 
688
                        /* If we have come this far, we have a full packet in the
689
         buffer, so we allocate a pbuf and copy the packet into it. We
690
         also reset the timer. */
691
                        uip_reasstmr = 0;
692
                        memcpy( BUF, FBUF, uip_reasslen );
693
 
694
                        /* Pretend to be a "normal" (i.e., not fragmented) IP packet
695
         from now on. */
696
                        BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
697
                        BUF->len[0] = uip_reasslen >> 8;
698
                        BUF->len[1] = uip_reasslen & 0xff;
699
                        BUF->ipchksum = 0;
700
                        BUF->ipchksum = ~( uip_ipchksum() );
701
 
702
                        return uip_reasslen;
703
                }
704
        }
705
 
706
nullreturn:
707
        return 0;
708
}
709
 
710
#endif /* UIP_REASSEMBLY */
711
 
712
/*---------------------------------------------------------------------------*/
713
static void uip_add_rcv_nxt( u16_t n )
714
{
715
        uip_add32( uip_conn->rcv_nxt, n );
716
        uip_conn->rcv_nxt[0] = uip_acc32[0];
717
        uip_conn->rcv_nxt[1] = uip_acc32[1];
718
        uip_conn->rcv_nxt[2] = uip_acc32[2];
719
        uip_conn->rcv_nxt[3] = uip_acc32[3];
720
}
721
 
722
/*---------------------------------------------------------------------------*/
723
void uip_process( u8_t flag )
724
{
725
        register struct uip_conn        *uip_connr = uip_conn;
726
 
727
        #if UIP_UDP
728
        if( flag == UIP_UDP_SEND_CONN )
729
        {
730
                goto udp_send;
731
        }
732
 
733
        #endif /* UIP_UDP */
734
 
735
        uip_sappdata = uip_appdata = &uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN];
736
 
737
        /* Check if we were invoked because of a poll request for a
738
     particular connection. */
739
        if( flag == UIP_POLL_REQUEST )
740
        {
741
                if( (uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED && !uip_outstanding(uip_connr) )
742
                {
743
                        uip_flags = UIP_POLL;
744
                        UIP_APPCALL();
745
                        goto appsend;
746
                }
747
 
748
                goto drop;
749
 
750
                /* Check if we were invoked because of the perodic timer fireing. */
751
        }
752
        else if( flag == UIP_TIMER )
753
        {
754
                #if UIP_REASSEMBLY
755
                if( uip_reasstmr != 0 )
756
                {
757
                        --uip_reasstmr;
758
                }
759
 
760
                #endif /* UIP_REASSEMBLY */
761
 
762
                /* Increase the initial sequence number. */
763
                if( ++iss[3] == 0 )
764
                {
765
                        if( ++iss[2] == 0 )
766
                        {
767
                                if( ++iss[1] == 0 )
768
                                {
769
                                        ++iss[0];
770
                                }
771
                        }
772
                }
773
 
774
                /* Reset the length variables. */
775
                uip_len = 0;
776
                uip_slen = 0;
777
 
778
                /* Check if the connection is in a state in which we simply wait
779
       for the connection to time out. If so, we increase the
780
       connection's timer and remove the connection if it times
781
       out. */
782
                if( uip_connr->tcpstateflags == UIP_TIME_WAIT || uip_connr->tcpstateflags == UIP_FIN_WAIT_2 )
783
                {
784
                        ++( uip_connr->timer );
785
                        if( uip_connr->timer == UIP_TIME_WAIT_TIMEOUT )
786
                        {
787
                                uip_connr->tcpstateflags = UIP_CLOSED;
788
                        }
789
                }
790
                else if( uip_connr->tcpstateflags != UIP_CLOSED )
791
                {
792
                        /* If the connection has outstanding data, we increase the
793
         connection's timer and see if it has reached the RTO value
794
         in which case we retransmit. */
795
                        if( uip_outstanding(uip_connr) )
796
                        {
797
                                uip_connr->timer = uip_connr->timer - 1;
798
                                if( uip_connr->timer == 0 )
799
                                {
800
                                        if
801
                                        (
802
                                                uip_connr->nrtx == UIP_MAXRTX ||
803
                                                (
804
                                                        (uip_connr->tcpstateflags == UIP_SYN_SENT || uip_connr->tcpstateflags == UIP_SYN_RCVD) &&
805
                                                        uip_connr->nrtx == UIP_MAXSYNRTX
806
                                                )
807
                                        )
808
                                        {
809
                                                uip_connr->tcpstateflags = UIP_CLOSED;
810
 
811
                                                /* We call UIP_APPCALL() with uip_flags set to
812
               UIP_TIMEDOUT to inform the application that the
813
               connection has timed out. */
814
                                                uip_flags = UIP_TIMEDOUT;
815
                                                UIP_APPCALL();
816
 
817
                                                /* We also send a reset packet to the remote host. */
818
                                                BUF->flags = TCP_RST | TCP_ACK;
819
                                                goto tcp_send_nodata;
820
                                        }
821
 
822
                                        /* Exponential backoff. */
823
                                        uip_connr->timer = UIP_RTO << ( uip_connr->nrtx > 4 ? 4 : uip_connr->nrtx );
824
                                        ++( uip_connr->nrtx );
825
 
826
                                        /* Ok, so we need to retransmit. We do this differently
827
             depending on which state we are in. In ESTABLISHED, we
828
             call upon the application so that it may prepare the
829
             data for the retransmit. In SYN_RCVD, we resend the
830
             SYNACK that we sent earlier and in LAST_ACK we have to
831
             retransmit our FINACK. */
832
                                        UIP_STAT( ++uip_stat.tcp.rexmit );
833
                                        switch( uip_connr->tcpstateflags & UIP_TS_MASK )
834
                                        {
835
                                                case UIP_SYN_RCVD:
836
                                                        /* In the SYN_RCVD state, we should retransmit our
837
               SYNACK. */
838
                                                        goto tcp_send_synack;
839
 
840
                                                        #if UIP_ACTIVE_OPEN
841
 
842
                                                case UIP_SYN_SENT:
843
                                                        /* In the SYN_SENT state, we retransmit out SYN. */
844
                                                        BUF->flags = 0;
845
                                                        goto tcp_send_syn;
846
                                                        #endif /* UIP_ACTIVE_OPEN */
847
 
848
                                                case UIP_ESTABLISHED:
849
                                                        /* In the ESTABLISHED state, we call upon the application
850
               to do the actual retransmit after which we jump into
851
               the code for sending out the packet (the apprexmit
852
               label). */
853
                                                        uip_flags = UIP_REXMIT;
854
                                                        UIP_APPCALL();
855
                                                        goto apprexmit;
856
 
857
                                                case UIP_FIN_WAIT_1:
858
                                                case UIP_CLOSING:
859
                                                case UIP_LAST_ACK:
860
                                                        /* In all these states we should retransmit a FINACK. */
861
                                                        goto tcp_send_finack;
862
                                        }
863
                                }
864
                        }
865
                        else if( (uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED )
866
                        {
867
                                /* If there was no need for a retransmission, we poll the
868
           application for new data. */
869
                                uip_flags = UIP_POLL;
870
                                UIP_APPCALL();
871
                                goto appsend;
872
                        }
873
                }
874
 
875
                goto drop;
876
        }
877
 
878
        #if UIP_UDP
879
        if( flag == UIP_UDP_TIMER )
880
        {
881
                if( uip_udp_conn->lport != 0 )
882
                {
883
                        uip_conn = NULL;
884
                        uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
885
                        uip_len = uip_slen = 0;
886
                        uip_flags = UIP_POLL;
887
                        UIP_UDP_APPCALL();
888
                        goto udp_send;
889
                }
890
                else
891
                {
892
                        goto drop;
893
                }
894
        }
895
 
896
        #endif
897
 
898
        /* This is where the input processing starts. */
899
        UIP_STAT( ++uip_stat.ip.recv );
900
 
901
        /* Start of IP input header processing code. */
902
        #if UIP_CONF_IPV6
903
 
904
        /* Check validity of the IP header. */
905
        if( (BUF->vtc & 0xf0) != 0x60 )
906
        {                                       /* IP version and header length. */
907
                UIP_STAT( ++uip_stat.ip.drop );
908
                UIP_STAT( ++uip_stat.ip.vhlerr );
909
                UIP_LOG( "ipv6: invalid version." );
910
                goto drop;
911
        }
912
 
913
        #else /* UIP_CONF_IPV6 */
914
 
915
        /* Check validity of the IP header. */
916
        if( BUF->vhl != 0x45 )
917
        {                                       /* IP version and header length. */
918
                UIP_STAT( ++uip_stat.ip.drop );
919
                UIP_STAT( ++uip_stat.ip.vhlerr );
920
                UIP_LOG( "ip: invalid version or header length." );
921
                goto drop;
922
        }
923
 
924
        #endif /* UIP_CONF_IPV6 */
925
 
926
        /* Check the size of the packet. If the size reported to us in
927
     uip_len is smaller the size reported in the IP header, we assume
928
     that the packet has been corrupted in transit. If the size of
929
     uip_len is larger than the size reported in the IP packet header,
930
     the packet has been padded and we set uip_len to the correct
931
     value.. */
932
        if( (BUF->len[0] << 8) + BUF->len[1] <= uip_len )
933
        {
934
                uip_len = ( BUF->len[0] << 8 ) + BUF->len[1];
935
                #if UIP_CONF_IPV6
936
                uip_len += 40;  /* The length reported in the IPv6 header is the
937
                      length of the payload that follows the
938
                      header. However, uIP uses the uip_len variable
939
                      for holding the size of the entire packet,
940
                      including the IP header. For IPv4 this is not a
941
                      problem as the length field in the IPv4 header
942
                      contains the length of the entire packet. But
943
                      for IPv6 we need to add the size of the IPv6
944
                      header (40 bytes). */
945
                #endif /* UIP_CONF_IPV6 */
946
        }
947
        else
948
        {
949
                UIP_LOG( "ip: packet shorter than reported in IP header." );
950
                goto drop;
951
        }
952
 
953
        #if !UIP_CONF_IPV6
954
 
955
        /* Check the fragment flag. */
956
        if( (BUF->ipoffset[0] & 0x3f) != 0 || BUF->ipoffset[1] != 0 )
957
        {
958
                        #if UIP_REASSEMBLY
959
                uip_len = uip_reass();
960
                if( uip_len == 0 )
961
                {
962
                        goto drop;
963
                }
964
 
965
                        #else /* UIP_REASSEMBLY */
966
                UIP_STAT( ++uip_stat.ip.drop );
967
                UIP_STAT( ++uip_stat.ip.fragerr );
968
                UIP_LOG( "ip: fragment dropped." );
969
                goto drop;
970
                        #endif /* UIP_REASSEMBLY */
971
        }
972
 
973
        #endif /* UIP_CONF_IPV6 */
974
 
975
        if( uip_ipaddr_cmp(uip_hostaddr, all_zeroes_addr) )
976
        {
977
                /* If we are configured to use ping IP address configuration and
978
       hasn't been assigned an IP address yet, we accept all ICMP
979
       packets. */
980
                #if UIP_PINGADDRCONF && !UIP_CONF_IPV6
981
                if( BUF->proto == UIP_PROTO_ICMP )
982
                {
983
                        UIP_LOG( "ip: possible ping config packet received." );
984
                        goto icmp_input;
985
                }
986
                else
987
                {
988
                        UIP_LOG( "ip: packet dropped since no address assigned." );
989
                        goto drop;
990
                }
991
 
992
                #endif /* UIP_PINGADDRCONF */
993
        }
994
        else
995
        {
996
                /* If IP broadcast support is configured, we check for a broadcast
997
       UDP packet, which may be destined to us. */
998
                #if UIP_BROADCAST
999
                DEBUG_PRINTF( "UDP IP checksum 0x%04x\n", uip_ipchksum() );
1000
                if( BUF->proto == UIP_PROTO_UDP && uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr) /*&&
1001
         uip_ipchksum() == 0xffff*/ )
1002
                {
1003
                        goto udp_input;
1004
                }
1005
 
1006
                #endif /* UIP_BROADCAST */
1007
 
1008
                /* Check if the packet is destined for our IP address. */
1009
                #if !UIP_CONF_IPV6
1010
                if( !uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr) )
1011
                {
1012
                        UIP_STAT( ++uip_stat.ip.drop );
1013
                        goto drop;
1014
                }
1015
 
1016
                #else /* UIP_CONF_IPV6 */
1017
 
1018
                /* For IPv6, packet reception is a little trickier as we need to
1019
       make sure that we listen to certain multicast addresses (all
1020
       hosts multicast address, and the solicited-node multicast
1021
       address) as well. However, we will cheat here and accept all
1022
       multicast packets that are sent to the ff02::/16 addresses. */
1023
                if( !uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr) && BUF->destipaddr[0] != HTONS(0xff02) )
1024
                {
1025
                        UIP_STAT( ++uip_stat.ip.drop );
1026
                        goto drop;
1027
                }
1028
 
1029
                #endif /* UIP_CONF_IPV6 */
1030
        }
1031
 
1032
        #if !UIP_CONF_IPV6
1033
        if( uip_ipchksum() != 0xffff )
1034
        {                                       /* Compute and check the IP header
1035
                                    checksum. */
1036
                UIP_STAT( ++uip_stat.ip.drop );
1037
                UIP_STAT( ++uip_stat.ip.chkerr );
1038
                UIP_LOG( "ip: bad checksum." );
1039
                goto drop;
1040
        }
1041
 
1042
        #endif /* UIP_CONF_IPV6 */
1043
 
1044
        if( BUF->proto == UIP_PROTO_TCP )
1045
        {                                       /* Check for TCP packet. If so,
1046
                                       proceed with TCP input
1047
                                       processing. */
1048
                goto tcp_input;
1049
        }
1050
 
1051
        #if UIP_UDP
1052
        if( BUF->proto == UIP_PROTO_UDP )
1053
        {
1054
                goto udp_input;
1055
        }
1056
 
1057
        #endif /* UIP_UDP */
1058
 
1059
        #if !UIP_CONF_IPV6
1060
 
1061
        /* ICMPv4 processing code follows. */
1062
        if( BUF->proto != UIP_PROTO_ICMP )
1063
        {                                       /* We only allow ICMP packets from
1064
                                        here. */
1065
                UIP_STAT( ++uip_stat.ip.drop );
1066
                UIP_STAT( ++uip_stat.ip.protoerr );
1067
                UIP_LOG( "ip: neither tcp nor icmp." );
1068
                goto drop;
1069
        }
1070
 
1071
                #if UIP_PINGADDRCONF
1072
        icmp_input :
1073
                #endif /* UIP_PINGADDRCONF */
1074
        UIP_STAT( ++uip_stat.icmp.recv );
1075
 
1076
        /* ICMP echo (i.e., ping) processing. This is simple, we only change
1077
     the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP
1078
     checksum before we return the packet. */
1079
        if( ICMPBUF->type != ICMP_ECHO )
1080
        {
1081
                UIP_STAT( ++uip_stat.icmp.drop );
1082
                UIP_STAT( ++uip_stat.icmp.typeerr );
1083
                UIP_LOG( "icmp: not icmp echo." );
1084
                goto drop;
1085
        }
1086
 
1087
        /* If we are configured to use ping IP address assignment, we use
1088
     the destination IP address of this ping packet and assign it to
1089
     ourself. */
1090
                #if UIP_PINGADDRCONF
1091
        if( (uip_hostaddr[0] | uip_hostaddr[1]) == 0 )
1092
        {
1093
                uip_hostaddr[0] = BUF->destipaddr[0];
1094
                uip_hostaddr[1] = BUF->destipaddr[1];
1095
        }
1096
 
1097
                #endif /* UIP_PINGADDRCONF */
1098
 
1099
        ICMPBUF->type = ICMP_ECHO_REPLY;
1100
 
1101
        if( ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8)) )
1102
        {
1103
                ICMPBUF->icmpchksum += HTONS( ICMP_ECHO << 8 ) + 1;
1104
        }
1105
        else
1106
        {
1107
                ICMPBUF->icmpchksum += HTONS( ICMP_ECHO << 8 );
1108
        }
1109
 
1110
        /* Swap IP addresses. */
1111
        uip_ipaddr_copy( BUF->destipaddr, BUF->srcipaddr );
1112
        uip_ipaddr_copy( BUF->srcipaddr, uip_hostaddr );
1113
 
1114
        UIP_STAT( ++uip_stat.icmp.sent );
1115
        goto send;
1116
 
1117
        /* End of IPv4 input header processing code. */
1118
        #else /* !UIP_CONF_IPV6 */
1119
 
1120
        /* This is IPv6 ICMPv6 processing code. */
1121
        DEBUG_PRINTF( "icmp6_input: length %d\n", uip_len );
1122
 
1123
        if( BUF->proto != UIP_PROTO_ICMP6 )
1124
        {                                       /* We only allow ICMPv6 packets from
1125
                                         here. */
1126
                UIP_STAT( ++uip_stat.ip.drop );
1127
                UIP_STAT( ++uip_stat.ip.protoerr );
1128
                UIP_LOG( "ip: neither tcp nor icmp6." );
1129
                goto drop;
1130
        }
1131
 
1132
        UIP_STAT( ++uip_stat.icmp.recv );
1133
 
1134
        /* If we get a neighbor solicitation for our address we should send
1135
     a neighbor advertisement message back. */
1136
        if( ICMPBUF->type == ICMP6_NEIGHBOR_SOLICITATION )
1137
        {
1138
                if( uip_ipaddr_cmp(ICMPBUF->icmp6data, uip_hostaddr) )
1139
                {
1140
                        if( ICMPBUF->options[0] == ICMP6_OPTION_SOURCE_LINK_ADDRESS )
1141
                        {
1142
                                /* Save the sender's address in our neighbor list. */
1143
                                uip_neighbor_add( ICMPBUF->srcipaddr, &(ICMPBUF->options[2]) );
1144
                        }
1145
 
1146
                        /* We should now send a neighbor advertisement back to where the
1147
         neighbor solicication came from. */
1148
                        ICMPBUF->type = ICMP6_NEIGHBOR_ADVERTISEMENT;
1149
                        ICMPBUF->flags = ICMP6_FLAG_S;  /* Solicited flag. */
1150
 
1151
                        ICMPBUF->reserved1 = ICMPBUF->reserved2 = ICMPBUF->reserved3 = 0;
1152
 
1153
                        uip_ipaddr_copy( ICMPBUF->destipaddr, ICMPBUF->srcipaddr );
1154
                        uip_ipaddr_copy( ICMPBUF->srcipaddr, uip_hostaddr );
1155
                        ICMPBUF->options[0] = ICMP6_OPTION_TARGET_LINK_ADDRESS;
1156
                        ICMPBUF->options[1] = 1;                /* Options length, 1 = 8 bytes. */
1157
                        memcpy( &(ICMPBUF->options[2]), &uip_ethaddr, sizeof(uip_ethaddr) );
1158
                        ICMPBUF->icmpchksum = 0;
1159
                        ICMPBUF->icmpchksum = ~uip_icmp6chksum();
1160
                        goto send;
1161
                }
1162
 
1163
                goto drop;
1164
        }
1165
        else if( ICMPBUF->type == ICMP6_ECHO )
1166
        {
1167
                /* ICMP echo (i.e., ping) processing. This is simple, we only
1168
       change the ICMP type from ECHO to ECHO_REPLY and update the
1169
       ICMP checksum before we return the packet. */
1170
                ICMPBUF->type = ICMP6_ECHO_REPLY;
1171
 
1172
                uip_ipaddr_copy( BUF->destipaddr, BUF->srcipaddr );
1173
                uip_ipaddr_copy( BUF->srcipaddr, uip_hostaddr );
1174
                ICMPBUF->icmpchksum = 0;
1175
                ICMPBUF->icmpchksum = ~uip_icmp6chksum();
1176
 
1177
                UIP_STAT( ++uip_stat.icmp.sent );
1178
                goto send;
1179
        }
1180
        else
1181
        {
1182
                DEBUG_PRINTF( "Unknown icmp6 message type %d\n", ICMPBUF->type );
1183
                UIP_STAT( ++uip_stat.icmp.drop );
1184
                UIP_STAT( ++uip_stat.icmp.typeerr );
1185
                UIP_LOG( "icmp: unknown ICMP message." );
1186
                goto drop;
1187
        }
1188
 
1189
        /* End of IPv6 ICMP processing. */
1190
        #endif /* !UIP_CONF_IPV6 */
1191
 
1192
        #if UIP_UDP
1193
 
1194
        /* UDP input processing. */
1195
        udp_input :
1196
        /* UDP processing is really just a hack. We don't do anything to the
1197
     UDP/IP headers, but let the UDP application do all the hard
1198
     work. If the application sets uip_slen, it has a packet to
1199
     send. */
1200
                #if UIP_UDP_CHECKSUMS
1201
        uip_len = uip_len - UIP_IPUDPH_LEN;
1202
        uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
1203
        if( UDPBUF->udpchksum != 0 && uip_udpchksum() != 0xffff )
1204
        {
1205
                UIP_STAT( ++uip_stat.udp.drop );
1206
                UIP_STAT( ++uip_stat.udp.chkerr );
1207
                UIP_LOG( "udp: bad checksum." );
1208
                goto drop;
1209
        }
1210
 
1211
                #else /* UIP_UDP_CHECKSUMS */
1212
        uip_len = uip_len - UIP_IPUDPH_LEN;
1213
                #endif /* UIP_UDP_CHECKSUMS */
1214
 
1215
        /* Demultiplex this UDP packet between the UDP "connections". */
1216
        for( uip_udp_conn = &uip_udp_conns[0]; uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS]; ++uip_udp_conn )
1217
        {
1218
                /* If the local UDP port is non-zero, the connection is considered
1219
       to be used. If so, the local port number is checked against the
1220
       destination port number in the received packet. If the two port
1221
       numbers match, the remote port number is checked if the
1222
       connection is bound to a remote port. Finally, if the
1223
       connection is bound to a remote IP address, the source IP
1224
       address of the packet is checked. */
1225
                if
1226
                (
1227
                        uip_udp_conn->lport != 0 &&
1228
                        UDPBUF->destport == uip_udp_conn->lport &&
1229
                        (uip_udp_conn->rport == 0 || UDPBUF->srcport == uip_udp_conn->rport) &&
1230
                        (
1231
                                uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) ||
1232
                                uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) ||
1233
                                uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr)
1234
                        )
1235
                )
1236
                {
1237
                        goto udp_found;
1238
                }
1239
        }
1240
 
1241
        UIP_LOG( "udp: no matching connection found" );
1242
        goto drop;
1243
 
1244
udp_found:
1245
        UIP_STAT( ++uip_stat.udp.recv );
1246
        uip_conn = NULL;
1247
        uip_flags = UIP_NEWDATA;
1248
        uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
1249
        uip_slen = 0;
1250
        UIP_UDP_APPCALL();
1251
udp_send:
1252
        if( uip_slen == 0 )
1253
        {
1254
                goto drop;
1255
        }
1256
 
1257
        uip_len = uip_slen + UIP_IPUDPH_LEN;
1258
 
1259
                #if UIP_CONF_IPV6
1260
 
1261
        /* For IPv6, the IP length field does not include the IPv6 IP header
1262
     length. */
1263
        BUF->len[0] = ( (uip_len - UIP_IPH_LEN) >> 8 );
1264
        BUF->len[1] = ( (uip_len - UIP_IPH_LEN) & 0xff );
1265
                #else /* UIP_CONF_IPV6 */
1266
        BUF->len[0] = ( uip_len >> 8 );
1267
        BUF->len[1] = ( uip_len & 0xff );
1268
                #endif /* UIP_CONF_IPV6 */
1269
 
1270
        BUF->ttl = uip_udp_conn->ttl;
1271
        BUF->proto = UIP_PROTO_UDP;
1272
 
1273
        UDPBUF->udplen = HTONS( uip_slen + UIP_UDPH_LEN );
1274
        UDPBUF->udpchksum = 0;
1275
 
1276
        BUF->srcport = uip_udp_conn->lport;
1277
        BUF->destport = uip_udp_conn->rport;
1278
 
1279
        uip_ipaddr_copy( BUF->srcipaddr, uip_hostaddr );
1280
        uip_ipaddr_copy( BUF->destipaddr, uip_udp_conn->ripaddr );
1281
 
1282
        uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN];
1283
 
1284
                #if UIP_UDP_CHECKSUMS
1285
 
1286
        /* Calculate UDP checksum. */
1287
        UDPBUF->udpchksum = ~( uip_udpchksum() );
1288
        if( UDPBUF->udpchksum == 0 )
1289
        {
1290
                UDPBUF->udpchksum = 0xffff;
1291
        }
1292
 
1293
                #endif /* UIP_UDP_CHECKSUMS */
1294
        UIP_STAT( ++uip_stat.udp.sent );
1295
        goto ip_send_nolen;
1296
        #endif /* UIP_UDP */
1297
 
1298
        /* TCP input processing. */
1299
        tcp_input : UIP_STAT( ++uip_stat.tcp.recv );
1300
 
1301
        /* Start of TCP input header processing code. */
1302
        if( uip_tcpchksum() != 0xffff )
1303
        {       /* Compute and check the TCP
1304
                                       checksum. */
1305
                UIP_STAT( ++uip_stat.tcp.drop );
1306
                UIP_STAT( ++uip_stat.tcp.chkerr );
1307
                UIP_LOG( "tcp: bad checksum." );
1308
                goto drop;
1309
        }
1310
 
1311
        /* Demultiplex this segment. */
1312
 
1313
        /* First check any active connections. */
1314
        for( uip_connr = &uip_conns[0]; uip_connr <= &uip_conns[UIP_CONNS - 1]; ++uip_connr )
1315
        {
1316
                if
1317
                (
1318
                        uip_connr->tcpstateflags != UIP_CLOSED &&
1319
                        BUF->destport == uip_connr->lport &&
1320
                        BUF->srcport == uip_connr->rport &&
1321
                        uip_ipaddr_cmp(BUF->srcipaddr, uip_connr->ripaddr)
1322
                )
1323
                {
1324
                        goto found;
1325
                }
1326
        }
1327
 
1328
        /* If we didn't find and active connection that expected the packet,
1329
     either this packet is an old duplicate, or this is a SYN packet
1330
     destined for a connection in LISTEN. If the SYN flag isn't set,
1331
     it is an old packet and we send a RST. */
1332
        if( (BUF->flags & TCP_CTL) != TCP_SYN )
1333
        {
1334
                goto reset;
1335
        }
1336
 
1337
        tmp16 = BUF->destport;
1338
 
1339
        /* Next, check listening connections. */
1340
        for( c = 0; c < UIP_LISTENPORTS; ++c )
1341
        {
1342
                if( tmp16 == uip_listenports[c] )
1343
                {
1344
                        goto found_listen;
1345
                }
1346
        }
1347
 
1348
        /* No matching connection found, so we send a RST packet. */
1349
        UIP_STAT( ++uip_stat.tcp.synrst );
1350
reset:
1351
        /* We do not send resets in response to resets. */
1352
        if( BUF->flags & TCP_RST )
1353
        {
1354
                goto drop;
1355
        }
1356
 
1357
        UIP_STAT( ++uip_stat.tcp.rst );
1358
 
1359
        BUF->flags = TCP_RST | TCP_ACK;
1360
        uip_len = UIP_IPTCPH_LEN;
1361
        BUF->tcpoffset = 5 << 4;
1362
 
1363
        /* Flip the seqno and ackno fields in the TCP header. */
1364
        c = BUF->seqno[3];
1365
        BUF->seqno[3] = BUF->ackno[3];
1366
        BUF->ackno[3] = c;
1367
 
1368
        c = BUF->seqno[2];
1369
        BUF->seqno[2] = BUF->ackno[2];
1370
        BUF->ackno[2] = c;
1371
 
1372
        c = BUF->seqno[1];
1373
        BUF->seqno[1] = BUF->ackno[1];
1374
        BUF->ackno[1] = c;
1375
 
1376
        c = BUF->seqno[0];
1377
        BUF->seqno[0] = BUF->ackno[0];
1378
        BUF->ackno[0] = c;
1379
 
1380
        /* We also have to increase the sequence number we are
1381
     acknowledging. If the least significant byte overflowed, we need
1382
     to propagate the carry to the other bytes as well. */
1383
        if( ++BUF->ackno[3] == 0 )
1384
        {
1385
                if( ++BUF->ackno[2] == 0 )
1386
                {
1387
                        if( ++BUF->ackno[1] == 0 )
1388
                        {
1389
                                ++BUF->ackno[0];
1390
                        }
1391
                }
1392
        }
1393
 
1394
        /* Swap port numbers. */
1395
        tmp16 = BUF->srcport;
1396
        BUF->srcport = BUF->destport;
1397
        BUF->destport = tmp16;
1398
 
1399
        /* Swap IP addresses. */
1400
        uip_ipaddr_copy( BUF->destipaddr, BUF->srcipaddr );
1401
        uip_ipaddr_copy( BUF->srcipaddr, uip_hostaddr );
1402
 
1403
        /* And send out the RST packet! */
1404
        goto tcp_send_noconn;
1405
 
1406
        /* This label will be jumped to if we matched the incoming packet
1407
     with a connection in LISTEN. In that case, we should create a new
1408
     connection and send a SYNACK in return. */
1409
found_listen:
1410
        /* First we check if there are any connections avaliable. Unused
1411
     connections are kept in the same table as used connections, but
1412
     unused ones have the tcpstate set to CLOSED. Also, connections in
1413
     TIME_WAIT are kept track of and we'll use the oldest one if no
1414
     CLOSED connections are found. Thanks to Eddie C. Dost for a very
1415
     nice algorithm for the TIME_WAIT search. */
1416
        uip_connr = 0;
1417
        for( c = 0; c < UIP_CONNS; ++c )
1418
        {
1419
                if( uip_conns[c].tcpstateflags == UIP_CLOSED )
1420
                {
1421
                        uip_connr = &uip_conns[c];
1422
                        break;
1423
                }
1424
 
1425
                if( uip_conns[c].tcpstateflags == UIP_TIME_WAIT )
1426
                {
1427
                        if( uip_connr == 0 || uip_conns[c].timer > uip_connr->timer )
1428
                        {
1429
                                uip_connr = &uip_conns[c];
1430
                        }
1431
                }
1432
        }
1433
 
1434
        if( uip_connr == 0 )
1435
        {
1436
                /* All connections are used already, we drop packet and hope that
1437
       the remote end will retransmit the packet at a time when we
1438
       have more spare connections. */
1439
                UIP_STAT( ++uip_stat.tcp.syndrop );
1440
                UIP_LOG( "tcp: found no unused connections." );
1441
                goto drop;
1442
        }
1443
 
1444
        uip_conn = uip_connr;
1445
 
1446
        /* Fill in the necessary fields for the new connection. */
1447
        uip_connr->rto = uip_connr->timer = UIP_RTO;
1448
        uip_connr->sa = 0;
1449
        uip_connr->sv = 4;
1450
        uip_connr->nrtx = 0;
1451
        uip_connr->lport = BUF->destport;
1452
        uip_connr->rport = BUF->srcport;
1453
        uip_ipaddr_copy( uip_connr->ripaddr, BUF->srcipaddr );
1454
        uip_connr->tcpstateflags = UIP_SYN_RCVD;
1455
 
1456
        uip_connr->snd_nxt[0] = iss[0];
1457
        uip_connr->snd_nxt[1] = iss[1];
1458
        uip_connr->snd_nxt[2] = iss[2];
1459
        uip_connr->snd_nxt[3] = iss[3];
1460
        uip_connr->len = 1;
1461
 
1462
        /* rcv_nxt should be the seqno from the incoming packet + 1. */
1463
        uip_connr->rcv_nxt[3] = BUF->seqno[3];
1464
        uip_connr->rcv_nxt[2] = BUF->seqno[2];
1465
        uip_connr->rcv_nxt[1] = BUF->seqno[1];
1466
        uip_connr->rcv_nxt[0] = BUF->seqno[0];
1467
        uip_add_rcv_nxt( 1 );
1468
 
1469
        /* Parse the TCP MSS option, if present. */
1470
        if( (BUF->tcpoffset & 0xf0) > 0x50 )
1471
        {
1472
                for( c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2; )
1473
                {
1474
                        opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c];
1475
                        if( opt == TCP_OPT_END )
1476
                        {
1477
                                /* End of options. */
1478
                                break;
1479
                        }
1480
                        else if( opt == TCP_OPT_NOOP )
1481
                        {
1482
                                ++c;
1483
 
1484
                                /* NOP option. */
1485
                        }
1486
                        else if( opt == TCP_OPT_MSS && uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN )
1487
                        {
1488
                                /* An MSS option with the right option length. */
1489
                                tmp16 = ( (u16_t) uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8 ) | ( u16_t ) uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c];
1490
                                uip_connr->initialmss = uip_connr->mss = tmp16 > UIP_TCP_MSS ? UIP_TCP_MSS : tmp16;
1491
 
1492
                                /* And we are done processing options. */
1493
                                break;
1494
                        }
1495
                        else
1496
                        {
1497
                                /* All other options have a length field, so that we easily
1498
           can skip past them. */
1499
                                if( uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0 )
1500
                                {
1501
                                        /* If the length field is zero, the options are malformed
1502
             and we don't process them further. */
1503
                                        break;
1504
                                }
1505
 
1506
                                c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
1507
                        }
1508
                }
1509
        }
1510
 
1511
        /* Our response will be a SYNACK. */
1512
        #if UIP_ACTIVE_OPEN
1513
        tcp_send_synack : BUF->flags = TCP_ACK;
1514
 
1515
tcp_send_syn:
1516
        BUF->flags |= TCP_SYN;
1517
        #else /* UIP_ACTIVE_OPEN */
1518
        tcp_send_synack : BUF->flags = TCP_SYN | TCP_ACK;
1519
        #endif /* UIP_ACTIVE_OPEN */
1520
 
1521
        /* We send out the TCP Maximum Segment Size option with our
1522
     SYNACK. */
1523
        BUF->optdata[0] = TCP_OPT_MSS;
1524
        BUF->optdata[1] = TCP_OPT_MSS_LEN;
1525
        BUF->optdata[2] = ( UIP_TCP_MSS ) / 256;
1526
        BUF->optdata[3] = ( UIP_TCP_MSS ) & 255;
1527
        uip_len = UIP_IPTCPH_LEN + TCP_OPT_MSS_LEN;
1528
        BUF->tcpoffset = ( (UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4 ) << 4;
1529
        goto tcp_send;
1530
 
1531
        /* This label will be jumped to if we found an active connection. */
1532
found:
1533
        uip_conn = uip_connr;
1534
        uip_flags = 0;
1535
 
1536
        /* We do a very naive form of TCP reset processing; we just accept
1537
     any RST and kill our connection. We should in fact check if the
1538
     sequence number of this reset is wihtin our advertised window
1539
     before we accept the reset. */
1540
        if( BUF->flags & TCP_RST )
1541
        {
1542
                uip_connr->tcpstateflags = UIP_CLOSED;
1543
                UIP_LOG( "tcp: got reset, aborting connection." );
1544
                uip_flags = UIP_ABORT;
1545
                UIP_APPCALL();
1546
                goto drop;
1547
        }
1548
 
1549
        /* Calculated the length of the data, if the application has sent
1550
     any data to us. */
1551
        c = ( BUF->tcpoffset >> 4 ) << 2;
1552
 
1553
        /* uip_len will contain the length of the actual TCP data. This is
1554
     calculated by subtracing the length of the TCP header (in
1555
     c) and the length of the IP header (20 bytes). */
1556
        uip_len = uip_len - c - UIP_IPH_LEN;
1557
 
1558
        /* First, check if the sequence number of the incoming packet is
1559
     what we're expecting next. If not, we send out an ACK with the
1560
     correct numbers in. */
1561
        if( !(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) && ((BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK))) )
1562
        {
1563
                if
1564
                (
1565
                        (uip_len > 0 || ((BUF->flags & (TCP_SYN | TCP_FIN)) != 0)) &&
1566
                        (
1567
                                BUF->seqno[0] != uip_connr->rcv_nxt[0] ||
1568
                                BUF->seqno[1] != uip_connr->rcv_nxt[1] ||
1569
                                BUF->seqno[2] != uip_connr->rcv_nxt[2] ||
1570
                                BUF->seqno[3] != uip_connr->rcv_nxt[3]
1571
                        )
1572
                )
1573
                {
1574
                        goto tcp_send_ack;
1575
                }
1576
        }
1577
 
1578
        /* Next, check if the incoming segment acknowledges any outstanding
1579
     data. If so, we update the sequence number, reset the length of
1580
     the outstanding data, calculate RTT estimations, and reset the
1581
     retransmission timer. */
1582
        if( (BUF->flags & TCP_ACK) && uip_outstanding(uip_connr) )
1583
        {
1584
                uip_add32( uip_connr->snd_nxt, uip_connr->len );
1585
 
1586
                if
1587
                (
1588
                        BUF->ackno[0] == uip_acc32[0] &&
1589
                        BUF->ackno[1] == uip_acc32[1] &&
1590
                        BUF->ackno[2] == uip_acc32[2] &&
1591
                        BUF->ackno[3] == uip_acc32[3]
1592
                )
1593
                {
1594
                        /* Update sequence number. */
1595
                        uip_connr->snd_nxt[0] = uip_acc32[0];
1596
                        uip_connr->snd_nxt[1] = uip_acc32[1];
1597
                        uip_connr->snd_nxt[2] = uip_acc32[2];
1598
                        uip_connr->snd_nxt[3] = uip_acc32[3];
1599
 
1600
                        /* Do RTT estimation, unless we have done retransmissions. */
1601
                        if( uip_connr->nrtx == 0 )
1602
                        {
1603
                                signed char m;
1604
                                m = uip_connr->rto - uip_connr->timer;
1605
 
1606
                                /* This is taken directly from VJs original code in his paper */
1607
                                m = m - ( uip_connr->sa >> 3 );
1608
                                uip_connr->sa += m;
1609
                                if( m < 0 )
1610
                                {
1611
                                        m = -m;
1612
                                }
1613
 
1614
                                m = m - ( uip_connr->sv >> 2 );
1615
                                uip_connr->sv += m;
1616
                                uip_connr->rto = ( uip_connr->sa >> 3 ) + uip_connr->sv;
1617
                        }
1618
 
1619
                        /* Set the acknowledged flag. */
1620
                        uip_flags = UIP_ACKDATA;
1621
 
1622
                        /* Reset the retransmission timer. */
1623
                        uip_connr->timer = uip_connr->rto;
1624
 
1625
                        /* Reset length of outstanding data. */
1626
                        uip_connr->len = 0;
1627
                }
1628
        }
1629
 
1630
        /* Do different things depending on in what state the connection is. */
1631
        switch( uip_connr->tcpstateflags & UIP_TS_MASK )
1632
        {
1633
                /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not
1634
        implemented, since we force the application to close when the
1635
        peer sends a FIN (hence the application goes directly from
1636
        ESTABLISHED to LAST_ACK). */
1637
                case UIP_SYN_RCVD:
1638
                        /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and
1639
       we are waiting for an ACK that acknowledges the data we sent
1640
       out the last time. Therefore, we want to have the UIP_ACKDATA
1641
       flag set. If so, we enter the ESTABLISHED state. */
1642
                        if( uip_flags & UIP_ACKDATA )
1643
                        {
1644
                                uip_connr->tcpstateflags = UIP_ESTABLISHED;
1645
                                uip_flags = UIP_CONNECTED;
1646
                                uip_connr->len = 0;
1647
                                if( uip_len > 0 )
1648
                                {
1649
                                        uip_flags |= UIP_NEWDATA;
1650
                                        uip_add_rcv_nxt( uip_len );
1651
                                }
1652
 
1653
                                uip_slen = 0;
1654
                                UIP_APPCALL();
1655
                                goto appsend;
1656
                        }
1657
 
1658
                        goto drop;
1659
                        #if UIP_ACTIVE_OPEN
1660
 
1661
                case UIP_SYN_SENT:
1662
                        /* In SYN_SENT, we wait for a SYNACK that is sent in response to
1663
       our SYN. The rcv_nxt is set to sequence number in the SYNACK
1664
       plus one, and we send an ACK. We move into the ESTABLISHED
1665
       state. */
1666
                        if( (uip_flags & UIP_ACKDATA) && (BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK) )
1667
                        {
1668
                                /* Parse the TCP MSS option, if present. */
1669
                                if( (BUF->tcpoffset & 0xf0) > 0x50 )
1670
                                {
1671
                                        for( c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2; )
1672
                                        {
1673
                                                opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c];
1674
                                                if( opt == TCP_OPT_END )
1675
                                                {
1676
                                                        /* End of options. */
1677
                                                        break;
1678
                                                }
1679
                                                else if( opt == TCP_OPT_NOOP )
1680
                                                {
1681
                                                        ++c;
1682
 
1683
                                                        /* NOP option. */
1684
                                                }
1685
                                                else if( opt == TCP_OPT_MSS && uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN )
1686
                                                {
1687
                                                        /* An MSS option with the right option length. */
1688
                                                        tmp16 = ( uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8 ) | uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c];
1689
                                                        uip_connr->initialmss = uip_connr->mss = tmp16 > UIP_TCP_MSS ? UIP_TCP_MSS : tmp16;
1690
 
1691
                                                        /* And we are done processing options. */
1692
                                                        break;
1693
                                                }
1694
                                                else
1695
                                                {
1696
                                                        /* All other options have a length field, so that we easily
1697
               can skip past them. */
1698
                                                        if( uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0 )
1699
                                                        {
1700
                                                                /* If the length field is zero, the options are malformed
1701
                 and we don't process them further. */
1702
                                                                break;
1703
                                                        }
1704
 
1705
                                                        c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
1706
                                                }
1707
                                        }
1708
                                }
1709
 
1710
                                uip_connr->tcpstateflags = UIP_ESTABLISHED;
1711
                                uip_connr->rcv_nxt[0] = BUF->seqno[0];
1712
                                uip_connr->rcv_nxt[1] = BUF->seqno[1];
1713
                                uip_connr->rcv_nxt[2] = BUF->seqno[2];
1714
                                uip_connr->rcv_nxt[3] = BUF->seqno[3];
1715
                                uip_add_rcv_nxt( 1 );
1716
                                uip_flags = UIP_CONNECTED | UIP_NEWDATA;
1717
                                uip_connr->len = 0;
1718
                                uip_len = 0;
1719
                                uip_slen = 0;
1720
                                UIP_APPCALL();
1721
                                goto appsend;
1722
                        }
1723
 
1724
                        /* Inform the application that the connection failed */
1725
                        uip_flags = UIP_ABORT;
1726
                        UIP_APPCALL();
1727
 
1728
                        /* The connection is closed after we send the RST */
1729
                        uip_conn->tcpstateflags = UIP_CLOSED;
1730
                        goto reset;
1731
                        #endif /* UIP_ACTIVE_OPEN */
1732
 
1733
                case UIP_ESTABLISHED:
1734
                        /* In the ESTABLISHED state, we call upon the application to feed
1735
    data into the uip_buf. If the UIP_ACKDATA flag is set, the
1736
    application should put new data into the buffer, otherwise we are
1737
    retransmitting an old segment, and the application should put that
1738
    data into the buffer.
1739
 
1740
    If the incoming packet is a FIN, we should close the connection on
1741
    this side as well, and we send out a FIN and enter the LAST_ACK
1742
    state. We require that there is no outstanding data; otherwise the
1743
    sequence numbers will be screwed up. */
1744
                        if( BUF->flags & TCP_FIN && !(uip_connr->tcpstateflags & UIP_STOPPED) )
1745
                        {
1746
                                if( uip_outstanding(uip_connr) )
1747
                                {
1748
                                        goto drop;
1749
                                }
1750
 
1751
                                uip_add_rcv_nxt( 1 + uip_len );
1752
                                uip_flags |= UIP_CLOSE;
1753
                                if( uip_len > 0 )
1754
                                {
1755
                                        uip_flags |= UIP_NEWDATA;
1756
                                }
1757
 
1758
                                UIP_APPCALL();
1759
                                uip_connr->len = 1;
1760
                                uip_connr->tcpstateflags = UIP_LAST_ACK;
1761
                                uip_connr->nrtx = 0;
1762
        tcp_send_finack:
1763
                                BUF->flags = TCP_FIN | TCP_ACK;
1764
                                goto tcp_send_nodata;
1765
                        }
1766
 
1767
                        /* Check the URG flag. If this is set, the segment carries urgent
1768
       data that we must pass to the application. */
1769
                        if( (BUF->flags & TCP_URG) != 0 )
1770
                        {
1771
                                #if UIP_URGDATA > 0
1772
                                uip_urglen = ( BUF->urgp[0] << 8 ) | BUF->urgp[1];
1773
                                if( uip_urglen > uip_len )
1774
                                {
1775
                                        /* There is more urgent data in the next segment to come. */
1776
                                        uip_urglen = uip_len;
1777
                                }
1778
 
1779
                                uip_add_rcv_nxt( uip_urglen );
1780
                                uip_len -= uip_urglen;
1781
                                uip_urgdata = uip_appdata;
1782
                                uip_appdata += uip_urglen;
1783
                        }
1784
                        else
1785
                        {
1786
                                uip_urglen = 0;
1787
                                #else /* UIP_URGDATA > 0 */
1788
                                uip_appdata = ( ( char * ) uip_appdata ) + ( (BUF->urgp[0] << 8) | BUF->urgp[1] );
1789
                                uip_len -= ( BUF->urgp[0] << 8 ) | BUF->urgp[1];
1790
                                #endif /* UIP_URGDATA > 0 */
1791
                        }
1792
 
1793
                        /* If uip_len > 0 we have TCP data in the packet, and we flag this
1794
       by setting the UIP_NEWDATA flag and update the sequence number
1795
       we acknowledge. If the application has stopped the dataflow
1796
       using uip_stop(), we must not accept any data packets from the
1797
       remote host. */
1798
                        if( uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED) )
1799
                        {
1800
                                uip_flags |= UIP_NEWDATA;
1801
                                uip_add_rcv_nxt( uip_len );
1802
                        }
1803
 
1804
                        /* Check if the available buffer space advertised by the other end
1805
       is smaller than the initial MSS for this connection. If so, we
1806
       set the current MSS to the window size to ensure that the
1807
       application does not send more data than the other end can
1808
       handle.
1809
 
1810
       If the remote host advertises a zero window, we set the MSS to
1811
       the initial MSS so that the application will send an entire MSS
1812
       of data. This data will not be acknowledged by the receiver,
1813
       and the application will retransmit it. This is called the
1814
       "persistent timer" and uses the retransmission mechanim.
1815
    */
1816
                        tmp16 = ( (u16_t) BUF->wnd[0] << 8 ) + ( u16_t ) BUF->wnd[1];
1817
                        if( tmp16 > (uip_connr->initialmss * FRAME_MULTIPLE) || tmp16 == 0 )
1818
                        {
1819
                                tmp16 = uip_connr->initialmss * FRAME_MULTIPLE;
1820
                        }
1821
 
1822
                        uip_connr->mss = tmp16;
1823
 
1824
                        /* If this packet constitutes an ACK for outstanding data (flagged
1825
       by the UIP_ACKDATA flag, we should call the application since it
1826
       might want to send more data. If the incoming packet had data
1827
       from the peer (as flagged by the UIP_NEWDATA flag), the
1828
       application must also be notified.
1829
 
1830
       When the application is called, the global variable uip_len
1831
       contains the length of the incoming data. The application can
1832
       access the incoming data through the global pointer
1833
       uip_appdata, which usually points UIP_IPTCPH_LEN + UIP_LLH_LEN
1834
       bytes into the uip_buf array.
1835
 
1836
       If the application wishes to send any data, this data should be
1837
       put into the uip_appdata and the length of the data should be
1838
       put into uip_len. If the application don't have any data to
1839
       send, uip_len must be set to 0. */
1840
                        if( uip_flags & (UIP_NEWDATA | UIP_ACKDATA) )
1841
                        {
1842
                                uip_slen = 0;
1843
                                UIP_APPCALL();
1844
 
1845
        appsend:
1846
                                if( uip_flags & UIP_ABORT )
1847
                                {
1848
                                        uip_slen = 0;
1849
                                        uip_connr->tcpstateflags = UIP_CLOSED;
1850
                                        BUF->flags = TCP_RST | TCP_ACK;
1851
                                        goto tcp_send_nodata;
1852
                                }
1853
 
1854
                                if( uip_flags & UIP_CLOSE )
1855
                                {
1856
                                        uip_slen = 0;
1857
                                        uip_connr->len = 1;
1858
                                        uip_connr->tcpstateflags = UIP_FIN_WAIT_1;
1859
                                        uip_connr->nrtx = 0;
1860
                                        BUF->flags = TCP_FIN | TCP_ACK;
1861
                                        goto tcp_send_nodata;
1862
                                }
1863
 
1864
                                /* If uip_slen > 0, the application has data to be sent. */
1865
                                if( uip_slen > 0 )
1866
                                {
1867
                                        /* If the connection has acknowledged data, the contents of
1868
           the ->len variable should be discarded. */
1869
                                        if( (uip_flags & UIP_ACKDATA) != 0 )
1870
                                        {
1871
                                                uip_connr->len = 0;
1872
                                        }
1873
 
1874
                                        /* If the ->len variable is non-zero the connection has
1875
           already data in transit and cannot send anymore right
1876
           now. */
1877
                                        if( uip_connr->len == 0 )
1878
                                        {
1879
                                                /* The application cannot send more than what is allowed by
1880
             the mss (the minumum of the MSS and the available
1881
             window). */
1882
                                                if( uip_slen > uip_connr->mss )
1883
                                                {
1884
                                                        uip_slen = uip_connr->mss;
1885
                                                }
1886
 
1887
                                                /* Remember how much data we send out now so that we know
1888
             when everything has been acknowledged. */
1889
                                                uip_connr->len = uip_slen;
1890
                                        }
1891
                                        else
1892
                                        {
1893
                                                /* If the application already had unacknowledged data, we
1894
             make sure that the application does not send (i.e.,
1895
             retransmit) out more than it previously sent out. */
1896
                                                uip_slen = uip_connr->len;
1897
                                        }
1898
                                }
1899
 
1900
                                uip_connr->nrtx = 0;
1901
        apprexmit:
1902
                                uip_appdata = uip_sappdata;
1903
 
1904
                                /* If the application has data to be sent, or if the incoming
1905
         packet had new data in it, we must send out a packet. */
1906
                                if( uip_slen > 0 && uip_connr->len > 0 )
1907
                                {
1908
                                        /* Add the length of the IP and TCP headers. */
1909
                                        uip_len = uip_connr->len + UIP_TCPIP_HLEN;
1910
 
1911
                                        /* We always set the ACK flag in response packets. */
1912
                                        BUF->flags = TCP_ACK | TCP_PSH;
1913
 
1914
                                        /* Send the packet. */
1915
                                        goto tcp_send_noopts;
1916
                                }
1917
 
1918
                                /* If there is no data to send, just send out a pure ACK if
1919
         there is newdata. */
1920
                                if( uip_flags & UIP_NEWDATA )
1921
                                {
1922
                                        uip_len = UIP_TCPIP_HLEN;
1923
                                        BUF->flags = TCP_ACK;
1924
                                        goto tcp_send_noopts;
1925
                                }
1926
                        }
1927
 
1928
                        goto drop;
1929
 
1930
                case UIP_LAST_ACK:
1931
                        /* We can close this connection if the peer has acknowledged our
1932
       FIN. This is indicated by the UIP_ACKDATA flag. */
1933
                        if( uip_flags & UIP_ACKDATA )
1934
                        {
1935
                                uip_connr->tcpstateflags = UIP_CLOSED;
1936
                                uip_flags = UIP_CLOSE;
1937
                                UIP_APPCALL();
1938
                        }
1939
 
1940
                        break;
1941
 
1942
                case UIP_FIN_WAIT_1:
1943
                        /* The application has closed the connection, but the remote host
1944
       hasn't closed its end yet. Thus we do nothing but wait for a
1945
       FIN from the other side. */
1946
                        if( uip_len > 0 )
1947
                        {
1948
                                uip_add_rcv_nxt( uip_len );
1949
                        }
1950
 
1951
                        if( BUF->flags & TCP_FIN )
1952
                        {
1953
                                if( uip_flags & UIP_ACKDATA )
1954
                                {
1955
                                        uip_connr->tcpstateflags = UIP_TIME_WAIT;
1956
                                        uip_connr->timer = 0;
1957
                                        uip_connr->len = 0;
1958
                                }
1959
                                else
1960
                                {
1961
                                        uip_connr->tcpstateflags = UIP_CLOSING;
1962
                                }
1963
 
1964
                                uip_add_rcv_nxt( 1 );
1965
                                uip_flags = UIP_CLOSE;
1966
                                UIP_APPCALL();
1967
                                goto tcp_send_ack;
1968
                        }
1969
                        else if( uip_flags & UIP_ACKDATA )
1970
                        {
1971
                                uip_connr->tcpstateflags = UIP_FIN_WAIT_2;
1972
                                uip_connr->len = 0;
1973
                                goto drop;
1974
                        }
1975
 
1976
                        if( uip_len > 0 )
1977
                        {
1978
                                goto tcp_send_ack;
1979
                        }
1980
 
1981
                        goto drop;
1982
 
1983
                case UIP_FIN_WAIT_2:
1984
                        if( uip_len > 0 )
1985
                        {
1986
                                uip_add_rcv_nxt( uip_len );
1987
                        }
1988
 
1989
                        if( BUF->flags & TCP_FIN )
1990
                        {
1991
                                uip_connr->tcpstateflags = UIP_TIME_WAIT;
1992
                                uip_connr->timer = 0;
1993
                                uip_add_rcv_nxt( 1 );
1994
                                uip_flags = UIP_CLOSE;
1995
                                UIP_APPCALL();
1996
                                goto tcp_send_ack;
1997
                        }
1998
 
1999
                        if( uip_len > 0 )
2000
                        {
2001
                                goto tcp_send_ack;
2002
                        }
2003
 
2004
                        goto drop;
2005
 
2006
                case UIP_TIME_WAIT:
2007
                        goto tcp_send_ack;
2008
 
2009
                case UIP_CLOSING:
2010
                        if( uip_flags & UIP_ACKDATA )
2011
                        {
2012
                                uip_connr->tcpstateflags = UIP_TIME_WAIT;
2013
                                uip_connr->timer = 0;
2014
                        }
2015
        }
2016
 
2017
        goto drop;
2018
 
2019
        /* We jump here when we are ready to send the packet, and just want
2020
     to set the appropriate TCP sequence numbers in the TCP header. */
2021
tcp_send_ack:
2022
        BUF->flags = TCP_ACK;
2023
tcp_send_nodata:
2024
        uip_len = UIP_IPTCPH_LEN;
2025
tcp_send_noopts:
2026
        BUF->tcpoffset = ( UIP_TCPH_LEN / 4 ) << 4;
2027
tcp_send:
2028
        /* We're done with the input processing. We are now ready to send a
2029
     reply. Our job is to fill in all the fields of the TCP and IP
2030
     headers before calculating the checksum and finally send the
2031
     packet. */
2032
        BUF->ackno[0] = uip_connr->rcv_nxt[0];
2033
        BUF->ackno[1] = uip_connr->rcv_nxt[1];
2034
        BUF->ackno[2] = uip_connr->rcv_nxt[2];
2035
        BUF->ackno[3] = uip_connr->rcv_nxt[3];
2036
 
2037
        BUF->seqno[0] = uip_connr->snd_nxt[0];
2038
        BUF->seqno[1] = uip_connr->snd_nxt[1];
2039
        BUF->seqno[2] = uip_connr->snd_nxt[2];
2040
        BUF->seqno[3] = uip_connr->snd_nxt[3];
2041
 
2042
        BUF->proto = UIP_PROTO_TCP;
2043
 
2044
        BUF->srcport = uip_connr->lport;
2045
        BUF->destport = uip_connr->rport;
2046
 
2047
        uip_ipaddr_copy( BUF->srcipaddr, uip_hostaddr );
2048
        uip_ipaddr_copy( BUF->destipaddr, uip_connr->ripaddr );
2049
 
2050
        if( uip_connr->tcpstateflags & UIP_STOPPED )
2051
        {
2052
                /* If the connection has issued uip_stop(), we advertise a zero
2053
       window so that the remote host will stop sending data. */
2054
                BUF->wnd[0] = BUF->wnd[1] = 0;
2055
        }
2056
        else
2057
        {
2058
                BUF->wnd[0] = ( (UIP_RECEIVE_WINDOW) >> 8 );
2059
                BUF->wnd[1] = ( (UIP_RECEIVE_WINDOW) & 0xff );
2060
        }
2061
 
2062
tcp_send_noconn:
2063
        BUF->ttl = UIP_TTL;
2064
        #if UIP_CONF_IPV6
2065
 
2066
        /* For IPv6, the IP length field does not include the IPv6 IP header
2067
     length. */
2068
        BUF->len[0] = ( (uip_len - UIP_IPH_LEN) >> 8 );
2069
        BUF->len[1] = ( (uip_len - UIP_IPH_LEN) & 0xff );
2070
        #else /* UIP_CONF_IPV6 */
2071
        BUF->len[0] = ( uip_len >> 8 );
2072
        BUF->len[1] = ( uip_len & 0xff );
2073
        #endif /* UIP_CONF_IPV6 */
2074
 
2075
        BUF->urgp[0] = BUF->urgp[1] = 0;
2076
 
2077
        /* Calculate TCP checksum. */
2078
        BUF->tcpchksum = 0;
2079
        BUF->tcpchksum = ~( uip_tcpchksum() );
2080
 
2081
        #if UIP_UDP
2082
        ip_send_nolen :
2083
        #endif
2084
        #if UIP_CONF_IPV6
2085
        BUF->vtc = 0x60;
2086
        BUF->tcflow = 0x00;
2087
        BUF->flow = 0x00;
2088
        #else /* UIP_CONF_IPV6 */
2089
        BUF->vhl = 0x45;
2090
        BUF->tos = 0;
2091
        BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
2092
        ++ipid;
2093
        BUF->ipid[0] = ipid >> 8;
2094
        BUF->ipid[1] = ipid & 0xff;
2095
 
2096
        /* Calculate IP checksum. */
2097
        BUF->ipchksum = 0;
2098
        BUF->ipchksum = ~( uip_ipchksum() );
2099
        DEBUG_PRINTF( "uip ip_send_nolen: chkecum 0x%04x\n", uip_ipchksum() );
2100
        #endif /* UIP_CONF_IPV6 */
2101
 
2102
        UIP_STAT( ++uip_stat.tcp.sent );
2103
send:
2104
        DEBUG_PRINTF( "Sending packet with length %d (%d)\n", uip_len, (BUF->len[0] << 8) | BUF->len[1] );
2105
 
2106
        UIP_STAT( ++uip_stat.ip.sent );
2107
 
2108
        /* Return and let the caller do the actual transmission. */
2109
        uip_flags = 0;
2110
        return;
2111
drop:
2112
        uip_len = 0;
2113
        uip_flags = 0;
2114
        return;
2115
}
2116
 
2117
/*---------------------------------------------------------------------------*/
2118
u16_t htons( u16_t val )
2119
{
2120
        return HTONS( val );
2121
}
2122
 
2123
/*---------------------------------------------------------------------------*/
2124
void uip_send( const void *data, int len )
2125
{
2126
        if( len > 0 )
2127
        {
2128
                uip_slen = len;
2129
                if( data != uip_sappdata )
2130
                {
2131
                        memcpy( uip_sappdata, (data), uip_slen );
2132
                }
2133
        }
2134
}
2135
 
2136
/*---------------------------------------------------------------------------*/
2137
int uip_fast_send( int xARP )
2138
{
2139
        ( void ) xARP;
2140
        #if NOT_YET_COMPLETE
2141
 
2142
        u16_t           tcplen, len1 = 0, uiAccumulatedLen = 0, len_previous = 0, split_len;
2143
        int                     iSplitNo = 0;
2144
        extern int      uip_low_level_output( unsigned char *pcBuf, int ilen );
2145
 
2146
        if( xARP == pdTRUE )
2147
        {
2148
                if( BUF->proto == UIP_PROTO_TCP && uip_slen > 1 )
2149
                {
2150
                        tcplen = uip_len - UIP_TCPIP_HLEN;
2151
 
2152
                        if( tcplen > UIP_TCP_MSS )
2153
                        {
2154
                                split_len = UIP_TCP_MSS;
2155
                        }
2156
                        else
2157
                        {
2158
                                split_len = tcplen / 2;
2159
                        }
2160
 
2161
                        while( tcplen > 0 )
2162
                        {
2163
                                uiAccumulatedLen += len1;
2164
 
2165
                                if( tcplen > split_len )
2166
                                {
2167
                                        len1 = split_len;
2168
                                        tcplen -= split_len;
2169
                                }
2170
                                else
2171
                                {
2172
                                        len1 = tcplen;
2173
                                        tcplen = 0;
2174
                                }
2175
 
2176
                                uip_len = len1 + UIP_TCPIP_HLEN;
2177
                                BUF->len[0] = uip_len >> 8;
2178
                                BUF->len[1] = uip_len & 0xff;
2179
                                if( iSplitNo == 0 )
2180
                                {
2181
                                        iSplitNo++;
2182
 
2183
                                        /* Create the first packet. This is done by altering the length
2184
                                        field of the IP header and updating the checksums. */
2185
                                }
2186
                                else
2187
                                {
2188
                                        /* Now, create the second packet. To do this, it is not enough to
2189
                                        just alter the length field, but we must also update the TCP
2190
                                        sequence number and point the uip_appdata to a new place in
2191
                                        memory. This place is determined by the length of the first
2192
                                        packet (len1). */
2193
 
2194
                                        /*    uip_appdata += len1;*/
2195
                                        memcpy( uip_appdata, ( u8_t * ) uip_appdata + uiAccumulatedLen, len1 );
2196
                                        uip_add32( BUF->seqno, len_previous );
2197
                                        BUF->seqno[0] = uip_acc32[0];
2198
                                        BUF->seqno[1] = uip_acc32[1];
2199
                                        BUF->seqno[2] = uip_acc32[2];
2200
                                        BUF->seqno[3] = uip_acc32[3];
2201
                                }
2202
 
2203
                                /* Recalculate the TCP checksum. */
2204
                                BUF->tcpchksum = 0;
2205
                                BUF->tcpchksum = ~( uip_tcpchksum() );
2206
 
2207
                                /* Recalculate the IP checksum. */
2208
                                BUF->ipchksum = 0;
2209
                                BUF->ipchksum = ~( uip_ipchksum() );
2210
 
2211
                                /* Transmit the packet. */
2212
                                uip_arp_out();
2213
                                uip_low_level_output( uip_buf, uip_len );
2214
 
2215
                                len_previous = len1;
2216
                        }
2217
                }
2218
                else
2219
                {
2220
                        uip_arp_out();
2221
                        uip_low_level_output( uip_buf, uip_len );
2222
                }
2223
        }
2224
        else
2225
        {
2226
                uip_low_level_output( uip_buf, uip_len );
2227
        }
2228
 
2229
        #endif
2230
        return 1;
2231
}
2232
 
2233
/** @} */

powered by: WebSVN 2.1.0

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