The Pedigree Project  0.1
vj.c
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
132 struct vj_u32_t {
133  PACK_STRUCT_FIELD(u32_t v);
134 } PACK_STRUCT_STRUCT;
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
144 struct vj_u16_t {
145  PACK_STRUCT_FIELD(u16_t v);
146 } PACK_STRUCT_STRUCT;
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 */
u16_t tot_len
Definition: pbuf.h:175
Definition: pbuf.h:113
struct pbuf * next
Definition: pbuf.h:163
u16_t len
Definition: pbuf.h:178
u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment)
Definition: pbuf.c:684
#define PACK_STRUCT_BEGIN
Definition: arch.h:261
err_t pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from)
Definition: pbuf.c:967
void pbuf_chain(struct pbuf *h, struct pbuf *t)
Definition: pbuf.c:901
u8_t flags
Definition: pbuf.h:184
Definition: pbuf.h:161
void pbuf_cat(struct pbuf *h, struct pbuf *t)
Definition: pbuf.c:859
#define PACK_STRUCT_END
Definition: arch.h:270
struct pbuf * pbuf_dechain(struct pbuf *p)
Definition: pbuf.c:918
#define PACK_STRUCT_FIELD(x)
Definition: arch.h:292
#define PBUF_POOL_BUFSIZE
Definition: opt.h:1392
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:267
#define LWIP_MEM_ALIGN(addr)
Definition: arch.h:248
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:734
Definition: err.h:82
void * payload
Definition: pbuf.h:166