ReactOS 0.4.16-dev-819-g75c0dc0
vj.c
Go to the documentation of this file.
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 MERCHANTABILITY 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
47void
48vj_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
132struct vj_u32_t {
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
144struct vj_u16_t {
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 */
159u8_t
160vj_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_clone(PBUF_RAW, PBUF_RAM, *pb);
206 if (!np) {
207 return (TYPE_IP);
208 }
209
210 *pb = np;
211 ip = (struct ip_hdr *)np->payload;
212
213 /*
214 * Packet is compressible -- we're going to send either a
215 * COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way we need
216 * to locate (or create) the connection state. Special case the
217 * most recently used connection since it's most likely to be used
218 * again & we don't have to do any reordering if it's used.
219 */
220 INCR(vjs_packets);
221 if (!ip4_addr_eq(&ip->src, &cs->cs_ip.src)
222 || !ip4_addr_eq(&ip->dest, &cs->cs_ip.dest)
223 || (*(struct vj_u32_t*)th).v != (((struct vj_u32_t*)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]).v) {
224 /*
225 * Wasn't the first -- search for it.
226 *
227 * States are kept in a circularly linked list with
228 * last_cs pointing to the end of the list. The
229 * list is kept in lru order by moving a state to the
230 * head of the list whenever it is referenced. Since
231 * the list is short and, empirically, the connection
232 * we want is almost always near the front, we locate
233 * states via linear search. If we don't find a state
234 * for the datagram, the oldest state is (re-)used.
235 */
236 struct cstate *lcs;
237 struct cstate *lastcs = comp->last_cs;
238
239 do {
240 lcs = cs; cs = cs->cs_next;
241 INCR(vjs_searches);
242 if (ip4_addr_eq(&ip->src, &cs->cs_ip.src)
243 && ip4_addr_eq(&ip->dest, &cs->cs_ip.dest)
244 && (*(struct vj_u32_t*)th).v == (((struct vj_u32_t*)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]).v) {
245 goto found;
246 }
247 } while (cs != lastcs);
248
249 /*
250 * Didn't find it -- re-use oldest cstate. Send an
251 * uncompressed packet that tells the other side what
252 * connection number we're using for this conversation.
253 * Note that since the state list is circular, the oldest
254 * state points to the newest and we only need to set
255 * last_cs to update the lru linkage.
256 */
257 INCR(vjs_misses);
258 comp->last_cs = lcs;
259 goto uncompressed;
260
261 found:
262 /*
263 * Found it -- move to the front on the connection list.
264 */
265 if (cs == lastcs) {
266 comp->last_cs = lcs;
267 } else {
268 lcs->cs_next = cs->cs_next;
269 cs->cs_next = lastcs->cs_next;
270 lastcs->cs_next = cs;
271 }
272 }
273
274 oth = (struct tcp_hdr *)&((struct vj_u32_t*)&cs->cs_ip)[ilen];
275 deltaS = ilen;
276
277 /*
278 * Make sure that only what we expect to change changed. The first
279 * line of the `if' checks the IP protocol version, header length &
280 * type of service. The 2nd line checks the "Don't fragment" bit.
281 * The 3rd line checks the time-to-live and protocol (the protocol
282 * check is unnecessary but costless). The 4th line checks the TCP
283 * header length. The 5th line checks IP options, if any. The 6th
284 * line checks TCP options, if any. If any of these things are
285 * different between the previous & current datagram, we send the
286 * current datagram `uncompressed'.
287 */
288 if ((((struct vj_u16_t*)ip)[0]).v != (((struct vj_u16_t*)&cs->cs_ip)[0]).v
289 || (((struct vj_u16_t*)ip)[3]).v != (((struct vj_u16_t*)&cs->cs_ip)[3]).v
290 || (((struct vj_u16_t*)ip)[4]).v != (((struct vj_u16_t*)&cs->cs_ip)[4]).v
291 || TCPH_HDRLEN(th) != TCPH_HDRLEN(oth)
292 || (deltaS > 5 && BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2))
293 || (TCPH_HDRLEN(th) > 5 && BCMP(th + 1, oth + 1, (TCPH_HDRLEN(th) - 5) << 2))) {
294 goto uncompressed;
295 }
296
297 /*
298 * Figure out which of the changing fields changed. The
299 * receiver expects changes in the order: urgent, window,
300 * ack, seq (the order minimizes the number of temporaries
301 * needed in this section of code).
302 */
303 if (TCPH_FLAGS(th) & TCP_URG) {
304 deltaS = lwip_ntohs(th->urgp);
305 ENCODEZ(deltaS);
306 changes |= NEW_U;
307 } else if (th->urgp != oth->urgp) {
308 /* argh! URG not set but urp changed -- a sensible
309 * implementation should never do this but RFC793
310 * doesn't prohibit the change so we have to deal
311 * with it. */
312 goto uncompressed;
313 }
314
315 if ((deltaS = (u16_t)(lwip_ntohs(th->wnd) - lwip_ntohs(oth->wnd))) != 0) {
316 ENCODE(deltaS);
317 changes |= NEW_W;
318 }
319
320 if ((deltaL = lwip_ntohl(th->ackno) - lwip_ntohl(oth->ackno)) != 0) {
321 if (deltaL > 0xffff) {
322 goto uncompressed;
323 }
324 deltaA = (u16_t)deltaL;
325 ENCODE(deltaA);
326 changes |= NEW_A;
327 }
328
329 if ((deltaL = lwip_ntohl(th->seqno) - lwip_ntohl(oth->seqno)) != 0) {
330 if (deltaL > 0xffff) {
331 goto uncompressed;
332 }
333 deltaS = (u16_t)deltaL;
334 ENCODE(deltaS);
335 changes |= NEW_S;
336 }
337
338 switch(changes) {
339 case 0:
340 /*
341 * Nothing changed. If this packet contains data and the
342 * last one didn't, this is probably a data packet following
343 * an ack (normal on an interactive connection) and we send
344 * it compressed. Otherwise it's probably a retransmit,
345 * retransmitted ack or window probe. Send it uncompressed
346 * in case the other side missed the compressed version.
347 */
348 if (IPH_LEN(ip) != IPH_LEN(&cs->cs_ip) &&
349 lwip_ntohs(IPH_LEN(&cs->cs_ip)) == hlen) {
350 break;
351 }
352 /* no break */
353 /* fall through */
354
355 case SPECIAL_I:
356 case SPECIAL_D:
357 /*
358 * actual changes match one of our special case encodings --
359 * send packet uncompressed.
360 */
361 goto uncompressed;
362
363 case NEW_S|NEW_A:
364 if (deltaS == deltaA && deltaS == lwip_ntohs(IPH_LEN(&cs->cs_ip)) - hlen) {
365 /* special case for echoed terminal traffic */
366 changes = SPECIAL_I;
367 cp = new_seq;
368 }
369 break;
370
371 case NEW_S:
372 if (deltaS == lwip_ntohs(IPH_LEN(&cs->cs_ip)) - hlen) {
373 /* special case for data xfer */
374 changes = SPECIAL_D;
375 cp = new_seq;
376 }
377 break;
378 default:
379 break;
380 }
381
382 deltaS = (u16_t)(lwip_ntohs(IPH_ID(ip)) - lwip_ntohs(IPH_ID(&cs->cs_ip)));
383 if (deltaS != 1) {
384 ENCODEZ(deltaS);
385 changes |= NEW_I;
386 }
387 if (TCPH_FLAGS(th) & TCP_PSH) {
388 changes |= TCP_PUSH_BIT;
389 }
390 /*
391 * Grab the cksum before we overwrite it below. Then update our
392 * state with this packet's header.
393 */
394 deltaA = lwip_ntohs(th->chksum);
395 MEMCPY(&cs->cs_ip, ip, hlen);
396
397 /*
398 * We want to use the original packet as our compressed packet.
399 * (cp - new_seq) is the number of bytes we need for compressed
400 * sequence numbers. In addition we need one byte for the change
401 * mask, one for the connection id and two for the tcp checksum.
402 * So, (cp - new_seq) + 4 bytes of header are needed. hlen is how
403 * many bytes of the original packet to toss so subtract the two to
404 * get the new packet size.
405 */
406 deltaS = (u16_t)(cp - new_seq);
407 if (!comp->compressSlot || comp->last_xmit != cs->cs_id) {
408 comp->last_xmit = cs->cs_id;
409 hlen -= deltaS + 4;
410 if (pbuf_remove_header(np, hlen)){
411 /* Can we cope with this failing? Just assert for now */
412 LWIP_ASSERT("pbuf_remove_header failed", 0);
413 }
414 cp = (u8_t*)np->payload;
415 *cp++ = (u8_t)(changes | NEW_C);
416 *cp++ = cs->cs_id;
417 } else {
418 hlen -= deltaS + 3;
419 if (pbuf_remove_header(np, hlen)) {
420 /* Can we cope with this failing? Just assert for now */
421 LWIP_ASSERT("pbuf_remove_header failed", 0);
422 }
423 cp = (u8_t*)np->payload;
424 *cp++ = (u8_t)changes;
425 }
426 *cp++ = (u8_t)(deltaA >> 8);
427 *cp++ = (u8_t)deltaA;
428 MEMCPY(cp, new_seq, deltaS);
429 INCR(vjs_compressed);
430 return (TYPE_COMPRESSED_TCP);
431
432 /*
433 * Update connection state cs & send uncompressed packet (that is,
434 * a regular ip/tcp packet but with the 'conversation id' we hope
435 * to use on future compressed packets in the protocol field).
436 */
438 MEMCPY(&cs->cs_ip, ip, hlen);
439 IPH_PROTO_SET(ip, cs->cs_id);
440 comp->last_xmit = cs->cs_id;
441 return (TYPE_UNCOMPRESSED_TCP);
442}
443
444/*
445 * Called when we may have missed a packet.
446 */
447void
448vj_uncompress_err(struct vjcompress *comp)
449{
450 comp->flags |= VJF_TOSS;
451 INCR(vjs_errorin);
452}
453
454/*
455 * "Uncompress" a packet of type TYPE_UNCOMPRESSED_TCP.
456 * Return 0 on success, -1 on failure.
457 */
458int
459vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp)
460{
461 u32_t hlen;
462 struct cstate *cs;
463 struct ip_hdr *ip;
464
465 ip = (struct ip_hdr *)nb->payload;
466 hlen = IPH_HL(ip) << 2;
467 if (IPH_PROTO(ip) >= MAX_SLOTS
468 || hlen + sizeof(struct tcp_hdr) > nb->len
469 || (hlen += TCPH_HDRLEN_BYTES((struct tcp_hdr *)&((char *)ip)[hlen]))
470 > nb->len
471 || hlen > MAX_HDR) {
472 PPPDEBUG(LOG_INFO, ("vj_uncompress_uncomp: bad cid=%d, hlen=%d buflen=%d\n",
473 IPH_PROTO(ip), hlen, nb->len));
474 vj_uncompress_err(comp);
475 return -1;
476 }
477 cs = &comp->rstate[comp->last_recv = IPH_PROTO(ip)];
478 comp->flags &=~ VJF_TOSS;
480 /* copy from/to bigger buffers checked above instead of cs->cs_ip and ip
481 just to help static code analysis to see this is correct ;-) */
482 MEMCPY(&cs->cs_hdr, nb->payload, hlen);
483 cs->cs_hlen = (u16_t)hlen;
484 INCR(vjs_uncompressedin);
485 return 0;
486}
487
488/*
489 * Uncompress a packet of type TYPE_COMPRESSED_TCP.
490 * The packet is composed of a buffer chain and the first buffer
491 * must contain an accurate chain length.
492 * The first buffer must include the entire compressed TCP/IP header.
493 * This procedure replaces the compressed header with the uncompressed
494 * header and returns the length of the VJ header.
495 */
496int
497vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp)
498{
499 u8_t *cp;
500 struct tcp_hdr *th;
501 struct cstate *cs;
502 struct vj_u16_t *bp;
503 struct pbuf *n0 = *nb;
504 u32_t tmp;
505 u32_t vjlen, hlen, changes;
506
507 INCR(vjs_compressedin);
508 cp = (u8_t*)n0->payload;
509 changes = *cp++;
510 if (changes & NEW_C) {
511 /*
512 * Make sure the state index is in range, then grab the state.
513 * If we have a good state index, clear the 'discard' flag.
514 */
515 if (*cp >= MAX_SLOTS) {
516 PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: bad cid=%d\n", *cp));
517 goto bad;
518 }
519
520 comp->flags &=~ VJF_TOSS;
521 comp->last_recv = *cp++;
522 } else {
523 /*
524 * this packet has an implicit state index. If we've
525 * had a line error since the last time we got an
526 * explicit state index, we have to toss the packet.
527 */
528 if (comp->flags & VJF_TOSS) {
529 PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: tossing\n"));
530 INCR(vjs_tossed);
531 return (-1);
532 }
533 }
534 cs = &comp->rstate[comp->last_recv];
535 hlen = IPH_HL(&cs->cs_ip) << 2;
536 th = (struct tcp_hdr *)&((u8_t*)&cs->cs_ip)[hlen];
537 th->chksum = lwip_htons((*cp << 8) | cp[1]);
538 cp += 2;
539 if (changes & TCP_PUSH_BIT) {
541 } else {
543 }
544
545 switch (changes & SPECIALS_MASK) {
546 case SPECIAL_I:
547 {
548 u32_t i = lwip_ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen;
549 /* some compilers can't nest inline assembler.. */
550 tmp = lwip_ntohl(th->ackno) + i;
551 th->ackno = lwip_htonl(tmp);
552 tmp = lwip_ntohl(th->seqno) + i;
553 th->seqno = lwip_htonl(tmp);
554 }
555 break;
556
557 case SPECIAL_D:
558 /* some compilers can't nest inline assembler.. */
559 tmp = lwip_ntohl(th->seqno) + lwip_ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen;
560 th->seqno = lwip_htonl(tmp);
561 break;
562
563 default:
564 if (changes & NEW_U) {
566 DECODEU(th->urgp);
567 } else {
569 }
570 if (changes & NEW_W) {
571 DECODES(th->wnd);
572 }
573 if (changes & NEW_A) {
574 DECODEL(th->ackno);
575 }
576 if (changes & NEW_S) {
577 DECODEL(th->seqno);
578 }
579 break;
580 }
581 if (changes & NEW_I) {
582 DECODES(cs->cs_ip._id);
583 } else {
584 IPH_ID_SET(&cs->cs_ip, lwip_ntohs(IPH_ID(&cs->cs_ip)) + 1);
585 IPH_ID_SET(&cs->cs_ip, lwip_htons(IPH_ID(&cs->cs_ip)));
586 }
587
588 /*
589 * At this point, cp points to the first byte of data in the
590 * packet. Fill in the IP total length and update the IP
591 * header checksum.
592 */
593 vjlen = (u16_t)(cp - (u8_t*)n0->payload);
594 if (n0->len < vjlen) {
595 /*
596 * We must have dropped some characters (crc should detect
597 * this but the old slip framing won't)
598 */
599 PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: head buffer %d too short %d\n",
600 n0->len, vjlen));
601 goto bad;
602 }
603
604#if BYTE_ORDER == LITTLE_ENDIAN
605 tmp = n0->tot_len - vjlen + cs->cs_hlen;
606 IPH_LEN_SET(&cs->cs_ip, lwip_htons((u16_t)tmp));
607#else
608 IPH_LEN_SET(&cs->cs_ip, lwip_htons(n0->tot_len - vjlen + cs->cs_hlen));
609#endif
610
611 /* recompute the ip header checksum */
612 bp = (struct vj_u16_t*) &cs->cs_ip;
613 IPH_CHKSUM_SET(&cs->cs_ip, 0);
614 for (tmp = 0; hlen > 0; hlen -= 2) {
615 tmp += (*bp++).v;
616 }
617 tmp = (tmp & 0xffff) + (tmp >> 16);
618 tmp = (tmp & 0xffff) + (tmp >> 16);
619 IPH_CHKSUM_SET(&cs->cs_ip, (u16_t)(~tmp));
620
621 /* Remove the compressed header and prepend the uncompressed header. */
622 if (pbuf_remove_header(n0, vjlen)) {
623 /* Can we cope with this failing? Just assert for now */
624 LWIP_ASSERT("pbuf_remove_header failed", 0);
625 goto bad;
626 }
627
628 if(LWIP_MEM_ALIGN(n0->payload) != n0->payload) {
629 struct pbuf *np;
630
631#if IP_FORWARD
632 /* If IP forwarding is enabled we are using a PBUF_LINK packet type so
633 * the packet is being allocated with enough header space to be
634 * forwarded (to Ethernet for example).
635 */
636 np = pbuf_alloc(PBUF_LINK, n0->len + cs->cs_hlen, PBUF_POOL);
637#else /* IP_FORWARD */
638 np = pbuf_alloc(PBUF_RAW, n0->len + cs->cs_hlen, PBUF_POOL);
639#endif /* IP_FORWARD */
640 if(!np) {
641 PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: realign failed\n"));
642 goto bad;
643 }
644
645 if (pbuf_remove_header(np, cs->cs_hlen)) {
646 /* Can we cope with this failing? Just assert for now */
647 LWIP_ASSERT("pbuf_remove_header failed", 0);
648 goto bad;
649 }
650
651 pbuf_take(np, n0->payload, n0->len);
652
653 if(n0->next) {
654 pbuf_chain(np, n0->next);
655 pbuf_dechain(n0);
656 }
657 pbuf_free(n0);
658 n0 = np;
659 }
660
661 if (pbuf_add_header(n0, cs->cs_hlen)) {
662 struct pbuf *np;
663
664 LWIP_ASSERT("vj_uncompress_tcp: cs->cs_hlen <= PBUF_POOL_BUFSIZE", cs->cs_hlen <= PBUF_POOL_BUFSIZE);
665 np = pbuf_alloc(PBUF_RAW, cs->cs_hlen, PBUF_POOL);
666 if(!np) {
667 PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: prepend failed\n"));
668 goto bad;
669 }
670 pbuf_cat(np, n0);
671 n0 = np;
672 }
673 LWIP_ASSERT("n0->len >= cs->cs_hlen", n0->len >= cs->cs_hlen);
674 MEMCPY(n0->payload, &cs->cs_ip, cs->cs_hlen);
675
676 *nb = n0;
677
678 return vjlen;
679
680bad:
681 vj_uncompress_err(comp);
682 return (-1);
683}
684
685#endif /* PPP_SUPPORT && VJ_SUPPORT */
#define PP_HTONS(x)
Definition: def.h:90
#define lwip_htons(x)
Definition: def.h:86
#define lwip_ntohl(x)
Definition: def.h:89
#define lwip_htonl(x)
Definition: def.h:88
#define lwip_ntohs(x)
Definition: def.h:87
#define PACK_STRUCT_STRUCT
Definition: cc.h:42
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:116
#define IP_PROTO_TCP
Definition: ip.h:50
const GLdouble * v
Definition: gl.h:2040
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define PACK_STRUCT_END
Definition: arch.h:316
uint32_t u32_t
Definition: arch.h:129
uint8_t u8_t
Definition: arch.h:125
#define PACK_STRUCT_BEGIN
Definition: arch.h:307
uint16_t u16_t
Definition: arch.h:127
#define LWIP_MEM_ALIGN(addr)
Definition: arch.h:294
#define PACK_STRUCT_FIELD(x)
Definition: arch.h:338
#define PBUF_POOL_BUFSIZE
Definition: opt.h:1599
void pbuf_cat(struct pbuf *h, struct pbuf *t)
Definition: pbuf.c:855
void pbuf_chain(struct pbuf *h, struct pbuf *t)
Definition: pbuf.c:897
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:224
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:727
struct pbuf * pbuf_clone(pbuf_layer layer, pbuf_type type, struct pbuf *p)
Definition: pbuf.c:1337
err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len)
Definition: pbuf.c:1227
@ PBUF_RAM
Definition: pbuf.h:152
@ PBUF_POOL
Definition: pbuf.h:167
@ PBUF_RAW
Definition: pbuf.h:111
@ PBUF_LINK
Definition: pbuf.h:102
#define cs
Definition: i386-dis.c:442
if(dx< 0)
Definition: linetemp.h:194
#define TCP_PSH
Definition: tcp.h:75
#define TCPH_HDRLEN_BYTES(phdr)
Definition: tcp.h:86
#define TCPH_SET_FLAG(phdr, flags)
Definition: tcp.h:93
#define TCP_ACK
Definition: tcp.h:76
#define TCPH_HDRLEN(phdr)
Definition: tcp.h:85
#define TCP_RST
Definition: tcp.h:74
#define TCP_SYN
Definition: tcp.h:73
#define TCP_FIN
Definition: tcp.h:72
#define TCP_URG
Definition: tcp.h:77
#define TCPH_FLAGS(phdr)
Definition: tcp.h:87
#define TCPH_UNSET_FLAG(phdr, flags)
Definition: tcp.h:94
#define MEMCPY(DST, SRC, BYTES)
Definition: macros.h:231
POINT cp
Definition: magnifier.c:59
static const BYTE uncompressed[]
Definition: misc.c:392
u8_t pbuf_add_header(struct pbuf *p, size_t header_size_increment)
Definition: pbuf.c:554
u8_t pbuf_remove_header(struct pbuf *p, size_t header_size_decrement)
Definition: pbuf.c:585
struct pbuf * pbuf_dechain(struct pbuf *p)
Definition: pbuf.c:914
#define IPH_LEN_SET(hdr, len)
Definition: ip4.h:119
#define IPH_ID_SET(hdr, id)
Definition: ip4.h:120
#define IPH_PROTO_SET(hdr, proto)
Definition: ip4.h:123
#define IPH_OFFSET(hdr)
Definition: ip4.h:110
#define IPH_HL(hdr)
Definition: ip4.h:105
#define IPH_PROTO(hdr)
Definition: ip4.h:113
#define IPH_ID(hdr)
Definition: ip4.h:109
#define IPH_LEN(hdr)
Definition: ip4.h:108
#define IPH_CHKSUM_SET(hdr, chksum)
Definition: ip4.h:124
static CHANGE * changes
Definition: io.c:49
#define memset(x, y, z)
Definition: compat.h:39
Definition: ip4.h:73
Definition: dhcpd.h:62
Definition: pbuf.h:186
u16_t tot_len
Definition: pbuf.h:200
struct pbuf * next
Definition: pbuf.h:188
u16_t len
Definition: pbuf.h:203
void * payload
Definition: pbuf.h:191
Definition: tcp.h:56
#define LOG_WARNING
Definition: syslog.h:49
#define LOG_INFO
Definition: syslog.h:51