slhc.c 19 KB

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