2005-04-17 02:20:36 +04:00
/*
* Routines to compress and uncompress tcp packets ( for transmission
* over low speed serial lines ) .
*
* Copyright ( c ) 1989 Regents of the University of California .
* All rights reserved .
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation ,
* advertising materials , and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California , Berkeley . The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission .
* THIS SOFTWARE IS PROVIDED ` ` AS IS ' ' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES , INCLUDING , WITHOUT LIMITATION , THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .
*
* Van Jacobson ( van @ helios . ee . lbl . gov ) , Dec 31 , 1989 :
* - Initial distribution .
*
*
* modified for KA9Q Internet Software Package by
* Katie Stevens ( dkstevens @ ucdavis . edu )
* University of California , Davis
* Computing Services
* - 01 - 31 - 90 initial adaptation ( from 1.19 )
* PPP .05 02 - 15 - 90 [ ks ]
* PPP .08 05 - 02 - 90 [ ks ] use PPP protocol field to signal compression
* PPP .15 09 - 90 [ ks ] improve mbuf handling
* PPP .16 11 - 02 [ karn ] substantially rewritten to use NOS facilities
*
* - Feb 1991 Bill_Simpson @ um . cc . umich . edu
* variable number of conversation slots
* allow zero or one slots
* separate routines
* status display
* - Jul 1994 Dmitry Gorodchanin
* Fixes for memory leaks .
* - Oct 1994 Dmitry Gorodchanin
* Modularization .
* - Jan 1995 Bjorn Ekwall
* Use ip_fast_csum from ip . h
2006-09-13 21:24:59 +04:00
* - July 1995 Christos A . Polyzols
2005-04-17 02:20:36 +04:00
* Spotted bug in tcp option checking
*
*
* This module is a difficult issue . It ' s clearly inet code but it ' s also clearly
* driver code belonging close to PPP and SLIP
*/
# include <linux/module.h>
# include <linux/types.h>
# include <linux/string.h>
# include <linux/errno.h>
# include <linux/kernel.h>
# include <net/slhc_vj.h>
# ifdef CONFIG_INET
/* Entire module is for IP only */
# include <linux/mm.h>
# include <linux/socket.h>
# include <linux/sockios.h>
# include <linux/termios.h>
# include <linux/in.h>
# include <linux/fcntl.h>
# include <linux/inet.h>
# include <linux/netdevice.h>
# include <net/ip.h>
# include <net/protocol.h>
# include <net/icmp.h>
# include <net/tcp.h>
# include <linux/skbuff.h>
# include <net/sock.h>
# include <linux/timer.h>
# include <asm/system.h>
# include <asm/uaccess.h>
# include <net/checksum.h>
# include <asm/unaligned.h>
static unsigned char * encode ( unsigned char * cp , unsigned short n ) ;
static long decode ( unsigned char * * cpp ) ;
static unsigned char * put16 ( unsigned char * cp , unsigned short x ) ;
static unsigned short pull16 ( unsigned char * * cpp ) ;
/* Initialize compression data structure
* slots must be in range 0 to 255 ( zero meaning no compression )
*/
struct slcompress *
slhc_init ( int rslots , int tslots )
{
register short i ;
register struct cstate * ts ;
struct slcompress * comp ;
2006-07-13 15:12:53 +04:00
comp = kzalloc ( sizeof ( struct slcompress ) , GFP_KERNEL ) ;
2005-04-17 02:20:36 +04:00
if ( ! comp )
goto out_fail ;
if ( rslots > 0 & & rslots < 256 ) {
size_t rsize = rslots * sizeof ( struct cstate ) ;
2006-07-13 15:12:53 +04:00
comp - > rstate = kzalloc ( rsize , GFP_KERNEL ) ;
2005-04-17 02:20:36 +04:00
if ( ! comp - > rstate )
goto out_free ;
comp - > rslot_limit = rslots - 1 ;
}
if ( tslots > 0 & & tslots < 256 ) {
size_t tsize = tslots * sizeof ( struct cstate ) ;
2006-07-13 15:12:53 +04:00
comp - > tstate = kzalloc ( tsize , GFP_KERNEL ) ;
2005-04-17 02:20:36 +04:00
if ( ! comp - > tstate )
goto out_free2 ;
comp - > tslot_limit = tslots - 1 ;
}
comp - > xmit_oldest = 0 ;
comp - > xmit_current = 255 ;
comp - > recv_current = 255 ;
/*
* don ' t accept any packets with implicit index until we get
* one with an explicit index . Otherwise the uncompress code
* will try to use connection 255 , which is almost certainly
* out of range
*/
comp - > flags | = SLF_TOSS ;
if ( tslots > 0 ) {
ts = comp - > tstate ;
for ( i = comp - > tslot_limit ; i > 0 ; - - i ) {
ts [ i ] . cs_this = i ;
ts [ i ] . next = & ( ts [ i - 1 ] ) ;
}
ts [ 0 ] . next = & ( ts [ comp - > tslot_limit ] ) ;
ts [ 0 ] . cs_this = 0 ;
}
return comp ;
out_free2 :
2006-07-13 15:12:53 +04:00
kfree ( comp - > rstate ) ;
2005-04-17 02:20:36 +04:00
out_free :
2006-07-13 15:12:53 +04:00
kfree ( comp ) ;
2005-04-17 02:20:36 +04:00
out_fail :
return NULL ;
}
/* Free a compression data structure */
void
slhc_free ( struct slcompress * comp )
{
if ( comp = = NULLSLCOMPR )
return ;
if ( comp - > tstate ! = NULLSLSTATE )
kfree ( comp - > tstate ) ;
if ( comp - > rstate ! = NULLSLSTATE )
kfree ( comp - > rstate ) ;
kfree ( comp ) ;
}
/* Put a short in host order into a char array in network order */
static inline unsigned char *
put16 ( unsigned char * cp , unsigned short x )
{
* cp + + = x > > 8 ;
* cp + + = x ;
return cp ;
}
/* Encode a number */
2008-01-24 07:54:07 +03:00
static unsigned char *
2005-04-17 02:20:36 +04:00
encode ( unsigned char * cp , unsigned short n )
{
if ( n > = 256 | | n = = 0 ) {
* cp + + = 0 ;
cp = put16 ( cp , n ) ;
} else {
* cp + + = n ;
}
return cp ;
}
/* Pull a 16-bit integer in host order from buffer in network byte order */
static unsigned short
pull16 ( unsigned char * * cpp )
{
short rval ;
rval = * ( * cpp ) + + ;
rval < < = 8 ;
rval | = * ( * cpp ) + + ;
return rval ;
}
/* Decode a number */
2008-01-24 07:54:07 +03:00
static long
2005-04-17 02:20:36 +04:00
decode ( unsigned char * * cpp )
{
register int x ;
x = * ( * cpp ) + + ;
if ( x = = 0 ) {
return pull16 ( cpp ) & 0xffff ; /* pull16 returns -1 on error */
} else {
return x & 0xff ; /* -1 if PULLCHAR returned error */
}
}
/*
* icp and isize are the original packet .
* ocp is a place to put a copy if necessary .
* cpp is initially a pointer to icp . If the copy is used ,
* change it to ocp .
*/
int
slhc_compress ( struct slcompress * comp , unsigned char * icp , int isize ,
unsigned char * ocp , unsigned char * * cpp , int compress_cid )
{
register struct cstate * ocs = & ( comp - > tstate [ comp - > xmit_oldest ] ) ;
register struct cstate * lcs = ocs ;
register struct cstate * cs = lcs - > next ;
register unsigned long deltaS , deltaA ;
register short changes = 0 ;
int hlen ;
unsigned char new_seq [ 16 ] ;
register unsigned char * cp = new_seq ;
struct iphdr * ip ;
struct tcphdr * th , * oth ;
2007-12-22 21:56:05 +03:00
__sum16 csum ;
2005-04-17 02:20:36 +04:00
/*
* Don ' t play with runt packets .
*/
2006-09-13 21:24:59 +04:00
2005-04-17 02:20:36 +04:00
if ( isize < sizeof ( struct iphdr ) )
return isize ;
2006-09-13 21:24:59 +04:00
2005-04-17 02:20:36 +04:00
ip = ( struct iphdr * ) icp ;
/* Bail if this packet isn't TCP, or is an IP fragment */
if ( ip - > protocol ! = IPPROTO_TCP | | ( ntohs ( ip - > frag_off ) & 0x3fff ) ) {
/* Send as regular IP */
if ( ip - > protocol ! = IPPROTO_TCP )
comp - > sls_o_nontcp + + ;
else
comp - > sls_o_tcp + + ;
return isize ;
}
/* Extract TCP header */
th = ( struct tcphdr * ) ( ( ( unsigned char * ) ip ) + ip - > ihl * 4 ) ;
hlen = ip - > ihl * 4 + th - > doff * 4 ;
/* Bail if the TCP packet isn't `compressible' (i.e., ACK isn't set or
* some other control bit is set ) . Also uncompressible if
* it ' s a runt .
*/
if ( hlen > isize | | th - > syn | | th - > fin | | th - > rst | |
! ( th - > ack ) ) {
/* TCP connection stuff; send as regular IP */
comp - > sls_o_tcp + + ;
return isize ;
}
/*
* Packet is compressible - - we ' re going to send either a
* COMPRESSED_TCP or UNCOMPRESSED_TCP packet . Either way ,
* we need to locate ( or create ) the connection state .
*
* States are kept in a circularly linked list with
* xmit_oldest pointing to the end of the list . The
* list is kept in lru order by moving a state to the
* head of the list whenever it is referenced . Since
* the list is short and , empirically , the connection
* we want is almost always near the front , we locate
* states via linear search . If we don ' t find a state
* for the datagram , the oldest state is ( re - ) used .
*/
for ( ; ; ) {
if ( ip - > saddr = = cs - > cs_ip . saddr
& & ip - > daddr = = cs - > cs_ip . daddr
& & th - > source = = cs - > cs_tcp . source
& & th - > dest = = cs - > cs_tcp . dest )
goto found ;
/* if current equal oldest, at end of list */
if ( cs = = ocs )
break ;
lcs = cs ;
cs = cs - > next ;
comp - > sls_o_searches + + ;
} ;
/*
* Didn ' t find it - - re - use oldest cstate . Send an
* uncompressed packet that tells the other side what
* connection number we ' re using for this conversation .
*
* Note that since the state list is circular , the oldest
* state points to the newest and we only need to set
* xmit_oldest to update the lru linkage .
*/
comp - > sls_o_misses + + ;
comp - > xmit_oldest = lcs - > cs_this ;
goto uncompressed ;
found :
/*
* Found it - - move to the front on the connection list .
*/
if ( lcs = = ocs ) {
/* found at most recently used */
} else if ( cs = = ocs ) {
/* found at least recently used */
comp - > xmit_oldest = lcs - > cs_this ;
} else {
/* more than 2 elements */
lcs - > next = cs - > next ;
cs - > next = ocs - > next ;
ocs - > next = cs ;
}
/*
* Make sure that only what we expect to change changed .
* Check the following :
* IP protocol version , header length & type of service .
* The " Don't fragment " bit .
* The time - to - live field .
* The TCP header length .
* IP options , if any .
* TCP options , if any .
* If any of these things are different between the previous &
* current datagram , we send the current datagram ` uncompressed ' .
*/
oth = & cs - > cs_tcp ;
if ( ip - > version ! = cs - > cs_ip . version | | ip - > ihl ! = cs - > cs_ip . ihl
| | ip - > tos ! = cs - > cs_ip . tos
| | ( ip - > frag_off & htons ( 0x4000 ) ) ! = ( cs - > cs_ip . frag_off & htons ( 0x4000 ) )
| | ip - > ttl ! = cs - > cs_ip . ttl
| | th - > doff ! = cs - > cs_tcp . doff
| | ( ip - > ihl > 5 & & memcmp ( ip + 1 , cs - > cs_ipopt , ( ( ip - > ihl ) - 5 ) * 4 ) ! = 0 )
| | ( th - > doff > 5 & & memcmp ( th + 1 , cs - > cs_tcpopt , ( ( th - > doff ) - 5 ) * 4 ) ! = 0 ) ) {
goto uncompressed ;
}
/*
* Figure out which of the changing fields changed . The
* receiver expects changes in the order : urgent , window ,
* ack , seq ( the order minimizes the number of temporaries
* needed in this section of code ) .
*/
if ( th - > urg ) {
deltaS = ntohs ( th - > urg_ptr ) ;
cp = encode ( cp , deltaS ) ;
changes | = NEW_U ;
} else if ( th - > urg_ptr ! = oth - > urg_ptr ) {
/* argh! URG not set but urp changed -- a sensible
* implementation should never do this but RFC793
* doesn ' t prohibit the change so we have to deal
* with it . */
goto uncompressed ;
}
if ( ( deltaS = ntohs ( th - > window ) - ntohs ( oth - > window ) ) ! = 0 ) {
cp = encode ( cp , deltaS ) ;
changes | = NEW_W ;
}
if ( ( deltaA = ntohl ( th - > ack_seq ) - ntohl ( oth - > ack_seq ) ) ! = 0L ) {
if ( deltaA > 0x0000ffff )
goto uncompressed ;
cp = encode ( cp , deltaA ) ;
changes | = NEW_A ;
}
if ( ( deltaS = ntohl ( th - > seq ) - ntohl ( oth - > seq ) ) ! = 0L ) {
if ( deltaS > 0x0000ffff )
goto uncompressed ;
cp = encode ( cp , deltaS ) ;
changes | = NEW_S ;
}
switch ( changes ) {
case 0 : /* Nothing changed. If this packet contains data and the
* last one didn ' t , this is probably a data packet following
* an ack ( normal on an interactive connection ) and we send
* it compressed . Otherwise it ' s probably a retransmit ,
* retransmitted ack or window probe . Send it uncompressed
* in case the other side missed the compressed version .
*/
if ( ip - > tot_len ! = cs - > cs_ip . tot_len & &
ntohs ( cs - > cs_ip . tot_len ) = = hlen )
break ;
goto uncompressed ;
break ;
case SPECIAL_I :
case SPECIAL_D :
/* actual changes match one of our special case encodings --
* send packet uncompressed .
*/
goto uncompressed ;
case NEW_S | NEW_A :
if ( deltaS = = deltaA & &
deltaS = = ntohs ( cs - > cs_ip . tot_len ) - hlen ) {
/* special case for echoed terminal traffic */
changes = SPECIAL_I ;
cp = new_seq ;
}
break ;
case NEW_S :
if ( deltaS = = ntohs ( cs - > cs_ip . tot_len ) - hlen ) {
/* special case for data xfer */
changes = SPECIAL_D ;
cp = new_seq ;
}
break ;
}
deltaS = ntohs ( ip - > id ) - ntohs ( cs - > cs_ip . id ) ;
if ( deltaS ! = 1 ) {
cp = encode ( cp , deltaS ) ;
changes | = NEW_I ;
}
if ( th - > psh )
changes | = TCP_PUSH_BIT ;
/* Grab the cksum before we overwrite it below. Then update our
* state with this packet ' s header .
*/
2007-12-22 21:56:05 +03:00
csum = th - > check ;
2005-04-17 02:20:36 +04:00
memcpy ( & cs - > cs_ip , ip , 20 ) ;
memcpy ( & cs - > cs_tcp , th , 20 ) ;
/* We want to use the original packet as our compressed packet.
* ( cp - new_seq ) is the number of bytes we need for compressed
* sequence numbers . In addition we need one byte for the change
* mask , one for the connection id and two for the tcp checksum .
* So , ( cp - new_seq ) + 4 bytes of header are needed .
*/
deltaS = cp - new_seq ;
if ( compress_cid = = 0 | | comp - > xmit_current ! = cs - > cs_this ) {
cp = ocp ;
* cpp = ocp ;
* cp + + = changes | NEW_C ;
* cp + + = cs - > cs_this ;
comp - > xmit_current = cs - > cs_this ;
} else {
cp = ocp ;
* cpp = ocp ;
* cp + + = changes ;
}
2007-12-22 21:56:05 +03:00
* ( __sum16 * ) cp = csum ;
cp + = 2 ;
2005-04-17 02:20:36 +04:00
/* deltaS is now the size of the change section of the compressed header */
memcpy ( cp , new_seq , deltaS ) ; /* Write list of deltas */
memcpy ( cp + deltaS , icp + hlen , isize - hlen ) ;
comp - > sls_o_compressed + + ;
ocp [ 0 ] | = SL_TYPE_COMPRESSED_TCP ;
return isize - hlen + deltaS + ( cp - ocp ) ;
/* Update connection state cs & send uncompressed packet (i.e.,
* a regular ip / tcp packet but with the ' conversation id ' we hope
* to use on future compressed packets in the protocol field ) .
*/
uncompressed :
memcpy ( & cs - > cs_ip , ip , 20 ) ;
memcpy ( & cs - > cs_tcp , th , 20 ) ;
if ( ip - > ihl > 5 )
memcpy ( cs - > cs_ipopt , ip + 1 , ( ( ip - > ihl ) - 5 ) * 4 ) ;
if ( th - > doff > 5 )
memcpy ( cs - > cs_tcpopt , th + 1 , ( ( th - > doff ) - 5 ) * 4 ) ;
comp - > xmit_current = cs - > cs_this ;
comp - > sls_o_uncompressed + + ;
memcpy ( ocp , icp , isize ) ;
* cpp = ocp ;
ocp [ 9 ] = cs - > cs_this ;
ocp [ 0 ] | = SL_TYPE_UNCOMPRESSED_TCP ;
return isize ;
}
int
slhc_uncompress ( struct slcompress * comp , unsigned char * icp , int isize )
{
register int changes ;
long x ;
register struct tcphdr * thp ;
register struct iphdr * ip ;
register struct cstate * cs ;
int len , hdrlen ;
unsigned char * cp = icp ;
/* We've got a compressed packet; read the change byte */
comp - > sls_i_compressed + + ;
if ( isize < 3 ) {
comp - > sls_i_error + + ;
return 0 ;
}
changes = * cp + + ;
if ( changes & NEW_C ) {
/* Make sure the state index is in range, then grab the state.
* If we have a good state index , clear the ' discard ' flag .
*/
x = * cp + + ; /* Read conn index */
if ( x < 0 | | x > comp - > rslot_limit )
goto bad ;
comp - > flags & = ~ SLF_TOSS ;
comp - > recv_current = x ;
} else {
/* this packet has an implicit state index. If we've
* had a line error since the last time we got an
* explicit state index , we have to toss the packet . */
if ( comp - > flags & SLF_TOSS ) {
comp - > sls_i_tossed + + ;
return 0 ;
}
}
cs = & comp - > rstate [ comp - > recv_current ] ;
thp = & cs - > cs_tcp ;
ip = & cs - > cs_ip ;
2007-12-22 21:56:05 +03:00
thp - > check = * ( __sum16 * ) cp ;
cp + = 2 ;
2005-04-17 02:20:36 +04:00
thp - > psh = ( changes & TCP_PUSH_BIT ) ? 1 : 0 ;
/*
* we can use the same number for the length of the saved header and
* the current one , because the packet wouldn ' t have been sent
* as compressed unless the options were the same as the previous one
*/
hdrlen = ip - > ihl * 4 + thp - > doff * 4 ;
switch ( changes & SPECIALS_MASK ) {
case SPECIAL_I : /* Echoed terminal traffic */
{
register short i ;
i = ntohs ( ip - > tot_len ) - hdrlen ;
thp - > ack_seq = htonl ( ntohl ( thp - > ack_seq ) + i ) ;
thp - > seq = htonl ( ntohl ( thp - > seq ) + i ) ;
}
break ;
case SPECIAL_D : /* Unidirectional data */
thp - > seq = htonl ( ntohl ( thp - > seq ) +
ntohs ( ip - > tot_len ) - hdrlen ) ;
break ;
default :
if ( changes & NEW_U ) {
thp - > urg = 1 ;
if ( ( x = decode ( & cp ) ) = = - 1 ) {
goto bad ;
}
thp - > urg_ptr = htons ( x ) ;
} else
thp - > urg = 0 ;
if ( changes & NEW_W ) {
if ( ( x = decode ( & cp ) ) = = - 1 ) {
goto bad ;
}
thp - > window = htons ( ntohs ( thp - > window ) + x ) ;
}
if ( changes & NEW_A ) {
if ( ( x = decode ( & cp ) ) = = - 1 ) {
goto bad ;
}
thp - > ack_seq = htonl ( ntohl ( thp - > ack_seq ) + x ) ;
}
if ( changes & NEW_S ) {
if ( ( x = decode ( & cp ) ) = = - 1 ) {
goto bad ;
}
thp - > seq = htonl ( ntohl ( thp - > seq ) + x ) ;
}
break ;
}
if ( changes & NEW_I ) {
if ( ( x = decode ( & cp ) ) = = - 1 ) {
goto bad ;
}
ip - > id = htons ( ntohs ( ip - > id ) + x ) ;
} else
ip - > id = htons ( ntohs ( ip - > id ) + 1 ) ;
/*
* At this point , cp points to the first byte of data in the
* packet . Put the reconstructed TCP and IP headers back on the
* packet . Recalculate IP checksum ( but not TCP checksum ) .
*/
len = isize - ( cp - icp ) ;
if ( len < 0 )
goto bad ;
len + = hdrlen ;
ip - > tot_len = htons ( len ) ;
ip - > check = 0 ;
memmove ( icp + hdrlen , cp , len - hdrlen ) ;
cp = icp ;
memcpy ( cp , ip , 20 ) ;
cp + = 20 ;
if ( ip - > ihl > 5 ) {
memcpy ( cp , cs - > cs_ipopt , ( ip - > ihl - 5 ) * 4 ) ;
cp + = ( ip - > ihl - 5 ) * 4 ;
}
put_unaligned ( ip_fast_csum ( icp , ip - > ihl ) ,
& ( ( struct iphdr * ) icp ) - > check ) ;
memcpy ( cp , thp , 20 ) ;
cp + = 20 ;
if ( thp - > doff > 5 ) {
memcpy ( cp , cs - > cs_tcpopt , ( ( thp - > doff ) - 5 ) * 4 ) ;
cp + = ( ( thp - > doff ) - 5 ) * 4 ;
}
return len ;
bad :
comp - > sls_i_error + + ;
return slhc_toss ( comp ) ;
}
int
slhc_remember ( struct slcompress * comp , unsigned char * icp , int isize )
{
register struct cstate * cs ;
unsigned ihl ;
unsigned char index ;
if ( isize < 20 ) {
/* The packet is shorter than a legal IP header */
comp - > sls_i_runt + + ;
return slhc_toss ( comp ) ;
}
/* Peek at the IP header's IHL field to find its length */
ihl = icp [ 0 ] & 0xf ;
if ( ihl < 20 / 4 ) {
/* The IP header length field is too small */
comp - > sls_i_runt + + ;
return slhc_toss ( comp ) ;
}
index = icp [ 9 ] ;
icp [ 9 ] = IPPROTO_TCP ;
if ( ip_fast_csum ( icp , ihl ) ) {
/* Bad IP header checksum; discard */
comp - > sls_i_badcheck + + ;
return slhc_toss ( comp ) ;
}
if ( index > comp - > rslot_limit ) {
comp - > sls_i_error + + ;
return slhc_toss ( comp ) ;
}
/* Update local state */
cs = & comp - > rstate [ comp - > recv_current = index ] ;
comp - > flags & = ~ SLF_TOSS ;
memcpy ( & cs - > cs_ip , icp , 20 ) ;
memcpy ( & cs - > cs_tcp , icp + ihl * 4 , 20 ) ;
if ( ihl > 5 )
memcpy ( cs - > cs_ipopt , icp + sizeof ( struct iphdr ) , ( ihl - 5 ) * 4 ) ;
if ( cs - > cs_tcp . doff > 5 )
memcpy ( cs - > cs_tcpopt , icp + ihl * 4 + sizeof ( struct tcphdr ) , ( cs - > cs_tcp . doff - 5 ) * 4 ) ;
cs - > cs_hsize = ihl * 2 + cs - > cs_tcp . doff * 2 ;
/* Put headers back on packet
* Neither header checksum is recalculated
*/
comp - > sls_i_uncompressed + + ;
return isize ;
}
int
slhc_toss ( struct slcompress * comp )
{
if ( comp = = NULLSLCOMPR )
return 0 ;
comp - > flags | = SLF_TOSS ;
return 0 ;
}
/* VJ header compression */
EXPORT_SYMBOL ( slhc_init ) ;
EXPORT_SYMBOL ( slhc_free ) ;
EXPORT_SYMBOL ( slhc_remember ) ;
EXPORT_SYMBOL ( slhc_compress ) ;
EXPORT_SYMBOL ( slhc_uncompress ) ;
EXPORT_SYMBOL ( slhc_toss ) ;
# else /* CONFIG_INET */
int
slhc_toss ( struct slcompress * comp )
{
printk ( KERN_DEBUG " Called IP function on non IP-system: slhc_toss " ) ;
return - EINVAL ;
}
int
slhc_uncompress ( struct slcompress * comp , unsigned char * icp , int isize )
{
printk ( KERN_DEBUG " Called IP function on non IP-system: slhc_uncompress " ) ;
return - EINVAL ;
}
int
slhc_compress ( struct slcompress * comp , unsigned char * icp , int isize ,
unsigned char * ocp , unsigned char * * cpp , int compress_cid )
{
printk ( KERN_DEBUG " Called IP function on non IP-system: slhc_compress " ) ;
return - EINVAL ;
}
int
slhc_remember ( struct slcompress * comp , unsigned char * icp , int isize )
{
printk ( KERN_DEBUG " Called IP function on non IP-system: slhc_remember " ) ;
return - EINVAL ;
}
void
slhc_free ( struct slcompress * comp )
{
printk ( KERN_DEBUG " Called IP function on non IP-system: slhc_free " ) ;
return ;
}
struct slcompress *
slhc_init ( int rslots , int tslots )
{
printk ( KERN_DEBUG " Called IP function on non IP-system: slhc_init " ) ;
return NULL ;
}
EXPORT_SYMBOL ( slhc_init ) ;
EXPORT_SYMBOL ( slhc_free ) ;
EXPORT_SYMBOL ( slhc_remember ) ;
EXPORT_SYMBOL ( slhc_compress ) ;
EXPORT_SYMBOL ( slhc_uncompress ) ;
EXPORT_SYMBOL ( slhc_toss ) ;
# endif /* CONFIG_INET */
MODULE_LICENSE ( " Dual BSD/GPL " ) ;