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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [net/] [ppp/] [current/] [src/] [slcompress.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      src/slcompress.c
4
//
5
//==========================================================================
6
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
7
// -------------------------------------------                              
8
// This file is part of eCos, the Embedded Configurable Operating System.   
9
// Copyright (C) 2003 Free Software Foundation, Inc.                        
10
//
11
// eCos is free software; you can redistribute it and/or modify it under    
12
// the terms of the GNU General Public License as published by the Free     
13
// Software Foundation; either version 2 or (at your option) any later      
14
// version.                                                                 
15
//
16
// eCos is distributed in the hope that it will be useful, but WITHOUT      
17
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
18
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
19
// for more details.                                                        
20
//
21
// You should have received a copy of the GNU General Public License        
22
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
23
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
24
//
25
// As a special exception, if other files instantiate templates or use      
26
// macros or inline functions from this file, or you compile this file      
27
// and link it with other works to produce a work based on this file,       
28
// this file does not by itself cause the resulting work to be covered by   
29
// the GNU General Public License. However the source code for this file    
30
// must still be made available in accordance with section (3) of the GNU   
31
// General Public License v2.                                               
32
//
33
// This exception does not invalidate any other reasons why a work based    
34
// on this file might be covered by the GNU General Public License.         
35
// -------------------------------------------                              
36
// ####ECOSGPLCOPYRIGHTEND####                                              
37
// ####BSDALTCOPYRIGHTBEGIN####                                             
38
// -------------------------------------------                              
39
// Portions of this software may have been derived from FreeBSD, OpenBSD,   
40
// or other sources, and if so are covered by the appropriate copyright     
41
// and license included herein.                                             
42
// -------------------------------------------                              
43
// ####BSDALTCOPYRIGHTEND####                                               
44
//==========================================================================
45
 
46
/*-
47
 * Copyright (c) 1989, 1993, 1994
48
 *      The Regents of the University of California.  All rights reserved.
49
 *
50
 * Redistribution and use in source and binary forms, with or without
51
 * modification, are permitted provided that the following conditions
52
 * are met:
53
 * 1. Redistributions of source code must retain the above copyright
54
 *    notice, this list of conditions and the following disclaimer.
55
 * 2. Redistributions in binary form must reproduce the above copyright
56
 *    notice, this list of conditions and the following disclaimer in the
57
 *    documentation and/or other materials provided with the distribution.
58
 * 3. Neither the name of the University nor the names of its contributors
59
 *    may be used to endorse or promote products derived from this software
60
 *    without specific prior written permission.
61
 *
62
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
63
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
64
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
65
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
66
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
67
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
68
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
69
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
70
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
71
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
72
 * SUCH DAMAGE.
73
 *
74
 *      @(#)slcompress.c        8.2 (Berkeley) 4/16/94
75
 * $FreeBSD: src/sys/net/slcompress.c,v 1.16 1999/12/29 04:38:37 peter Exp $
76
 */
77
 
78
/*
79
 * Routines to compress and uncompess tcp packets (for transmission
80
 * over low speed serial lines.
81
 *
82
 * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
83
 *      - Initial distribution.
84
 *
85
 */
86
 
87
#define _KERNEL
88
 
89
 
90
#include <sys/param.h>
91
#include <sys/mbuf.h>
92
//#include <sys/systm.h>
93
 
94
#include <netinet/in.h>
95
#include <netinet/in_systm.h>
96
#include <netinet/ip.h>
97
#include <netinet/tcp.h>
98
 
99
#include <cyg/ppp/slcompress.h>
100
 
101
typedef CYG_ADDRWORD intptr_t;
102
 
103
#ifndef SL_NO_STATS
104
#define INCR(counter) ++comp->counter;
105
#else
106
#define INCR(counter)
107
#endif
108
 
109
#define BCMP(p1, p2, n) bcmp((char *)(p1), (char *)(p2), (int)(n))
110
#define BCOPY(p1, p2, n) bcopy((char *)(p1), (char *)(p2), (int)(n))
111
#ifndef _KERNEL
112
#define ovbcopy bcopy
113
#endif
114
 
115
void
116
sl_compress_init(comp, max_state)
117
        struct slcompress *comp;
118
        int max_state;
119
{
120
        register u_int i;
121
        register struct cstate *tstate = comp->tstate;
122
 
123
        if (max_state == -1) {
124
                max_state = MAX_STATES - 1;
125
                bzero((char *)comp, sizeof(*comp));
126
        } else {
127
                /* Don't reset statistics */
128
                bzero((char *)comp->tstate, sizeof(comp->tstate));
129
                bzero((char *)comp->rstate, sizeof(comp->rstate));
130
        }
131
        for (i = max_state; i > 0; --i) {
132
                tstate[i].cs_id = i;
133
                tstate[i].cs_next = &tstate[i - 1];
134
        }
135
        tstate[0].cs_next = &tstate[max_state];
136
        tstate[0].cs_id = 0;
137
        comp->last_cs = &tstate[0];
138
        comp->last_recv = 255;
139
        comp->last_xmit = 255;
140
        comp->flags = SLF_TOSS;
141
}
142
 
143
 
144
/* ENCODE encodes a number that is known to be non-zero.  ENCODEZ
145
 * checks for zero (since zero has to be encoded in the long, 3 byte
146
 * form).
147
 */
148
#define ENCODE(n) { \
149
        if ((u_int16_t)(n) >= 256) { \
150
                *cp++ = 0; \
151
                cp[1] = (n); \
152
                cp[0] = (n) >> 8; \
153
                cp += 2; \
154
        } else { \
155
                *cp++ = (n); \
156
        } \
157
}
158
#define ENCODEZ(n) { \
159
        if ((u_int16_t)(n) >= 256 || (u_int16_t)(n) == 0) { \
160
                *cp++ = 0; \
161
                cp[1] = (n); \
162
                cp[0] = (n) >> 8; \
163
                cp += 2; \
164
        } else { \
165
                *cp++ = (n); \
166
        } \
167
}
168
 
169
#define DECODEL(f) { \
170
        if (*cp == 0) {\
171
                (f) = htonl(ntohl(f) + ((cp[1] << 8) | cp[2])); \
172
                cp += 3; \
173
        } else { \
174
                (f) = htonl(ntohl(f) + (u_int32_t)*cp++); \
175
        } \
176
}
177
 
178
#define DECODES(f) { \
179
        if (*cp == 0) {\
180
                (f) = htons(ntohs(f) + ((cp[1] << 8) | cp[2])); \
181
                cp += 3; \
182
        } else { \
183
                (f) = htons(ntohs(f) + (u_int32_t)*cp++); \
184
        } \
185
}
186
 
187
#define DECODEU(f) { \
188
        if (*cp == 0) {\
189
                (f) = htons((cp[1] << 8) | cp[2]); \
190
                cp += 3; \
191
        } else { \
192
                (f) = htons((u_int32_t)*cp++); \
193
        } \
194
}
195
 
196
/*
197
 * Attempt to compress an outgoing TCP packet and return the type of
198
 * the result.  The caller must have already verified that the protocol
199
 * is TCP.  The first mbuf must contain the complete IP and TCP headers,
200
 * and "ip" must be == mtod(m, struct ip *).  "comp" supplies the
201
 * compression state, and "compress_cid" tells us whether it is OK
202
 * to leave out the CID field when feasible.
203
 *
204
 * The caller is responsible for adjusting m->m_pkthdr.len upon return,
205
 * if m is an M_PKTHDR mbuf.
206
 */
207
u_int
208
sl_compress_tcp(m, ip, comp, compress_cid)
209
        struct mbuf *m;
210
        register struct ip *ip;
211
        struct slcompress *comp;
212
        int compress_cid;
