📄 vj.c
字号:
break; /* (fall through) */ case SPECIAL_I: case SPECIAL_D: /* * actual changes match one of our special case encodings -- * send packet uncompressed. */ goto uncompressed; case NEW_S|NEW_A: if (deltaS == deltaA && deltaS == ntohs(cs->cs_ip.ip_len) - hlen) { /* special case for echoed terminal traffic */ changes = SPECIAL_I; cp = new_seq; } break; case NEW_S: if (deltaS == ntohs(cs->cs_ip.ip_len) - hlen) { /* special case for data xfer */ changes = SPECIAL_D; cp = new_seq; } break; } deltaS = (u_short)(ntohs(ip->ip_id) - ntohs(cs->cs_ip.ip_id)); if (deltaS != 1) { ENCODEZ(deltaS); changes |= NEW_I; } if (th->th_flags & TCP_PSH) changes |= TCP_PUSH_BIT; /* * Grab the cksum before we overwrite it below. Then update our * state with this packet's header. */ deltaA = ntohs(th->th_sum); BCOPY(ip, &cs->cs_ip, hlen); /* * We want to use the original packet as our compressed packet. * (cp - new_seq) is the number of bytes we need for compressed * sequence numbers. In addition we need one byte for the change * mask, one for the connection id and two for the tcp checksum. * So, (cp - new_seq) + 4 bytes of header are needed. hlen is how * many bytes of the original packet to toss so subtract the two to * get the new packet size. */ deltaS = (u_short)(cp - new_seq); if (!comp->compressSlot || comp->last_xmit != cs->cs_id) { comp->last_xmit = cs->cs_id; hlen -= deltaS + 4; pbuf_header(pb, -hlen); cp = (u_char *)pb->payload; *cp++ = changes | NEW_C; *cp++ = cs->cs_id; } else { hlen -= deltaS + 3; pbuf_header(pb, -hlen); cp = (u_char *)pb->payload; *cp++ = changes; } *cp++ = deltaA >> 8; *cp++ = deltaA; BCOPY(new_seq, cp, deltaS); INCR(vjs_compressed); return (TYPE_COMPRESSED_TCP); /* * Update connection state cs & send uncompressed packet (that is, * a regular ip/tcp packet but with the 'conversation id' we hope * to use on future compressed packets in the protocol field). */uncompressed: BCOPY(ip, &cs->cs_ip, hlen); ip->ip_p = cs->cs_id; comp->last_xmit = cs->cs_id; return (TYPE_UNCOMPRESSED_TCP);}/* * Called when we may have missed a packet. */void vj_uncompress_err(struct vjcompress *comp){ comp->flags |= VJF_TOSS; INCR(vjs_errorin);}/* * "Uncompress" a packet of type TYPE_UNCOMPRESSED_TCP. * Return 0 on success, -1 on failure. */int vj_uncompress_uncomp( struct pbuf *nb, struct vjcompress *comp){ register u_int hlen; register struct cstate *cs; register struct ip *ip; ip = (struct ip *)nb->payload; hlen = getip_hl(*ip) << 2; if (ip->ip_p >= MAX_SLOTS || hlen + sizeof(struct tcphdr) > nb->len || (hlen += getth_off(*((struct tcphdr *)&((char *)ip)[hlen])) << 2) > nb->len || hlen > MAX_HDR) { PPPDEBUG((LOG_INFO, "vj_uncompress_uncomp: bad cid=%d, hlen=%d buflen=%d\n", ip->ip_p, hlen, nb->len)); comp->flags |= VJF_TOSS; INCR(vjs_errorin); return -1; } cs = &comp->rstate[comp->last_recv = ip->ip_p]; comp->flags &=~ VJF_TOSS; ip->ip_p = IPPROTO_TCP; BCOPY(ip, &cs->cs_ip, hlen); cs->cs_hlen = hlen; INCR(vjs_uncompressedin); return 0;}/* * Uncompress a packet of type TYPE_COMPRESSED_TCP. * The packet is composed of a buffer chain and the first buffer * must contain an accurate chain length. * The first buffer must include the entire compressed TCP/IP header. * This procedure replaces the compressed header with the uncompressed * header and returns the length of the VJ header. */int vj_uncompress_tcp( struct pbuf **nb, struct vjcompress *comp){ u_char *cp; struct tcphdr *th; struct cstate *cs; u_short *bp; struct pbuf *n0 = *nb; u32_t tmp; u_int vjlen, hlen, changes; INCR(vjs_compressedin); cp = (u_char *)n0->payload; changes = *cp++; if (changes & NEW_C) { /* * Make sure the state index is in range, then grab the state. * If we have a good state index, clear the 'discard' flag. */ if (*cp >= MAX_SLOTS) { PPPDEBUG((LOG_INFO, "vj_uncompress_tcp: bad cid=%d\n", *cp)); goto bad; } comp->flags &=~ VJF_TOSS; comp->last_recv = *cp++; } else { /* * this packet has an implicit state index. If we've * had a line error since the last time we got an * explicit state index, we have to toss the packet. */ if (comp->flags & VJF_TOSS) { PPPDEBUG((LOG_INFO, "vj_uncompress_tcp: tossing\n")); INCR(vjs_tossed); return (-1); } } cs = &comp->rstate[comp->last_recv]; hlen = getip_hl(cs->cs_ip) << 2; th = (struct tcphdr *)&((u_char *)&cs->cs_ip)[hlen]; th->th_sum = htons((*cp << 8) | cp[1]); cp += 2; if (changes & TCP_PUSH_BIT) th->th_flags |= TCP_PSH; else th->th_flags &=~ TCP_PSH; switch (changes & SPECIALS_MASK) { case SPECIAL_I: { register u32_t i = ntohs(cs->cs_ip.ip_len) - cs->cs_hlen; /* some compilers can't nest inline assembler.. */ tmp = ntohl(th->th_ack) + i; th->th_ack = htonl(tmp); tmp = ntohl(th->th_seq) + i; th->th_seq = htonl(tmp); } break; case SPECIAL_D: /* some compilers can't nest inline assembler.. */ tmp = ntohl(th->th_seq) + ntohs(cs->cs_ip.ip_len) - cs->cs_hlen; th->th_seq = htonl(tmp); break; default: if (changes & NEW_U) { th->th_flags |= TCP_URG; DECODEU(th->th_urp); } else th->th_flags &=~ TCP_URG; if (changes & NEW_W) DECODES(th->th_win); if (changes & NEW_A) DECODEL(th->th_ack); if (changes & NEW_S) DECODEL(th->th_seq); break; } if (changes & NEW_I) { DECODES(cs->cs_ip.ip_id); } else { cs->cs_ip.ip_id = ntohs(cs->cs_ip.ip_id) + 1; cs->cs_ip.ip_id = htons(cs->cs_ip.ip_id); } /* * At this point, cp points to the first byte of data in the * packet. Fill in the IP total length and update the IP * header checksum. */ vjlen = (u_short)(cp - (u_char*)n0->payload); if (n0->len < vjlen) { /* * We must have dropped some characters (crc should detect * this but the old slip framing won't) */ PPPDEBUG((LOG_INFO, "vj_uncompress_tcp: head buffer %d too short %d\n", n0->len, vjlen)); goto bad; } #if BYTE_ORDER == LITTLE_ENDIAN tmp = n0->tot_len - vjlen + cs->cs_hlen; cs->cs_ip.ip_len = htons(tmp);#else cs->cs_ip.ip_len = htons(n0->tot_len - vjlen + cs->cs_hlen);#endif /* recompute the ip header checksum */ bp = (u_short *) &cs->cs_ip; cs->cs_ip.ip_sum = 0; for (tmp = 0; hlen > 0; hlen -= 2) tmp += *bp++; tmp = (tmp & 0xffff) + (tmp >> 16); tmp = (tmp & 0xffff) + (tmp >> 16); cs->cs_ip.ip_sum = (u_short)(~tmp); /* Remove the compressed header and prepend the uncompressed header. */ pbuf_header(n0, -vjlen); if(MEM_ALIGN(n0->payload) != n0->payload) { struct pbuf *np, *q; u8_t *bufptr; np = pbuf_alloc(PBUF_RAW, n0->len + cs->cs_hlen, PBUF_POOL); if(!np) { PPPDEBUG((LOG_WARNING, "vj_uncompress_tcp: realign failed\n")); *nb = NULL; goto bad; } pbuf_header(np, -cs->cs_hlen); bufptr = n0->payload; for(q = np; q != NULL; q = q->next) { memcpy(q->payload, bufptr, q->len); bufptr += q->len; } if(n0->next) { pbuf_chain(np, n0->next); pbuf_dechain(n0); } pbuf_free(n0); n0 = np; } if(pbuf_header(n0, cs->cs_hlen)) { struct pbuf *np; LWIP_ASSERT("vj_uncompress_tcp: cs->cs_hlen <= PBUF_POOL_BUFSIZE", cs->cs_hlen <= PBUF_POOL_BUFSIZE); np = pbuf_alloc(PBUF_RAW, cs->cs_hlen, PBUF_POOL); if(!np) { PPPDEBUG((LOG_WARNING, "vj_uncompress_tcp: prepend failed\n")); *nb = NULL; goto bad; } pbuf_cat(np, n0); n0 = np; } LWIP_ASSERT("n0->len >= cs->cs_hlen", n0->len >= cs->cs_hlen); memcpy(n0->payload, &cs->cs_ip, cs->cs_hlen); *nb = n0; return vjlen; bad: comp->flags |= VJF_TOSS; INCR(vjs_errorin); return (-1);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -