home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / drivers / net / slhc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-06  |  18.6 KB  |  748 lines

  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.  *
  46.  *
  47.  *    This module is a difficult issue. It's clearly inet code but it's also clearly
  48.  *    driver code belonging close to PPP and SLIP
  49.  */
  50.  
  51. #include <linux/config.h>
  52. #ifdef CONFIG_INET
  53. /* Entire module is for IP only */
  54. #ifdef MODULE
  55. #include <linux/module.h>
  56. #include <linux/version.h>
  57. #endif
  58.  
  59. #include <linux/types.h>
  60. #include <linux/sched.h>
  61. #include <linux/mm.h>
  62. #include <linux/string.h>
  63. #include <linux/socket.h>
  64. #include <linux/sockios.h>
  65. #include <linux/termios.h>
  66. #include <linux/in.h>
  67. #include <linux/fcntl.h>
  68. #include <linux/inet.h>
  69. #include <linux/netdevice.h>
  70. #include "ip.h"
  71. #include "protocol.h"
  72. #include "icmp.h"
  73. #include "tcp.h"
  74. #include <linux/skbuff.h>
  75. #include "sock.h"
  76. #include <linux/errno.h>
  77. #include <linux/timer.h>
  78. #include <asm/system.h>
  79. #include <asm/segment.h>
  80. #include <linux/mm.h>
  81. #include "slhc.h"
  82.  
  83. int last_retran;
  84.  
  85. static unsigned char *encode(unsigned char *cp, unsigned short n);
  86. static long decode(unsigned char **cpp);
  87. static unsigned char * put16(unsigned char *cp, unsigned short x);
  88. static unsigned short pull16(unsigned char **cpp);
  89.  
  90. /* Initialize compression data structure
  91.  *    slots must be in range 0 to 255 (zero meaning no compression)
  92.  */
  93. struct slcompress *
  94. slhc_init(int rslots, int tslots)
  95. {
  96.     register short i;
  97.     register struct cstate *ts;
  98.     struct slcompress *comp;
  99.  
  100.     comp = (struct slcompress *)kmalloc(sizeof(struct slcompress),
  101.                         GFP_KERNEL);
  102.     if (! comp)
  103.         return NULL;
  104.  
  105.     memset(comp, 0, sizeof(struct slcompress));
  106.  
  107.     if ( rslots > 0  &&  rslots < 256 ) {
  108.         comp->rstate =
  109.           (struct cstate *)kmalloc(rslots * sizeof(struct cstate),
  110.                        GFP_KERNEL);
  111.         if (! comp->rstate)
  112.         {
  113.             kfree((unsigned char *)comp);
  114.             return NULL;
  115.         }
  116.         memset(comp->rstate, 0, rslots * sizeof(struct cstate));
  117.         comp->rslot_limit = rslots - 1;
  118.     }
  119.  
  120.     if ( tslots > 0  &&  tslots < 256 ) {
  121.         comp->tstate =
  122.           (struct cstate *)kmalloc(tslots * sizeof(struct cstate),
  123.                        GFP_KERNEL);
  124.         if (! comp->tstate)
  125.         {
  126.             kfree((unsigned char *)comp->rstate);
  127.             kfree((unsigned char *)comp);
  128.             return NULL;
  129.         }
  130.         memset(comp->tstate, 0, rslots * sizeof(struct cstate));
  131.         comp->tslot_limit = tslots - 1;
  132.     }
  133.  
  134.     comp->xmit_oldest = 0;
  135.     comp->xmit_current = 255;
  136.     comp->recv_current = 255;
  137.     /*
  138.      * don't accept any packets with implicit index until we get
  139.      * one with an explicit index.  Otherwise the uncompress code
  140.      * will try to use connection 255, which is almost certainly
  141.      * out of range
  142.      */
  143.     comp->flags |= SLF_TOSS;
  144.  
  145.     if ( tslots > 0 ) {
  146.         ts = comp->tstate;
  147.         for(i = comp->tslot_limit; i > 0; --i){
  148.             ts[i].cs_this = i;
  149.             ts[i].next = &(ts[i - 1]);
  150.         }
  151.         ts[0].next = &(ts[comp->tslot_limit]);
  152.         ts[0].cs_this = 0;
  153.     }
  154. #ifdef MODULE
  155.     MOD_INC_USE_COUNT;
  156. #endif
  157.     return comp;
  158. }
  159.  
  160.  
  161. /* Free a compression data structure */
  162. void
  163. slhc_free(struct slcompress *comp)
  164. {
  165.     if ( comp == NULLSLCOMPR )
  166.         return;
  167.  
  168.     if ( comp->rstate != NULLSLSTATE )
  169.         kfree( comp->rstate );
  170.  
  171.     if ( comp->tstate != NULLSLSTATE )
  172.         kfree( comp->tstate );
  173.  
  174. #ifdef MODULE
  175.     MOD_DEC_USE_COUNT;
  176. #endif
  177.     kfree( comp );
  178. }
  179.  
  180.  
  181. /* Put a short in host order into a char array in network order */
  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. /* Encode a number */
  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. /* Pull a 16-bit integer in host order from buffer in network byte order */
  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. /* Decode a number */
  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;    /* pull16 returns -1 on error */
  226.     } else {
  227.         return x & 0xff;        /* -1 if PULLCHAR returned error */
  228.     }
  229. }
  230.  
  231. /*
  232.  * icp and isize are the original packet.
  233.  * ocp is a place to put a copy if necessary.
  234.  * cpp is initially a pointer to icp.  If the copy is used,
  235.  *    change it to ocp.
  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.     /* Bail if this packet isn't TCP, or is an IP fragment */
  256.     if(ip->protocol != IPPROTO_TCP || (ntohs(ip->frag_off) & 0x1fff) ||
  257.                        (ip->frag_off & 32)){
  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).
  272.      */
  273.     if(th->syn || th->fin || th->rst ||
  274.         ! (th->ack)){
  275.         /* TCP connection stuff; send as regular IP */
  276.         comp->sls_o_tcp++;
  277.         return isize;
  278.     }
  279.     /*
  280.      * Packet is compressible -- we're going to send either a
  281.      * COMPRESSED_TCP or UNCOMPRESSED_TCP packet.  Either way,
  282.      * we need to locate (or create) the connection state.
  283.      *
  284.      * States are kept in a circularly linked list with
  285.      * xmit_oldest pointing to the end of the list.  The
  286.      * list is kept in lru order by moving a state to the
  287.      * head of the list whenever it is referenced.  Since
  288.      * the list is short and, empirically, the connection
  289.      * we want is almost always near the front, we locate
  290.      * states via linear search.  If we don't find a state
  291.      * for the datagram, the oldest state is (re-)used.
  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.         /* if current equal oldest, at end of list */
  301.         if ( cs == ocs )
  302.             break;
  303.         lcs = cs;
  304.         cs = cs->next;
  305.         comp->sls_o_searches++;
  306.     };
  307.     /*
  308.      * Didn't find it -- re-use oldest cstate.  Send an
  309.      * uncompressed packet that tells the other side what
  310.      * connection number we're using for this conversation.
  311.      *
  312.      * Note that since the state list is circular, the oldest
  313.      * state points to the newest and we only need to set
  314.      * xmit_oldest to update the lru linkage.
  315.      */
  316.     comp->sls_o_misses++;
  317.     comp->xmit_oldest = lcs->cs_this;
  318.     goto uncompressed;
  319.  
  320. found:
  321.     /*
  322.      * Found it -- move to the front on the connection list.
  323.      */
  324.     if(lcs == ocs) {
  325.          /* found at most recently used */
  326.     } else if (cs == ocs) {
  327.         /* found at least recently used */
  328.         comp->xmit_oldest = lcs->cs_this;
  329.     } else {
  330.         /* more than 2 elements */
  331.         lcs->next = cs->next;
  332.         cs->next = ocs->next;
  333.         ocs->next = cs;
  334.     }
  335.  
  336.     /*
  337.      * Make sure that only what we expect to change changed.
  338.      * Check the following:
  339.      * IP protocol version, header length & type of service.
  340.      * The "Don't fragment" bit.
  341.      * The time-to-live field.
  342.      * The TCP header length.
  343.      * IP options, if any.
  344.      * TCP options, if any.
  345.      * If any of these things are different between the previous &
  346.      * current datagram, we send the current datagram `uncompressed'.
  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.      * 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.     ((struct iphdr *)icp)->check = ip_fast_csum(icp, ((struct iphdr*)icp)->ihl);
  622.  
  623.     memcpy(cp, thp, 20);
  624.     cp += 20;
  625.  
  626.     if (thp->doff > 5) {
  627.       memcpy(cp, cs->cs_tcpopt, ((thp->doff) - 5) * 4);
  628.       cp += ((thp->doff) - 5) * 4;
  629.     }
  630.  
  631.     return len;
  632. bad:
  633.     comp->sls_i_error++;
  634.     return slhc_toss( comp );
  635. }
  636.  
  637.  
  638. int
  639. slhc_remember(struct slcompress *comp, unsigned char *icp, int isize)
  640. {
  641.     register struct cstate *cs;
  642.     short ip_len;
  643.     struct iphdr *ip;
  644.     struct tcphdr *thp;
  645.  
  646.     unsigned char index;
  647.  
  648.     if(isize < 20) {
  649.         /* The packet is shorter than a legal IP header */
  650.         comp->sls_i_runt++;
  651.         return slhc_toss( comp );
  652.     }
  653.     /* Sneak a peek at the IP header's IHL field to find its length */
  654.     ip_len = (icp[0] & 0xf) << 2;
  655.     if(ip_len < 20){
  656.         /* The IP header length field is too small */
  657.         comp->sls_i_runt++;
  658.         return slhc_toss( comp );
  659.     }
  660.     index = icp[9];
  661.     icp[9] = IPPROTO_TCP;
  662.     ip = (struct iphdr *) icp;
  663.  
  664.     if (ip_fast_csum(icp, ip->ihl)) {
  665.         /* Bad IP header checksum; discard */
  666.         comp->sls_i_badcheck++;
  667.         return slhc_toss( comp );
  668.     }
  669.     thp = (struct tcphdr *)(((unsigned char *)ip) + ip->ihl*4);
  670.     if(index > comp->rslot_limit) {
  671.         comp->sls_i_error++;
  672.         return slhc_toss(comp);
  673.     }
  674.  
  675.     /* Update local state */
  676.     cs = &comp->rstate[comp->recv_current = index];
  677.     comp->flags &=~ SLF_TOSS;
  678.     memcpy(&cs->cs_ip,ip,20);
  679.     memcpy(&cs->cs_tcp,thp,20);
  680.     if (ip->ihl > 5)
  681.       memcpy(cs->cs_ipopt, ip+1, ((ip->ihl) - 5) * 4);
  682.     if (thp->doff > 5)
  683.       memcpy(cs->cs_tcpopt, thp+1, ((thp->doff) - 5) * 4);
  684.     cs->cs_hsize = ip->ihl*2 + thp->doff*2;
  685.     /* Put headers back on packet
  686.      * Neither header checksum is recalculated
  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. char kernel_version[] = UTS_RELEASE;
  732.  
  733. int init_module(void)
  734. {
  735.     printk("CSLIP: code copyright 1989 Regents of the University of California\n");
  736.     return 0;
  737. }
  738.  
  739. void cleanup_module(void)
  740. {
  741.     if (MOD_IN_USE)  {
  742.         printk("CSLIP: module in use, remove delayed");
  743.     }
  744.     return;
  745. }
  746. #endif /* MODULE */
  747. #endif /* CONFIG_INET */
  748.