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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [net/] [slhc.c] - Blame information for rev 1626

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

Line No. Rev Author Line
1 1626 jcastillo
/*
2
 * Routines to compress and uncompress tcp packets (for transmission
3
 * over low speed serial lines).
4
 *
5
 * Copyright (c) 1989 Regents of the University of California.
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms are permitted
9
 * provided that the above copyright notice and this paragraph are
10
 * duplicated in all such forms and that any documentation,
11
 * advertising materials, and other materials related to such
12
 * distribution and use acknowledge that the software was developed
13
 * by the University of California, Berkeley.  The name of the
14
 * University may not be used to endorse or promote products derived
15
 * from this software without specific prior written permission.
16
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19
 *
20
 *      Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
21
 *      - Initial distribution.
22
 *
23
 *
24
 * modified for KA9Q Internet Software Package by
25
 * Katie Stevens (dkstevens@ucdavis.edu)
26
 * University of California, Davis
27
 * Computing Services
28
 *      - 01-31-90      initial adaptation (from 1.19)
29
 *      PPP.05  02-15-90 [ks]
30
 *      PPP.08  05-02-90 [ks]   use PPP protocol field to signal compression
31
 *      PPP.15  09-90    [ks]   improve mbuf handling
32
 *      PPP.16  11-02    [karn] substantially rewritten to use NOS facilities
33
 *
34
 *      - Feb 1991      Bill_Simpson@um.cc.umich.edu
35
 *                      variable number of conversation slots
36
 *                      allow zero or one slots
37
 *                      separate routines
38
 *                      status display
39
 *      - Jul 1994      Dmitry Gorodchanin
40
 *                      Fixes for memory leaks.
41
 *      - Oct 1994      Dmitry Gorodchanin
42
 *                      Modularization.
43
 *      - Jan 1995      Bjorn Ekwall
44
 *                      Use ip_fast_csum from ip.h
45
 *      - July 1995     Christos A. Polyzols
46
 *                      Spotted bug in tcp option checking
47
 *
48
 *
49
 *      This module is a difficult issue. It's clearly inet code but it's also clearly
50
 *      driver code belonging close to PPP and SLIP
51
 */
52
 
53
#include <linux/config.h>
54
#ifdef CONFIG_INET
55
/* Entire module is for IP only */
56
#include <linux/module.h>
57
 
58
#include <linux/types.h>
59
#include <linux/sched.h>
60
#include <linux/mm.h>
61
#include <linux/string.h>
62
#include <linux/socket.h>
63
#include <linux/sockios.h>
64
#include <linux/termios.h>
65
#include <linux/in.h>
66
#include <linux/fcntl.h>
67
#include <linux/inet.h>
68
#include <linux/netdevice.h>
69
#include <net/ip.h>
70
#include <net/protocol.h>
71
#include <net/icmp.h>
72
#include <net/tcp.h>
73
#include <linux/skbuff.h>
74
#include <net/sock.h>
75
#include <linux/errno.h>
76
#include <linux/timer.h>
77
#include <asm/system.h>
78
#include <asm/segment.h>
79
#include <linux/mm.h>
80
#include <net/checksum.h>
81
#include <net/slhc_vj.h>
82
#include <asm/unaligned.h>
83
 
84
int last_retran;
85
 
86
static unsigned char *encode(unsigned char *cp, unsigned short n);
87
static long decode(unsigned char **cpp);
88
static unsigned char * put16(unsigned char *cp, unsigned short x);
89
static unsigned short pull16(unsigned char **cpp);
90
static void export_slhc_syms(void);
91
 
92
/* Initialize compression data structure
93
 *      slots must be in range 0 to 255 (zero meaning no compression)
94
 */