213
{
214
        register struct cstate *cs = comp->last_cs->cs_next;
215
        register u_int hlen = ip->ip_hl;
216
        register struct tcphdr *oth;
217
        register struct tcphdr *th;
218
        register u_int deltaS, deltaA;
219
        register u_int changes = 0;
220
        u_char new_seq[16];
221
        register u_char *cp = new_seq;
222
 
223
        /*
224
         * Bail if this is an IP fragment or if the TCP packet isn't
225
         * `compressible' (i.e., ACK isn't set or some other control bit is
226
         * set).  (We assume that the caller has already made sure the
227
         * packet is IP proto TCP).
228
         */
229
        if ((ip->ip_off & htons(0x3fff)) || m->m_len < 40)
230
                return (TYPE_IP);
231
 
232
        th = (struct tcphdr *)&((int32_t *)ip)[hlen];
233
        if ((th->th_flags & (TH_SYN|TH_FIN|TH_RST|TH_ACK)) != TH_ACK)
234
                return (TYPE_IP);
235
        /*
236
         * Packet is compressible -- we're going to send either a
237
         * COMPRESSED_TCP or UNCOMPRESSED_TCP packet.  Either way we need
238
         * to locate (or create) the connection state.  Special case the
239
         * most recently used connection since it's most likely to be used
240
         * again & we don't have to do any reordering if it's used.
241
         */
242
        INCR(sls_packets)
243
        if (ip->ip_src.s_addr != cs->cs_ip.ip_src.s_addr ||
244
            ip->ip_dst.s_addr != cs->cs_ip.ip_dst.s_addr ||
245
            *(int32_t *)th != ((int32_t *)&cs->cs_ip)[cs->cs_ip.ip_hl]) {
246
                /*
247
                 * Wasn't the first -- search for it.
248
                 *
249
                 * States are kept in a circularly linked list with
250
                 * last_cs pointing to the end of the list.  The
251
                 * list is kept in lru order by moving a state to the
252
                 * head of the list whenever it is referenced.  Since
253
                 * the list is short and, empirically, the connection
254
                 * we want is almost always near the front, we locate
255
                 * states via linear search.  If we don't find a state
256
                 * for the datagram, the oldest state is (re-)used.
257
                 */
258
                register struct cstate *lcs;
259
                register struct cstate *lastcs = comp->last_cs;
260
 
261
                do {
262
                        lcs = cs; cs = cs->cs_next;
263
                        INCR(sls_searches)
264
                        if (ip->ip_src.s_addr == cs->cs_ip.ip_src.s_addr
265
                            && ip->ip_dst.s_addr == cs->cs_ip.ip_dst.s_addr
266
                            && *(int32_t *)th ==
267
                            ((int32_t *)&cs->cs_ip)[cs->cs_ip.ip_hl])
268
                                goto found;
269
                } while (cs != lastcs);
270
 
271
                /*
272
                 * Didn't find it -- re-use oldest cstate.  Send an
273
                 * uncompressed packet that tells the other side what
274
                 * connection number we're using for this conversation.
275
                 * Note that since the state list is circular, the oldest
276
                 * state points to the newest and we only need to set
277
                 * last_cs to update the lru linkage.
278
                 */
279
                INCR(sls_misses)
280
                comp->last_cs = lcs;
281
                hlen += th->th_off;
282
                hlen <<= 2;
283
                if (hlen > m->m_len)
284
                    return TYPE_IP;
285
                goto uncompressed;
286
 
287
        found:
288
                /*
289
                 * Found it -- move to the front on the connection list.
290
                 */
291
                if (cs == lastcs)
292
                        comp->last_cs = lcs;
293
                else {
294
                        lcs->cs_next = cs->cs_next;
295
                        cs->cs_next = lastcs->cs_next;
296
                        lastcs->cs_next = cs;
297
                }
298
        }
299
 
300
        /*
301
         * Make sure that only what we expect to change changed. The first
302
         * line of the `if' checks the IP protocol version, header length &
303
         * type of service.  The 2nd line checks the "Don't fragment" bit.
304
         * The 3rd line checks the time-to-live and protocol (the protocol
305
         * check is unnecessary but costless).  The 4th line checks the TCP
306
         * header length.  The 5th line checks IP options, if any.  The 6th
307
         * line checks TCP options, if any.  If any of these things are
308
         * different between the previous & current datagram, we send the
309
         * current datagram `uncompressed'.
310
         */
311
        oth = (struct tcphdr *)&((int32_t *)&cs->cs_ip)[hlen];
312
        deltaS = hlen;
313
        hlen += th->th_off;
314
        hlen <<= 2;
315
        if (hlen > m->m_len)
316
            return TYPE_IP;
317
 
318
        if (((u_int16_t *)ip)[0] != ((u_int16_t *)&cs->cs_ip)[0] ||
319
            ((u_int16_t *)ip)[3] != ((u_int16_t *)&cs->cs_ip)[3] ||
320
            ((u_int16_t *)ip)[4] != ((u_int16_t *)&cs->cs_ip)[4] ||
321
            th->th_off != oth->th_off ||
322
            (deltaS > 5 &&
323
             BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2)) ||
324
            (th->th_off > 5 &&
325
             BCMP(th + 1, oth + 1, (th->th_off - 5) << 2)))
326
                goto uncompressed;
327
 
