slhc.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768
  1. /*
  2. * Routines to compress and uncompress tcp packets (for transmission
  3. * over low speed serial lines).
  4. *
  5. * Copyright (c) 1989 Regents of the University of California.
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms are permitted
  9. * provided that the above copyright notice and this paragraph are
  10. * duplicated in all such forms and that any documentation,
  11. * advertising materials, and other materials related to such
  12. * distribution and use acknowledge that the software was developed
  13. * by the University of California, Berkeley. The name of the
  14. * University may not be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  17. * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19. *
  20. * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
  21. * - Initial distribution.
  22. *
  23. *
  24. * modified for KA9Q Internet Software Package by
  25. * Katie Stevens (dkstevens@ucdavis.edu)
  26. * University of California, Davis
  27. * Computing Services
  28. * - 01-31-90 initial adaptation (from 1.19)
  29. * PPP.05 02-15-90 [ks]
  30. * PPP.08 05-02-90 [ks] use PPP protocol field to signal compression
  31. * PPP.15 09-90 [ks] improve mbuf handling
  32. * PPP.16 11-02 [karn] substantially rewritten to use NOS facilities
  33. *
  34. * - Feb 1991 Bill_Simpson@um.cc.umich.edu
  35. * variable number of conversation slots
  36. * allow zero or one slots
  37. * separate routines
  38. * status display
  39. * - Jul 1994 Dmitry Gorodchanin
  40. * Fixes for memory leaks.
  41. * - Oct 1994 Dmitry Gorodchanin
  42. * Modularization.
  43. * - Jan 1995 Bjorn Ekwall
  44. * Use ip_fast_csum from ip.h
  45. * - July 1995 Christos A. Polyzols
  46. * Spotted bug in tcp option checking
  47. *
  48. *
  49. * This module is a difficult issue. It's clearly inet code but it's also clearly
  50. * driver code belonging close to PPP and SLIP
  51. */
  52. #include <linux/config.h>
  53. #include <linux/module.h>
  54. #include <linux/types.h>
  55. #include <linux/string.h>
  56. #include <linux/errno.h>
  57. #include <linux/kernel.h>
  58. #include <net/slhc_vj.h>
  59. #ifdef CONFIG_INET
  60. /* Entire module is for IP only */
  61. #include <linux/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 = (struct slcompress *)kmalloc(sizeof(struct slcompress),
  94. GFP_KERNEL);
  95. if (! comp)
  96. goto out_fail;
  97. memset(comp, 0, sizeof(struct slcompress));
  98. if ( rslots > 0 && rslots < 256 ) {
  99. size_t rsize = rslots * sizeof(struct cstate);
  100. comp->rstate = (struct cstate *) kmalloc(rsize, GFP_KERNEL);
  101. if (! comp->rstate)
  102. goto out_free;
  103. memset(comp->rstate, 0, rsize);
  104. comp->rslot_limit = rslots - 1;
  105. }
  106. if ( tslots > 0 && tslots < 256 ) {
  107. size_t tsize = tslots * sizeof(struct cstate);
  108. comp->tstate = (struct cstate *) kmalloc(tsize, GFP_KERNEL);
  109. if (! comp->tstate)
  110. goto out_free2;
  111. memset(comp->tstate, 0, tsize);
  112. comp->tslot_limit = tslots - 1;
  113. }
  114. comp->xmit_oldest = 0;
  115. comp->xmit_current = 255;
  116. comp->recv_current = 255;
  117. /*
  118. * don't accept any packets with implicit index until we get
  119. * one with an explicit index. Otherwise the uncompress code
  120. * will try to use connection 255, which is almost certainly
  121. * out of range
  122. */
  123. comp->flags |= SLF_TOSS;
  124. if ( tslots > 0 ) {
  125. ts = comp->tstate;
  126. for(i = comp->tslot_limit; i > 0; --i){
  127. ts[i].cs_this = i;
  128. ts[i].next = &(ts[i - 1]);
  129. }
  130. ts[0].next = &(ts[comp->tslot_limit]);
  131. ts[0].cs_this = 0;
  132. }
  133. return comp;
  134. out_free2:
  135. kfree((unsigned char *)comp->rstate);
  136. out_free:
  137. kfree((unsigned char *)comp);
  138. out_fail:
  139. return NULL;
  140. }
  141. /* Free a compression data structure */
  142. void
  143. slhc_free(struct slcompress *comp)
  144. {
  145. if ( comp == NULLSLCOMPR )
  146. return;
  147. if ( comp->tstate != NULLSLSTATE )
  148. kfree( comp->tstate );
  149. if ( comp->rstate != NULLSLSTATE )
  150. kfree( comp->rstate );
  151. kfree( comp );
  152. }
  153. /* Put a short in host order into a char array in network order */
  154. static inline unsigned char *
  155. put16(unsigned char *cp, unsigned short x)
  156. {
  157. *cp++ = x >> 8;
  158. *cp++ = x;
  159. return cp;
  160. }
  161. /* Encode a number */
  162. unsigned char *
  163. encode(unsigned char *cp, unsigned short n)
  164. {
  165. if(n >= 256 || n == 0){
  166. *cp++ = 0;
  167. cp = put16(cp,n);
  168. } else {
  169. *cp++ = n;
  170. }
  171. return cp;
  172. }
  173. /* Pull a 16-bit integer in host order from buffer in network byte order */
  174. static unsigned short
  175. pull16(unsigned char **cpp)
  176. {
  177. short rval;
  178. rval = *(*cpp)++;
  179. rval <<= 8;
  180. rval |= *(*cpp)++;
  181. return rval;
  182. }
  183. /* Decode a number */
  184. long
  185. decode(unsigned char **cpp)
  186. {
  187. register int x;
  188. x = *(*cpp)++;
  189. if(x == 0){
  190. return pull16(cpp) & 0xffff; /* pull16 returns -1 on error */
  191. } else {
  192. return x & 0xff; /* -1 if PULLCHAR returned error */
  193. }
  194. }
  195. /*
  196. * icp and isize are the original packet.
  197. * ocp is a place to put a copy if necessary.
  198. * cpp is initially a pointer to icp. If the copy is used,
  199. * change it to ocp.
  200. */
  201. int
  202. slhc_compress(struct slcompress *comp, unsigned char *icp, int isize,
  203. unsigned char *ocp, unsigned char **cpp, int compress_cid)
  204. {
  205. register struct cstate *ocs = &(comp->tstate[comp->xmit_oldest]);
  206. register struct cstate *lcs = ocs;
  207. register struct cstate *cs = lcs->next;
  208. register unsigned long deltaS, deltaA;
  209. register short changes = 0;
  210. int hlen;
  211. unsigned char new_seq[16];
  212. register unsigned char *cp = new_seq;
  213. struct iphdr *ip;
  214. struct tcphdr *th, *oth;
  215. /*
  216. * Don't play with runt packets.
  217. */
  218. if(isize<sizeof(struct iphdr))
  219. return isize;
  220. ip = (struct iphdr *) icp;
  221. /* Bail if this packet isn't TCP, or is an IP fragment */
  222. if (ip->protocol != IPPROTO_TCP || (ntohs(ip->frag_off) & 0x3fff)) {
  223. /* Send as regular IP */
  224. if(ip->protocol != IPPROTO_TCP)
  225. comp->sls_o_nontcp++;
  226. else
  227. comp->sls_o_tcp++;
  228. return isize;
  229. }
  230. /* Extract TCP header */
  231. th = (struct tcphdr *)(((unsigned char *)ip) + ip->ihl*4);
  232. hlen = ip->ihl*4 + th->doff*4;
  233. /* Bail if the TCP packet isn't `compressible' (i.e., ACK isn't set or
  234. * some other control bit is set). Also uncompressible if
  235. * it's a runt.
  236. */
  237. if(hlen > isize || th->syn || th->fin || th->rst ||
  238. ! (th->ack)){
  239. /* TCP connection stuff; send as regular IP */
  240. comp->sls_o_tcp++;
  241. return isize;
  242. }
  243. /*
  244. * Packet is compressible -- we're going to send either a
  245. * COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way,
  246. * we need to locate (or create) the connection state.
  247. *
  248. * States are kept in a circularly linked list with
  249. * xmit_oldest pointing to the end of the list. The
  250. * list is kept in lru order by moving a state to the
  251. * head of the list whenever it is referenced. Since
  252. * the list is short and, empirically, the connection
  253. * we want is almost always near the front, we locate
  254. * states via linear search. If we don't find a state
  255. * for the datagram, the oldest state is (re-)used.
  256. */
  257. for ( ; ; ) {
  258. if( ip->saddr == cs->cs_ip.saddr
  259. && ip->daddr == cs->cs_ip.daddr
  260. && th->source == cs->cs_tcp.source
  261. && th->dest == cs->cs_tcp.dest)
  262. goto found;
  263. /* if current equal oldest, at end of list */
  264. if ( cs == ocs )
  265. break;
  266. lcs = cs;
  267. cs = cs->next;
  268. comp->sls_o_searches++;
  269. };
  270. /*
  271. * Didn't find it -- re-use oldest cstate. Send an
  272. * uncompressed packet that tells the other side what
  273. * connection number we're using for this conversation.
  274. *
  275. * Note that since the state list is circular, the oldest
  276. * state points to the newest and we only need to set
  277. * xmit_oldest to update the lru linkage.
  278. */
  279. comp->sls_o_misses++;
  280. comp->xmit_oldest = lcs->cs_this;
  281. goto uncompressed;
  282. found:
  283. /*
  284. * Found it -- move to the front on the connection list.
  285. */
  286. if(lcs == ocs) {
  287. /* found at most recently used */
  288. } else if (cs == ocs) {
  289. /* found at least recently used */
  290. comp->xmit_oldest = lcs->cs_this;
  291. } else {
  292. /* more than 2 elements */
  293. lcs->next = cs->next;
  294. cs->next = ocs->next;
  295. ocs->next = cs;
  296. }
  297. /*
  298. * Make sure that only what we expect to change changed.
  299. * Check the following:
  300. * IP protocol version, header length & type of service.
  301. * The "Don't fragment" bit.
  302. * The time-to-live field.
  303. * The TCP header length.
  304. * IP options, if any.
  305. * TCP options, if any.
  306. * If any of these things are different between the previous &
  307. * current datagram, we send the current datagram `uncompressed'.
  308. */
  309. oth = &cs->cs_tcp;
  310. if(ip->version != cs->cs_ip.version || ip->ihl != cs->cs_ip.ihl
  311. || ip->tos != cs->cs_ip.tos
  312. || (ip->frag_off & htons(0x4000)) != (cs->cs_ip.frag_off & htons(0x4000))
  313. || ip->ttl != cs->cs_ip.ttl
  314. || th->doff != cs->cs_tcp.doff
  315. || (ip->ihl > 5 && memcmp(ip+1,cs->cs_ipopt,((ip->ihl)-5)*4) != 0)
  316. || (th->doff > 5 && memcmp(th+1,cs->cs_tcpopt,((th->doff)-5)*4) != 0)){
  317. goto uncompressed;
  318. }
  319. /*
  320. * Figure out which of the changing fields changed. The
  321. * receiver expects changes in the order: urgent, window,
  322. * ack, seq (the order minimizes the number of temporaries
  323. * needed in this section of code).
  324. */
  325. if(th->urg){
  326. deltaS = ntohs(th->urg_ptr);
  327. cp = encode(cp,deltaS);
  328. changes |= NEW_U;
  329. } else if(th->urg_ptr != oth->urg_ptr){
  330. /* argh! URG not set but urp changed -- a sensible
  331. * implementation should never do this but RFC793
  332. * doesn't prohibit the change so we have to deal
  333. * with it. */
  334. goto uncompressed;
  335. }
  336. if((deltaS = ntohs(th->window) - ntohs(oth->window)) != 0){
  337. cp = encode(cp,deltaS);
  338. changes |= NEW_W;
  339. }
  340. if((deltaA = ntohl(th->ack_seq) - ntohl(oth->ack_seq)) != 0L){
  341. if(deltaA > 0x0000ffff)
  342. goto uncompressed;
  343. cp = encode(cp,deltaA);
  344. changes |= NEW_A;
  345. }
  346. if((deltaS = ntohl(th->seq) - ntohl(oth->seq)) != 0L){
  347. if(deltaS > 0x0000ffff)
  348. goto uncompressed;
  349. cp = encode(cp,deltaS);
  350. changes |= NEW_S;
  351. }
  352. switch(changes){
  353. case 0: /* Nothing changed. If this packet contains data and the
  354. * last one didn't, this is probably a data packet following
  355. * an ack (normal on an interactive connection) and we send
  356. * it compressed. Otherwise it's probably a retransmit,
  357. * retransmitted ack or window probe. Send it uncompressed
  358. * in case the other side missed the compressed version.
  359. */
  360. if(ip->tot_len != cs->cs_ip.tot_len &&
  361. ntohs(cs->cs_ip.tot_len) == hlen)
  362. break;
  363. goto uncompressed;
  364. break;
  365. case SPECIAL_I:
  366. case SPECIAL_D:
  367. /* actual changes match one of our special case encodings --
  368. * send packet uncompressed.
  369. */
  370. goto uncompressed;
  371. case NEW_S|NEW_A:
  372. if(deltaS == deltaA &&
  373. deltaS == ntohs(cs->cs_ip.tot_len) - hlen){
  374. /* special case for echoed terminal traffic */
  375. changes = SPECIAL_I;
  376. cp = new_seq;
  377. }
  378. break;
  379. case NEW_S:
  380. if(deltaS == ntohs(cs->cs_ip.tot_len) - hlen){
  381. /* special case for data xfer */
  382. changes = SPECIAL_D;
  383. cp = new_seq;
  384. }
  385. break;
  386. }
  387. deltaS = ntohs(ip->id) - ntohs(cs->cs_ip.id);
  388. if(deltaS != 1){
  389. cp = encode(cp,deltaS);
  390. changes |= NEW_I;
  391. }
  392. if(th->psh)
  393. changes |= TCP_PUSH_BIT;
  394. /* Grab the cksum before we overwrite it below. Then update our
  395. * state with this packet's header.
  396. */
  397. deltaA = ntohs(th->check);
  398. memcpy(&cs->cs_ip,ip,20);
  399. memcpy(&cs->cs_tcp,th,20);
  400. /* We want to use the original packet as our compressed packet.
  401. * (cp - new_seq) is the number of bytes we need for compressed
  402. * sequence numbers. In addition we need one byte for the change
  403. * mask, one for the connection id and two for the tcp checksum.
  404. * So, (cp - new_seq) + 4 bytes of header are needed.
  405. */
  406. deltaS = cp - new_seq;
  407. if(compress_cid == 0 || comp->xmit_current != cs->cs_this){
  408. cp = ocp;
  409. *cpp = ocp;
  410. *cp++ = changes | NEW_C;
  411. *cp++ = cs->cs_this;
  412. comp->xmit_current = cs->cs_this;
  413. } else {
  414. cp = ocp;
  415. *cpp = ocp;
  416. *cp++ = changes;
  417. }
  418. cp = put16(cp,(short)deltaA); /* Write TCP checksum */
  419. /* deltaS is now the size of the change section of the compressed header */
  420. memcpy(cp,new_seq,deltaS); /* Write list of deltas */
  421. memcpy(cp+deltaS,icp+hlen,isize-hlen);
  422. comp->sls_o_compressed++;
  423. ocp[0] |= SL_TYPE_COMPRESSED_TCP;
  424. return isize - hlen + deltaS + (cp - ocp);
  425. /* Update connection state cs & send uncompressed packet (i.e.,
  426. * a regular ip/tcp packet but with the 'conversation id' we hope
  427. * to use on future compressed packets in the protocol field).
  428. */
  429. uncompressed:
  430. memcpy(&cs->cs_ip,ip,20);
  431. memcpy(&cs->cs_tcp,th,20);
  432. if (ip->ihl > 5)
  433. memcpy(cs->cs_ipopt, ip+1, ((ip->ihl) - 5) * 4);
  434. if (th->doff > 5)
  435. memcpy(cs->cs_tcpopt, th+1, ((th->doff) - 5) * 4);
  436. comp->xmit_current = cs->cs_this;
  437. comp->sls_o_uncompressed++;
  438. memcpy(ocp, icp, isize);
  439. *cpp = ocp;
  440. ocp[9] = cs->cs_this;
  441. ocp[0] |= SL_TYPE_UNCOMPRESSED_TCP;
  442. return isize;
  443. }
  444. int
  445. slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
  446. {
  447. register int changes;
  448. long x;
  449. register struct tcphdr *thp;
  450. register struct iphdr *ip;
  451. register struct cstate *cs;
  452. int len, hdrlen;
  453. unsigned char *cp = icp;
  454. /* We've got a compressed packet; read the change byte */
  455. comp->sls_i_compressed++;
  456. if(isize < 3){
  457. comp->sls_i_error++;
  458. return 0;
  459. }
  460. changes = *cp++;
  461. if(changes & NEW_C){
  462. /* Make sure the state index is in range, then grab the state.
  463. * If we have a good state index, clear the 'discard' flag.
  464. */
  465. x = *cp++; /* Read conn index */
  466. if(x < 0 || x > comp->rslot_limit)
  467. goto bad;
  468. comp->flags &=~ SLF_TOSS;
  469. comp->recv_current = x;
  470. } else {
  471. /* this packet has an implicit state index. If we've
  472. * had a line error since the last time we got an
  473. * explicit state index, we have to toss the packet. */
  474. if(comp->flags & SLF_TOSS){
  475. comp->sls_i_tossed++;
  476. return 0;
  477. }
  478. }
  479. cs = &comp->rstate[comp->recv_current];
  480. thp = &cs->cs_tcp;
  481. ip = &cs->cs_ip;
  482. if((x = pull16(&cp)) == -1) { /* Read the TCP checksum */
  483. goto bad;
  484. }
  485. thp->check = htons(x);
  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. /* Put headers back on packet
  614. * Neither header checksum is recalculated
  615. */
  616. comp->sls_i_uncompressed++;
  617. return isize;
  618. }
  619. int
  620. slhc_toss(struct slcompress *comp)
  621. {
  622. if ( comp == NULLSLCOMPR )
  623. return 0;
  624. comp->flags |= SLF_TOSS;
  625. return 0;
  626. }
  627. /* VJ header compression */
  628. EXPORT_SYMBOL(slhc_init);
  629. EXPORT_SYMBOL(slhc_free);
  630. EXPORT_SYMBOL(slhc_remember);
  631. EXPORT_SYMBOL(slhc_compress);
  632. EXPORT_SYMBOL(slhc_uncompress);
  633. EXPORT_SYMBOL(slhc_toss);
  634. #ifdef MODULE
  635. int init_module(void)
  636. {
  637. printk(KERN_INFO "CSLIP: code copyright 1989 Regents of the University of California\n");
  638. return 0;
  639. }
  640. void cleanup_module(void)
  641. {
  642. return;
  643. }
  644. #endif /* MODULE */
  645. #else /* CONFIG_INET */
  646. int
  647. slhc_toss(struct slcompress *comp)
  648. {
  649. printk(KERN_DEBUG "Called IP function on non IP-system: slhc_toss");
  650. return -EINVAL;
  651. }
  652. int
  653. slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
  654. {
  655. printk(KERN_DEBUG "Called IP function on non IP-system: slhc_uncompress");
  656. return -EINVAL;
  657. }
  658. int
  659. slhc_compress(struct slcompress *comp, unsigned char *icp, int isize,
  660. unsigned char *ocp, unsigned char **cpp, int compress_cid)
  661. {
  662. printk(KERN_DEBUG "Called IP function on non IP-system: slhc_compress");
  663. return -EINVAL;
  664. }
  665. int
  666. slhc_remember(struct slcompress *comp, unsigned char *icp, int isize)
  667. {
  668. printk(KERN_DEBUG "Called IP function on non IP-system: slhc_remember");
  669. return -EINVAL;
  670. }
  671. void
  672. slhc_free(struct slcompress *comp)
  673. {
  674. printk(KERN_DEBUG "Called IP function on non IP-system: slhc_free");
  675. return;
  676. }
  677. struct slcompress *
  678. slhc_init(int rslots, int tslots)
  679. {
  680. printk(KERN_DEBUG "Called IP function on non IP-system: slhc_init");
  681. return NULL;
  682. }
  683. EXPORT_SYMBOL(slhc_init);
  684. EXPORT_SYMBOL(slhc_free);
  685. EXPORT_SYMBOL(slhc_remember);
  686. EXPORT_SYMBOL(slhc_compress);
  687. EXPORT_SYMBOL(slhc_uncompress);
  688. EXPORT_SYMBOL(slhc_toss);
  689. #endif /* CONFIG_INET */
  690. MODULE_LICENSE("Dual BSD/GPL");