95
struct slcompress *
96
slhc_init(int rslots, int tslots)
97
{
98
        register short i;
99
        register struct cstate *ts;
100
        struct slcompress *comp;
101
 
102
        comp = (struct slcompress *)kmalloc(sizeof(struct slcompress),
103
                                            GFP_KERNEL);
104
        if (! comp)
105
                return NULL;
106
 
107
        memset(comp, 0, sizeof(struct slcompress));
108
 
109
        if ( rslots > 0  &&  rslots < 256 ) {
110
                size_t rsize = rslots * sizeof(struct cstate);
111
                comp->rstate = (struct cstate *) kmalloc(rsize, GFP_KERNEL);
112
                if (! comp->rstate)
113
                {
114
                        kfree((unsigned char *)comp);
115
                        return NULL;
116
                }
117
                memset(comp->rstate, 0, rsize);
118
                comp->rslot_limit = rslots - 1;
119
        }
120
 
121
        if ( tslots > 0  &&  tslots < 256 ) {
122
                size_t tsize = tslots * sizeof(struct cstate);
123
                comp->tstate = (struct cstate *) kmalloc(tsize, GFP_KERNEL);
124
                if (! comp->tstate)
125
                {
126
                        kfree((unsigned char *)comp->rstate);
127
                        kfree((unsigned char *)comp);
128
                        return NULL;
129
                }
130
                memset(comp->tstate, 0, tsize);
131
                comp->tslot_limit = tslots - 1;
132
        }
133
 
134
        comp->xmit_oldest = 0;
135
        comp->xmit_current = 255;
136
        comp->recv_current = 255;
137
        /*
138
         * don't accept any packets with implicit index until we get
139
         * one with an explicit index.  Otherwise the uncompress code
140
         * will try to use connection 255, which is almost certainly
141
         * out of range
142
         */
143
        comp->flags |= SLF_TOSS;
144
 
145
        if ( tslots > 0 ) {
146
                ts = comp->tstate;
147
                for(i = comp->tslot_limit; i > 0; --i){
148
                        ts[i].cs_this = i;
149
                        ts[i].next = &(ts[i - 1]);
150
                }
151
                ts[0].next = &(ts[comp->tslot_limit]);
152
                ts[0].cs_this = 0;
153
        }
154
        MOD_INC_USE_COUNT;
155
        return comp;
156
}
157
 
158
 
159
/* Free a compression data structure */
160
void
161
slhc_free(struct slcompress *comp)
162
{
163
        if ( comp == NULLSLCOMPR )
164
                return;
165
 
166
        if ( comp->rstate != NULLSLSTATE )
167
                kfree( comp->rstate );
168
 
169
        if ( comp->tstate != NULLSLSTATE )
170
                kfree( comp->tstate );
171
 
172
        MOD_DEC_USE_COUNT;
173
        kfree( comp );
174
}
175
 
176
 
177
/* Put a short in host order into a char array in network order */
178
static inline unsigned char *
179
put16(unsigned char *cp, unsigned short x)
180
{
181
        *cp++ = x >> 8;
182
        *cp++ = x;
183
 
184
        return cp;
185
}
186
 
187
 
188
/* Encode a number */
189
unsigned char *
190
encode(unsigned char *cp, unsigned short n)
191
{
192
        if(n >= 256 || n == 0){
193
                *cp++ = 0;
194
                cp = put16(cp,n);
195
        } else {
196
                *cp++ = n;
197
        }
198
        return cp;
199
}
200
 
201
/* Pull a 16-bit integer in host order from buffer in network byte order */
202
static unsigned short
203
pull16(unsigned char **cpp)
204
{
205
        short rval;
206
 
207
        rval = *(*cpp)++;
208
        rval <<= 8;
209
        rval |= *(*cpp)++;
210
        return rval;
211
}
212
 
213
/* Decode a number */
214
long
215
decode(unsigned char **cpp)
216
{
217
        register int x;
218
 
219
        x = *(*cpp)++;
220
        if(x == 0){
221
                return pull16(cpp) & 0xffff;    /* pull16 returns -1 on error */
222
        } else {
223
                return x & 0xff;                /* -1 if PULLCHAR returned error */
224
        }
225
}
226
 
227
/*
228
 * icp and isize are the original packet.
229
 * ocp is a place to put a copy if necessary.
230
 * cpp is initially a pointer to icp.  If the copy is used,
231
 *    change it to ocp.
232
 */
233
 
234
int
235
slhc_compress(struct slcompress *comp, unsigned char *icp, int isize,
236
        unsigned char *ocp, unsigned char **cpp, int compress_cid)
