Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of lwip by
vj.c
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 Tue Jul 12 2022 11:29:38 by