328
        /*
329
         * Figure out which of the changing fields changed.  The
330
         * receiver expects changes in the order: urgent, window,
331
         * ack, seq (the order minimizes the number of temporaries
332
         * needed in this section of code).
333
         */
334
        if (th->th_flags & TH_URG) {
335
                deltaS = ntohs(th->th_urp);
336
                ENCODEZ(deltaS);
337
                changes |= NEW_U;
338
        } else if (th->th_urp != oth->th_urp)
339
                /* argh! URG not set but urp changed -- a sensible
340
                 * implementation should never do this but RFC793
341
                 * doesn't prohibit the change so we have to deal
342
                 * with it. */
343
                 goto uncompressed;
344
 
345
        deltaS = (u_int16_t)(ntohs(th->th_win) - ntohs(oth->th_win));
346
        if (deltaS) {
347
                ENCODE(deltaS);
348
                changes |= NEW_W;
349
        }
350
 
351
        deltaA = ntohl(th->th_ack) - ntohl(oth->th_ack);
352
        if (deltaA) {
353
                if (deltaA > 0xffff)
354
                        goto uncompressed;
355
                ENCODE(deltaA);
356
                changes |= NEW_A;
357
        }
358
 
359
        deltaS = ntohl(th->th_seq) - ntohl(oth->th_seq);
360
        if (deltaS) {
361
                if (deltaS > 0xffff)
362
                        goto uncompressed;
363
                ENCODE(deltaS);
364
                changes |= NEW_S;
365
        }
366
 
367
        switch(changes) {
368
 
369
        case 0:
370
                /*
371
                 * Nothing changed. If this packet contains data and the
372
                 * last one didn't, this is probably a data packet following
373
                 * an ack (normal on an interactive connection) and we send
374
                 * it compressed.  Otherwise it's probably a retransmit,
375
                 * retransmitted ack or window probe.  Send it uncompressed
376
                 * in case the other side missed the compressed version.
377
                 */
378
                if (ip->ip_len != cs->cs_ip.ip_len &&
379
                    ntohs(cs->cs_ip.ip_len) == hlen)
380
                        break;
381
 
382
                /* (fall through) */
383
 
384
        case SPECIAL_I:
385
        case SPECIAL_D:
386
                /*
387
                 * actual changes match one of our special case encodings --
388
                 * send packet uncompressed.
389
                 */
390
                goto uncompressed;
391
 
392
        case NEW_S|NEW_A:
393
                if (deltaS == deltaA &&
394
                    deltaS == ntohs(cs->cs_ip.ip_len) - hlen) {
395
                        /* special case for echoed terminal traffic */
396
                        changes = SPECIAL_I;
397
                        cp = new_seq;
398
                }
399
                break;
400
 
401
        case NEW_S:
402
                if (deltaS == ntohs(cs->cs_ip.ip_len) - hlen) {
403
                        /* special case for data xfer */
404
                        changes = SPECIAL_D;
405
                        cp = new_seq;
406
                }
407
                break;
408
        }
409
 
410
        deltaS = ntohs(ip->ip_id) - ntohs(cs->cs_ip.ip_id);
411
        if (deltaS != 1) {
412
                ENCODEZ(deltaS);
413
                changes |= NEW_I;
414
        }
415
        if (th->th_flags & TH_PUSH)
416
                changes |= TCP_PUSH_BIT;
417
        /*
418
         * Grab the cksum before we overwrite it below.  Then update our
419
         * state with this packet's header.
420
         */
421
        deltaA = ntohs(th->th_sum);
422
        BCOPY(ip, &cs->cs_ip, hlen);
423
 
424
        /*
425
         * We want to use the original packet as our compressed packet.
426
         * (cp - new_seq) is the number of bytes we need for compressed
427
         * sequence numbers.  In addition we need one byte for the change
428
         * mask, one for the connection id and two for the tcp checksum.
429
         * So, (cp - new_seq) + 4 bytes of header are needed.  hlen is how
430
         * many bytes of the original packet to toss so subtract the two to
431
         * get the new packet size.
432
         */
433
        deltaS = cp - new_seq;
434
        cp = (u_char *)ip;
435
        if (compress_cid == 0 || comp->last_xmit != cs->cs_id) {
436
                comp->last_xmit = cs->cs_id;
437
                hlen -= deltaS + 4;
438
                cp += hlen;
439
                *cp++ = changes | NEW_C;
440
                *cp++ = cs->cs_id;
441
        } else {
442
                hlen -= deltaS + 3;
443
                cp += hlen;
444
                *cp++ = changes;
445
        }
