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