237
{
238
        register struct cstate *ocs = &(comp->tstate[comp->xmit_oldest]);
239
        register struct cstate *lcs = ocs;
240
        register struct cstate *cs = lcs->next;
241
        register unsigned long deltaS, deltaA;
242
        register short changes = 0;
243
        int hlen;
244
        unsigned char new_seq[16];
245
        register unsigned char *cp = new_seq;
246
        struct iphdr *ip;
247
        struct tcphdr *th, *oth;
248
 
249
 
250
        /*
251
         *      Don't play with runt packets.
252
         */
253
 
254
        if(isize<sizeof(struct iphdr))
255
                return isize;
256
 
257
        ip = (struct iphdr *) icp;
258
 
259
        /* Bail if this packet isn't TCP, or is an IP fragment */
260
        if(ip->protocol != IPPROTO_TCP || (ntohs(ip->frag_off) & 0x1fff) ||
261
                                       (ip->frag_off & 32)){
262
                /* Send as regular IP */
263
                if(ip->protocol != IPPROTO_TCP)
264
                        comp->sls_o_nontcp++;
265
                else
266
                        comp->sls_o_tcp++;
267
                return isize;
268
        }
269
        /* Extract TCP header */
270
 
271
        th = (struct tcphdr *)(((unsigned char *)ip) + ip->ihl*4);
272
        hlen = ip->ihl*4 + th->doff*4;
273
 
274
        /*  Bail if the TCP packet isn't `compressible' (i.e., ACK isn't set or
275
         *  some other control bit is set). Also uncompressible if
276
         *  its a runt.
277
         */
278
        if(hlen > isize || th->syn || th->fin || th->rst ||
279
            ! (th->ack)){
280
                /* TCP connection stuff; send as regular IP */
281
                comp->sls_o_tcp++;
282
                return isize;
283
        }
284
        /*
285
         * Packet is compressible -- we're going to send either a
286
         * COMPRESSED_TCP or UNCOMPRESSED_TCP packet.  Either way,
287
         * we need to locate (or create) the connection state.
288
         *
289
         * States are kept in a circularly linked list with
290
         * xmit_oldest pointing to the end of the list.  The
291
         * list is kept in lru order by moving a state to the
292
         * head of the list whenever it is referenced.  Since
293
         * the list is short and, empirically, the connection
294
         * we want is almost always near the front, we locate
295
         * states via linear search.  If we don't find a state
296
         * for the datagram, the oldest state is (re-)used.
297
         */
298
        for ( ; ; ) {
299
                if( ip->saddr == cs->cs_ip.saddr
300
                 && ip->daddr == cs->cs_ip.daddr
301
                 && th->source == cs->cs_tcp.source
302
                 && th->dest == cs->cs_tcp.dest)
303
                        goto found;
304
 
305
                /* if current equal oldest, at end of list */
306
                if ( cs == ocs )
307
                        break;
308
                lcs = cs;
309
                cs = cs->next;
310
                comp->sls_o_searches++;
311
        };
312
        /*
313
         * Didn't find it -- re-use oldest cstate.  Send an
314
         * uncompressed packet that tells the other side what
315
         * connection number we're using for this conversation.
316
         *
317
         * Note that since the state list is circular, the oldest
318
         * state points to the newest and we only need to set
319
         * xmit_oldest to update the lru linkage.
320
         */
321
        comp->sls_o_misses++;
322
        comp->xmit_oldest = lcs->cs_this;
323
        goto uncompressed;
324
 
325
found:
326
        /*
327
         * Found it -- move to the front on the connection list.
328
         */
329
        if(lcs == ocs) {
330
                /* found at most recently used */
331
        } else if (cs == ocs) {
332
                /* found at least recently used */
333
                comp->xmit_oldest = lcs->cs_this;
334
        } else {
335
                /* more than 2 elements */
336
                lcs->next = cs->next;
337
                cs->next = ocs->next;
338
                ocs->next = cs;
339
        }
340
 
341
        /*
342
         * Make sure that only what we expect to change changed.
343
         * Check the following:
344
         * IP protocol version, header length & type of service.
345
         * The "Don't fragment" bit.
346
         * The time-to-live field.
347
         * The TCP header length.
348
         * IP options, if any.
349
         * TCP options, if any.
350
         * If any of these things are different between the previous &
351
         * current datagram, we send the current datagram `uncompressed'.
352
         */
353
        oth = &cs->cs_tcp;
354
 
355
        if(last_retran
356
         || ip->version != cs->cs_ip.version || ip->ihl != cs->cs_ip.ihl
357
         || ip->tos != cs->cs_ip.tos
358
         || (ip->frag_off & 64) != (cs->cs_ip.frag_off & 64)
359
         || ip->ttl != cs->cs_ip.ttl
360
         || th->doff != cs->cs_tcp.doff
361
         || (ip->ihl > 5 && memcmp(ip+1,cs->cs_ipopt,((ip->ihl)-5)*4) != 0)
362
         || (th->doff > 5 && memcmp(th+1,cs->cs_tcpopt,((th->doff)-5)*4) != 0)){
363
                goto uncompressed;
364
        }
365
 
366
        /*
367
         * Figure out which of the changing fields changed.  The
368
         * receiver expects changes in the order: urgent, window,
369
         * ack, seq (the order minimizes the number of temporaries
370
         * needed in this section of code).
371
         */
372
        if(th->urg){
373
                deltaS = ntohs(th->urg_ptr);
374
                cp = encode(cp,deltaS);
375
                changes |= NEW_U;
376
        } else if(th->urg_ptr != oth->urg_ptr){
377
                /* argh! URG not set but urp changed -- a sensible
378
                 * implementation should never do this but RFC793
379
                 * doesn't prohibit the change so we have to deal
380
                 * with it. */
381
                goto uncompressed;
382
        }
383
        if((deltaS = ntohs(th->window) - ntohs(oth->window)) != 0){
384
                cp = encode(cp,deltaS);
385
                changes |= NEW_W;
386
        }
387
        if((deltaA = ntohl(th->ack_seq) - ntohl(oth->ack_seq)) != 0L){
388
                if(deltaA > 0x0000ffff)
389
                        goto uncompressed;
390
                cp = encode(cp,deltaA);
391
                changes |= NEW_A;
392
        }
393
        if((deltaS = ntohl(th->seq) - ntohl(oth->seq)) != 0L){
394
                if(deltaS > 0x0000ffff)
395
                        goto uncompressed;
396
                cp = encode(cp,deltaS);
397
                changes |= NEW_S;
398
        }
399
 
400
        switch(changes){
401
        case 0:  /* Nothing changed. If this packet contains data and the
402
                 * last one didn't, this is probably a data packet following
403
                 * an ack (normal on an interactive connection) and we send
404
                 * it compressed.  Otherwise it's probably a retransmit,
405
                 * retransmitted ack or window probe.  Send it uncompressed
406
                 * in case the other side missed the compressed version.
407
                 */
408
                if(ip->tot_len != cs->cs_ip.tot_len &&
409
                   ntohs(cs->cs_ip.tot_len) == hlen)
410
                        break;
411
                goto uncompressed;
412
                break;
413
        case SPECIAL_I:
414
        case SPECIAL_D:
415
                /* actual changes match one of our special case encodings --
416
                 * send packet uncompressed.
417
                 */
418
                goto uncompressed;
419
        case NEW_S|NEW_A:
420
                if(deltaS == deltaA &&
421
                    deltaS == ntohs(cs->cs_ip.tot_len) - hlen){
422
                        /* special case for echoed terminal traffic */
423
                        changes = SPECIAL_I;
424
                        cp = new_seq;
425
                }
426
                break;
427
        case NEW_S:
428
                if(deltaS == ntohs(cs->cs_ip.tot_len) - hlen){
429
                        /* special case for data xfer */
430
                        changes = SPECIAL_D;
431
                        cp = new_seq;
432
                }
433
                break;
434
        }
435
        deltaS = ntohs(ip->id) - ntohs(cs->cs_ip.id);
436
        if(deltaS != 1){
437
                cp = encode(cp,deltaS);
438
                changes |= NEW_I;
439
        }
440
        if(th->psh)
441
                changes |= TCP_PUSH_BIT;
442
        /* Grab the cksum before we overwrite it below.  Then update our
443
         * state with this packet's header.
444
         */
445
        deltaA = ntohs(th->check);
446
        memcpy(&cs->cs_ip,ip,20);
447
        memcpy(&cs->cs_tcp,th,20);
448
        /* We want to use the original packet as our compressed packet.
449
         * (cp - new_seq) is the number of bytes we need for compressed
450
         * sequence numbers.  In addition we need one byte for the change
451
         * mask, one for the connection id and two for the tcp checksum.
452
         * So, (cp - new_seq) + 4 bytes of header are needed.
453
         */
454
        deltaS = cp - new_seq;
455
        if(compress_cid == 0 || comp->xmit_current != cs->cs_this){
456
                cp = ocp;
457
                *cpp = ocp;
458
                *cp++ = changes | NEW_C;
459
                *cp++ = cs->cs_this;
460
                comp->xmit_current = cs->cs_this;
461
        } else {
462
                cp = ocp;
463
                *cpp = ocp;
464
                *cp++ = changes;
465
        }
466
        cp = put16(cp,(short)deltaA);   /* Write TCP checksum */
467
/* deltaS is now the size of the change section of the compressed header */
468
        memcpy(cp,new_seq,deltaS);      /* Write list of deltas */
469
        memcpy(cp+deltaS,icp+hlen,isize-hlen);
470
        comp->sls_o_compressed++;
471
        ocp[0] |= SL_TYPE_COMPRESSED_TCP;
472
        return isize - hlen + deltaS + (cp - ocp);
473
 
474
        /* Update connection state cs & send uncompressed packet (i.e.,
475
         * a regular ip/tcp packet but with the 'conversation id' we hope
476
         * to use on future compressed packets in the protocol field).
477
         */
478
uncompressed:
479
        memcpy(&cs->cs_ip,ip,20);
480
        memcpy(&cs->cs_tcp,th,20);
481
        if (ip->ihl > 5)
482
          memcpy(cs->cs_ipopt, ip+1, ((ip->ihl) - 5) * 4);
483
        if (th->doff > 5)
484
          memcpy(cs->cs_tcpopt, th+1, ((th->doff) - 5) * 4);
485
        comp->xmit_current = cs->cs_this;
486
        comp->sls_o_uncompressed++;
487
        memcpy(ocp, icp, isize);
488
        *cpp = ocp;
489
        ocp[9] = cs->cs_this;
490
        ocp[0] |= SL_TYPE_UNCOMPRESSED_TCP;
491
        return isize;
492
}
493
 