446
        m->m_len -= hlen;
447
        m->m_data += hlen;
448
        *cp++ = deltaA >> 8;
449
        *cp++ = deltaA;
450
        BCOPY(new_seq, cp, deltaS);
451
        INCR(sls_compressed)
452
        return (TYPE_COMPRESSED_TCP);
453
 
454
        /*
455
         * Update connection state cs & send uncompressed packet ('uncompressed'
456
         * means a regular ip/tcp packet but with the 'conversation id' we hope
457
         * to use on future compressed packets in the protocol field).
458
         */
459
uncompressed:
460
        BCOPY(ip, &cs->cs_ip, hlen);
461
        ip->ip_p = cs->cs_id;
462
        comp->last_xmit = cs->cs_id;
463
        return (TYPE_UNCOMPRESSED_TCP);
464
}
465
 
466
 
467
int
468
sl_uncompress_tcp(bufp, len, type, comp)
469
        u_char **bufp;
470
        int len;
471
        u_int type;
472
        struct slcompress *comp;
473
{
474
        u_char *hdr, *cp;
475
        unsigned int hlen;
476
        int vjlen;
477
 
478
        cp = bufp? *bufp: NULL;
479
        vjlen = sl_uncompress_tcp_core(cp, len, len, type, comp, &hdr, &hlen);
480
        if (vjlen < 0)
481
                return (0);      /* error */
482
        if (vjlen == 0)
483
                return (len);   /* was uncompressed already */
484
 
485
        cp += vjlen;
486
        len -= vjlen;
487
 
488
        /*
489
         * At this point, cp points to the first byte of data in the
490
         * packet.  If we're not aligned on a 4-byte boundary, copy the
491
         * data down so the ip & tcp headers will be aligned.  Then back up
492
         * cp by the tcp/ip header length to make room for the reconstructed
493
         * header (we assume the packet we were handed has enough space to
494
         * prepend 128 bytes of header).
495
         */
496
        if ((intptr_t)cp & 3) {
497
                if (len > 0)
498
                        (void) ovbcopy(cp, (caddr_t)((intptr_t)cp &~ 3), len);
499
                cp = (u_char *)((intptr_t)cp &~ 3);
500
        }
501
        cp -= hlen;
502
        len += hlen;
503
        BCOPY(hdr, cp, hlen);
504
 
505
        *bufp = cp;
506
        return (len);
507
}
508
 
509
/*
510
 * Uncompress a packet of total length total_len.  The first buflen
511
 * bytes are at buf; this must include the entire (compressed or
512
 * uncompressed) TCP/IP header.  This procedure returns the length
513
 * of the VJ header, with a pointer to the uncompressed IP header
514
 * in *hdrp and its length in *hlenp.
515
 */
516
int
517
sl_uncompress_tcp_core(buf, buflen, total_len, type, comp, hdrp, hlenp)
518
        u_char *buf;
519
        int buflen, total_len;
520
        u_int type;
521
        struct slcompress *comp;
522
        u_char **hdrp;
523
        u_int *hlenp;
