slhc.c 19 KB

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