494
 
495
int
496
slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
497
{
498
        register int changes;
499
        long x;
500
        register struct tcphdr *thp;
501
        register struct iphdr *ip;
502
        register struct cstate *cs;
503
        int len, hdrlen;
504
        unsigned char *cp = icp;
505
 
506
        /* We've got a compressed packet; read the change byte */
507
        comp->sls_i_compressed++;
508
        if(isize < 3){
509
                comp->sls_i_error++;
510
                return 0;
511
        }
512
        changes = *cp++;
513
        if(changes & NEW_C){
514
                /* Make sure the state index is in range, then grab the state.
515
                 * If we have a good state index, clear the 'discard' flag.
516
                 */
517
                x = *cp++;      /* Read conn index */
518
                if(x < 0 || x > comp->rslot_limit)
519
                        goto bad;
520
 
521
                comp->flags &=~ SLF_TOSS;
522
                comp->recv_current = x;
523
        } else {
524
                /* this packet has an implicit state index.  If we've
525
                 * had a line error since the last time we got an
526
                 * explicit state index, we have to toss the packet. */
527
                if(comp->flags & SLF_TOSS){
528
                        comp->sls_i_tossed++;
529
                        return 0;
530
                }
531
        }
532
        cs = &comp->rstate[comp->recv_current];
533
        thp = &cs->cs_tcp;
534
        ip = &cs->cs_ip;
535
 
536
        if((x = pull16(&cp)) == -1) {   /* Read the TCP checksum */
537
                goto bad;
538
        }
539
        thp->check = htons(x);
540
 
541
        thp->psh = (changes & TCP_PUSH_BIT) ? 1 : 0;
542
/*
543
 * we can use the same number for the length of the saved header and
544
 * the current one, because the packet wouldn't have been sent
545
 * as compressed unless the options were the same as the previous one
546
 */
547
 
548
        hdrlen = ip->ihl * 4 + thp->doff * 4;
549
 
550
        switch(changes & SPECIALS_MASK){
551
        case SPECIAL_I:         /* Echoed terminal traffic */
552
                {
553
                register short i;
554
                i = ntohs(ip->tot_len) - hdrlen;
555
                thp->ack_seq = htonl( ntohl(thp->ack_seq) + i);
556
                thp->seq = htonl( ntohl(thp->seq) + i);
557
                }
558
                break;
559
 
560
        case SPECIAL_D:                 /* Unidirectional data */
561
                thp->seq = htonl( ntohl(thp->seq) +
562
                                  ntohs(ip->tot_len) - hdrlen);
563
                break;
564
 
565
        default:
566
                if(changes & NEW_U){
567
                        thp->urg = 1;
568
                        if((x = decode(&cp)) == -1) {
569
                                goto bad;
570
                        }
571
                        thp->urg_ptr = htons(x);
572
                } else
573
                        thp->urg = 0;
574
                if(changes & NEW_W){
575
                        if((x = decode(&cp)) == -1) {
576
                                goto bad;
577
                        }
578
                        thp->window = htons( ntohs(thp->window) + x);
579
                }
580
                if(changes & NEW_A){
581
                        if((x = decode(&cp)) == -1) {
582
                                goto bad;
583
                        }
584
                        thp->ack_seq = htonl( ntohl(thp->ack_seq) + x);
585
                }
586
                if(changes & NEW_S){
587
                        if((x = decode(&cp)) == -1) {
588
                                goto bad;
589
                        }
590
                        thp->seq = htonl( ntohl(thp->seq) + x);
591
                }
592
                break;
593
        }
594
        if(changes & NEW_I){
595
                if((x = decode(&cp)) == -1) {
596
                        goto bad;
597
                }
598
                ip->id = htons (ntohs (ip->id) + x);
599
        } else
600
                ip->id = htons (ntohs (ip->id) + 1);
601
 
602
        /*
603
         * At this point, cp points to the first byte of data in the
604
         * packet.  Put the reconstructed TCP and IP headers back on the
605
         * packet.  Recalculate IP checksum (but not TCP checksum).
606
         */
607
 
608
        len = isize - (cp - icp);
609
        if (len < 0)
610
                goto bad;
611
        len += hdrlen;
612
        ip->tot_len = htons(len);
613
        ip->check = 0;
614
 
615
        memmove(icp + hdrlen, cp, len - hdrlen);
616
 
617
        cp = icp;
618
        memcpy(cp, ip, 20);
619
        cp += 20;
620
 
621
        if (ip->ihl > 5) {
622
          memcpy(cp, cs->cs_ipopt, (ip->ihl - 5) * 4);
623
          cp += (ip->ihl - 5) * 4;
624
        }
625
 
626
        put_unaligned(ip_fast_csum(icp, ip->ihl),
627
                      &((struct iphdr *)icp)->check);
628
 
629
        memcpy(cp, thp, 20);
630
        cp += 20;
631
 
632
        if (thp->doff > 5) {
633
          memcpy(cp, cs->cs_tcpopt, ((thp->doff) - 5) * 4);
634
          cp += ((thp->doff) - 5) * 4;
635
        }
636
 
637
        return len;
638
bad:
639
        comp->sls_i_error++;
640
        return slhc_toss( comp );
641
}
642
 
