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
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 #include <linux/config.h>
48 #ifdef CONFIG_INET
49
50 #include <linux/types.h>
51 #include <linux/sched.h>
52 #include <linux/mm.h>
53 #include <linux/string.h>
54 #include <linux/socket.h>
55 #include <linux/sockios.h>
56 #include <linux/termios.h>
57 #include <linux/in.h>
58 #include <linux/fcntl.h>
59 #include <linux/inet.h>
60 #include <linux/netdevice.h>
61 #include "ip.h"
62 #include "protocol.h"
63 #include "icmp.h"
64 #include "tcp.h"
65 #include <linux/skbuff.h>
66 #include "sock.h"
67 #include <linux/errno.h>
68 #include <linux/timer.h>
69 #include <asm/system.h>
70 #include <asm/segment.h>
71 #include <linux/mm.h>
72 #include "slhc.h"
73
74 int last_retran;
75
76 static unsigned char *encode(unsigned char *cp, unsigned short n);
77 static long decode(unsigned char **cpp);
78 static unsigned char * put16(unsigned char *cp, unsigned short x);
79 static unsigned short pull16(unsigned char **cpp);
80
81 extern int ip_csum(struct iphdr *iph);
82
83
84
85
86
87 struct slcompress *
88 slhc_init(int rslots, int tslots)
89 {
90 register short i;
91 register struct cstate *ts;
92 struct slcompress *comp;
93
94 comp = (struct slcompress *)kmalloc(sizeof(struct slcompress),
95 GFP_KERNEL);
96 if (! comp)
97 return NULL;
98
99 memset(comp, 0, sizeof(struct slcompress));
100
101 if ( rslots > 0 && rslots < 256 ) {
102 comp->rstate =
103 (struct cstate *)kmalloc(rslots * sizeof(struct cstate),
104 GFP_KERNEL);
105 if (! comp->rstate)
106 {
107 kfree((unsigned char *)comp);
108 return NULL;
109 }
110 memset(comp->rstate, 0, rslots * sizeof(struct cstate));
111 comp->rslot_limit = rslots - 1;
112 }
113
114 if ( tslots > 0 && tslots < 256 ) {
115 comp->tstate =
116 (struct cstate *)kmalloc(tslots * sizeof(struct cstate),
117 GFP_KERNEL);
118 if (! comp->tstate)
119 {
120 kfree((unsigned char *)comp->rstate);
121 kfree((unsigned char *)comp);
122 return NULL;
123 }
124 memset(comp->tstate, 0, rslots * sizeof(struct cstate));
125 comp->tslot_limit = tslots - 1;
126 }
127
128 comp->xmit_oldest = 0;
129 comp->xmit_current = 255;
130 comp->recv_current = 255;
131
132
133
134
135
136
137 comp->flags |= SLF_TOSS;
138
139 if ( tslots > 0 ) {
140 ts = comp->tstate;
141 for(i = comp->tslot_limit; i > 0; --i){
142 ts[i].cs_this = i;
143 ts[i].next = &(ts[i - 1]);
144 }
145 ts[0].next = &(ts[comp->tslot_limit]);
146 ts[0].cs_this = 0;
147 }
148 return comp;
149 }
150
151
152
153 void
154 slhc_free(struct slcompress *comp)
155 {
156 if ( comp == NULLSLCOMPR )
157 return;
158
159 if ( comp->rstate != NULLSLSTATE )
160 kfree( comp->rstate );
161
162 if ( comp->tstate != NULLSLSTATE )
163 kfree( comp->tstate );
164
165 kfree( comp );
166 }
167
168
169
170 static inline unsigned char *
171 put16(unsigned char *cp, unsigned short x)
172 {
173 *cp++ = x >> 8;
174 *cp++ = x;
175
176 return cp;
177 }
178
179
180
181 unsigned char *
182 encode(unsigned char *cp, unsigned short n)
183 {
184 if(n >= 256 || n == 0){
185 *cp++ = 0;
186 cp = put16(cp,n);
187 } else {
188 *cp++ = n;
189 }
190 return cp;
191 }
192
193
194 static unsigned short
195 pull16(unsigned char **cpp)
196 {
197 short rval;
198
199 rval = *(*cpp)++;
200 rval <<= 8;
201 rval |= *(*cpp)++;
202 return rval;
203 }
204
205
206 long
207 decode(unsigned char **cpp)
208 {
209 register int x;
210
211 x = *(*cpp)++;
212 if(x == 0){
213 return pull16(cpp) & 0xffff;
214 } else {
215 return x & 0xff;
216 }
217 }
218
219
220
221
222
223
224
225
226 int
227 slhc_compress(struct slcompress *comp, unsigned char *icp, int isize,
228 unsigned char *ocp, unsigned char **cpp, int compress_cid)
229 {
230 register struct cstate *ocs = &(comp->tstate[comp->xmit_oldest]);
231 register struct cstate *lcs = ocs;
232 register struct cstate *cs = lcs->next;
233 register unsigned long deltaS, deltaA;
234 register short changes = 0;
235 int hlen;
236 unsigned char new_seq[16];
237 register unsigned char *cp = new_seq;
238 struct iphdr *ip;
239 struct tcphdr *th, *oth;
240
241 ip = (struct iphdr *) icp;
242
243
244 if(ip->protocol != IPPROTO_TCP || (ntohs(ip->frag_off) & 0x1fff) ||
245 (ip->frag_off & 32)){
246
247 if(ip->protocol != IPPROTO_TCP)
248 comp->sls_o_nontcp++;
249 else
250 comp->sls_o_tcp++;
251 return isize;
252 }
253
254
255 th = (struct tcphdr *)(((unsigned char *)ip) + ip->ihl*4);
256 hlen = ip->ihl*4 + th->doff*4;
257
258
259
260
261 if(th->syn || th->fin || th->rst ||
262 ! (th->ack)){
263
264 comp->sls_o_tcp++;
265 return isize;
266 }
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281 for ( ; ; ) {
282 if( ip->saddr == cs->cs_ip.saddr
283 && ip->daddr == cs->cs_ip.daddr
284 && th->source == cs->cs_tcp.source
285 && th->dest == cs->cs_tcp.dest)
286 goto found;
287
288
289 if ( cs == ocs )
290 break;
291 lcs = cs;
292 cs = cs->next;
293 comp->sls_o_searches++;
294 };
295
296
297
298
299
300
301
302
303
304 comp->sls_o_misses++;
305 comp->xmit_oldest = lcs->cs_this;
306 goto uncompressed;
307
308 found:
309
310
311
312 if(lcs == ocs) {
313
314 } else if (cs == ocs) {
315
316 comp->xmit_oldest = lcs->cs_this;
317 } else {
318
319 lcs->next = cs->next;
320 cs->next = ocs->next;
321 ocs->next = cs;
322 }
323
324
325
326
327
328
329
330
331
332
333
334
335
336 oth = &cs->cs_tcp;
337
338 if(last_retran
339 || ip->version != cs->cs_ip.version || ip->ihl != cs->cs_ip.ihl
340 || ip->tos != cs->cs_ip.tos
341 || (ip->frag_off & 64) != (cs->cs_ip.frag_off & 64)
342 || ip->ttl != cs->cs_ip.ttl
343 || th->doff != cs->cs_tcp.doff
344 || (ip->ihl > 5 && memcmp(ip+1,cs->cs_ipopt,((ip->ihl)-5)*4) != 0)
345 || (th->doff > 5 && memcmp(th+1,cs->cs_tcpopt,((th->doff)-5)*4 != 0))){
346 goto uncompressed;
347 }
348
349
350
351
352
353
354
355 if(th->urg){
356 deltaS = ntohs(th->urg_ptr);
357 cp = encode(cp,deltaS);
358 changes |= NEW_U;
359 } else if(th->urg_ptr != oth->urg_ptr){
360
361
362
363
364 goto uncompressed;
365 }
366 if((deltaS = ntohs(th->window) - ntohs(oth->window)) != 0){
367 cp = encode(cp,deltaS);
368 changes |= NEW_W;
369 }
370 if((deltaA = ntohl(th->ack_seq) - ntohl(oth->ack_seq)) != 0L){
371 if(deltaA > 0x0000ffff)
372 goto uncompressed;
373 cp = encode(cp,deltaA);
374 changes |= NEW_A;
375 }
376 if((deltaS = ntohl(th->seq) - ntohl(oth->seq)) != 0L){
377 if(deltaS > 0x0000ffff)
378 goto uncompressed;
379 cp = encode(cp,deltaS);
380 changes |= NEW_S;
381 }
382
383 switch(changes){
384 case 0:
385
386
387
388
389
390
391 if(ip->tot_len != cs->cs_ip.tot_len &&
392 ntohs(cs->cs_ip.tot_len) == hlen)
393 break;
394 goto uncompressed;
395 break;
396 case SPECIAL_I:
397 case SPECIAL_D:
398
399
400
401 goto uncompressed;
402 case NEW_S|NEW_A:
403 if(deltaS == deltaA &&
404 deltaS == ntohs(cs->cs_ip.tot_len) - hlen){
405
406 changes = SPECIAL_I;
407 cp = new_seq;
408 }
409 break;
410 case NEW_S:
411 if(deltaS == ntohs(cs->cs_ip.tot_len) - hlen){
412
413 changes = SPECIAL_D;
414 cp = new_seq;
415 }
416 break;
417 }
418 deltaS = ntohs(ip->id) - ntohs(cs->cs_ip.id);
419 if(deltaS != 1){
420 cp = encode(cp,deltaS);
421 changes |= NEW_I;
422 }
423 if(th->psh)
424 changes |= TCP_PUSH_BIT;
425
426
427
428 deltaA = ntohs(th->check);
429 memcpy(&cs->cs_ip,ip,20);
430 memcpy(&cs->cs_tcp,th,20);
431
432
433
434
435
436
437 deltaS = cp - new_seq;
438 if(compress_cid == 0 || comp->xmit_current != cs->cs_this){
439 cp = ocp;
440 *cpp = ocp;
441 *cp++ = changes | NEW_C;
442 *cp++ = cs->cs_this;
443 comp->xmit_current = cs->cs_this;
444 } else {
445 cp = ocp;
446 *cpp = ocp;
447 *cp++ = changes;
448 }
449 cp = put16(cp,(short)deltaA);
450
451 memcpy(cp,new_seq,deltaS);
452 memcpy(cp+deltaS,icp+hlen,isize-hlen);
453 comp->sls_o_compressed++;
454 ocp[0] |= SL_TYPE_COMPRESSED_TCP;
455 return isize - hlen + deltaS + (cp - ocp);
456
457
458
459
460
461 uncompressed:
462 memcpy(&cs->cs_ip,ip,20);
463 memcpy(&cs->cs_tcp,th,20);
464 if (ip->ihl > 5)
465 memcpy(cs->cs_ipopt, ip+1, ((ip->ihl) - 5) * 4);
466 if (th->doff > 5)
467 memcpy(cs->cs_tcpopt, th+1, ((th->doff) - 5) * 4);
468 comp->xmit_current = cs->cs_this;
469 comp->sls_o_uncompressed++;
470 memcpy(ocp, icp, isize);
471 *cpp = ocp;
472 ocp[9] = cs->cs_this;
473 ocp[0] |= SL_TYPE_UNCOMPRESSED_TCP;
474 return isize;
475 }
476
477
478 int
479 slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
480 {
481 register int changes;
482 long x;
483 register struct tcphdr *thp;
484 register struct iphdr *ip;
485 register struct cstate *cs;
486 int len, hdrlen;
487 unsigned char *cp = icp;
488
489
490 comp->sls_i_compressed++;
491 if(isize < 3){
492 comp->sls_i_error++;
493 return 0;
494 }
495 changes = *cp++;
496 if(changes & NEW_C){
497
498
499
500 x = *cp++;
501 if(x < 0 || x > comp->rslot_limit)
502 goto bad;
503
504 comp->flags &=~ SLF_TOSS;
505 comp->recv_current = x;
506 } else {
507
508
509
510 if(comp->flags & SLF_TOSS){
511 comp->sls_i_tossed++;
512 return 0;
513 }
514 }
515 cs = &comp->rstate[comp->recv_current];
516 thp = &cs->cs_tcp;
517 ip = &cs->cs_ip;
518
519 if((x = pull16(&cp)) == -1) {
520 goto bad;
521 }
522 thp->check = htons(x);
523
524 thp->psh = (changes & TCP_PUSH_BIT) ? 1 : 0;
525
526
527
528
529
530
531 hdrlen = ip->ihl * 4 + thp->doff * 4;
532
533 switch(changes & SPECIALS_MASK){
534 case SPECIAL_I:
535 {
536 register short i;
537 i = ntohs(ip->tot_len) - hdrlen;
538 thp->ack_seq = htonl( ntohl(thp->ack_seq) + i);
539 thp->seq = htonl( ntohl(thp->seq) + i);
540 }
541 break;
542
543 case SPECIAL_D:
544 thp->seq = htonl( ntohl(thp->seq) +
545 ntohs(ip->tot_len) - hdrlen);
546 break;
547
548 default:
549 if(changes & NEW_U){
550 thp->urg = 1;
551 if((x = decode(&cp)) == -1) {
552 goto bad;
553 }
554 thp->urg_ptr = htons(x);
555 } else
556 thp->urg = 0;
557 if(changes & NEW_W){
558 if((x = decode(&cp)) == -1) {
559 goto bad;
560 }
561 thp->window = htons( ntohs(thp->window) + x);
562 }
563 if(changes & NEW_A){
564 if((x = decode(&cp)) == -1) {
565 goto bad;
566 }
567 thp->ack_seq = htonl( ntohl(thp->ack_seq) + x);
568 }
569 if(changes & NEW_S){
570 if((x = decode(&cp)) == -1) {
571 goto bad;
572 }
573 thp->seq = htonl( ntohl(thp->seq) + x);
574 }
575 break;
576 }
577 if(changes & NEW_I){
578 if((x = decode(&cp)) == -1) {
579 goto bad;
580 }
581 ip->id = htons (ntohs (ip->id) + x);
582 } else
583 ip->id = htons (ntohs (ip->id) + 1);
584
585
586
587
588
589
590
591 len = isize - (cp - icp);
592 if (len < 0)
593 goto bad;
594 len += hdrlen;
595 ip->tot_len = htons(len);
596 ip->check = 0;
597
598 memmove(icp + hdrlen, cp, len - hdrlen);
599
600 cp = icp;
601 memcpy(cp, ip, 20);
602 cp += 20;
603
604 if (ip->ihl > 5) {
605 memcpy(cp, cs->cs_ipopt, ((ip->ihl) - 5) * 4);
606 cp += ((ip->ihl) - 5) * 4;
607 }
608
609 ((struct iphdr *)icp)->check = ip_csum((struct iphdr*)icp);
610
611 memcpy(cp, thp, 20);
612 cp += 20;
613
614 if (thp->doff > 5) {
615 memcpy(cp, cs->cs_tcpopt, ((thp->doff) - 5) * 4);
616 cp += ((thp->doff) - 5) * 4;
617 }
618
619 return len;
620 bad:
621 comp->sls_i_error++;
622 return slhc_toss( comp );
623 }
624
625
626 int
627 slhc_remember(struct slcompress *comp, unsigned char *icp, int isize)
628 {
629 register struct cstate *cs;
630 short ip_len;
631 struct iphdr *ip;
632 struct tcphdr *thp;
633
634 unsigned char index;
635
636 if(isize < 20) {
637
638 comp->sls_i_runt++;
639 return slhc_toss( comp );
640 }
641
642 ip_len = (icp[0] & 0xf) << 2;
643 if(ip_len < 20){
644
645 comp->sls_i_runt++;
646 return slhc_toss( comp );
647 }
648 index = icp[9];
649 icp[9] = IPPROTO_TCP;
650 ip = (struct iphdr *) icp;
651
652 if (ip_csum(ip)) {
653
654 comp->sls_i_badcheck++;
655 return slhc_toss( comp );
656 }
657 thp = (struct tcphdr *)(((unsigned char *)ip) + ip->ihl*4);
658 if(index > comp->rslot_limit) {
659 comp->sls_i_error++;
660 return slhc_toss(comp);
661 }
662
663
664 cs = &comp->rstate[comp->recv_current = index];
665 comp->flags &=~ SLF_TOSS;
666 memcpy(&cs->cs_ip,ip,20);
667 memcpy(&cs->cs_tcp,thp,20);
668 if (ip->ihl > 5)
669 memcpy(cs->cs_ipopt, ip+1, ((ip->ihl) - 5) * 4);
670 if (thp->doff > 5)
671 memcpy(cs->cs_tcpopt, thp+1, ((thp->doff) - 5) * 4);
672 cs->cs_hsize = ip->ihl*2 + thp->doff*2;
673
674
675
676 comp->sls_i_uncompressed++;
677 return isize;
678 }
679
680
681 int
682 slhc_toss(struct slcompress *comp)
683 {
684 if ( comp == NULLSLCOMPR )
685 return 0;
686
687 comp->flags |= SLF_TOSS;
688 return 0;
689 }
690
691
692 void slhc_i_status(struct slcompress *comp)
693 {
694 if (comp != NULLSLCOMPR) {
695 printk("\t%ld Cmp, %ld Uncmp, %ld Bad, %ld Tossed\n",
696 comp->sls_i_compressed,
697 comp->sls_i_uncompressed,
698 comp->sls_i_error,
699 comp->sls_i_tossed);
700 }
701 }
702
703
704 void slhc_o_status(struct slcompress *comp)
705 {
706 if (comp != NULLSLCOMPR) {
707 printk("\t%ld Cmp, %ld Uncmp, %ld AsIs, %ld NotTCP\n",
708 comp->sls_o_compressed,
709 comp->sls_o_uncompressed,
710 comp->sls_o_tcp,
711 comp->sls_o_nontcp);
712 printk("\t%10ld Searches, %10ld Misses\n",
713 comp->sls_o_searches,
714 comp->sls_o_misses);
715 }
716 }
717
718 #endif