|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /*- ! 23: * Copyright (c) 1989, 1993, 1994 ! 24: * The Regents of the University of California. All rights reserved. ! 25: * ! 26: * Redistribution and use in source and binary forms, with or without ! 27: * modification, are permitted provided that the following conditions ! 28: * are met: ! 29: * 1. Redistributions of source code must retain the above copyright ! 30: * notice, this list of conditions and the following disclaimer. ! 31: * 2. Redistributions in binary form must reproduce the above copyright ! 32: * notice, this list of conditions and the following disclaimer in the ! 33: * documentation and/or other materials provided with the distribution. ! 34: * 3. All advertising materials mentioning features or use of this software ! 35: * must display the following acknowledgement: ! 36: * This product includes software developed by the University of ! 37: * California, Berkeley and its contributors. ! 38: * 4. Neither the name of the University nor the names of its contributors ! 39: * may be used to endorse or promote products derived from this software ! 40: * without specific prior written permission. ! 41: * ! 42: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 43: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 44: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 45: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 46: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 47: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 48: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 49: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 50: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 51: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 52: * SUCH DAMAGE. ! 53: * ! 54: * @(#)slcompress.c 8.2 (Berkeley) 4/16/94 ! 55: */ ! 56: ! 57: /* ! 58: * Routines to compress and uncompess tcp packets (for transmission ! 59: * over low speed serial lines. ! 60: * ! 61: * Van Jacobson ([email protected]), Dec 31, 1989: ! 62: * - Initial distribution. ! 63: * ! 64: */ ! 65: ! 66: #include <sys/param.h> ! 67: #include <sys/mbuf.h> ! 68: #include <sys/systm.h> ! 69: ! 70: #include <netinet/in.h> ! 71: #include <netinet/in_systm.h> ! 72: #include <netinet/ip.h> ! 73: #include <netinet/tcp.h> ! 74: ! 75: #include <net/slcompress.h> ! 76: ! 77: #ifndef SL_NO_STATS ! 78: #define INCR(counter) ++comp->counter; ! 79: #else ! 80: #define INCR(counter) ! 81: #endif ! 82: ! 83: #define BCMP(p1, p2, n) bcmp((char *)(p1), (char *)(p2), (int)(n)) ! 84: #define BCOPY(p1, p2, n) bcopy((char *)(p1), (char *)(p2), (int)(n)) ! 85: #ifndef KERNEL ! 86: #define ovbcopy bcopy ! 87: #endif ! 88: ! 89: void ! 90: sl_compress_init(comp, max_state) ! 91: struct slcompress *comp; ! 92: int max_state; ! 93: { ! 94: register u_int i; ! 95: register struct cstate *tstate = comp->tstate; ! 96: ! 97: if (max_state == -1) { ! 98: max_state = MAX_STATES - 1; ! 99: bzero((char *)comp, sizeof(*comp)); ! 100: } else { ! 101: /* Don't reset statistics */ ! 102: bzero((char *)comp->tstate, sizeof(comp->tstate)); ! 103: bzero((char *)comp->rstate, sizeof(comp->rstate)); ! 104: } ! 105: for (i = max_state; i > 0; --i) { ! 106: tstate[i].cs_id = i; ! 107: tstate[i].cs_next = &tstate[i - 1]; ! 108: } ! 109: tstate[0].cs_next = &tstate[max_state]; ! 110: tstate[0].cs_id = 0; ! 111: comp->last_cs = &tstate[0]; ! 112: comp->last_recv = 255; ! 113: comp->last_xmit = 255; ! 114: comp->flags = SLF_TOSS; ! 115: } ! 116: ! 117: ! 118: /* ENCODE encodes a number that is known to be non-zero. ENCODEZ ! 119: * checks for zero (since zero has to be encoded in the long, 3 byte ! 120: * form). ! 121: */ ! 122: #define ENCODE(n) { \ ! 123: if ((u_int16_t)(n) >= 256) { \ ! 124: *cp++ = 0; \ ! 125: cp[1] = (n); \ ! 126: cp[0] = (n) >> 8; \ ! 127: cp += 2; \ ! 128: } else { \ ! 129: *cp++ = (n); \ ! 130: } \ ! 131: } ! 132: #define ENCODEZ(n) { \ ! 133: if ((u_int16_t)(n) >= 256 || (u_int16_t)(n) == 0) { \ ! 134: *cp++ = 0; \ ! 135: cp[1] = (n); \ ! 136: cp[0] = (n) >> 8; \ ! 137: cp += 2; \ ! 138: } else { \ ! 139: *cp++ = (n); \ ! 140: } \ ! 141: } ! 142: ! 143: #define DECODEL(f) { \ ! 144: if (*cp == 0) {\ ! 145: (f) = htonl(ntohl(f) + ((cp[1] << 8) | cp[2])); \ ! 146: cp += 3; \ ! 147: } else { \ ! 148: (f) = htonl(ntohl(f) + (u_int32_t)*cp++); \ ! 149: } \ ! 150: } ! 151: ! 152: #define DECODES(f) { \ ! 153: if (*cp == 0) {\ ! 154: (f) = htons(ntohs(f) + ((cp[1] << 8) | cp[2])); \ ! 155: cp += 3; \ ! 156: } else { \ ! 157: (f) = htons(ntohs(f) + (u_int32_t)*cp++); \ ! 158: } \ ! 159: } ! 160: ! 161: #define DECODEU(f) { \ ! 162: if (*cp == 0) {\ ! 163: (f) = htons((cp[1] << 8) | cp[2]); \ ! 164: cp += 3; \ ! 165: } else { \ ! 166: (f) = htons((u_int32_t)*cp++); \ ! 167: } \ ! 168: } ! 169: ! 170: u_int ! 171: sl_compress_tcp(m, ip, comp, compress_cid) ! 172: struct mbuf *m; ! 173: register struct ip *ip; ! 174: struct slcompress *comp; ! 175: int compress_cid; ! 176: { ! 177: register struct cstate *cs = comp->last_cs->cs_next; ! 178: register u_int hlen = ip->ip_hl; ! 179: register struct tcphdr *oth; ! 180: register struct tcphdr *th; ! 181: register u_int deltaS, deltaA; ! 182: register u_int changes = 0; ! 183: u_char new_seq[16]; ! 184: register u_char *cp = new_seq; ! 185: ! 186: /* ! 187: * Bail if this is an IP fragment or if the TCP packet isn't ! 188: * `compressible' (i.e., ACK isn't set or some other control bit is ! 189: * set). (We assume that the caller has already made sure the ! 190: * packet is IP proto TCP). ! 191: */ ! 192: if ((ip->ip_off & htons(0x3fff)) || m->m_len < 40) ! 193: return (TYPE_IP); ! 194: ! 195: th = (struct tcphdr *)&((int32_t *)ip)[hlen]; ! 196: if ((th->th_flags & (TH_SYN|TH_FIN|TH_RST|TH_ACK)) != TH_ACK) ! 197: return (TYPE_IP); ! 198: /* ! 199: * Packet is compressible -- we're going to send either a ! 200: * COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way we need ! 201: * to locate (or create) the connection state. Special case the ! 202: * most recently used connection since it's most likely to be used ! 203: * again & we don't have to do any reordering if it's used. ! 204: */ ! 205: INCR(sls_packets) ! 206: if (ip->ip_src.s_addr != cs->cs_ip.ip_src.s_addr || ! 207: ip->ip_dst.s_addr != cs->cs_ip.ip_dst.s_addr || ! 208: *(int32_t *)th != ((int32_t *)&cs->cs_ip)[cs->cs_ip.ip_hl]) { ! 209: /* ! 210: * Wasn't the first -- search for it. ! 211: * ! 212: * States are kept in a circularly linked list with ! 213: * last_cs pointing to the end of the list. The ! 214: * list is kept in lru order by moving a state to the ! 215: * head of the list whenever it is referenced. Since ! 216: * the list is short and, empirically, the connection ! 217: * we want is almost always near the front, we locate ! 218: * states via linear search. If we don't find a state ! 219: * for the datagram, the oldest state is (re-)used. ! 220: */ ! 221: register struct cstate *lcs; ! 222: register struct cstate *lastcs = comp->last_cs; ! 223: ! 224: do { ! 225: lcs = cs; cs = cs->cs_next; ! 226: INCR(sls_searches) ! 227: if (ip->ip_src.s_addr == cs->cs_ip.ip_src.s_addr ! 228: && ip->ip_dst.s_addr == cs->cs_ip.ip_dst.s_addr ! 229: && *(int32_t *)th == ! 230: ((int32_t *)&cs->cs_ip)[cs->cs_ip.ip_hl]) ! 231: goto found; ! 232: } while (cs != lastcs); ! 233: ! 234: /* ! 235: * Didn't find it -- re-use oldest cstate. Send an ! 236: * uncompressed packet that tells the other side what ! 237: * connection number we're using for this conversation. ! 238: * Note that since the state list is circular, the oldest ! 239: * state points to the newest and we only need to set ! 240: * last_cs to update the lru linkage. ! 241: */ ! 242: INCR(sls_misses) ! 243: comp->last_cs = lcs; ! 244: hlen += th->th_off; ! 245: hlen <<= 2; ! 246: if (hlen > m->m_len) ! 247: return TYPE_IP; ! 248: goto uncompressed; ! 249: ! 250: found: ! 251: /* ! 252: * Found it -- move to the front on the connection list. ! 253: */ ! 254: if (cs == lastcs) ! 255: comp->last_cs = lcs; ! 256: else { ! 257: lcs->cs_next = cs->cs_next; ! 258: cs->cs_next = lastcs->cs_next; ! 259: lastcs->cs_next = cs; ! 260: } ! 261: } ! 262: ! 263: /* ! 264: * Make sure that only what we expect to change changed. The first ! 265: * line of the `if' checks the IP protocol version, header length & ! 266: * type of service. The 2nd line checks the "Don't fragment" bit. ! 267: * The 3rd line checks the time-to-live and protocol (the protocol ! 268: * check is unnecessary but costless). The 4th line checks the TCP ! 269: * header length. The 5th line checks IP options, if any. The 6th ! 270: * line checks TCP options, if any. If any of these things are ! 271: * different between the previous & current datagram, we send the ! 272: * current datagram `uncompressed'. ! 273: */ ! 274: oth = (struct tcphdr *)&((int32_t *)&cs->cs_ip)[hlen]; ! 275: deltaS = hlen; ! 276: hlen += th->th_off; ! 277: hlen <<= 2; ! 278: if (hlen > m->m_len) ! 279: return TYPE_IP; ! 280: ! 281: if (((u_int16_t *)ip)[0] != ((u_int16_t *)&cs->cs_ip)[0] || ! 282: ((u_int16_t *)ip)[3] != ((u_int16_t *)&cs->cs_ip)[3] || ! 283: ((u_int16_t *)ip)[4] != ((u_int16_t *)&cs->cs_ip)[4] || ! 284: th->th_off != oth->th_off || ! 285: (deltaS > 5 && ! 286: BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2)) || ! 287: (th->th_off > 5 && ! 288: BCMP(th + 1, oth + 1, (th->th_off - 5) << 2))) ! 289: goto uncompressed; ! 290: ! 291: /* ! 292: * Figure out which of the changing fields changed. The ! 293: * receiver expects changes in the order: urgent, window, ! 294: * ack, seq (the order minimizes the number of temporaries ! 295: * needed in this section of code). ! 296: */ ! 297: if (th->th_flags & TH_URG) { ! 298: deltaS = ntohs(th->th_urp); ! 299: ENCODEZ(deltaS); ! 300: changes |= NEW_U; ! 301: } else if (th->th_urp != oth->th_urp) ! 302: /* argh! URG not set but urp changed -- a sensible ! 303: * implementation should never do this but RFC793 ! 304: * doesn't prohibit the change so we have to deal ! 305: * with it. */ ! 306: goto uncompressed; ! 307: ! 308: deltaS = (u_int16_t)(ntohs(th->th_win) - ntohs(oth->th_win)); ! 309: if (deltaS) { ! 310: ENCODE(deltaS); ! 311: changes |= NEW_W; ! 312: } ! 313: ! 314: deltaA = ntohl(th->th_ack) - ntohl(oth->th_ack); ! 315: if (deltaA) { ! 316: if (deltaA > 0xffff) ! 317: goto uncompressed; ! 318: ENCODE(deltaA); ! 319: changes |= NEW_A; ! 320: } ! 321: ! 322: deltaS = ntohl(th->th_seq) - ntohl(oth->th_seq); ! 323: if (deltaS) { ! 324: if (deltaS > 0xffff) ! 325: goto uncompressed; ! 326: ENCODE(deltaS); ! 327: changes |= NEW_S; ! 328: } ! 329: ! 330: switch(changes) { ! 331: ! 332: case 0: ! 333: /* ! 334: * Nothing changed. If this packet contains data and the ! 335: * last one didn't, this is probably a data packet following ! 336: * an ack (normal on an interactive connection) and we send ! 337: * it compressed. Otherwise it's probably a retransmit, ! 338: * retransmitted ack or window probe. Send it uncompressed ! 339: * in case the other side missed the compressed version. ! 340: */ ! 341: if (ip->ip_len != cs->cs_ip.ip_len && ! 342: ntohs(cs->cs_ip.ip_len) == hlen) ! 343: break; ! 344: ! 345: /* (fall through) */ ! 346: ! 347: case SPECIAL_I: ! 348: case SPECIAL_D: ! 349: /* ! 350: * actual changes match one of our special case encodings -- ! 351: * send packet uncompressed. ! 352: */ ! 353: goto uncompressed; ! 354: ! 355: case NEW_S|NEW_A: ! 356: if (deltaS == deltaA && ! 357: deltaS == ntohs(cs->cs_ip.ip_len) - hlen) { ! 358: /* special case for echoed terminal traffic */ ! 359: changes = SPECIAL_I; ! 360: cp = new_seq; ! 361: } ! 362: break; ! 363: ! 364: case NEW_S: ! 365: if (deltaS == ntohs(cs->cs_ip.ip_len) - hlen) { ! 366: /* special case for data xfer */ ! 367: changes = SPECIAL_D; ! 368: cp = new_seq; ! 369: } ! 370: break; ! 371: } ! 372: ! 373: deltaS = ntohs(ip->ip_id) - ntohs(cs->cs_ip.ip_id); ! 374: if (deltaS != 1) { ! 375: ENCODEZ(deltaS); ! 376: changes |= NEW_I; ! 377: } ! 378: if (th->th_flags & TH_PUSH) ! 379: changes |= TCP_PUSH_BIT; ! 380: /* ! 381: * Grab the cksum before we overwrite it below. Then update our ! 382: * state with this packet's header. ! 383: */ ! 384: deltaA = ntohs(th->th_sum); ! 385: BCOPY(ip, &cs->cs_ip, hlen); ! 386: ! 387: /* ! 388: * We want to use the original packet as our compressed packet. ! 389: * (cp - new_seq) is the number of bytes we need for compressed ! 390: * sequence numbers. In addition we need one byte for the change ! 391: * mask, one for the connection id and two for the tcp checksum. ! 392: * So, (cp - new_seq) + 4 bytes of header are needed. hlen is how ! 393: * many bytes of the original packet to toss so subtract the two to ! 394: * get the new packet size. ! 395: */ ! 396: deltaS = cp - new_seq; ! 397: cp = (u_char *)ip; ! 398: if (compress_cid == 0 || comp->last_xmit != cs->cs_id) { ! 399: comp->last_xmit = cs->cs_id; ! 400: hlen -= deltaS + 4; ! 401: cp += hlen; ! 402: *cp++ = changes | NEW_C; ! 403: *cp++ = cs->cs_id; ! 404: } else { ! 405: hlen -= deltaS + 3; ! 406: cp += hlen; ! 407: *cp++ = changes; ! 408: } ! 409: m->m_len -= hlen; ! 410: m->m_data += hlen; ! 411: *cp++ = deltaA >> 8; ! 412: *cp++ = deltaA; ! 413: BCOPY(new_seq, cp, deltaS); ! 414: INCR(sls_compressed) ! 415: return (TYPE_COMPRESSED_TCP); ! 416: ! 417: /* ! 418: * Update connection state cs & send uncompressed packet ('uncompressed' ! 419: * means a regular ip/tcp packet but with the 'conversation id' we hope ! 420: * to use on future compressed packets in the protocol field). ! 421: */ ! 422: uncompressed: ! 423: BCOPY(ip, &cs->cs_ip, hlen); ! 424: ip->ip_p = cs->cs_id; ! 425: comp->last_xmit = cs->cs_id; ! 426: return (TYPE_UNCOMPRESSED_TCP); ! 427: } ! 428: ! 429: ! 430: int ! 431: sl_uncompress_tcp(bufp, len, type, comp) ! 432: u_char **bufp; ! 433: int len; ! 434: u_int type; ! 435: struct slcompress *comp; ! 436: { ! 437: u_char *hdr, *cp; ! 438: int hlen, vjlen; ! 439: ! 440: cp = bufp? *bufp: NULL; ! 441: vjlen = sl_uncompress_tcp_core(cp, len, len, type, comp, &hdr, &hlen); ! 442: if (vjlen < 0) ! 443: return (0); /* error */ ! 444: if (vjlen == 0) ! 445: return (len); /* was uncompressed already */ ! 446: ! 447: cp += vjlen; ! 448: len -= vjlen; ! 449: ! 450: /* ! 451: * At this point, cp points to the first byte of data in the ! 452: * packet. If we're not aligned on a 4-byte boundary, copy the ! 453: * data down so the ip & tcp headers will be aligned. Then back up ! 454: * cp by the tcp/ip header length to make room for the reconstructed ! 455: * header (we assume the packet we were handed has enough space to ! 456: * prepend 128 bytes of header). ! 457: */ ! 458: if ((intptr_t)cp & 3) { ! 459: if (len > 0) ! 460: (void) ovbcopy(cp, (caddr_t)((intptr_t)cp &~ 3), len); ! 461: cp = (u_char *)((intptr_t)cp &~ 3); ! 462: } ! 463: cp -= hlen; ! 464: len += hlen; ! 465: BCOPY(hdr, cp, hlen); ! 466: ! 467: *bufp = cp; ! 468: return (len); ! 469: } ! 470: ! 471: /* ! 472: * Uncompress a packet of total length total_len. The first buflen ! 473: * bytes are at buf; this must include the entire (compressed or ! 474: * uncompressed) TCP/IP header. This procedure returns the length ! 475: * of the VJ header, with a pointer to the uncompressed IP header ! 476: * in *hdrp and its length in *hlenp. ! 477: */ ! 478: int ! 479: sl_uncompress_tcp_core(buf, buflen, total_len, type, comp, hdrp, hlenp) ! 480: u_char *buf; ! 481: int buflen, total_len; ! 482: u_int type; ! 483: struct slcompress *comp; ! 484: u_char **hdrp; ! 485: u_int *hlenp; ! 486: { ! 487: register u_char *cp; ! 488: register u_int hlen, changes; ! 489: register struct tcphdr *th; ! 490: register struct cstate *cs; ! 491: register struct ip *ip; ! 492: register u_int16_t *bp; ! 493: register u_int vjlen; ! 494: ! 495: switch (type) { ! 496: ! 497: case TYPE_UNCOMPRESSED_TCP: ! 498: ip = (struct ip *) buf; ! 499: if (ip->ip_p >= MAX_STATES) ! 500: goto bad; ! 501: cs = &comp->rstate[comp->last_recv = ip->ip_p]; ! 502: comp->flags &=~ SLF_TOSS; ! 503: ip->ip_p = IPPROTO_TCP; ! 504: /* ! 505: * Calculate the size of the TCP/IP header and make sure that ! 506: * we don't overflow the space we have available for it. ! 507: */ ! 508: hlen = ip->ip_hl << 2; ! 509: if (hlen + sizeof(struct tcphdr) > buflen) ! 510: goto bad; ! 511: hlen += ((struct tcphdr *)&((char *)ip)[hlen])->th_off << 2; ! 512: if (hlen > MAX_HDR || hlen > buflen) ! 513: goto bad; ! 514: BCOPY(ip, &cs->cs_ip, hlen); ! 515: cs->cs_hlen = hlen; ! 516: INCR(sls_uncompressedin) ! 517: *hdrp = (u_char *) &cs->cs_ip; ! 518: *hlenp = hlen; ! 519: return (0); ! 520: ! 521: default: ! 522: goto bad; ! 523: ! 524: case TYPE_COMPRESSED_TCP: ! 525: break; ! 526: } ! 527: /* We've got a compressed packet. */ ! 528: INCR(sls_compressedin) ! 529: cp = buf; ! 530: changes = *cp++; ! 531: if (changes & NEW_C) { ! 532: /* Make sure the state index is in range, then grab the state. ! 533: * If we have a good state index, clear the 'discard' flag. */ ! 534: if (*cp >= MAX_STATES) ! 535: goto bad; ! 536: ! 537: comp->flags &=~ SLF_TOSS; ! 538: comp->last_recv = *cp++; ! 539: } else { ! 540: /* this packet has an implicit state index. If we've ! 541: * had a line error since the last time we got an ! 542: * explicit state index, we have to toss the packet. */ ! 543: if (comp->flags & SLF_TOSS) { ! 544: INCR(sls_tossed) ! 545: return (-1); ! 546: } ! 547: } ! 548: cs = &comp->rstate[comp->last_recv]; ! 549: hlen = cs->cs_ip.ip_hl << 2; ! 550: th = (struct tcphdr *)&((u_char *)&cs->cs_ip)[hlen]; ! 551: th->th_sum = htons((*cp << 8) | cp[1]); ! 552: cp += 2; ! 553: if (changes & TCP_PUSH_BIT) ! 554: th->th_flags |= TH_PUSH; ! 555: else ! 556: th->th_flags &=~ TH_PUSH; ! 557: ! 558: switch (changes & SPECIALS_MASK) { ! 559: case SPECIAL_I: ! 560: { ! 561: register u_int i = ntohs(cs->cs_ip.ip_len) - cs->cs_hlen; ! 562: th->th_ack = htonl(ntohl(th->th_ack) + i); ! 563: th->th_seq = htonl(ntohl(th->th_seq) + i); ! 564: } ! 565: break; ! 566: ! 567: case SPECIAL_D: ! 568: th->th_seq = htonl(ntohl(th->th_seq) + ntohs(cs->cs_ip.ip_len) ! 569: - cs->cs_hlen); ! 570: break; ! 571: ! 572: default: ! 573: if (changes & NEW_U) { ! 574: th->th_flags |= TH_URG; ! 575: DECODEU(th->th_urp) ! 576: } else ! 577: th->th_flags &=~ TH_URG; ! 578: if (changes & NEW_W) ! 579: DECODES(th->th_win) ! 580: if (changes & NEW_A) ! 581: DECODEL(th->th_ack) ! 582: if (changes & NEW_S) ! 583: DECODEL(th->th_seq) ! 584: break; ! 585: } ! 586: if (changes & NEW_I) { ! 587: DECODES(cs->cs_ip.ip_id) ! 588: } else ! 589: cs->cs_ip.ip_id = htons(ntohs(cs->cs_ip.ip_id) + 1); ! 590: ! 591: /* ! 592: * At this point, cp points to the first byte of data in the ! 593: * packet. Fill in the IP total length and update the IP ! 594: * header checksum. ! 595: */ ! 596: vjlen = cp - buf; ! 597: buflen -= vjlen; ! 598: if (buflen < 0) ! 599: /* we must have dropped some characters (crc should detect ! 600: * this but the old slip framing won't) */ ! 601: goto bad; ! 602: ! 603: total_len += cs->cs_hlen - vjlen; ! 604: cs->cs_ip.ip_len = htons(total_len); ! 605: ! 606: /* recompute the ip header checksum */ ! 607: bp = (u_int16_t *) &cs->cs_ip; ! 608: cs->cs_ip.ip_sum = 0; ! 609: for (changes = 0; hlen > 0; hlen -= 2) ! 610: changes += *bp++; ! 611: changes = (changes & 0xffff) + (changes >> 16); ! 612: changes = (changes & 0xffff) + (changes >> 16); ! 613: cs->cs_ip.ip_sum = ~ changes; ! 614: ! 615: *hdrp = (u_char *) &cs->cs_ip; ! 616: *hlenp = cs->cs_hlen; ! 617: return vjlen; ! 618: ! 619: bad: ! 620: comp->flags |= SLF_TOSS; ! 621: INCR(sls_errorin) ! 622: return (-1); ! 623: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.