643
 
644
int
645
slhc_remember(struct slcompress *comp, unsigned char *icp, int isize)
646
{
647
        register struct cstate *cs;
648
        unsigned ihl;
649
 
650
        unsigned char index;
651
 
652
        if(isize < 20) {
653
                /* The packet is shorter than a legal IP header */
654
                comp->sls_i_runt++;
655
                return slhc_toss( comp );
656
        }
657
        /* Peek at the IP header's IHL field to find its length */
658
        ihl = icp[0] & 0xf;
659
        if(ihl < 20 / 4){
660
                /* The IP header length field is too small */
661
                comp->sls_i_runt++;
662
                return slhc_toss( comp );
663
        }
664
        index = icp[9];
665
        icp[9] = IPPROTO_TCP;
666
 
667
        if (ip_fast_csum(icp, ihl)) {
668
                /* Bad IP header checksum; discard */
669
                comp->sls_i_badcheck++;
670
                return slhc_toss( comp );
671
        }
672
        if(index > comp->rslot_limit) {
673
                comp->sls_i_error++;
674
                return slhc_toss(comp);
675
        }
676
 
677
        /* Update local state */
678
        cs = &comp->rstate[comp->recv_current = index];
679
        comp->flags &=~ SLF_TOSS;
680
        memcpy(&cs->cs_ip,icp,20);
681
        memcpy(&cs->cs_tcp,icp + ihl*4,20);
682
        if (ihl > 5)
683
          memcpy(cs->cs_ipopt, icp + sizeof(struct iphdr), (ihl - 5) * 4);
684
        if (cs->cs_tcp.doff > 5)
685
          memcpy(cs->cs_tcpopt, icp + ihl*4 + sizeof(struct tcphdr), (cs->cs_tcp.doff - 5) * 4);
686
        cs->cs_hsize = ihl*2 + cs->cs_tcp.doff*2;
687
        /* Put headers back on packet
688
         * Neither header checksum is recalculated
689
         */
690
        comp->sls_i_uncompressed++;
691
        return isize;
692
}
693
 
