1 /* 2 * Routines to compress and uncompess 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 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19 * 20 * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: 21 * Initial distribution. 22 * 23 * Modified June 1993 by Paul Mackerras, paulus@cs.anu.edu.au, 24 * so that the entire packet being decompressed doesn't have 25 * to be in contiguous memory (just the compressed header). 26 * 27 * Modified March 1998 by Guy Lancaster, glanca@gesn.com, 28 * for a 16 bit processor. 29 */ 30 31 #include "netif/ppp/ppp_opts.h" 32 #if PPP_SUPPORT && VJ_SUPPORT /* don't build if not configured for use in lwipopts.h */ 33 34 #include "netif/ppp/ppp_impl.h" 35 #include "netif/ppp/pppdebug.h" 36 37 #include "netif/ppp/vj.h" 38 39 #include <string.h> 40 41 #if LINK_STATS 42 #define INCR(counter) ++comp->stats.counter 43 #else 44 #define INCR(counter) 45 #endif 46 47 void 48 vj_compress_init(struct vjcompress *comp) 49 { 50 u8_t i; 51 struct cstate *tstate = comp->tstate; 52 53 #if MAX_SLOTS == 0 54 memset((char *)comp, 0, sizeof(*comp)); 55 #endif 56 comp->maxSlotIndex = MAX_SLOTS - 1; 57 comp->compressSlot = 0; /* Disable slot ID compression by default. */ 58 for (i = MAX_SLOTS - 1; i > 0; --i) { 59 tstate[i].cs_id = i; 60 tstate[i].cs_next = &tstate[i - 1]; 61 } 62 tstate[0].cs_next = &tstate[MAX_SLOTS - 1]; 63 tstate[0].cs_id = 0; 64 comp->last_cs = &tstate[0]; 65 comp->last_recv = 255; 66 comp->last_xmit = 255; 67 comp->flags = VJF_TOSS; 68 } 69 70 71 /* ENCODE encodes a number that is known to be non-zero. ENCODEZ 72 * checks for zero (since zero has to be encoded in the long, 3 byte 73 * form). 74 */ 75 #define ENCODE(n) { \ 76 if ((u16_t)(n) >= 256) { \ 77 *cp++ = 0; \ 78 cp[1] = (u8_t)(n); \ 79 cp[0] = (u8_t)((n) >> 8); \ 80 cp += 2; \ 81 } else { \ 82 *cp++ = (u8_t)(n); \ 83 } \ 84 } 85 #define ENCODEZ(n) { \ 86 if ((u16_t)(n) >= 256 || (u16_t)(n) == 0) { \ 87 *cp++ = 0; \ 88 cp[1] = (u8_t)(n); \ 89 cp[0] = (u8_t)((n) >> 8); \ 90 cp += 2; \ 91 } else { \ 92 *cp++ = (u8_t)(n); \ 93 } \ 94 } 95 96 #define DECODEL(f) { \ 97 if (*cp == 0) {\ 98 u32_t tmp_ = lwip_ntohl(f) + ((cp[1] << 8) | cp[2]); \ 99 (f) = lwip_htonl(tmp_); \ 100 cp += 3; \ 101 } else { \ 102 u32_t tmp_ = lwip_ntohl(f) + (u32_t)*cp++; \ 103 (f) = lwip_htonl(tmp_); \ 104 } \ 105 } 106 107 #define DECODES(f) { \ 108 if (*cp == 0) {\ 109 u16_t tmp_ = lwip_ntohs(f) + (((u16_t)cp[1] << 8) | cp[2]); \ 110 (f) = lwip_htons(tmp_); \ 111 cp += 3; \ 112 } else { \ 113 u16_t tmp_ = lwip_ntohs(f) + (u16_t)*cp++; \ 114 (f) = lwip_htons(tmp_); \ 115 } \ 116 } 117 118 #define DECODEU(f) { \ 119 if (*cp == 0) {\ 120 (f) = lwip_htons(((u16_t)cp[1] << 8) | cp[2]); \ 121 cp += 3; \ 122 } else { \ 123 (f) = lwip_htons((u16_t)*cp++); \ 124 } \ 125 } 126 127 /* Helper structures for unaligned *u32_t and *u16_t accesses */ 128 #ifdef PACK_STRUCT_USE_INCLUDES 129 # include "arch/bpstruct.h" 130 #endif 131 PACK_STRUCT_BEGIN 132 struct vj_u32_t { 133 PACK_STRUCT_FIELD(u32_t v); 134 } PACK_STRUCT_STRUCT; 135 PACK_STRUCT_END 136 #ifdef PACK_STRUCT_USE_INCLUDES 137 # include "arch/epstruct.h" 138 #endif 139 140 #ifdef PACK_STRUCT_USE_INCLUDES 141 # include "arch/bpstruct.h" 142 #endif 143 PACK_STRUCT_BEGIN 144 struct vj_u16_t { 145 PACK_STRUCT_FIELD(u16_t v); 146 } PACK_STRUCT_STRUCT; 147 PACK_STRUCT_END 148 #ifdef PACK_STRUCT_USE_INCLUDES 149 # include "arch/epstruct.h" 150 #endif 151 152 /* 153 * vj_compress_tcp - Attempt to do Van Jacobson header compression on a 154 * packet. This assumes that nb and comp are not null and that the first 155 * buffer of the chain contains a valid IP header. 156 * Return the VJ type code indicating whether or not the packet was 157 * compressed. 158 */ 159 u8_t 160 vj_compress_tcp(struct vjcompress *comp, struct pbuf **pb) 161 { 162 struct pbuf *np = *pb; 163 struct ip_hdr *ip = (struct ip_hdr *)np->payload; 164 struct cstate *cs = comp->last_cs->cs_next; 165 u16_t ilen = IPH_HL(ip); 166 u16_t hlen; 167 struct tcp_hdr *oth; 168 struct tcp_hdr *th; 169 u16_t deltaS, deltaA = 0; 170 u32_t deltaL; 171 u32_t changes = 0; 172 u8_t new_seq[16]; 173 u8_t *cp = new_seq; 174 175 /* 176 * Check that the packet is IP proto TCP. 177 */ 178 if (IPH_PROTO(ip) != IP_PROTO_TCP) { 179 return (TYPE_IP); 180 } 181 182 /* 183 * Bail if this is an IP fragment or if the TCP packet isn't 184 * `compressible' (i.e., ACK isn't set or some other control bit is 185 * set). 186 */ 187 if ((IPH_OFFSET(ip) & PP_HTONS(0x3fff)) || np->tot_len < 40) { 188 return (TYPE_IP); 189 } 190 th = (struct tcp_hdr *)&((struct vj_u32_t*)ip)[ilen]; 191 if ((TCPH_FLAGS(th) & (TCP_SYN|TCP_FIN|TCP_RST|TCP_ACK)) != TCP_ACK) { 192 return (TYPE_IP); 193 } 194 195 /* Check that the TCP/IP headers are contained in the first buffer. */ 196 hlen = ilen + TCPH_HDRLEN(th); 197 hlen <<= 2; 198 if (np->len < hlen) { 199 PPPDEBUG(LOG_INFO, ("vj_compress_tcp: header len %d spans buffers\n", hlen)); 200 return (TYPE_IP); 201 } 202 203 /* TCP stack requires that we don't change the packet payload, therefore we copy 204 * the whole packet before compression. */ 205 np = pbuf_alloc(PBUF_RAW, np->tot_len, PBUF_POOL); 206 if (!np) { 207 return (TYPE_IP); 208 } 209 210 if (pbuf_copy(np, *pb) != ERR_OK) { 211 pbuf_free(np); 212 return (TYPE_IP); 213 } 214 215 *pb = np; 216 ip = (struct ip_hdr *)np->payload; 217 218 /* 219 * Packet is compressible -- we're going to send either a 220 * COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way we need 221 * to locate (or create) the connection state. Special case the 222 * most recently used connection since it's most likely to be used 223 * again & we don't have to do any reordering if it's used. 224 */ 225 INCR(vjs_packets); 226 if (!ip4_addr_cmp(&ip->src, &cs->cs_ip.src) 227 || !ip4_addr_cmp(&ip->dest, &cs->cs_ip.dest) 228 || (*(struct vj_u32_t*)th).v != (((struct vj_u32_t*)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]).v) { 229 /* 230 * Wasn't the first -- search for it. 231 * 232 * States are kept in a circularly linked list with 233 * last_cs pointing to the end of the list. The 234 * list is kept in lru order by moving a state to the 235 * head of the list whenever it is referenced. Since 236 * the list is short and, empirically, the connection 237 * we want is almost always near the front, we locate 238 * states via linear search. If we don't find a state 239 * for the datagram, the oldest state is (re-)used. 240 */ 241 struct cstate *lcs; 242 struct cstate *lastcs = comp->last_cs; 243 244 do { 245 lcs = cs; cs = cs->cs_next; 246 INCR(vjs_searches); 247 if (ip4_addr_cmp(&ip->src, &cs->cs_ip.src) 248 && ip4_addr_cmp(&ip->dest, &cs->cs_ip.dest) 249 && (*(struct vj_u32_t*)th).v == (((struct vj_u32_t*)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]).v) { 250 goto found; 251 } 252 } while (cs != lastcs); 253 254 /* 255 * Didn't find it -- re-use oldest cstate. Send an 256 * uncompressed packet that tells the other side what 257 * connection number we're using for this conversation. 258 * Note that since the state list is circular, the oldest 259 * state points to the newest and we only need to set 260 * last_cs to update the lru linkage. 261 */ 262 INCR(vjs_misses); 263 comp->last_cs = lcs; 264 goto uncompressed; 265 266 found: 267 /* 268 * Found it -- move to the front on the connection list. 269 */ 270 if (cs == lastcs) { 271 comp->last_cs = lcs; 272 } else { 273 lcs->cs_next = cs->cs_next; 274 cs->cs_next = lastcs->cs_next; 275 lastcs->cs_next = cs; 276 } 277 } 278 279 oth = (struct tcp_hdr *)&((struct vj_u32_t*)&cs->cs_ip)[ilen]; 280 deltaS = ilen; 281 282 /* 283 * Make sure that only what we expect to change changed. The first 284 * line of the `if' checks the IP protocol version, header length & 285 * type of service. The 2nd line checks the "Don't fragment" bit. 286 * The 3rd line checks the time-to-live and protocol (the protocol 287 * check is unnecessary but costless). The 4th line checks the TCP 288 * header length. The 5th line checks IP options, if any. The 6th 289 * line checks TCP options, if any. If any of these things are 290 * different between the previous & current datagram, we send the 291 * current datagram `uncompressed'. 292 */ 293 if ((((struct vj_u16_t*)ip)[0]).v != (((struct vj_u16_t*)&cs->cs_ip)[0]).v 294 || (((struct vj_u16_t*)ip)[3]).v != (((struct vj_u16_t*)&cs->cs_ip)[3]).v 295 || (((struct vj_u16_t*)ip)[4]).v != (((struct vj_u16_t*)&cs->cs_ip)[4]).v 296 || TCPH_HDRLEN(th) != TCPH_HDRLEN(oth) 297 || (deltaS > 5 && BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2)) 298 || (TCPH_HDRLEN(th) > 5 && BCMP(th + 1, oth + 1, (TCPH_HDRLEN(th) - 5) << 2))) { 299 goto uncompressed; 300 } 301 302 /* 303 * Figure out which of the changing fields changed. The 304 * receiver expects changes in the order: urgent, window, 305 * ack, seq (the order minimizes the number of temporaries 306 * needed in this section of code). 307 */ 308 if (TCPH_FLAGS(th) & TCP_URG) { 309 deltaS = lwip_ntohs(th->urgp); 310 ENCODEZ(deltaS); 311 changes |= NEW_U; 312 } else if (th->urgp != oth->urgp) { 313 /* argh! URG not set but urp changed -- a sensible 314 * implementation should never do this but RFC793 315 * doesn't prohibit the change so we have to deal 316 * with it. */ 317 goto uncompressed; 318 } 319 320 if ((deltaS = (u16_t)(lwip_ntohs(th->wnd) - lwip_ntohs(oth->wnd))) != 0) { 321 ENCODE(deltaS); 322 changes |= NEW_W; 323 } 324 325 if ((deltaL = lwip_ntohl(th->ackno) - lwip_ntohl(oth->ackno)) != 0) { 326 if (deltaL > 0xffff) { 327 goto uncompressed; 328 } 329 deltaA = (u16_t)deltaL; 330 ENCODE(deltaA); 331 changes |= NEW_A; 332 } 333 334 if ((deltaL = lwip_ntohl(th->seqno) - lwip_ntohl(oth->seqno)) != 0) { 335 if (deltaL > 0xffff) { 336 goto uncompressed; 337 } 338 deltaS = (u16_t)deltaL; 339 ENCODE(deltaS); 340 changes |= NEW_S; 341 } 342 343 switch(changes) { 344 case 0: 345 /* 346 * Nothing changed. If this packet contains data and the 347 * last one didn't, this is probably a data packet following 348 * an ack (normal on an interactive connection) and we send 349 * it compressed. Otherwise it's probably a retransmit, 350 * retransmitted ack or window probe. Send it uncompressed 351 * in case the other side missed the compressed version. 352 */ 353 if (IPH_LEN(ip) != IPH_LEN(&cs->cs_ip) && 354 lwip_ntohs(IPH_LEN(&cs->cs_ip)) == hlen) { 355 break; 356 } 357 /* no break */ 358 /* fall through */ 359 360 case SPECIAL_I: 361 case SPECIAL_D: 362 /* 363 * actual changes match one of our special case encodings -- 364 * send packet uncompressed. 365 */ 366 goto uncompressed; 367 368 case NEW_S|NEW_A: 369 if (deltaS == deltaA && deltaS == lwip_ntohs(IPH_LEN(&cs->cs_ip)) - hlen) { 370 /* special case for echoed terminal traffic */ 371 changes = SPECIAL_I; 372 cp = new_seq; 373 } 374 break; 375 376 case NEW_S: 377 if (deltaS == lwip_ntohs(IPH_LEN(&cs->cs_ip)) - hlen) { 378 /* special case for data xfer */ 379 changes = SPECIAL_D; 380 cp = new_seq; 381 } 382 break; 383 default: 384 break; 385 } 386 387 deltaS = (u16_t)(lwip_ntohs(IPH_ID(ip)) - lwip_ntohs(IPH_ID(&cs->cs_ip))); 388 if (deltaS != 1) { 389 ENCODEZ(deltaS); 390 changes |= NEW_I; 391 } 392 if (TCPH_FLAGS(th) & TCP_PSH) { 393 changes |= TCP_PUSH_BIT; 394 } 395 /* 396 * Grab the cksum before we overwrite it below. Then update our 397 * state with this packet's header. 398 */ 399 deltaA = lwip_ntohs(th->chksum); 400 MEMCPY(&cs->cs_ip, ip, hlen); 401 402 /* 403 * We want to use the original packet as our compressed packet. 404 * (cp - new_seq) is the number of bytes we need for compressed 405 * sequence numbers. In addition we need one byte for the change 406 * mask, one for the connection id and two for the tcp checksum. 407 * So, (cp - new_seq) + 4 bytes of header are needed. hlen is how 408 * many bytes of the original packet to toss so subtract the two to 409 * get the new packet size. 410 */ 411 deltaS = (u16_t)(cp - new_seq); 412 if (!comp->compressSlot || comp->last_xmit != cs->cs_id) { 413 comp->last_xmit = cs->cs_id; 414 hlen -= deltaS + 4; 415 if (pbuf_header(np, -(s16_t)hlen)){ 416 /* Can we cope with this failing? Just assert for now */ 417 LWIP_ASSERT("pbuf_header failed\n", 0); 418 } 419 cp = (u8_t*)np->payload; 420 *cp++ = (u8_t)(changes | NEW_C); 421 *cp++ = cs->cs_id; 422 } else { 423 hlen -= deltaS + 3; 424 if (pbuf_header(np, -(s16_t)hlen)) { 425 /* Can we cope with this failing? Just assert for now */ 426 LWIP_ASSERT("pbuf_header failed\n", 0); 427 } 428 cp = (u8_t*)np->payload; 429 *cp++ = (u8_t)changes; 430 } 431 *cp++ = (u8_t)(deltaA >> 8); 432 *cp++ = (u8_t)deltaA; 433 MEMCPY(cp, new_seq, deltaS); 434 INCR(vjs_compressed); 435 return (TYPE_COMPRESSED_TCP); 436 437 /* 438 * Update connection state cs & send uncompressed packet (that is, 439 * a regular ip/tcp packet but with the 'conversation id' we hope 440 * to use on future compressed packets in the protocol field). 441 */ 442 uncompressed: 443 MEMCPY(&cs->cs_ip, ip, hlen); 444 IPH_PROTO_SET(ip, cs->cs_id); 445 comp->last_xmit = cs->cs_id; 446 return (TYPE_UNCOMPRESSED_TCP); 447 } 448 449 /* 450 * Called when we may have missed a packet. 451 */ 452 void 453 vj_uncompress_err(struct vjcompress *comp) 454 { 455 comp->flags |= VJF_TOSS; 456 INCR(vjs_errorin); 457 } 458 459 /* 460 * "Uncompress" a packet of type TYPE_UNCOMPRESSED_TCP. 461 * Return 0 on success, -1 on failure. 462 */ 463 int 464 vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp) 465 { 466 u32_t hlen; 467 struct cstate *cs; 468 struct ip_hdr *ip; 469 470 ip = (struct ip_hdr *)nb->payload; 471 hlen = IPH_HL(ip) << 2; 472 if (IPH_PROTO(ip) >= MAX_SLOTS 473 || hlen + sizeof(struct tcp_hdr) > nb->len 474 || (hlen += TCPH_HDRLEN(((struct tcp_hdr *)&((char *)ip)[hlen])) << 2) 475 > nb->len 476 || hlen > MAX_HDR) { 477 PPPDEBUG(LOG_INFO, ("vj_uncompress_uncomp: bad cid=%d, hlen=%d buflen=%d\n", 478 IPH_PROTO(ip), hlen, nb->len)); 479 comp->flags |= VJF_TOSS; 480 INCR(vjs_errorin); 481 return -1; 482 } 483 cs = &comp->rstate[comp->last_recv = IPH_PROTO(ip)]; 484 comp->flags &=~ VJF_TOSS; 485 IPH_PROTO_SET(ip, IP_PROTO_TCP); 486 MEMCPY(&cs->cs_ip, ip, hlen); 487 cs->cs_hlen = (u16_t)hlen; 488 INCR(vjs_uncompressedin); 489 return 0; 490 } 491 492 /* 493 * Uncompress a packet of type TYPE_COMPRESSED_TCP. 494 * The packet is composed of a buffer chain and the first buffer 495 * must contain an accurate chain length. 496 * The first buffer must include the entire compressed TCP/IP header. 497 * This procedure replaces the compressed header with the uncompressed 498 * header and returns the length of the VJ header. 499 */ 500 int 501 vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp) 502 { 503 u8_t *cp; 504 struct tcp_hdr *th; 505 struct cstate *cs; 506 struct vj_u16_t *bp; 507 struct pbuf *n0 = *nb; 508 u32_t tmp; 509 u32_t vjlen, hlen, changes; 510 511 INCR(vjs_compressedin); 512 cp = (u8_t*)n0->payload; 513 changes = *cp++; 514 if (changes & NEW_C) { 515 /* 516 * Make sure the state index is in range, then grab the state. 517 * If we have a good state index, clear the 'discard' flag. 518 */ 519 if (*cp >= MAX_SLOTS) { 520 PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: bad cid=%d\n", *cp)); 521 goto bad; 522 } 523 524 comp->flags &=~ VJF_TOSS; 525 comp->last_recv = *cp++; 526 } else { 527 /* 528 * this packet has an implicit state index. If we've 529 * had a line error since the last time we got an 530 * explicit state index, we have to toss the packet. 531 */ 532 if (comp->flags & VJF_TOSS) { 533 PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: tossing\n")); 534 INCR(vjs_tossed); 535 return (-1); 536 } 537 } 538 cs = &comp->rstate[comp->last_recv]; 539 hlen = IPH_HL(&cs->cs_ip) << 2; 540 th = (struct tcp_hdr *)&((u8_t*)&cs->cs_ip)[hlen]; 541 th->chksum = lwip_htons((*cp << 8) | cp[1]); 542 cp += 2; 543 if (changes & TCP_PUSH_BIT) { 544 TCPH_SET_FLAG(th, TCP_PSH); 545 } else { 546 TCPH_UNSET_FLAG(th, TCP_PSH); 547 } 548 549 switch (changes & SPECIALS_MASK) { 550 case SPECIAL_I: 551 { 552 u32_t i = lwip_ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen; 553 /* some compilers can't nest inline assembler.. */ 554 tmp = lwip_ntohl(th->ackno) + i; 555 th->ackno = lwip_htonl(tmp); 556 tmp = lwip_ntohl(th->seqno) + i; 557 th->seqno = lwip_htonl(tmp); 558 } 559 break; 560 561 case SPECIAL_D: 562 /* some compilers can't nest inline assembler.. */ 563 tmp = lwip_ntohl(th->seqno) + lwip_ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen; 564 th->seqno = lwip_htonl(tmp); 565 break; 566 567 default: 568 if (changes & NEW_U) { 569 TCPH_SET_FLAG(th, TCP_URG); 570 DECODEU(th->urgp); 571 } else { 572 TCPH_UNSET_FLAG(th, TCP_URG); 573 } 574 if (changes & NEW_W) { 575 DECODES(th->wnd); 576 } 577 if (changes & NEW_A) { 578 DECODEL(th->ackno); 579 } 580 if (changes & NEW_S) { 581 DECODEL(th->seqno); 582 } 583 break; 584 } 585 if (changes & NEW_I) { 586 DECODES(cs->cs_ip._id); 587 } else { 588 IPH_ID_SET(&cs->cs_ip, lwip_ntohs(IPH_ID(&cs->cs_ip)) + 1); 589 IPH_ID_SET(&cs->cs_ip, lwip_htons(IPH_ID(&cs->cs_ip))); 590 } 591 592 /* 593 * At this point, cp points to the first byte of data in the 594 * packet. Fill in the IP total length and update the IP 595 * header checksum. 596 */ 597 vjlen = (u16_t)(cp - (u8_t*)n0->payload); 598 if (n0->len < vjlen) { 599 /* 600 * We must have dropped some characters (crc should detect 601 * this but the old slip framing won't) 602 */ 603 PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: head buffer %d too short %d\n", 604 n0->len, vjlen)); 605 goto bad; 606 } 607 608 #if BYTE_ORDER == LITTLE_ENDIAN 609 tmp = n0->tot_len - vjlen + cs->cs_hlen; 610 IPH_LEN_SET(&cs->cs_ip, lwip_htons((u16_t)tmp)); 611 #else 612 IPH_LEN_SET(&cs->cs_ip, lwip_htons(n0->tot_len - vjlen + cs->cs_hlen)); 613 #endif 614 615 /* recompute the ip header checksum */ 616 bp = (struct vj_u16_t*) &cs->cs_ip; 617 IPH_CHKSUM_SET(&cs->cs_ip, 0); 618 for (tmp = 0; hlen > 0; hlen -= 2) { 619 tmp += (*bp++).v; 620 } 621 tmp = (tmp & 0xffff) + (tmp >> 16); 622 tmp = (tmp & 0xffff) + (tmp >> 16); 623 IPH_CHKSUM_SET(&cs->cs_ip, (u16_t)(~tmp)); 624 625 /* Remove the compressed header and prepend the uncompressed header. */ 626 if (pbuf_header(n0, -(s16_t)vjlen)) { 627 /* Can we cope with this failing? Just assert for now */ 628 LWIP_ASSERT("pbuf_header failed\n", 0); 629 goto bad; 630 } 631 632 if(LWIP_MEM_ALIGN(n0->payload) != n0->payload) { 633 struct pbuf *np, *q; 634 u8_t *bufptr; 635 636 #if IP_FORWARD 637 /* If IP forwarding is enabled we are using a PBUF_LINK packet type so 638 * the packet is being allocated with enough header space to be 639 * forwarded (to Ethernet for example). 640 */ 641 np = pbuf_alloc(PBUF_LINK, n0->len + cs->cs_hlen, PBUF_POOL); 642 #else /* IP_FORWARD */ 643 np = pbuf_alloc(PBUF_RAW, n0->len + cs->cs_hlen, PBUF_POOL); 644 #endif /* IP_FORWARD */ 645 if(!np) { 646 PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: realign failed\n")); 647 goto bad; 648 } 649 650 if (pbuf_header(np, -(s16_t)cs->cs_hlen)) { 651 /* Can we cope with this failing? Just assert for now */ 652 LWIP_ASSERT("pbuf_header failed\n", 0); 653 goto bad; 654 } 655 656 bufptr = (u8_t*)n0->payload; 657 for(q = np; q != NULL; q = q->next) { 658 MEMCPY(q->payload, bufptr, q->len); 659 bufptr += q->len; 660 } 661 662 if(n0->next) { 663 pbuf_chain(np, n0->next); 664 pbuf_dechain(n0); 665 } 666 pbuf_free(n0); 667 n0 = np; 668 } 669 670 if (pbuf_header(n0, (s16_t)cs->cs_hlen)) { 671 struct pbuf *np; 672 673 LWIP_ASSERT("vj_uncompress_tcp: cs->cs_hlen <= PBUF_POOL_BUFSIZE", cs->cs_hlen <= PBUF_POOL_BUFSIZE); 674 np = pbuf_alloc(PBUF_RAW, cs->cs_hlen, PBUF_POOL); 675 if(!np) { 676 PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: prepend failed\n")); 677 goto bad; 678 } 679 pbuf_cat(np, n0); 680 n0 = np; 681 } 682 LWIP_ASSERT("n0->len >= cs->cs_hlen", n0->len >= cs->cs_hlen); 683 MEMCPY(n0->payload, &cs->cs_ip, cs->cs_hlen); 684 685 *nb = n0; 686 687 return vjlen; 688 689 bad: 690 comp->flags |= VJF_TOSS; 691 INCR(vjs_errorin); 692 return (-1); 693 } 694 695 #endif /* PPP_SUPPORT && VJ_SUPPORT */ 696