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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [net/] [slhc.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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