524
{
525
        register u_char *cp;
526
        register u_int hlen, changes;
527
        register struct tcphdr *th;
528
        register struct cstate *cs;
529
        register struct ip *ip;
530
        register u_int16_t *bp;
531
        register u_int vjlen;
532
 
533
        switch (type) {
534
 
535
        case TYPE_UNCOMPRESSED_TCP:
536
                ip = (struct ip *) buf;
537
                if (ip->ip_p >= MAX_STATES)
538
                        goto bad;
539
                cs = &comp->rstate[comp->last_recv = ip->ip_p];
540
                comp->flags &=~ SLF_TOSS;
541
                ip->ip_p = IPPROTO_TCP;
542
                /*
543
                 * Calculate the size of the TCP/IP header and make sure that
544
                 * we don't overflow the space we have available for it.
545
                 */
546
                hlen = ip->ip_hl << 2;
547
                if (hlen + sizeof(struct tcphdr) > buflen)
548
                        goto bad;
549
                hlen += ((struct tcphdr *)&((char *)ip)[hlen])->th_off << 2;
550
                if (hlen > MAX_HDR || hlen > buflen)
551
                        goto bad;
552
                BCOPY(ip, &cs->cs_ip, hlen);
553
                cs->cs_hlen = hlen;
554
                INCR(sls_uncompressedin)
555
                *hdrp = (u_char *) &cs->cs_ip;
556
                *hlenp = hlen;
557
                return (0);
558
 
559
        default:
560
                goto bad;
561
 
562
        case TYPE_COMPRESSED_TCP:
563
                break;
564
        }
565
        /* We've got a compressed packet. */
566
        INCR(sls_compressedin)
567
        cp = buf;
568
        changes = *cp++;
569
        if (changes & NEW_C) {
570
                /* Make sure the state index is in range, then grab the state.
571
                 * If we have a good state index, clear the 'discard' flag. */
572
                if (*cp >= MAX_STATES)
573
                        goto bad;
574
 
575
                comp->flags &=~ SLF_TOSS;
576
                comp->last_recv = *cp++;
577
        } else {
578
                /* this packet has an implicit state index.  If we've
579
                 * had a line error since the last time we got an
580
                 * explicit state index, we have to toss the packet. */
581
                if (comp->flags & SLF_TOSS) {
582
                        INCR(sls_tossed)
583
                        return (-1);
584
                }
585
        }
586
        cs = &comp->rstate[comp->last_recv];
587
        hlen = cs->cs_ip.ip_hl << 2;
588
        th = (struct tcphdr *)&((u_char *)&cs->cs_ip)[hlen];
589
        th->th_sum = htons((*cp << 8) | cp[1]);
590
        cp += 2;
591
        if (changes & TCP_PUSH_BIT)
592
                th->th_flags |= TH_PUSH;
593
        else
594
                th->th_flags &=~ TH_PUSH;
595
 
596
        switch (changes & SPECIALS_MASK) {
597
        case SPECIAL_I:
598
                {
599
                register u_int i = ntohs(cs->cs_ip.ip_len) - cs->cs_hlen;
600
                th->th_ack = htonl(ntohl(th->th_ack) + i);
601
                th->th_seq = htonl(ntohl(th->th_seq) + i);
602
                }
603
                break;
604
 
605
        case SPECIAL_D:
606
                th->th_seq = htonl(ntohl(th->th_seq) + ntohs(cs->cs_ip.ip_len)
607
                                   - cs->cs_hlen);
608
                break;
609
 
610
        default:
611
                if (changes & NEW_U) {
612
                        th->th_flags |= TH_URG;
613
                        DECODEU(th->th_urp)
614
                } else
615
                        th->th_flags &=~ TH_URG;
616
                if (changes & NEW_W)
617
                        DECODES(th->th_win)
618
                if (changes & NEW_A)
619
                        DECODEL(th->th_ack)
620
                if (changes & NEW_S)
621
                        DECODEL(th->th_seq)
622
                break;
623
        }
624
        if (changes & NEW_I) {
625
                DECODES(cs->cs_ip.ip_id)
626
        } else
627
                cs->cs_ip.ip_id = htons(ntohs(cs->cs_ip.ip_id) + 1);
628
 
629
        /*
630
         * At this point, cp points to the first byte of data in the
631
         * packet.  Fill in the IP total length and update the IP
632
         * header checksum.
633
         */
634
        vjlen = cp - buf;
635
        buflen -= vjlen;
636
        if (buflen < 0)
637
                /* we must have dropped some characters (crc should detect
638
                 * this but the old slip framing won't) */
639
                goto bad;
640
 
641
        total_len += cs->cs_hlen - vjlen;
642
        cs->cs_ip.ip_len = htons(total_len);
643
 
644
        /* recompute the ip header checksum */
645
        bp = (u_int16_t *) &cs->cs_ip;
646
        cs->cs_ip.ip_sum = 0;
647
                for (changes = 0; hlen > 0; hlen -= 2)
648
                        changes += *bp++;
649
                changes = (changes & 0xffff) + (changes >> 16);
650
                changes = (changes & 0xffff) + (changes >> 16);
651
        cs->cs_ip.ip_sum = ~ changes;
652
 
653
        *hdrp = (u_char *) &cs->cs_ip;
654
        *hlenp = cs->cs_hlen;
655
        return vjlen;
656
 
657
bad:
658
        comp->flags |= SLF_TOSS;
659
        INCR(sls_errorin)
660
        return (-1);
661
}

powered by: WebSVN 2.1.0

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