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