/[pengfork]/pengfork/src/vjcompress.c
ViewVC logotype

Diff of /pengfork/src/vjcompress.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1 by chupa, Fri Aug 30 14:57:29 2002 UTC revision 1.2 by chupa, Fri Aug 30 20:23:27 2002 UTC
# Line 36  Line 36 
36    Modified by Jean-Charles Salzeber <jc@varspool.net>    Modified by Jean-Charles Salzeber <jc@varspool.net>
37    to fit pengfork needs    to fit pengfork needs
38   */   */
39    #include <string.h>
40  #include <sys/types.h>  #include <sys/types.h>
41  #include <sys/param.h>  #include <sys/param.h>
42    
43  #ifdef SVR4  #ifdef SVR4
44  #ifndef __GNUC__  #ifndef __GNUC__
45  #include <sys/byteorder.h>      /* for ntohl, etc. */  #include <sys/byteorder.h>      /* for ntohl, etc. */
46  #else  #else
47  /* make sure we don't get the gnu "fixed" one! */  /* make sure we don't get the gnu "fixed" one! */
48  #include "/usr/include/sys/byteorder.h"  #include "/usr/include/sys/byteorder.h"
# Line 56  Line 56 
56    
57  #ifdef AIX4  #ifdef AIX4
58  #define _NETINET_IN_SYSTM_H_  #define _NETINET_IN_SYSTM_H_
59  typedef u_long  n_long;  typedef u_long n_long;
60  #else  #else
61  #include <netinet/in_systm.h>  #include <netinet/in_systm.h>
62  #endif  #endif
# Line 90  typedef u_long  n_long; Line 90  typedef u_long  n_long;
90  #endif  #endif
91    
92  void  void
93  vj_compress_init(comp, max_state)  vj_compress_init (comp, max_state)
94      struct vjcompress *comp;       struct vjcompress *comp;
95      int max_state;       int max_state;
96  {  {
97      register u_int i;    register u_int i;
98      register struct cstate *tstate = comp->tstate;    register struct cstate *tstate = comp->tstate;
99    
100      if (max_state == -1)    if (max_state == -1)
101          max_state = MAX_STATES - 1;      max_state = MAX_STATES - 1;
102      bzero((char *)comp, sizeof(*comp));    bzero ((char *) comp, sizeof (*comp));
103      for (i = max_state; i > 0; --i) {    for (i = max_state; i > 0; --i)
104          tstate[i].cs_id = i;      {
105          tstate[i].cs_next = &tstate[i - 1];        tstate[i].cs_id = i;
106      }        tstate[i].cs_next = &tstate[i - 1];
107      tstate[0].cs_next = &tstate[max_state];      }
108      tstate[0].cs_id = 0;    tstate[0].cs_next = &tstate[max_state];
109      comp->last_cs = &tstate[0];    tstate[0].cs_id = 0;
110      comp->last_recv = 255;    comp->last_cs = &tstate[0];
111      comp->last_xmit = 255;    comp->last_recv = 255;
112      comp->flags = VJF_TOSS;    comp->last_xmit = 255;
113      comp->flags = VJF_TOSS;
114  }  }
115    
116    
# Line 170  vj_compress_init(comp, max_state) Line 171  vj_compress_init(comp, max_state)
171  }  }
172    
173  u_int  u_int
174  vj_compress_tcp(ip, mlen, comp, compress_cid, vjhdrp)  vj_compress_tcp (ip, mlen, comp, compress_cid, vjhdrp)
175      register struct ip *ip;       register struct ip *ip;
176      u_int mlen;       u_int mlen;
177      struct vjcompress *comp;       struct vjcompress *comp;
178      int compress_cid;       int compress_cid;
179      u_char **vjhdrp;       u_char **vjhdrp;
180  {  {
181      register struct cstate *cs = comp->last_cs->cs_next;    register struct cstate *cs = comp->last_cs->cs_next;
182      register u_int hlen = getip_hl(*ip);    register u_int hlen = getip_hl (*ip);
183      register struct tcphdr *oth;    register struct tcphdr *oth;
184      register struct tcphdr *th;    register struct tcphdr *th;
185      register u_int deltaS, deltaA;    register u_int deltaS, deltaA;
186      register u_int changes = 0;    register u_int changes = 0;
187      u_char new_seq[16];    u_char new_seq[16];
188      register u_char *cp = new_seq;    register u_char *cp = new_seq;
189    
190      /*    /*
191       * Bail if this is an IP fragment or if the TCP packet isn't     * Bail if this is an IP fragment or if the TCP packet isn't
192       * `compressible' (i.e., ACK isn't set or some other control bit is     * `compressible' (i.e., ACK isn't set or some other control bit is
193       * set).  (We assume that the caller has already made sure the     * set).  (We assume that the caller has already made sure the
194       * packet is IP proto TCP).     * packet is IP proto TCP).
195       */     */
196      if ((ip->ip_off & htons(0x3fff)) || mlen < 40)    if ((ip->ip_off & htons (0x3fff)) || mlen < 40)
197          return (TYPE_IP);      return (TYPE_IP);
198    
199      th = (struct tcphdr *)&((int *)ip)[hlen];    th = (struct tcphdr *) &((int *) ip)[hlen];
200      if ((th->th_flags & (TH_SYN|TH_FIN|TH_RST|TH_ACK)) != TH_ACK)    if ((th->th_flags & (TH_SYN | TH_FIN | TH_RST | TH_ACK)) != TH_ACK)
201          return (TYPE_IP);      return (TYPE_IP);
202      /*    /*
203       * Packet is compressible -- we're going to send either a     * Packet is compressible -- we're going to send either a
204       * COMPRESSED_TCP or UNCOMPRESSED_TCP packet.  Either way we need     * COMPRESSED_TCP or UNCOMPRESSED_TCP packet.  Either way we need
205       * to locate (or create) the connection state.  Special case the     * to locate (or create) the connection state.  Special case the
206       * most recently used connection since it's most likely to be used     * most recently used connection since it's most likely to be used
207       * again & we don't have to do any reordering if it's used.     * again & we don't have to do any reordering if it's used.
208       */     */
209      INCR(vjs_packets);    INCR (vjs_packets);
210      if (ip->ip_src.s_addr != cs->cs_ip.ip_src.s_addr ||    if (ip->ip_src.s_addr != cs->cs_ip.ip_src.s_addr ||
211          ip->ip_dst.s_addr != cs->cs_ip.ip_dst.s_addr ||        ip->ip_dst.s_addr != cs->cs_ip.ip_dst.s_addr ||
212          *(int *)th != ((int *)&cs->cs_ip)[getip_hl(cs->cs_ip)]) {        *(int *) th != ((int *) &cs->cs_ip)[getip_hl (cs->cs_ip)])
213          /*      {
214           * Wasn't the first -- search for it.        /*
215           *         * Wasn't the first -- search for it.
216           * States are kept in a circularly linked list with         *
217           * last_cs pointing to the end of the list.  The         * States are kept in a circularly linked list with
218           * list is kept in lru order by moving a state to the         * last_cs pointing to the end of the list.  The
219           * head of the list whenever it is referenced.  Since         * list is kept in lru order by moving a state to the
220           * the list is short and, empirically, the connection         * head of the list whenever it is referenced.  Since
221           * we want is almost always near the front, we locate         * the list is short and, empirically, the connection
222           * states via linear search.  If we don't find a state         * we want is almost always near the front, we locate
223           * for the datagram, the oldest state is (re-)used.         * states via linear search.  If we don't find a state
224           */         * for the datagram, the oldest state is (re-)used.
225          register struct cstate *lcs;         */
226          register struct cstate *lastcs = comp->last_cs;        register struct cstate *lcs;
227          register struct cstate *lastcs = comp->last_cs;
228          do {  
229              lcs = cs; cs = cs->cs_next;        do
230              INCR(vjs_searches);          {
231              if (ip->ip_src.s_addr == cs->cs_ip.ip_src.s_addr            lcs = cs;
232                  && ip->ip_dst.s_addr == cs->cs_ip.ip_dst.s_addr            cs = cs->cs_next;
233                  && *(int *)th == ((int *)&cs->cs_ip)[getip_hl(cs->cs_ip)])            INCR (vjs_searches);
234                  goto found;            if (ip->ip_src.s_addr == cs->cs_ip.ip_src.s_addr
235          } while (cs != lastcs);                && ip->ip_dst.s_addr == cs->cs_ip.ip_dst.s_addr
236                  && *(int *) th == ((int *) &cs->cs_ip)[getip_hl (cs->cs_ip)])
237          /*              goto found;
238           * Didn't find it -- re-use oldest cstate.  Send an          }
239           * uncompressed packet that tells the other side what        while (cs != lastcs);
240           * connection number we're using for this conversation.  
241           * Note that since the state list is circular, the oldest        /*
242           * state points to the newest and we only need to set         * Didn't find it -- re-use oldest cstate.  Send an
243           * last_cs to update the lru linkage.         * uncompressed packet that tells the other side what
244           */         * connection number we're using for this conversation.
245          INCR(vjs_misses);         * Note that since the state list is circular, the oldest
246          comp->last_cs = lcs;         * state points to the newest and we only need to set
247          hlen += getth_off(*th);         * last_cs to update the lru linkage.
248          hlen <<= 2;         */
249          if (hlen > mlen)        INCR (vjs_misses);
250              return (TYPE_IP);        comp->last_cs = lcs;
251          goto uncompressed;        hlen += getth_off (*th);
252          hlen <<= 2;
253          if (hlen > mlen)
254            return (TYPE_IP);
255          goto uncompressed;
256    
257      found:      found:
258          /*        /*
259           * Found it -- move to the front on the connection list.         * Found it -- move to the front on the connection list.
260           */         */
261          if (cs == lastcs)        if (cs == lastcs)
262              comp->last_cs = lcs;          comp->last_cs = lcs;
263          else {        else
264              lcs->cs_next = cs->cs_next;          {
265              cs->cs_next = lastcs->cs_next;            lcs->cs_next = cs->cs_next;
266              lastcs->cs_next = cs;            cs->cs_next = lastcs->cs_next;
267          }            lastcs->cs_next = cs;
268      }          }
269        }
270      /*  
271       * Make sure that only what we expect to change changed. The first    /*
272       * line of the `if' checks the IP protocol version, header length &     * Make sure that only what we expect to change changed. The first
273       * type of service.  The 2nd line checks the "Don't fragment" bit.     * line of the `if' checks the IP protocol version, header length &
274       * The 3rd line checks the time-to-live and protocol (the protocol     * type of service.  The 2nd line checks the "Don't fragment" bit.
275       * check is unnecessary but costless).  The 4th line checks the TCP     * The 3rd line checks the time-to-live and protocol (the protocol
276       * header length.  The 5th line checks IP options, if any.  The 6th     * check is unnecessary but costless).  The 4th line checks the TCP
277       * line checks TCP options, if any.  If any of these things are     * header length.  The 5th line checks IP options, if any.  The 6th
278       * different between the previous & current datagram, we send the     * line checks TCP options, if any.  If any of these things are
279       * current datagram `uncompressed'.     * different between the previous & current datagram, we send the
280       */     * current datagram `uncompressed'.
281      oth = (struct tcphdr *)&((int *)&cs->cs_ip)[hlen];     */
282      deltaS = hlen;    oth = (struct tcphdr *) &((int *) &cs->cs_ip)[hlen];
283      hlen += getth_off(*th);    deltaS = hlen;
284      hlen <<= 2;    hlen += getth_off (*th);
285      if (hlen > mlen)    hlen <<= 2;
286          return (TYPE_IP);    if (hlen > mlen)
287        return (TYPE_IP);
288      if (((u_short *)ip)[0] != ((u_short *)&cs->cs_ip)[0] ||  
289          ((u_short *)ip)[3] != ((u_short *)&cs->cs_ip)[3] ||    if (((u_short *) ip)[0] != ((u_short *) & cs->cs_ip)[0] ||
290          ((u_short *)ip)[4] != ((u_short *)&cs->cs_ip)[4] ||        ((u_short *) ip)[3] != ((u_short *) & cs->cs_ip)[3] ||
291          getth_off(*th) != getth_off(*oth) ||        ((u_short *) ip)[4] != ((u_short *) & cs->cs_ip)[4] ||
292          (deltaS > 5 && BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2)) ||        getth_off (*th) != getth_off (*oth) ||
293          (getth_off(*th) > 5 && BCMP(th + 1, oth + 1, (getth_off(*th) - 5) << 2)))        (deltaS > 5 && BCMP (ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2)) ||
294          goto uncompressed;        (getth_off (*th) > 5
295           && BCMP (th + 1, oth + 1, (getth_off (*th) - 5) << 2)))
296      /*      goto uncompressed;
297       * Figure out which of the changing fields changed.  The  
298       * receiver expects changes in the order: urgent, window,    /*
299       * ack, seq (the order minimizes the number of temporaries     * Figure out which of the changing fields changed.  The
300       * needed in this section of code).     * receiver expects changes in the order: urgent, window,
301       */     * ack, seq (the order minimizes the number of temporaries
302      if (th->th_flags & TH_URG) {     * needed in this section of code).
303          deltaS = ntohs(th->th_urp);     */
304          ENCODEZ(deltaS);    if (th->th_flags & TH_URG)
305          changes |= NEW_U;      {
306      } else if (th->th_urp != oth->th_urp)        deltaS = ntohs (th->th_urp);
307          /* argh! URG not set but urp changed -- a sensible        ENCODEZ (deltaS);
308           * implementation should never do this but RFC793        changes |= NEW_U;
309           * doesn't prohibit the change so we have to deal      }
310           * with it. */    else if (th->th_urp != oth->th_urp)
311          goto uncompressed;      /* argh! URG not set but urp changed -- a sensible
312         * implementation should never do this but RFC793
313      if (deltaS = (u_short)(ntohs(th->th_win) - ntohs(oth->th_win))) {       * doesn't prohibit the change so we have to deal
314          ENCODE(deltaS);       * with it. */
315          changes |= NEW_W;      goto uncompressed;
316      }  
317      if ((deltaS = (u_short) (ntohs (th->th_win) - ntohs (oth->th_win))))
318      if (deltaA = ntohl(th->th_ack) - ntohl(oth->th_ack)) {      {
319          if (deltaA > 0xffff)        ENCODE (deltaS);
320              goto uncompressed;        changes |= NEW_W;
321          ENCODE(deltaA);      }
322          changes |= NEW_A;  
323      }    if ((deltaA = ntohl (th->th_ack) - ntohl (oth->th_ack)))
324        {
325      if (deltaS = ntohl(th->th_seq) - ntohl(oth->th_seq)) {        if (deltaA > 0xffff)
326          if (deltaS > 0xffff)          goto uncompressed;
327              goto uncompressed;        ENCODE (deltaA);
328          ENCODE(deltaS);        changes |= NEW_A;
329          changes |= NEW_S;      }
330    
331      if ((deltaS = ntohl (th->th_seq) - ntohl (oth->th_seq)))
332        {
333          if (deltaS > 0xffff)
334            goto uncompressed;
335          ENCODE (deltaS);
336          changes |= NEW_S;
337      }      }
338    
339      switch(changes) {    switch (changes)
340        {
341    
342      case 0:      case 0:
343          /*        /*
344           * Nothing changed. If this packet contains data and the         * Nothing changed. If this packet contains data and the
345           * last one didn't, this is probably a data packet following         * last one didn't, this is probably a data packet following
346           * an ack (normal on an interactive connection) and we send         * an ack (normal on an interactive connection) and we send
347           * it compressed.  Otherwise it's probably a retransmit,         * it compressed.  Otherwise it's probably a retransmit,
348           * retransmitted ack or window probe.  Send it uncompressed         * retransmitted ack or window probe.  Send it uncompressed
349           * in case the other side missed the compressed version.         * in case the other side missed the compressed version.
350           */         */
351          if (ip->ip_len != cs->cs_ip.ip_len &&        if (ip->ip_len != cs->cs_ip.ip_len && ntohs (cs->cs_ip.ip_len) == hlen)
352              ntohs(cs->cs_ip.ip_len) == hlen)          break;
             break;  
353    
354          /* (fall through) */        /* (fall through) */
355    
356      case SPECIAL_I:      case SPECIAL_I:
357      case SPECIAL_D:      case SPECIAL_D:
358          /*        /*
359           * actual changes match one of our special case encodings --         * actual changes match one of our special case encodings --
360           * send packet uncompressed.         * send packet uncompressed.
361           */         */
362          goto uncompressed;        goto uncompressed;
363    
364      case NEW_S|NEW_A:      case NEW_S | NEW_A:
365          if (deltaS == deltaA && deltaS == ntohs(cs->cs_ip.ip_len) - hlen) {        if (deltaS == deltaA && deltaS == ntohs (cs->cs_ip.ip_len) - hlen)
366              /* special case for echoed terminal traffic */          {
367              changes = SPECIAL_I;            /* special case for echoed terminal traffic */
368              cp = new_seq;            changes = SPECIAL_I;
369          }            cp = new_seq;
370          break;          }
371          break;
372    
373      case NEW_S:      case NEW_S:
374          if (deltaS == ntohs(cs->cs_ip.ip_len) - hlen) {        if (deltaS == ntohs (cs->cs_ip.ip_len) - hlen)
375              /* special case for data xfer */          {
376              changes = SPECIAL_D;            /* special case for data xfer */
377              cp = new_seq;            changes = SPECIAL_D;
378          }            cp = new_seq;
379          break;          }
380      }        break;
381        }
382      deltaS = ntohs(ip->ip_id) - ntohs(cs->cs_ip.ip_id);  
383      if (deltaS != 1) {    deltaS = ntohs (ip->ip_id) - ntohs (cs->cs_ip.ip_id);
384          ENCODEZ(deltaS);    if (deltaS != 1)
385          changes |= NEW_I;      {
386      }        ENCODEZ (deltaS);
387      if (th->th_flags & TH_PUSH)        changes |= NEW_I;
388          changes |= TCP_PUSH_BIT;      }
389      /*    if (th->th_flags & TH_PUSH)
390       * Grab the cksum before we overwrite it below.  Then update our      changes |= TCP_PUSH_BIT;
391       * state with this packet's header.    /*
392       */     * Grab the cksum before we overwrite it below.  Then update our
393      deltaA = ntohs(th->th_sum);     * state with this packet's header.
394      BCOPY(ip, &cs->cs_ip, hlen);     */
395      deltaA = ntohs (th->th_sum);
396      /*    BCOPY (ip, &cs->cs_ip, hlen);
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     * We want to use the original packet as our compressed packet.
400       * mask, one for the connection id and two for the tcp checksum.     * (cp - new_seq) is the number of bytes we need for compressed
401       * So, (cp - new_seq) + 4 bytes of header are needed.  hlen is how     * sequence numbers.  In addition we need one byte for the change
402       * many bytes of the original packet to toss so subtract the two to     * mask, one for the connection id and two for the tcp checksum.
403       * get the new packet size.     * So, (cp - new_seq) + 4 bytes of header are needed.  hlen is how
404       */     * many bytes of the original packet to toss so subtract the two to
405      deltaS = cp - new_seq;     * get the new packet size.
406      cp = (u_char *)ip;     */
407      if (compress_cid == 0 || comp->last_xmit != cs->cs_id) {    deltaS = cp - new_seq;
408          comp->last_xmit = cs->cs_id;    cp = (u_char *) ip;
409          hlen -= deltaS + 4;    if (compress_cid == 0 || comp->last_xmit != cs->cs_id)
410          *vjhdrp = (cp += hlen);      {
411          *cp++ = changes | NEW_C;        comp->last_xmit = cs->cs_id;
412          *cp++ = cs->cs_id;        hlen -= deltaS + 4;
413      } else {        *vjhdrp = (cp += hlen);
414          hlen -= deltaS + 3;        *cp++ = changes | NEW_C;
415          *vjhdrp = (cp += hlen);        *cp++ = cs->cs_id;
416          *cp++ = changes;      }
417      }    else
418      *cp++ = deltaA >> 8;      {
419      *cp++ = deltaA;        hlen -= deltaS + 3;
420      BCOPY(new_seq, cp, deltaS);        *vjhdrp = (cp += hlen);
421      INCR(vjs_compressed);        *cp++ = changes;
422      return (TYPE_COMPRESSED_TCP);      }
423      *cp++ = deltaA >> 8;
424      /*    *cp++ = deltaA;
425       * Update connection state cs & send uncompressed packet (that is,    BCOPY (new_seq, cp, deltaS);
426       * a regular ip/tcp packet but with the 'conversation id' we hope    INCR (vjs_compressed);
427       * to use on future compressed packets in the protocol field).    return (TYPE_COMPRESSED_TCP);
428       */  
429   uncompressed:    /*
430      BCOPY(ip, &cs->cs_ip, hlen);     * Update connection state cs & send uncompressed packet (that is,
431      ip->ip_p = cs->cs_id;     * a regular ip/tcp packet but with the 'conversation id' we hope
432      comp->last_xmit = cs->cs_id;     * to use on future compressed packets in the protocol field).
433      return (TYPE_UNCOMPRESSED_TCP);     */
434    uncompressed:
435      BCOPY (ip, &cs->cs_ip, hlen);
436      ip->ip_p = cs->cs_id;
437      comp->last_xmit = cs->cs_id;
438      return (TYPE_UNCOMPRESSED_TCP);
439  }  }
440    
441  /*  /*
442   * Called when we may have missed a packet.   * Called when we may have missed a packet.
443   */   */
444  void  void
445  vj_uncompress_err(comp)  vj_uncompress_err (comp)
446      struct vjcompress *comp;       struct vjcompress *comp;
447  {  {
448      comp->flags |= VJF_TOSS;    comp->flags |= VJF_TOSS;
449      INCR(vjs_errorin);    INCR (vjs_errorin);
450  }  }
451    
452  /*  /*
453   * "Uncompress" a packet of type TYPE_UNCOMPRESSED_TCP.   * "Uncompress" a packet of type TYPE_UNCOMPRESSED_TCP.
454   */   */
455  int  int
456  vj_uncompress_uncomp(buf, buflen, comp)  vj_uncompress_uncomp (buf, buflen, comp)
457      u_char *buf;       u_char *buf;
458      int buflen;       int buflen;
459      struct vjcompress *comp;       struct vjcompress *comp;
460  {  {
461      register u_int hlen;    register u_int hlen;
462      register struct cstate *cs;    register struct cstate *cs;
463      register struct ip *ip;    register struct ip *ip;
464    
465      ip = (struct ip *) buf;    ip = (struct ip *) buf;
466      hlen = getip_hl(*ip) << 2;    hlen = getip_hl (*ip) << 2;
467      if (ip->ip_p >= MAX_STATES    if (ip->ip_p >= MAX_STATES
468          || hlen + sizeof(struct tcphdr) > buflen        || hlen + sizeof (struct tcphdr) > buflen
469          || (hlen += getth_off(*((struct tcphdr *)&((char *)ip)[hlen])) << 2)        || (hlen += getth_off (*((struct tcphdr *) &((char *) ip)[hlen])) << 2)
470              > buflen        > buflen || hlen > MAX_HDR)
471          || hlen > MAX_HDR) {      {
472          comp->flags |= VJF_TOSS;        comp->flags |= VJF_TOSS;
473          INCR(vjs_errorin);        INCR (vjs_errorin);
474          return (0);        return (0);
475      }      }
476      cs = &comp->rstate[comp->last_recv = ip->ip_p];    cs = &comp->rstate[comp->last_recv = ip->ip_p];
477      comp->flags &=~ VJF_TOSS;    comp->flags &= ~VJF_TOSS;
478      ip->ip_p = IPPROTO_TCP;    ip->ip_p = IPPROTO_TCP;
479      BCOPY(ip, &cs->cs_ip, hlen);    BCOPY (ip, &cs->cs_ip, hlen);
480      cs->cs_hlen = hlen;    cs->cs_hlen = hlen;
481      INCR(vjs_uncompressedin);    INCR (vjs_uncompressedin);
482      return (1);    return (1);
483  }  }
484    
485  /*  /*
# Line 473  vj_uncompress_uncomp(buf, buflen, comp) Line 491  vj_uncompress_uncomp(buf, buflen, comp)
491   * in *hdrp and its length in *hlenp.   * in *hdrp and its length in *hlenp.
492   */   */
493  int  int
494  vj_uncompress_tcp(buf, buflen, total_len, comp, hdrp, hlenp)  vj_uncompress_tcp (buf, buflen, total_len, comp, hdrp, hlenp)
495      u_char *buf;       u_char *buf;
496      int buflen, total_len;       int buflen, total_len;
497      struct vjcompress *comp;       struct vjcompress *comp;
498      u_char **hdrp;       u_char **hdrp;
499      u_int *hlenp;       u_int *hlenp;
500  {  {
501      register u_char *cp;    register u_char *cp;
502      register u_int hlen, changes;    register u_int hlen, changes;
503      register struct tcphdr *th;    register struct tcphdr *th;
504      register struct cstate *cs;    register struct cstate *cs;
505      register u_short *bp;    register u_short *bp;
506      register u_int vjlen;    register u_int vjlen;
507      register u_int32_t tmp;    register u_int32_t tmp;
508    
509      INCR(vjs_compressedin);    INCR (vjs_compressedin);
510      cp = buf;    cp = buf;
511      changes = *cp++;    changes = *cp++;
512      if (changes & NEW_C) {    if (changes & NEW_C)
513          /* Make sure the state index is in range, then grab the state.      {
514           * If we have a good state index, clear the 'discard' flag. */        /* Make sure the state index is in range, then grab the state.
515          if (*cp >= MAX_STATES)         * If we have a good state index, clear the 'discard' flag. */
516              goto bad;        if (*cp >= MAX_STATES)
517            goto bad;
518          comp->flags &=~ VJF_TOSS;  
519          comp->last_recv = *cp++;        comp->flags &= ~VJF_TOSS;
520      } else {        comp->last_recv = *cp++;
521          /* this packet has an implicit state index.  If we've      }
522           * had a line error since the last time we got an    else
523           * explicit state index, we have to toss the packet. */      {
524          if (comp->flags & VJF_TOSS) {        /* this packet has an implicit state index.  If we've
525              INCR(vjs_tossed);         * had a line error since the last time we got an
526              return (-1);         * explicit state index, we have to toss the packet. */
527          }        if (comp->flags & VJF_TOSS)
528      }          {
529      cs = &comp->rstate[comp->last_recv];            INCR (vjs_tossed);
530      hlen = getip_hl(cs->cs_ip) << 2;            return (-1);
531      th = (struct tcphdr *)&((u_char *)&cs->cs_ip)[hlen];          }
532      th->th_sum = htons((*cp << 8) | cp[1]);      }
533      cp += 2;    cs = &comp->rstate[comp->last_recv];
534      if (changes & TCP_PUSH_BIT)    hlen = getip_hl (cs->cs_ip) << 2;
535          th->th_flags |= TH_PUSH;    th = (struct tcphdr *) &((u_char *) & cs->cs_ip)[hlen];
536      else    th->th_sum = htons ((*cp << 8) | cp[1]);
537          th->th_flags &=~ TH_PUSH;    cp += 2;
538      if (changes & TCP_PUSH_BIT)
539        th->th_flags |= TH_PUSH;
540      else
541        th->th_flags &= ~TH_PUSH;
542    
543      switch (changes & SPECIALS_MASK) {    switch (changes & SPECIALS_MASK)
544        {
545      case SPECIAL_I:      case SPECIAL_I:
546          {        {
547              register u_int32_t i = ntohs(cs->cs_ip.ip_len) - cs->cs_hlen;          register u_int32_t i = ntohs (cs->cs_ip.ip_len) - cs->cs_hlen;
548              /* some compilers can't nest inline assembler.. */          /* some compilers can't nest inline assembler.. */
549              tmp = ntohl(th->th_ack) + i;          tmp = ntohl (th->th_ack) + i;
550              th->th_ack = htonl(tmp);          th->th_ack = htonl (tmp);
551              tmp = ntohl(th->th_seq) + i;          tmp = ntohl (th->th_seq) + i;
552              th->th_seq = htonl(tmp);          th->th_seq = htonl (tmp);
553          }        }
554          break;        break;
555    
556      case SPECIAL_D:      case SPECIAL_D:
557          /* some compilers can't nest inline assembler.. */        /* some compilers can't nest inline assembler.. */
558          tmp = ntohl(th->th_seq) + ntohs(cs->cs_ip.ip_len) - cs->cs_hlen;        tmp = ntohl (th->th_seq) + ntohs (cs->cs_ip.ip_len) - cs->cs_hlen;
559          th->th_seq = htonl(tmp);        th->th_seq = htonl (tmp);
560          break;        break;
561    
562      default:      default:
563          if (changes & NEW_U) {        if (changes & NEW_U)
564              th->th_flags |= TH_URG;          {
565              DECODEU(th->th_urp);            th->th_flags |= TH_URG;
566          } else            DECODEU (th->th_urp);
567              th->th_flags &=~ TH_URG;          }
568          if (changes & NEW_W)        else
569              DECODES(th->th_win);          th->th_flags &= ~TH_URG;
570          if (changes & NEW_A)        if (changes & NEW_W)
571              DECODEL(th->th_ack);          DECODES (th->th_win);
572          if (changes & NEW_S)        if (changes & NEW_A)
573              DECODEL(th->th_seq);          DECODEL (th->th_ack);
574          break;        if (changes & NEW_S)
575      }          DECODEL (th->th_seq);
576      if (changes & NEW_I) {        break;
577          DECODES(cs->cs_ip.ip_id);      }
578      } else {    if (changes & NEW_I)
579          cs->cs_ip.ip_id = ntohs(cs->cs_ip.ip_id) + 1;      {
580          cs->cs_ip.ip_id = htons(cs->cs_ip.ip_id);        DECODES (cs->cs_ip.ip_id);
581      }      }
582      else
583      /*      {
584       * At this point, cp points to the first byte of data in the        cs->cs_ip.ip_id = ntohs (cs->cs_ip.ip_id) + 1;
585       * packet.  Fill in the IP total length and update the IP        cs->cs_ip.ip_id = htons (cs->cs_ip.ip_id);
586       * header checksum.      }
587       */  
588      vjlen = cp - buf;    /*
589      buflen -= vjlen;     * At this point, cp points to the first byte of data in the
590      if (buflen < 0)     * packet.  Fill in the IP total length and update the IP
591          /* we must have dropped some characters (crc should detect     * header checksum.
592           * this but the old slip framing won't) */     */
593          goto bad;    vjlen = cp - buf;
594      buflen -= vjlen;
595      total_len += cs->cs_hlen - vjlen;    if (buflen < 0)
596      cs->cs_ip.ip_len = htons(total_len);      /* we must have dropped some characters (crc should detect
597         * this but the old slip framing won't) */
598      /* recompute the ip header checksum */      goto bad;
599      bp = (u_short *) &cs->cs_ip;  
600      cs->cs_ip.ip_sum = 0;    total_len += cs->cs_hlen - vjlen;
601      for (changes = 0; hlen > 0; hlen -= 2)    cs->cs_ip.ip_len = htons (total_len);
602          changes += *bp++;  
603      changes = (changes & 0xffff) + (changes >> 16);    /* recompute the ip header checksum */
604      changes = (changes & 0xffff) + (changes >> 16);    bp = (u_short *) & cs->cs_ip;
605      cs->cs_ip.ip_sum = ~ changes;    cs->cs_ip.ip_sum = 0;
606      for (changes = 0; hlen > 0; hlen -= 2)
607      *hdrp = (u_char *) &cs->cs_ip;      changes += *bp++;
608      *hlenp = cs->cs_hlen;    changes = (changes & 0xffff) + (changes >> 16);
609      return vjlen;    changes = (changes & 0xffff) + (changes >> 16);
610      cs->cs_ip.ip_sum = ~changes;
611   bad:  
612      comp->flags |= VJF_TOSS;    *hdrp = (u_char *) & cs->cs_ip;
613      INCR(vjs_errorin);    *hlenp = cs->cs_hlen;
614      return (-1);    return vjlen;
615    
616    bad:
617      comp->flags |= VJF_TOSS;
618      INCR (vjs_errorin);
619      return (-1);
620  }  }

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26