Library for Bert van Dam's book "ARM MICROCONTROLLERS" For all chapters with internet.

Dependencies:   mbed

Committer:
ICTFBI
Date:
Fri Oct 16 14:28:26 2015 +0000
Revision:
0:4edb816d21e1
Pre-update 16-10-15

Who changed what in which revision?

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