📄 vjhc.c
字号:
} deltaA = ntohl(th->ack_num) - ntohl(oth->ack_num); if (deltaA) { if (deltaA > 0xFFFF) goto uncompressed; ENCODE(deltaA); changes |= NEW_A; } deltaS = ntohl(th->seq_num) - ntohl(oth->seq_num); if (deltaS) { if (deltaS > 0xFFFF) goto uncompressed; ENCODE(deltaS); changes |= NEW_S; } /*-------------------------------------------------------------------*/ /* Look for the special-case encodings. */ /*-------------------------------------------------------------------*/ switch (changes) { case 0: /*---------------------------------------------------------------*/ /* Nothing changed. If this packet contains data and the last */ /* one didn't, this is probably a data packet following an ack */ /* (normal on an interactive connection) and we send it */ /* compressed. Otherwise it's probably a retransmit, */ /* retransmitted ack or window probe. Send it uncompressed in */ /* case the other side missed the compressed version. */ /*---------------------------------------------------------------*/ if (ip->length != cs->cs_ip.length && ntohs(cs->cs_ip.length) == hlen) break; /*lint -fallthrough */ 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.length) - hlen) { /*-------------------------------------------------------------*/ /* Special case for echoed terminal traffic. */ /*-------------------------------------------------------------*/ changes = SPECIAL_I; cp = new_seq; } break; case NEW_S: if (deltaS == ntohs(cs->cs_ip.length) - hlen) { /*-------------------------------------------------------------*/ /* Special case for data transfer. */ /*-------------------------------------------------------------*/ changes = SPECIAL_D; cp = new_seq; } break; } deltaS = ntohs(ip->ip_id) - ntohs(cs->cs_ip.ip_id); if (deltaS != 1) { ENCODEZ(deltaS); changes |= NEW_I; } if (th->flags & TCPF_PSH) changes |= TCP_PUSH_BIT; /*-------------------------------------------------------------------*/ /* Grab the checksum before we overwrite it below. Then update our */ /* state with this packet's header. */ /*-------------------------------------------------------------------*/ deltaA = ntohs(th->cksum); memcpy(&cs->cs_ip, 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 = cp - new_seq; cp = (ui8 *) ip; if (comp_cid == 0 || comp->last_xmit != cs->cs_id) { comp->last_xmit = cs->cs_id; hlen -= deltaS + 4; cp += hlen; *cp++ = changes | NEW_C; *cp++ = cs->cs_id; } else { hlen -= deltaS + 3; cp += hlen; *cp++ = changes; } buf->length -= hlen; buf->ip_pkt += hlen; *cp++ = deltaA >> 8; *cp++ = deltaA; memcpy(cp, new_seq, deltaS); return PPP_COMP_PROTO; /*-------------------------------------------------------------------*/ /* Update connection state cs and send uncompressed packet (This is */ /* a regular IP/TCP packet with the 'conversation id' we hope to use */ /* on future compressed packets in the protocol field). */ /*-------------------------------------------------------------------*/uncompressed: memcpy(&cs->cs_ip, ip, hlen); ip->protocol = cs->cs_id; comp->last_xmit = cs->cs_id; return PPP_UNCOMP_PROTO;}/***********************************************************************//* vjhc_uncompress: Called if packet protocol is PPP_COMP_PROTO *//* *//* Inputs: comp = points to line's compression state structure *//* buf = points to compressed packet *//* *//* Returns: 0 if no errors, else -1 to drop packet *//* *//* The new packet is constructed in-place. There must be 128 bytes of *//* free space in front of bufp to allow room for the reconstructed IP *//* and TCP headers. The reconstructed packet is aligned on a 32-bit *//* boundary. The compression state is updated. *//* *//***********************************************************************/int vjhc_uncompress(struct vjcompress *comp, NetBuf *buf){ ui8 *cp; uint hlen, changes; Tcp *th; struct cstate *cs; /*-------------------------------------------------------------------*/ /* We've got a compressed packet. */ /*-------------------------------------------------------------------*/ cp = buf->ip_pkt; 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 > comp->rslot_limit) goto bad; comp->flags &= ~VJHCF_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 & VJHCF_TOSS) return -1; } /*-------------------------------------------------------------------*/ /* Find the state then fill in the TCP checksum and PUSH bit. */ /*-------------------------------------------------------------------*/ cs = &comp->rstate[comp->last_recv]; hlen = (cs->cs_ip.ver_len & 0xF) << 2; th = (Tcp *) &((ui8 *)&cs->cs_ip)[hlen]; th->cksum = htons((cp[0] << 8) | cp[1]); cp += 2; if (changes & TCP_PUSH_BIT) th->flags |= TCPF_PSH; else th->flags &= ~TCPF_PSH; /*-------------------------------------------------------------------*/ /* Fix up the state's ack, seq, urg and win fields based on the */ /* change mask. */ /*-------------------------------------------------------------------*/ switch (changes & SPECIALS_MASK) { case SPECIAL_I: { uint i = ntohs(cs->cs_ip.length) - cs->cs_hlen; th->ack_num = htonl(ntohl(th->ack_num) + i); th->seq_num = htonl(ntohl(th->seq_num) + i); break; } case SPECIAL_D: th->seq_num = htonl(ntohl(th->seq_num) + ntohs(cs->cs_ip.length) - cs->cs_hlen); break; default: if (changes & NEW_U) { th->flags |= TCPF_URG; DECODEU(th->urg_ptr) } else th->flags &= ~TCPF_URG; if (changes & NEW_W) DECODES(th->window) if (changes & NEW_A) DECODEL(th->ack_num) if (changes & NEW_S) DECODEL(th->seq_num) break; } /*-------------------------------------------------------------------*/ /* Update the IP ID. */ /*-------------------------------------------------------------------*/ if (changes & NEW_I) DECODES(cs->cs_ip.ip_id) else cs->cs_ip.ip_id = htons(ntohs(cs->cs_ip.ip_id) + 1); /*-------------------------------------------------------------------*/ /* cp now points to first byte of packet data. Subtract compressed */ /* header length to get just segment data length. */ /*-------------------------------------------------------------------*/ if (buf->length < (cp - buf->ip_pkt)) { /*-----------------------------------------------------------------*/ /* We must have dropped some characters (CRC should detect this */ /* but SLIP framing won't). */ /*-----------------------------------------------------------------*/ goto bad; } buf->length -= (cp - buf->ip_pkt); /*-------------------------------------------------------------------*/ /* Promote to 1st order buffer, recording start and length of data. */ /*-------------------------------------------------------------------*/ buf->app_data = cp; buf->order = 1; buf->app_len = buf->length; /*-------------------------------------------------------------------*/ /* Advance "cp" past segment data and round up to 4-byte boundary. */ /*-------------------------------------------------------------------*/ cp += buf->length; cp = (ui8 *)(((ui32)cp + 3) & ~3); /*-------------------------------------------------------------------*/ /* Correct buffer and IP lengths and IP header pointer. */ /*-------------------------------------------------------------------*/ buf->length += cs->cs_hlen; cs->cs_ip.length = htons(buf->length); buf->ip_pkt = cp; /*-------------------------------------------------------------------*/ /* Copy saved and corrected IP/TCP headers to buffer (after data). */ /*-------------------------------------------------------------------*/ memcpy(cp, &cs->cs_ip, cs->cs_hlen); /*-------------------------------------------------------------------*/ /* Recompute the IP header checksum. */ /*-------------------------------------------------------------------*/ { ui16 *bp = (ui16 *)cp; for (changes = 0; hlen > 0; hlen -= 2) changes += *bp++; changes = (changes & 0xFFFF) + (changes >> 16); changes = (changes & 0xFFFF) + (changes >> 16); ((Ip *) cp)->checksum = ~changes; } return 0;bad: comp->flags |= VJHCF_TOSS; return -1;}/***********************************************************************//* vjhc_remember: Called if packet protocol equals PPP_UNCOMP_PROTO, *//* regular TCP packet with connection ID in place of *//* protocol field. Updates saved context. *//* *//* Returns: 0 if no errors, else -1 to drop packet *//* *//***********************************************************************/int vjhc_remember(struct vjcompress *comp, const NetBuf *buf){ struct cstate *cs; Ip *ip = (Ip *)buf->ip_pkt; uint hlen = ip->ver_len & 0xF; /*-------------------------------------------------------------------*/ /* Locate saved state. If index is legal, clear 'discard' flag. */ /*-------------------------------------------------------------------*/ if (ip->protocol > comp->rslot_limit) goto bad; cs = &comp->rstate[comp->last_recv = ip->protocol]; comp->flags &= ~VJHCF_TOSS; /*-------------------------------------------------------------------*/ /* Restore IP protocol field, then save a copy of packet header. The */ /* checksum is zeroed in the copy so we don't have to zero it each */ /* time we process a compressed packet. */ /*-------------------------------------------------------------------*/ ip->protocol = IPT_TCP; hlen += ((Tcp *) &((int *)ip)[hlen])->offset >> 4; hlen <<= 2; memcpy(&cs->cs_ip, ip, hlen); cs->cs_ip.checksum = 0; cs->cs_hlen = hlen; return 0;bad: comp->flags |= VJHCF_TOSS; return -1;}/***********************************************************************//* vjhc_toss: Called to record need to resynch compression ID *//* *//***********************************************************************/void vjhc_toss(struct vjcompress *comp){ comp->flags |= VJHCF_TOSS;}#endif /* MAX_PPP_INTF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -