This source file includes following definitions.
- slhc_init
- slhc_free
- put16
- encode
- pull16
- decode
- slhc_compress
- slhc_uncompress
- slhc_remember
- slhc_toss
- slhc_i_status
- slhc_o_status
- init_module
- cleanup_module
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 #include <linux/config.h>
54 #ifdef CONFIG_INET
55
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 "slhc.h"
82
83 #ifdef __alpha__
84 # include <asm/unaligned.h>
85 #endif
86
87 int last_retran;
88
89 static unsigned char *encode(unsigned char *cp, unsigned short n);
90 static long decode(unsigned char **cpp);
91 static unsigned char * put16(unsigned char *cp, unsigned short x);
92 static unsigned short pull16(unsigned char **cpp);
93
94
95
96
97 struct slcompress *
98 slhc_init(int rslots, int tslots)
99 {
100 register short i;
101 register struct cstate *ts;
102 struct slcompress *comp;
103
104 comp = (struct slcompress *)kmalloc(sizeof(struct slcompress),
105 GFP_KERNEL);
106 if (! comp)
107 return NULL;
108
109 memset(comp, 0, sizeof(struct slcompress));
110
111 if ( rslots > 0 && rslots < 256 ) {
112 comp->rstate =
113 (struct cstate *)kmalloc(rslots * sizeof(struct cstate),
114 GFP_KERNEL);
115 if (! comp->rstate)
116 {
117 kfree((unsigned char *)comp);
118 return NULL;
119 }
120 memset(comp->rstate, 0, rslots * sizeof(struct cstate));
121 comp->rslot_limit = rslots - 1;
122 }
123
124 if ( tslots > 0 && tslots < 256 ) {
125 comp->tstate =
126 (struct cstate *)kmalloc(tslots * sizeof(struct cstate),
127 GFP_KERNEL);
128 if (! comp->tstate)
129 {
130 kfree((unsigned char *)comp->rstate);
131 kfree((unsigned char *)comp);
132 return NULL;
133 }
134 memset(comp->tstate, 0, tslots * sizeof(struct cstate));
135 comp->tslot_limit = tslots - 1;
136 }
137
138 comp->xmit_oldest = 0;
139 comp->xmit_current = 255;
140 comp->recv_current = 255;
141
142
143
144
145
146
147 comp->flags |= SLF_TOSS;
148
149 if ( tslots > 0 ) {
150 ts = comp->tstate;
151 for(i = comp->tslot_limit; i > 0; --i){
152 ts[i].cs_this = i;
153 ts[i].next = &(ts[i - 1]);
154 }
155 ts[0].next = &(ts[comp->tslot_limit]);
156 ts[0].cs_this = 0;
157 }
158 MOD_INC_USE_COUNT;
159 return comp;
160 }
161
162
163
164 void
165 slhc_free(struct slcompress *comp)
166 {
167 if ( comp == NULLSLCOMPR )
168 return;
169
170 if ( comp->rstate != NULLSLSTATE )
171 kfree( comp->rstate );
172
173 if ( comp->tstate != NULLSLSTATE )
174 kfree( comp->tstate );
175
176 MOD_DEC_USE_COUNT;
177 kfree( comp );
178 }
179
180
181
182 static inline unsigned char *
183 put16(unsigned char *cp, unsigned short x)
184 {
185 *cp++ = x >> 8;
186 *cp++ = x;
187
188 return cp;
189 }
190
191
192
193 unsigned char *
194 encode(unsigned char *cp, unsigned short n)
195 {
196 if(n >= 256 || n == 0){
197 *cp++ = 0;
198 cp = put16(cp,n);
199 } else {
200 *cp++ = n;
201 }
202 return cp;
203 }
204
205
206 static unsigned short
207 pull16(unsigned char **cpp)
208 {
209 short rval;
210
211 rval = *(*cpp)++;
212 rval <<= 8;
213 rval |= *(*cpp)++;
214 return rval;
215 }
216
217
218 long
219 decode(unsigned char **cpp)
220 {
221 register int x;
222
223 x = *(*cpp)++;
224 if(x == 0){
225 return pull16(cpp) & 0xffff;
226 } else {
227 return x & 0xff;
228 }
229 }
230
231
232
233
234
235
236
237
238 int
239 slhc_compress(struct slcompress *comp, unsigned char *icp, int isize,
240 unsigned char *ocp, unsigned char **cpp, int compress_cid)
241 {
242 register struct cstate *ocs = &(comp->tstate[comp->xmit_oldest]);
243 register struct cstate *lcs = ocs;
244 register struct cstate *cs = lcs->next;
245 register unsigned long deltaS, deltaA;
246 register short changes = 0;
247 int hlen;
248 unsigned char new_seq[16];
249 register unsigned char *cp = new_seq;
250 struct iphdr *ip;
251 struct tcphdr *th, *oth;
252
253 ip = (struct iphdr *) icp;
254
255
256 if(ip->protocol != IPPROTO_TCP || (ntohs(ip->frag_off) & 0x1fff) ||
257 (ip->frag_off & 32)){
258
259 if(ip->protocol != IPPROTO_TCP)
260 comp->sls_o_nontcp++;
261 else
262 comp->sls_o_tcp++;
263 return isize;
264 }
265
266
267 th = (struct tcphdr *)(((unsigned char *)ip) + ip->ihl*4);
268 hlen = ip->ihl*4 + th->doff*4;
269
270
271
272
273 if(th->syn || th->fin || th->rst ||
274 ! (th->ack)){
275
276 comp->sls_o_tcp++;
277 return isize;
278 }
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293 for ( ; ; ) {
294 if( ip->saddr == cs->cs_ip.saddr
295 && ip->daddr == cs->cs_ip.daddr
296 && th->source == cs->cs_tcp.source
297 && th->dest == cs->cs_tcp.dest)
298 goto found;
299
300
301 if ( cs == ocs )
302 break;
303 lcs = cs;
304 cs = cs->next;
305 comp->sls_o_searches++;
306 };
307
308
309
310
311
312
313
314
315
316 comp->sls_o_misses++;
317 comp->xmit_oldest = lcs->cs_this;
318 goto uncompressed;
319
320 found:
321
322
323
324 if(lcs == ocs) {
325
326 } else if (cs == ocs) {
327
328 comp->xmit_oldest = lcs->cs_this;
329 } else {
330
331 lcs->next = cs->next;
332 cs->next = ocs->next;
333 ocs->next = cs;
334 }
335
336
337
338
339
340
341
342
343
344
345
346
347
348 oth = &cs->cs_tcp;
349
350 if(last_retran
351 || ip->version != cs->cs_ip.version || ip->ihl != cs->cs_ip.ihl
352 || ip->tos != cs->cs_ip.tos
353 || (ip->frag_off & 64) != (cs->cs_ip.frag_off & 64)
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
363
364
365
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
373
374
375
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:
397
398
399
400
401
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
411
412
413 goto uncompressed;
414 case NEW_S|NEW_A:
415 if(deltaS == deltaA &&
416 deltaS == ntohs(cs->cs_ip.tot_len) - hlen){
417
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
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
438
439
440 deltaA = ntohs(th->check);
441 memcpy(&cs->cs_ip,ip,20);
442 memcpy(&cs->cs_tcp,th,20);
443
444
445
446
447
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);
462
463 memcpy(cp,new_seq,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
470
471
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
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
510
511
512 x = *cp++;
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
520
521
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) {
532 goto bad;
533 }
534 thp->check = htons(x);
535
536 thp->psh = (changes & TCP_PUSH_BIT) ? 1 : 0;
537
538
539
540
541
542
543 hdrlen = ip->ihl * 4 + thp->doff * 4;
544
545 switch(changes & SPECIALS_MASK){
546 case SPECIAL_I:
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:
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
599
600
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 #ifdef __alpha__
622 stw_u(ip_fast_csum(icp, ip->ihl), &((struct iphdr *)icp)->check);
623 #else
624 ((struct iphdr *)icp)->check = ip_fast_csum(icp, ((struct iphdr*)icp)->ihl);
625 #endif
626
627 memcpy(cp, thp, 20);
628 cp += 20;
629
630 if (thp->doff > 5) {
631 memcpy(cp, cs->cs_tcpopt, ((thp->doff) - 5) * 4);
632 cp += ((thp->doff) - 5) * 4;
633 }
634
635 return len;
636 bad:
637 comp->sls_i_error++;
638 return slhc_toss( comp );
639 }
640
641
642 int
643 slhc_remember(struct slcompress *comp, unsigned char *icp, int isize)
644 {
645 register struct cstate *cs;
646 unsigned ihl;
647
648 unsigned char index;
649
650 if(isize < 20) {
651
652 comp->sls_i_runt++;
653 return slhc_toss( comp );
654 }
655
656 ihl = icp[0] & 0xf;
657 if(ihl < 20 / 4){
658
659 comp->sls_i_runt++;
660 return slhc_toss( comp );
661 }
662 index = icp[9];
663 icp[9] = IPPROTO_TCP;
664
665 if (ip_fast_csum(icp, ihl)) {
666
667 comp->sls_i_badcheck++;
668 return slhc_toss( comp );
669 }
670 if(index > comp->rslot_limit) {
671 comp->sls_i_error++;
672 return slhc_toss(comp);
673 }
674
675
676 cs = &comp->rstate[comp->recv_current = index];
677 comp->flags &=~ SLF_TOSS;
678 memcpy(&cs->cs_ip,icp,20);
679 memcpy(&cs->cs_tcp,icp + ihl*4,20);
680 if (ihl > 5)
681 memcpy(cs->cs_ipopt, icp + sizeof(struct iphdr), (ihl - 5) * 4);
682 if (cs->cs_tcp.doff > 5)
683 memcpy(cs->cs_tcpopt, icp + ihl*4 + sizeof(struct tcphdr), (cs->cs_tcp.doff - 5) * 4);
684 cs->cs_hsize = ihl*2 + cs->cs_tcp.doff*2;
685
686
687
688 comp->sls_i_uncompressed++;
689 return isize;
690 }
691
692
693 int
694 slhc_toss(struct slcompress *comp)
695 {
696 if ( comp == NULLSLCOMPR )
697 return 0;
698
699 comp->flags |= SLF_TOSS;
700 return 0;
701 }
702
703
704 void slhc_i_status(struct slcompress *comp)
705 {
706 if (comp != NULLSLCOMPR) {
707 printk("\t%ld Cmp, %ld Uncmp, %ld Bad, %ld Tossed\n",
708 comp->sls_i_compressed,
709 comp->sls_i_uncompressed,
710 comp->sls_i_error,
711 comp->sls_i_tossed);
712 }
713 }
714
715
716 void slhc_o_status(struct slcompress *comp)
717 {
718 if (comp != NULLSLCOMPR) {
719 printk("\t%ld Cmp, %ld Uncmp, %ld AsIs, %ld NotTCP\n",
720 comp->sls_o_compressed,
721 comp->sls_o_uncompressed,
722 comp->sls_o_tcp,
723 comp->sls_o_nontcp);
724 printk("\t%10ld Searches, %10ld Misses\n",
725 comp->sls_o_searches,
726 comp->sls_o_misses);
727 }
728 }
729
730 #ifdef MODULE
731
732 int init_module(void)
733 {
734 printk("CSLIP: code copyright 1989 Regents of the University of California\n");
735 return 0;
736 }
737
738 void cleanup_module(void)
739 {
740 return;
741 }
742 #endif
743 #endif