Official mbed lwIP library (version 1.4.0)

Dependents:   LwIPNetworking NetServicesMin EthernetInterface EthernetInterface_RSF ... more

Legacy Networking Libraries

This is an mbed 2 networking library. For mbed OS 5, lwip has been integrated with built-in networking interfaces. The networking libraries have been revised to better support additional network stacks and thread safety here.

This library is based on the code of lwIP v1.4.0

Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
All rights reserved. 

Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
   derived from this software without specific prior written permission. 

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
OF SUCH DAMAGE.
Committer:
mbed_official
Date:
Mon Mar 14 16:15:36 2016 +0000
Revision:
20:08f08bfc3f3d
Parent:
0:51ac1d130fd4
Synchronized with git revision fec574a5ed6db26aca1b13992ff271bf527d4a0d

Full URL: https://github.com/mbedmicro/mbed/commit/fec574a5ed6db26aca1b13992ff271bf527d4a0d/

Increased allocated netbufs to handle DTLS handshakes

Who changed what in which revision?

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