ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

vj.c
Go to the documentation of this file.
00001 /*
00002  * Routines to compress and uncompess tcp packets (for transmission
00003  * over low speed serial lines.
00004  *
00005  * Copyright (c) 1989 Regents of the University of California.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms are permitted
00009  * provided that the above copyright notice and this paragraph are
00010  * duplicated in all such forms and that any documentation,
00011  * advertising materials, and other materials related to such
00012  * distribution and use acknowledge that the software was developed
00013  * by the University of California, Berkeley.  The name of the
00014  * University may not be used to endorse or promote products derived
00015  * from this software without specific prior written permission.
00016  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
00017  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
00018  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00019  *
00020  * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
00021  *   Initial distribution.
00022  *
00023  * Modified June 1993 by Paul Mackerras, paulus@cs.anu.edu.au,
00024  * so that the entire packet being decompressed doesn't have
00025  * to be in contiguous memory (just the compressed header).
00026  *
00027  * Modified March 1998 by Guy Lancaster, glanca@gesn.com,
00028  * for a 16 bit processor.
00029  */
00030 
00031 #include "lwip/opt.h"
00032 
00033 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
00034 
00035 #include "ppp.h"
00036 #include "pppdebug.h"
00037 
00038 #include "vj.h"
00039 
00040 #include <string.h>
00041 
00042 #if VJ_SUPPORT
00043 
00044 #if LINK_STATS
00045 #define INCR(counter) ++comp->stats.counter
00046 #else
00047 #define INCR(counter)
00048 #endif
00049 
00050 void
00051 vj_compress_init(struct vjcompress *comp)
00052 {
00053   register u_char i;
00054   register struct cstate *tstate = comp->tstate;
00055   
00056 #if MAX_SLOTS == 0
00057   memset((char *)comp, 0, sizeof(*comp));
00058 #endif
00059   comp->maxSlotIndex = MAX_SLOTS - 1;
00060   comp->compressSlot = 0;    /* Disable slot ID compression by default. */
00061   for (i = MAX_SLOTS - 1; i > 0; --i) {
00062     tstate[i].cs_id = i;
00063     tstate[i].cs_next = &tstate[i - 1];
00064   }
00065   tstate[0].cs_next = &tstate[MAX_SLOTS - 1];
00066   tstate[0].cs_id = 0;
00067   comp->last_cs = &tstate[0];
00068   comp->last_recv = 255;
00069   comp->last_xmit = 255;
00070   comp->flags = VJF_TOSS;
00071 }
00072 
00073 
00074 /* ENCODE encodes a number that is known to be non-zero.  ENCODEZ
00075  * checks for zero (since zero has to be encoded in the long, 3 byte
00076  * form).
00077  */
00078 #define ENCODE(n) { \
00079   if ((u_short)(n) >= 256) { \
00080     *cp++ = 0; \
00081     cp[1] = (u_char)(n); \
00082     cp[0] = (u_char)((n) >> 8); \
00083     cp += 2; \
00084   } else { \
00085     *cp++ = (u_char)(n); \
00086   } \
00087 }
00088 #define ENCODEZ(n) { \
00089   if ((u_short)(n) >= 256 || (u_short)(n) == 0) { \
00090     *cp++ = 0; \
00091     cp[1] = (u_char)(n); \
00092     cp[0] = (u_char)((n) >> 8); \
00093     cp += 2; \
00094   } else { \
00095     *cp++ = (u_char)(n); \
00096   } \
00097 }
00098 
00099 #define DECODEL(f) { \
00100   if (*cp == 0) {\
00101     u32_t tmp = ntohl(f) + ((cp[1] << 8) | cp[2]); \
00102     (f) = htonl(tmp); \
00103     cp += 3; \
00104   } else { \
00105     u32_t tmp = ntohl(f) + (u32_t)*cp++; \
00106     (f) = htonl(tmp); \
00107   } \
00108 }
00109 
00110 #define DECODES(f) { \
00111   if (*cp == 0) {\
00112     u_short tmp = ntohs(f) + (((u_short)cp[1] << 8) | cp[2]); \
00113     (f) = htons(tmp); \
00114     cp += 3; \
00115   } else { \
00116     u_short tmp = ntohs(f) + (u_short)*cp++; \
00117     (f) = htons(tmp); \
00118   } \
00119 }
00120 
00121 #define DECODEU(f) { \
00122   if (*cp == 0) {\
00123     (f) = htons(((u_short)cp[1] << 8) | cp[2]); \
00124     cp += 3; \
00125   } else { \
00126     (f) = htons((u_short)*cp++); \
00127   } \
00128 }
00129 
00130 /*
00131  * vj_compress_tcp - Attempt to do Van Jacobson header compression on a
00132  * packet.  This assumes that nb and comp are not null and that the first
00133  * buffer of the chain contains a valid IP header.
00134  * Return the VJ type code indicating whether or not the packet was
00135  * compressed.
00136  */
00137 u_int
00138 vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb)
00139 {
00140   register struct ip_hdr *ip = (struct ip_hdr *)pb->payload;
00141   register struct cstate *cs = comp->last_cs->cs_next;
00142   register u_short hlen = IPH_HL(ip);
00143   register struct tcp_hdr *oth;
00144   register struct tcp_hdr *th;
00145   register u_short deltaS, deltaA;
00146   register u_long deltaL;
00147   register u_int changes = 0;
00148   u_char new_seq[16];
00149   register u_char *cp = new_seq;
00150 
00151   /*  
00152    * Check that the packet is IP proto TCP.
00153    */
00154   if (IPH_PROTO(ip) != IP_PROTO_TCP) {
00155     return (TYPE_IP);
00156   }
00157 
00158   /*
00159    * Bail if this is an IP fragment or if the TCP packet isn't
00160    * `compressible' (i.e., ACK isn't set or some other control bit is
00161    * set).  
00162    */
00163   if ((IPH_OFFSET(ip) & PP_HTONS(0x3fff)) || pb->tot_len < 40) {
00164     return (TYPE_IP);
00165   }
00166   th = (struct tcp_hdr *)&((long *)ip)[hlen];
00167   if ((TCPH_FLAGS(th) & (TCP_SYN|TCP_FIN|TCP_RST|TCP_ACK)) != TCP_ACK) {
00168     return (TYPE_IP);
00169   }
00170   /*
00171    * Packet is compressible -- we're going to send either a
00172    * COMPRESSED_TCP or UNCOMPRESSED_TCP packet.  Either way we need
00173    * to locate (or create) the connection state.  Special case the
00174    * most recently used connection since it's most likely to be used
00175    * again & we don't have to do any reordering if it's used.
00176    */
00177   INCR(vjs_packets);
00178   if (!ip_addr_cmp(&ip->src, &cs->cs_ip.src)
00179       || !ip_addr_cmp(&ip->dest, &cs->cs_ip.dest)
00180       || *(long *)th != ((long *)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]) {
00181     /*
00182      * Wasn't the first -- search for it.
00183      *
00184      * States are kept in a circularly linked list with
00185      * last_cs pointing to the end of the list.  The
00186      * list is kept in lru order by moving a state to the
00187      * head of the list whenever it is referenced.  Since
00188      * the list is short and, empirically, the connection
00189      * we want is almost always near the front, we locate
00190      * states via linear search.  If we don't find a state
00191      * for the datagram, the oldest state is (re-)used.
00192      */
00193     register struct cstate *lcs;
00194     register struct cstate *lastcs = comp->last_cs;
00195     
00196     do {
00197       lcs = cs; cs = cs->cs_next;
00198       INCR(vjs_searches);
00199       if (ip_addr_cmp(&ip->src, &cs->cs_ip.src)
00200           && ip_addr_cmp(&ip->dest, &cs->cs_ip.dest)
00201           && *(long *)th == ((long *)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]) {
00202         goto found;
00203       }
00204     } while (cs != lastcs);
00205 
00206     /*
00207      * Didn't find it -- re-use oldest cstate.  Send an
00208      * uncompressed packet that tells the other side what
00209      * connection number we're using for this conversation.
00210      * Note that since the state list is circular, the oldest
00211      * state points to the newest and we only need to set
00212      * last_cs to update the lru linkage.
00213      */
00214     INCR(vjs_misses);
00215     comp->last_cs = lcs;
00216     hlen += TCPH_OFFSET(th);
00217     hlen <<= 2;
00218     /* Check that the IP/TCP headers are contained in the first buffer. */
00219     if (hlen > pb->len) {
00220       return (TYPE_IP);
00221     }
00222     goto uncompressed;
00223 
00224     found:
00225     /*
00226      * Found it -- move to the front on the connection list.
00227      */
00228     if (cs == lastcs) {
00229       comp->last_cs = lcs;
00230     } else {
00231       lcs->cs_next = cs->cs_next;
00232       cs->cs_next = lastcs->cs_next;
00233       lastcs->cs_next = cs;
00234     }
00235   }
00236 
00237   oth = (struct tcp_hdr *)&((long *)&cs->cs_ip)[hlen];
00238   deltaS = hlen;
00239   hlen += TCPH_OFFSET(th);
00240   hlen <<= 2;
00241   /* Check that the IP/TCP headers are contained in the first buffer. */
00242   if (hlen > pb->len) {
00243     PPPDEBUG(LOG_INFO, ("vj_compress_tcp: header len %d spans buffers\n", hlen));
00244     return (TYPE_IP);
00245   }
00246 
00247   /*
00248    * Make sure that only what we expect to change changed. The first
00249    * line of the `if' checks the IP protocol version, header length &
00250    * type of service.  The 2nd line checks the "Don't fragment" bit.
00251    * The 3rd line checks the time-to-live and protocol (the protocol
00252    * check is unnecessary but costless).  The 4th line checks the TCP
00253    * header length.  The 5th line checks IP options, if any.  The 6th
00254    * line checks TCP options, if any.  If any of these things are
00255    * different between the previous & current datagram, we send the
00256    * current datagram `uncompressed'.
00257    */
00258   if (((u_short *)ip)[0] != ((u_short *)&cs->cs_ip)[0] 
00259       || ((u_short *)ip)[3] != ((u_short *)&cs->cs_ip)[3] 
00260       || ((u_short *)ip)[4] != ((u_short *)&cs->cs_ip)[4] 
00261       || TCPH_OFFSET(th) != TCPH_OFFSET(oth) 
00262       || (deltaS > 5 && BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2)) 
00263       || (TCPH_OFFSET(th) > 5 && BCMP(th + 1, oth + 1, (TCPH_OFFSET(th) - 5) << 2))) {
00264     goto uncompressed;
00265   }
00266 
00267   /*
00268    * Figure out which of the changing fields changed.  The
00269    * receiver expects changes in the order: urgent, window,
00270    * ack, seq (the order minimizes the number of temporaries
00271    * needed in this section of code).
00272    */
00273   if (TCPH_FLAGS(th) & TCP_URG) {
00274     deltaS = ntohs(th->urgp);
00275     ENCODEZ(deltaS);
00276     changes |= NEW_U;
00277   } else if (th->urgp != oth->urgp) {
00278     /* argh! URG not set but urp changed -- a sensible
00279      * implementation should never do this but RFC793
00280      * doesn't prohibit the change so we have to deal
00281      * with it. */
00282     goto uncompressed;
00283   }
00284 
00285   if ((deltaS = (u_short)(ntohs(th->wnd) - ntohs(oth->wnd))) != 0) {
00286     ENCODE(deltaS);
00287     changes |= NEW_W;
00288   }
00289 
00290   if ((deltaL = ntohl(th->ackno) - ntohl(oth->ackno)) != 0) {
00291     if (deltaL > 0xffff) {
00292       goto uncompressed;
00293     }
00294     deltaA = (u_short)deltaL;
00295     ENCODE(deltaA);
00296     changes |= NEW_A;
00297   }
00298 
00299   if ((deltaL = ntohl(th->seqno) - ntohl(oth->seqno)) != 0) {
00300     if (deltaL > 0xffff) {
00301       goto uncompressed;
00302     }
00303     deltaS = (u_short)deltaL;
00304     ENCODE(deltaS);
00305     changes |= NEW_S;
00306   }
00307 
00308   switch(changes) {
00309   case 0:
00310     /*
00311      * Nothing changed. If this packet contains data and the
00312      * last one didn't, this is probably a data packet following
00313      * an ack (normal on an interactive connection) and we send
00314      * it compressed.  Otherwise it's probably a retransmit,
00315      * retransmitted ack or window probe.  Send it uncompressed
00316      * in case the other side missed the compressed version.
00317      */
00318     if (IPH_LEN(ip) != IPH_LEN(&cs->cs_ip) &&
00319       ntohs(IPH_LEN(&cs->cs_ip)) == hlen) {
00320       break;
00321     }
00322 
00323   /* (fall through) */
00324 
00325   case SPECIAL_I:
00326   case SPECIAL_D:
00327     /*
00328      * actual changes match one of our special case encodings --
00329      * send packet uncompressed.
00330      */
00331     goto uncompressed;
00332 
00333   case NEW_S|NEW_A:
00334     if (deltaS == deltaA && deltaS == ntohs(IPH_LEN(&cs->cs_ip)) - hlen) {
00335       /* special case for echoed terminal traffic */
00336       changes = SPECIAL_I;
00337       cp = new_seq;
00338     }
00339     break;
00340 
00341   case NEW_S:
00342     if (deltaS == ntohs(IPH_LEN(&cs->cs_ip)) - hlen) {
00343       /* special case for data xfer */
00344       changes = SPECIAL_D;
00345       cp = new_seq;
00346     }
00347     break;
00348   }
00349 
00350   deltaS = (u_short)(ntohs(IPH_ID(ip)) - ntohs(IPH_ID(&cs->cs_ip)));
00351   if (deltaS != 1) {
00352     ENCODEZ(deltaS);
00353     changes |= NEW_I;
00354   }
00355   if (TCPH_FLAGS(th) & TCP_PSH) {
00356     changes |= TCP_PUSH_BIT;
00357   }
00358   /*
00359    * Grab the cksum before we overwrite it below.  Then update our
00360    * state with this packet's header.
00361    */
00362   deltaA = ntohs(th->chksum);
00363   BCOPY(ip, &cs->cs_ip, hlen);
00364 
00365   /*
00366    * We want to use the original packet as our compressed packet.
00367    * (cp - new_seq) is the number of bytes we need for compressed
00368    * sequence numbers.  In addition we need one byte for the change
00369    * mask, one for the connection id and two for the tcp checksum.
00370    * So, (cp - new_seq) + 4 bytes of header are needed.  hlen is how
00371    * many bytes of the original packet to toss so subtract the two to
00372    * get the new packet size.
00373    */
00374   deltaS = (u_short)(cp - new_seq);
00375   if (!comp->compressSlot || comp->last_xmit != cs->cs_id) {
00376     comp->last_xmit = cs->cs_id;
00377     hlen -= deltaS + 4;
00378     if(pbuf_header(pb, -hlen)){
00379       /* Can we cope with this failing?  Just assert for now */
00380       LWIP_ASSERT("pbuf_header failed\n", 0);
00381     }
00382     cp = (u_char *)pb->payload;
00383     *cp++ = (u_char)(changes | NEW_C);
00384     *cp++ = cs->cs_id;
00385   } else {
00386     hlen -= deltaS + 3;
00387     if(pbuf_header(pb, -hlen)) {
00388       /* Can we cope with this failing?  Just assert for now */
00389       LWIP_ASSERT("pbuf_header failed\n", 0);
00390     }
00391     cp = (u_char *)pb->payload;
00392     *cp++ = (u_char)changes;
00393   }
00394   *cp++ = (u_char)(deltaA >> 8);
00395   *cp++ = (u_char)deltaA;
00396   BCOPY(new_seq, cp, deltaS);
00397   INCR(vjs_compressed);
00398   return (TYPE_COMPRESSED_TCP);
00399 
00400   /*
00401    * Update connection state cs & send uncompressed packet (that is,
00402    * a regular ip/tcp packet but with the 'conversation id' we hope
00403    * to use on future compressed packets in the protocol field).
00404    */
00405 uncompressed:
00406   BCOPY(ip, &cs->cs_ip, hlen);
00407   IPH_PROTO_SET(ip, cs->cs_id);
00408   comp->last_xmit = cs->cs_id;
00409   return (TYPE_UNCOMPRESSED_TCP);
00410 }
00411 
00412 /*
00413  * Called when we may have missed a packet.
00414  */
00415 void
00416 vj_uncompress_err(struct vjcompress *comp)
00417 {
00418   comp->flags |= VJF_TOSS;
00419   INCR(vjs_errorin);
00420 }
00421 
00422 /*
00423  * "Uncompress" a packet of type TYPE_UNCOMPRESSED_TCP.
00424  * Return 0 on success, -1 on failure.
00425  */
00426 int
00427 vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp)
00428 {
00429   register u_int hlen;
00430   register struct cstate *cs;
00431   register struct ip_hdr *ip;
00432   
00433   ip = (struct ip_hdr *)nb->payload;
00434   hlen = IPH_HL(ip) << 2;
00435   if (IPH_PROTO(ip) >= MAX_SLOTS
00436       || hlen + sizeof(struct tcp_hdr) > nb->len
00437       || (hlen += TCPH_OFFSET(((struct tcp_hdr *)&((char *)ip)[hlen])) << 2)
00438           > nb->len
00439       || hlen > MAX_HDR) {
00440     PPPDEBUG(LOG_INFO, ("vj_uncompress_uncomp: bad cid=%d, hlen=%d buflen=%d\n", 
00441       IPH_PROTO(ip), hlen, nb->len));
00442     comp->flags |= VJF_TOSS;
00443     INCR(vjs_errorin);
00444     return -1;
00445   }
00446   cs = &comp->rstate[comp->last_recv = IPH_PROTO(ip)];
00447   comp->flags &=~ VJF_TOSS;
00448   IPH_PROTO_SET(ip, IP_PROTO_TCP);
00449   BCOPY(ip, &cs->cs_ip, hlen);
00450   cs->cs_hlen = (u_short)hlen;
00451   INCR(vjs_uncompressedin);
00452   return 0;
00453 }
00454 
00455 /*
00456  * Uncompress a packet of type TYPE_COMPRESSED_TCP.
00457  * The packet is composed of a buffer chain and the first buffer
00458  * must contain an accurate chain length.
00459  * The first buffer must include the entire compressed TCP/IP header. 
00460  * This procedure replaces the compressed header with the uncompressed
00461  * header and returns the length of the VJ header.
00462  */
00463 int
00464 vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp)
00465 {
00466   u_char *cp;
00467   struct tcp_hdr *th;
00468   struct cstate *cs;
00469   u_short *bp;
00470   struct pbuf *n0 = *nb;
00471   u32_t tmp;
00472   u_int vjlen, hlen, changes;
00473 
00474   INCR(vjs_compressedin);
00475   cp = (u_char *)n0->payload;
00476   changes = *cp++;
00477   if (changes & NEW_C) {
00478     /* 
00479      * Make sure the state index is in range, then grab the state.
00480      * If we have a good state index, clear the 'discard' flag. 
00481      */
00482     if (*cp >= MAX_SLOTS) {
00483       PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: bad cid=%d\n", *cp));
00484       goto bad;
00485     }
00486 
00487     comp->flags &=~ VJF_TOSS;
00488     comp->last_recv = *cp++;
00489   } else {
00490     /* 
00491      * this packet has an implicit state index.  If we've
00492      * had a line error since the last time we got an
00493      * explicit state index, we have to toss the packet. 
00494      */
00495     if (comp->flags & VJF_TOSS) {
00496       PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: tossing\n"));
00497       INCR(vjs_tossed);
00498       return (-1);
00499     }
00500   }
00501   cs = &comp->rstate[comp->last_recv];
00502   hlen = IPH_HL(&cs->cs_ip) << 2;
00503   th = (struct tcp_hdr *)&((u_char *)&cs->cs_ip)[hlen];
00504   th->chksum = htons((*cp << 8) | cp[1]);
00505   cp += 2;
00506   if (changes & TCP_PUSH_BIT) {
00507     TCPH_SET_FLAG(th, TCP_PSH);
00508   } else {
00509     TCPH_UNSET_FLAG(th, TCP_PSH);
00510   }
00511 
00512   switch (changes & SPECIALS_MASK) {
00513   case SPECIAL_I:
00514     {
00515       register u32_t i = ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen;
00516       /* some compilers can't nest inline assembler.. */
00517       tmp = ntohl(th->ackno) + i;
00518       th->ackno = htonl(tmp);
00519       tmp = ntohl(th->seqno) + i;
00520       th->seqno = htonl(tmp);
00521     }
00522     break;
00523 
00524   case SPECIAL_D:
00525     /* some compilers can't nest inline assembler.. */
00526     tmp = ntohl(th->seqno) + ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen;
00527     th->seqno = htonl(tmp);
00528     break;
00529 
00530   default:
00531     if (changes & NEW_U) {
00532       TCPH_SET_FLAG(th, TCP_URG);
00533       DECODEU(th->urgp);
00534     } else {
00535       TCPH_UNSET_FLAG(th, TCP_URG);
00536     }
00537     if (changes & NEW_W) {
00538       DECODES(th->wnd);
00539     }
00540     if (changes & NEW_A) {
00541       DECODEL(th->ackno);
00542     }
00543     if (changes & NEW_S) {
00544       DECODEL(th->seqno);
00545     }
00546     break;
00547   }
00548   if (changes & NEW_I) {
00549     DECODES(cs->cs_ip._id);
00550   } else {
00551     IPH_ID_SET(&cs->cs_ip, ntohs(IPH_ID(&cs->cs_ip)) + 1);
00552     IPH_ID_SET(&cs->cs_ip, htons(IPH_ID(&cs->cs_ip)));
00553   }
00554 
00555   /*
00556    * At this point, cp points to the first byte of data in the
00557    * packet.  Fill in the IP total length and update the IP
00558    * header checksum.
00559    */
00560   vjlen = (u_short)(cp - (u_char*)n0->payload);
00561   if (n0->len < vjlen) {
00562     /* 
00563      * We must have dropped some characters (crc should detect
00564      * this but the old slip framing won't) 
00565      */
00566     PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: head buffer %d too short %d\n", 
00567           n0->len, vjlen));
00568     goto bad;
00569   }
00570 
00571 #if BYTE_ORDER == LITTLE_ENDIAN
00572   tmp = n0->tot_len - vjlen + cs->cs_hlen;
00573   IPH_LEN_SET(&cs->cs_ip, htons((u_short)tmp));
00574 #else
00575   IPH_LEN_SET(&cs->cs_ip, htons(n0->tot_len - vjlen + cs->cs_hlen));
00576 #endif
00577 
00578   /* recompute the ip header checksum */
00579   bp = (u_short *) &cs->cs_ip;
00580   IPH_CHKSUM_SET(&cs->cs_ip, 0);
00581   for (tmp = 0; hlen > 0; hlen -= 2) {
00582     tmp += *bp++;
00583   }
00584   tmp = (tmp & 0xffff) + (tmp >> 16);
00585   tmp = (tmp & 0xffff) + (tmp >> 16);
00586   IPH_CHKSUM_SET(&cs->cs_ip,  (u_short)(~tmp));
00587   
00588   /* Remove the compressed header and prepend the uncompressed header. */
00589   if(pbuf_header(n0, -((s16_t)(vjlen)))) {
00590     /* Can we cope with this failing?  Just assert for now */
00591     LWIP_ASSERT("pbuf_header failed\n", 0);
00592     goto bad;
00593   }
00594 
00595   if(LWIP_MEM_ALIGN(n0->payload) != n0->payload) {
00596     struct pbuf *np, *q;
00597     u8_t *bufptr;
00598 
00599     np = pbuf_alloc(PBUF_RAW, n0->len + cs->cs_hlen, PBUF_POOL);
00600     if(!np) {
00601       PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: realign failed\n"));
00602       goto bad;
00603     }
00604 
00605     if(pbuf_header(np, -cs->cs_hlen)) {
00606       /* Can we cope with this failing?  Just assert for now */
00607       LWIP_ASSERT("pbuf_header failed\n", 0);
00608       goto bad;
00609     }
00610 
00611     bufptr = n0->payload;
00612     for(q = np; q != NULL; q = q->next) {
00613       MEMCPY(q->payload, bufptr, q->len);
00614       bufptr += q->len;
00615     }
00616 
00617     if(n0->next) {
00618       pbuf_chain(np, n0->next);
00619       pbuf_dechain(n0);
00620     }
00621     pbuf_free(n0);
00622     n0 = np;
00623   }
00624 
00625   if(pbuf_header(n0, cs->cs_hlen)) {
00626     struct pbuf *np;
00627 
00628     LWIP_ASSERT("vj_uncompress_tcp: cs->cs_hlen <= PBUF_POOL_BUFSIZE", cs->cs_hlen <= PBUF_POOL_BUFSIZE);
00629     np = pbuf_alloc(PBUF_RAW, cs->cs_hlen, PBUF_POOL);
00630     if(!np) {
00631       PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: prepend failed\n"));
00632       goto bad;
00633     }
00634     pbuf_cat(np, n0);
00635     n0 = np;
00636   }
00637   LWIP_ASSERT("n0->len >= cs->cs_hlen", n0->len >= cs->cs_hlen);
00638   MEMCPY(n0->payload, &cs->cs_ip, cs->cs_hlen);
00639 
00640   *nb = n0;
00641 
00642   return vjlen;
00643 
00644 bad:
00645   comp->flags |= VJF_TOSS;
00646   INCR(vjs_errorin);
00647   return (-1);
00648 }
00649 
00650 #endif /* VJ_SUPPORT */
00651 
00652 #endif /* PPP_SUPPORT */

Generated on Sat May 26 2012 04:35:01 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.