slhc.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  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 ([email protected]), Dec 31, 1989:
  21. * - Initial distribution.
  22. *
  23. *
  24. * modified for KA9Q Internet Software Package by
  25. * Katie Stevens ([email protected])
  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 [email protected]
  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 <linux/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. short i;
  91. 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 ( IS_ERR_OR_NULL(comp) )
  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. 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. struct cstate *ocs = &(comp->tstate[comp->xmit_oldest]);
  204. struct cstate *lcs = ocs;
  205. struct cstate *cs = lcs->next;
  206. unsigned long deltaS, deltaA;
  207. short changes = 0;
  208. int nlen, hlen;
  209. unsigned char new_seq[16];
  210. 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. if (ip->version != 4 || ip->ihl < 5)
  221. return isize;
  222. /* Bail if this packet isn't TCP, or is an IP fragment */
  223. if (ip->protocol != IPPROTO_TCP || (ntohs(ip->frag_off) & 0x3fff)) {
  224. /* Send as regular IP */
  225. if(ip->protocol != IPPROTO_TCP)
  226. comp->sls_o_nontcp++;
  227. else
  228. comp->sls_o_tcp++;
  229. return isize;
  230. }
  231. nlen = ip->ihl * 4;
  232. if (isize < nlen + sizeof(*th))
  233. return isize;
  234. th = (struct tcphdr *)(icp + nlen);
  235. if (th->doff < sizeof(struct tcphdr) / 4)
  236. return isize;
  237. hlen = nlen + 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. * it's 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. case SPECIAL_I:
  370. case SPECIAL_D:
  371. /* actual changes match one of our special case encodings --
  372. * send packet uncompressed.
  373. */
  374. goto uncompressed;
  375. case NEW_S|NEW_A:
  376. if(deltaS == deltaA &&
  377. deltaS == ntohs(cs->cs_ip.tot_len) - hlen){
  378. /* special case for echoed terminal traffic */
  379. changes = SPECIAL_I;
  380. cp = new_seq;
  381. }
  382. break;
  383. case NEW_S:
  384. if(deltaS == ntohs(cs->cs_ip.tot_len) - hlen){
  385. /* special case for data xfer */
  386. changes = SPECIAL_D;
  387. cp = new_seq;
  388. }
  389. break;
  390. }
  391. deltaS = ntohs(ip->id) - ntohs(cs->cs_ip.id);
  392. if(deltaS != 1){
  393. cp = encode(cp,deltaS);
  394. changes |= NEW_I;
  395. }
  396. if(th->psh)
  397. changes |= TCP_PUSH_BIT;
  398. /* Grab the cksum before we overwrite it below. Then update our
  399. * state with this packet's header.
  400. */
  401. csum = th->check;
  402. memcpy(&cs->cs_ip,ip,20);
  403. memcpy(&cs->cs_tcp,th,20);
  404. /* We want to use the original packet as our compressed packet.
  405. * (cp - new_seq) is the number of bytes we need for compressed
  406. * sequence numbers. In addition we need one byte for the change
  407. * mask, one for the connection id and two for the tcp checksum.
  408. * So, (cp - new_seq) + 4 bytes of header are needed.
  409. */
  410. deltaS = cp - new_seq;
  411. if(compress_cid == 0 || comp->xmit_current != cs->cs_this){
  412. cp = ocp;
  413. *cpp = ocp;
  414. *cp++ = changes | NEW_C;
  415. *cp++ = cs->cs_this;
  416. comp->xmit_current = cs->cs_this;
  417. } else {
  418. cp = ocp;
  419. *cpp = ocp;
  420. *cp++ = changes;
  421. }
  422. *(__sum16 *)cp = csum;
  423. cp += 2;
  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. int changes;
  453. long x;
  454. struct tcphdr *thp;
  455. struct iphdr *ip;
  456. 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. /* Check if the cstate is initialized */
  474. if (!comp->rstate[x].initialized)
  475. goto bad;
  476. comp->flags &=~ SLF_TOSS;
  477. comp->recv_current = x;
  478. } else {
  479. /* this packet has an implicit state index. If we've
  480. * had a line error since the last time we got an
  481. * explicit state index, we have to toss the packet. */
  482. if(comp->flags & SLF_TOSS){
  483. comp->sls_i_tossed++;
  484. return 0;
  485. }
  486. }
  487. cs = &comp->rstate[comp->recv_current];
  488. thp = &cs->cs_tcp;
  489. ip = &cs->cs_ip;
  490. thp->check = *(__sum16 *)cp;
  491. cp += 2;
  492. thp->psh = (changes & TCP_PUSH_BIT) ? 1 : 0;
  493. /*
  494. * we can use the same number for the length of the saved header and
  495. * the current one, because the packet wouldn't have been sent
  496. * as compressed unless the options were the same as the previous one
  497. */
  498. hdrlen = ip->ihl * 4 + thp->doff * 4;
  499. switch(changes & SPECIALS_MASK){
  500. case SPECIAL_I: /* Echoed terminal traffic */
  501. {
  502. short i;
  503. i = ntohs(ip->tot_len) - hdrlen;
  504. thp->ack_seq = htonl( ntohl(thp->ack_seq) + i);
  505. thp->seq = htonl( ntohl(thp->seq) + i);
  506. }
  507. break;
  508. case SPECIAL_D: /* Unidirectional data */
  509. thp->seq = htonl( ntohl(thp->seq) +
  510. ntohs(ip->tot_len) - hdrlen);
  511. break;
  512. default:
  513. if(changes & NEW_U){
  514. thp->urg = 1;
  515. if((x = decode(&cp)) == -1) {
  516. goto bad;
  517. }
  518. thp->urg_ptr = htons(x);
  519. } else
  520. thp->urg = 0;
  521. if(changes & NEW_W){
  522. if((x = decode(&cp)) == -1) {
  523. goto bad;
  524. }
  525. thp->window = htons( ntohs(thp->window) + x);
  526. }
  527. if(changes & NEW_A){
  528. if((x = decode(&cp)) == -1) {
  529. goto bad;
  530. }
  531. thp->ack_seq = htonl( ntohl(thp->ack_seq) + x);
  532. }
  533. if(changes & NEW_S){
  534. if((x = decode(&cp)) == -1) {
  535. goto bad;
  536. }
  537. thp->seq = htonl( ntohl(thp->seq) + x);
  538. }
  539. break;
  540. }
  541. if(changes & NEW_I){
  542. if((x = decode(&cp)) == -1) {
  543. goto bad;
  544. }
  545. ip->id = htons (ntohs (ip->id) + x);
  546. } else
  547. ip->id = htons (ntohs (ip->id) + 1);
  548. /*
  549. * At this point, cp points to the first byte of data in the
  550. * packet. Put the reconstructed TCP and IP headers back on the
  551. * packet. Recalculate IP checksum (but not TCP checksum).
  552. */
  553. len = isize - (cp - icp);
  554. if (len < 0)
  555. goto bad;
  556. len += hdrlen;
  557. ip->tot_len = htons(len);
  558. ip->check = 0;
  559. memmove(icp + hdrlen, cp, len - hdrlen);
  560. cp = icp;
  561. memcpy(cp, ip, 20);
  562. cp += 20;
  563. if (ip->ihl > 5) {
  564. memcpy(cp, cs->cs_ipopt, (ip->ihl - 5) * 4);
  565. cp += (ip->ihl - 5) * 4;
  566. }
  567. put_unaligned(ip_fast_csum(icp, ip->ihl),
  568. &((struct iphdr *)icp)->check);
  569. memcpy(cp, thp, 20);
  570. cp += 20;
  571. if (thp->doff > 5) {
  572. memcpy(cp, cs->cs_tcpopt, ((thp->doff) - 5) * 4);
  573. cp += ((thp->doff) - 5) * 4;
  574. }
  575. return len;
  576. bad:
  577. comp->sls_i_error++;
  578. return slhc_toss( comp );
  579. }
  580. int
  581. slhc_remember(struct slcompress *comp, unsigned char *icp, int isize)
  582. {
  583. struct cstate *cs;
  584. unsigned ihl;
  585. unsigned char index;
  586. if(isize < 20) {
  587. /* The packet is shorter than a legal IP header */
  588. comp->sls_i_runt++;
  589. return slhc_toss( comp );
  590. }
  591. /* Peek at the IP header's IHL field to find its length */
  592. ihl = icp[0] & 0xf;
  593. if(ihl < 20 / 4){
  594. /* The IP header length field is too small */
  595. comp->sls_i_runt++;
  596. return slhc_toss( comp );
  597. }
  598. index = icp[9];
  599. icp[9] = IPPROTO_TCP;
  600. if (ip_fast_csum(icp, ihl)) {
  601. /* Bad IP header checksum; discard */
  602. comp->sls_i_badcheck++;
  603. return slhc_toss( comp );
  604. }
  605. if(index > comp->rslot_limit) {
  606. comp->sls_i_error++;
  607. return slhc_toss(comp);
  608. }
  609. /* Update local state */
  610. cs = &comp->rstate[comp->recv_current = index];
  611. comp->flags &=~ SLF_TOSS;
  612. memcpy(&cs->cs_ip,icp,20);
  613. memcpy(&cs->cs_tcp,icp + ihl*4,20);
  614. if (ihl > 5)
  615. memcpy(cs->cs_ipopt, icp + sizeof(struct iphdr), (ihl - 5) * 4);
  616. if (cs->cs_tcp.doff > 5)
  617. memcpy(cs->cs_tcpopt, icp + ihl*4 + sizeof(struct tcphdr), (cs->cs_tcp.doff - 5) * 4);
  618. cs->cs_hsize = ihl*2 + cs->cs_tcp.doff*2;
  619. cs->initialized = true;
  620. /* Put headers back on packet
  621. * Neither header checksum is recalculated
  622. */
  623. comp->sls_i_uncompressed++;
  624. return isize;
  625. }
  626. int
  627. slhc_toss(struct slcompress *comp)
  628. {
  629. if ( comp == NULLSLCOMPR )
  630. return 0;
  631. comp->flags |= SLF_TOSS;
  632. return 0;
  633. }
  634. #else /* CONFIG_INET */
  635. int
  636. slhc_toss(struct slcompress *comp)
  637. {
  638. printk(KERN_DEBUG "Called IP function on non IP-system: slhc_toss");
  639. return -EINVAL;
  640. }
  641. int
  642. slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
  643. {
  644. printk(KERN_DEBUG "Called IP function on non IP-system: slhc_uncompress");
  645. return -EINVAL;
  646. }
  647. int
  648. slhc_compress(struct slcompress *comp, unsigned char *icp, int isize,
  649. unsigned char *ocp, unsigned char **cpp, int compress_cid)
  650. {
  651. printk(KERN_DEBUG "Called IP function on non IP-system: slhc_compress");
  652. return -EINVAL;
  653. }
  654. int
  655. slhc_remember(struct slcompress *comp, unsigned char *icp, int isize)
  656. {
  657. printk(KERN_DEBUG "Called IP function on non IP-system: slhc_remember");
  658. return -EINVAL;
  659. }
  660. void
  661. slhc_free(struct slcompress *comp)
  662. {
  663. printk(KERN_DEBUG "Called IP function on non IP-system: slhc_free");
  664. }
  665. struct slcompress *
  666. slhc_init(int rslots, int tslots)
  667. {
  668. printk(KERN_DEBUG "Called IP function on non IP-system: slhc_init");
  669. return NULL;
  670. }
  671. #endif /* CONFIG_INET */
  672. /* VJ header compression */
  673. EXPORT_SYMBOL(slhc_init);
  674. EXPORT_SYMBOL(slhc_free);
  675. EXPORT_SYMBOL(slhc_remember);
  676. EXPORT_SYMBOL(slhc_compress);
  677. EXPORT_SYMBOL(slhc_uncompress);
  678. EXPORT_SYMBOL(slhc_toss);
  679. MODULE_LICENSE("Dual BSD/GPL");