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