slhc.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:20k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

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