694
 
695
int
696
slhc_toss(struct slcompress *comp)
697
{
698
        if ( comp == NULLSLCOMPR )
699
                return 0;
700
 
701
        comp->flags |= SLF_TOSS;
702
        return 0;
703
}
704
 
705
 
706
void slhc_i_status(struct slcompress *comp)
707
{
708
        if (comp != NULLSLCOMPR) {
709
                printk("\t%ld Cmp, %ld Uncmp, %ld Bad, %ld Tossed\n",
710
                        comp->sls_i_compressed,
711
                        comp->sls_i_uncompressed,
712
                        comp->sls_i_error,
713
                        comp->sls_i_tossed);
714
        }
715
}
716
 
717
 
718
void slhc_o_status(struct slcompress *comp)
719
{
720
        if (comp != NULLSLCOMPR) {
721
                printk("\t%ld Cmp, %ld Uncmp, %ld AsIs, %ld NotTCP\n",
722
                        comp->sls_o_compressed,
723
                        comp->sls_o_uncompressed,
724
                        comp->sls_o_tcp,
725
                        comp->sls_o_nontcp);
726
                printk("\t%10ld Searches, %10ld Misses\n",
727
                        comp->sls_o_searches,
728
                        comp->sls_o_misses);
729
        }
730
}
731
 
732
static struct symbol_table slhc_syms = {
733
/* Should this be surrounded with "#ifdef CONFIG_MODULES" ? */
734
#include <linux/symtab_begin.h>
735
        /* VJ header compression */
736
        X(slhc_init),
737
        X(slhc_free),
738
        X(slhc_remember),
739
        X(slhc_compress),
740
        X(slhc_uncompress),
741
        X(slhc_toss),
742
#include <linux/symtab_end.h>
743
};
744
 
745
static void export_slhc_syms(void)
746
{
747
        register_symtab(&slhc_syms);
748
}
749
 
750
#ifdef MODULE
751
 
752
int init_module(void)
753
{
754
        printk(KERN_INFO "CSLIP: code copyright 1989 Regents of the University of California\n");
755
        export_slhc_syms();
756
        return 0;
757
}
758
 
759
void cleanup_module(void)
760
{
761
        return;
762
}
763
#else /* MODULE */
764
 
765
void slhc_install(void)
766
{
767
        export_slhc_syms();
768
}
769
#endif
770
#endif /* CONFIG_INET */

powered by: WebSVN 2.1.0

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