?? slhc.c
字號:
if((deltaA = ntohl(th->ack_seq) - ntohl(oth->ack_seq)) != 0L){ if(deltaA > 0x0000ffff) goto uncompressed; cp = encode(cp,deltaA); changes |= NEW_A; } if((deltaS = ntohl(th->seq) - ntohl(oth->seq)) != 0L){ if(deltaS > 0x0000ffff) goto uncompressed; cp = encode(cp,deltaS); changes |= NEW_S; } switch(changes){ * 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->tot_len != cs->cs_ip.tot_len && ntohs(cs->cs_ip.tot_len) == hlen) break; DPRINT(("comp: retrans\n")); goto uncompressed; break; case SPECIAL_I: case SPECIAL_D: /* actual changes match one of our special case encodings -- * send packet uncompressed. */ DPRINT(("comp: special\n")); goto uncompressed; case NEW_S|NEW_A: if(deltaS == deltaA && deltaS == ntohs(cs->cs_ip.tot_len) - hlen){ /* special case for echoed terminal traffic */ changes = SPECIAL_I; cp = new_seq; } break; case NEW_S: if(deltaS == ntohs(cs->cs_ip.tot_len) - hlen){ /* special case for data xfer */ changes = SPECIAL_D; cp = new_seq; } break; } deltaS = ntohs(ip->id) - ntohs(cs->cs_ip.id); if(deltaS != 1){ cp = encode(cp,deltaS); changes |= NEW_I; } if(th->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->check); memcpy(&cs->cs_ip,ip,20); memcpy(&cs->cs_tcp,th,20); /* 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. */ deltaS = cp - new_seq; if(compress_cid == 0 || comp->xmit_current != cs->cs_this){ cp = ocp; *cpp = ocp; *cp++ = changes | NEW_C; *cp++ = cs->cs_this; comp->xmit_current = cs->cs_this; } else { cp = ocp; *cpp = ocp; *cp++ = changes; } cp = put16(cp,(short)deltaA); /* Write TCP checksum *//* deltaS is now the size of the change section of the compressed header */ DPRINT(("comp: %x %x %x %d %d\n", icp, cp, new_seq, hlen, deltaS)); memcpy(cp,new_seq,deltaS); /* Write list of deltas */ memcpy(cp+deltaS,icp+hlen,isize-hlen); comp->sls_o_compressed++; ocp[0] |= SL_TYPE_COMPRESSED_TCP; return isize - hlen + deltaS + (cp - ocp); /* Update connection state cs & send uncompressed packet (i.e., * a regular ip/tcp packet but with the 'conversation id' we hope * to use on future compressed packets in the protocol field). */uncompressed: memcpy(&cs->cs_ip,ip,20); memcpy(&cs->cs_tcp,th,20); if (ip->ihl > 5) memcpy(cs->cs_ipopt, ip+1, ((ip->ihl) - 5) * 4); if (th->doff > 5) memcpy(cs->cs_tcpopt, th+1, ((th->doff) - 5) * 4); comp->xmit_current = cs->cs_this; comp->sls_o_uncompressed++; memcpy(ocp, icp, isize); *cpp = ocp; ocp[9] = cs->cs_this; ocp[0] |= SL_TYPE_UNCOMPRESSED_TCP; return isize;}intslhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize){ register int changes; long x; register struct tcphdr *thp; register struct iphdr *ip; register struct cstate *cs; int len, hdrlen; unsigned char *cp = icp; /* We've got a compressed packet; read the change byte */ comp->sls_i_compressed++; if(isize < 3){ comp->sls_i_error++; DPRINT(("uncomp: runt\n")); return 0; } 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. */ x = *cp++; /* Read conn index */ if(x < 0 || x > comp->rslot_limit) goto bad; comp->flags &=~ SLF_TOSS; comp->recv_current = x; } 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 & SLF_TOSS){ comp->sls_i_tossed++; DPRINT(("uncomp: toss\n")); return 0; } } cs = &comp->rstate[comp->recv_current]; thp = &cs->cs_tcp; ip = &cs->cs_ip; if((x = pull16(&cp)) == -1) { /* Read the TCP checksum */ DPRINT(("uncomp: bad tcp chk\n")); goto bad; } thp->check = htons(x); thp->psh = (changes & TCP_PUSH_BIT) ? 1 : 0;/* * we can use the same number for the length of the saved header and * the current one, because the packet wouldn't have been sent * as compressed unless the options were the same as the previous one */ hdrlen = ip->ihl * 4 + thp->doff * 4; switch(changes & SPECIALS_MASK){ case SPECIAL_I: /* Echoed terminal traffic */ { register short i; i = ntohs(ip->tot_len) - hdrlen; thp->ack_seq = htonl( ntohl(thp->ack_seq) + i); thp->seq = htonl( ntohl(thp->seq) + i); } break; case SPECIAL_D: /* Unidirectional data */ thp->seq = htonl( ntohl(thp->seq) + ntohs(ip->tot_len) - hdrlen); break; default: if(changes & NEW_U){ thp->urg = 1; if((x = decode(&cp)) == -1) { DPRINT(("uncomp: bad U\n")); goto bad; } thp->urg_ptr = htons(x); } else thp->urg = 0; if(changes & NEW_W){ if((x = decode(&cp)) == -1) { DPRINT(("uncomp: bad W\n")); goto bad; } thp->window = htons( ntohs(thp->window) + x); } if(changes & NEW_A){ if((x = decode(&cp)) == -1) { DPRINT(("uncomp: bad A\n")); goto bad; } thp->ack_seq = htonl( ntohl(thp->ack_seq) + x); } if(changes & NEW_S){ if((x = decode(&cp)) == -1) { DPRINT(("uncomp: bad S\n")); goto bad; } thp->seq = htonl( ntohl(thp->seq) + x); } break; } if(changes & NEW_I){ if((x = decode(&cp)) == -1) { DPRINT(("uncomp: bad I\n")); goto bad; } ip->id = htons (ntohs (ip->id) + x); } else ip->id = htons (ntohs (ip->id) + 1); /* * At this point, cp points to the first byte of data in the * packet. Put the reconstructed TCP and IP headers back on the * packet. Recalculate IP checksum (but not TCP checksum). */ len = isize - (cp - icp); if (len < 0) goto bad; len += hdrlen; ip->tot_len = htons(len); ip->check = 0; DPRINT(("uncomp: %d %d %d %d\n", cp - icp, hdrlen, isize, len)); memmove(icp + hdrlen, cp, len - hdrlen); cp = icp; memcpy(cp, ip, 20); cp += 20; if (ip->ihl > 5) { memcpy(cp, cs->cs_ipopt, ((ip->ihl) - 5) * 4); cp += ((ip->ihl) - 5) * 4; } ((struct iphdr *)icp)->check = ip_csum((struct iphdr*)icp); memcpy(cp, thp, 20); cp += 20; if (thp->doff > 5) { memcpy(cp, cs->cs_tcpopt, ((thp->doff) - 5) * 4); cp += ((thp->doff) - 5) * 4; }if (inet_debug == DBG_SLIP) printk("\runcomp: change %x len %d\n", changes, len); return len;bad: comp->sls_i_error++; return slhc_toss( comp );}intslhc_remember(struct slcompress *comp, unsigned char *icp, int isize){ register struct cstate *cs; short ip_len; struct iphdr *ip; struct tcphdr *thp; unsigned char index; if(isize < 20) { /* The packet is shorter than a legal IP header */ comp->sls_i_runt++; return slhc_toss( comp ); } /* Sneak a peek at the IP header's IHL field to find its length */ ip_len = (icp[0] & 0xf) << 2; if(ip_len < 20){ /* The IP header length field is too small */ comp->sls_i_runt++; return slhc_toss( comp ); } index = icp[9]; icp[9] = IPPROTO_TCP; ip = (struct iphdr *) icp; if (ip_csum(ip)) { /* Bad IP header checksum; discard */ comp->sls_i_badcheck++; return slhc_toss( comp ); } thp = (struct tcphdr *)(((unsigned char *)ip) + ip->ihl*4); if(index > comp->rslot_limit) { comp->sls_i_error++; return slhc_toss(comp); } /* Update local state */ cs = &comp->rstate[comp->recv_current = index]; comp->flags &=~ SLF_TOSS; memcpy(&cs->cs_ip,ip,20); memcpy(&cs->cs_tcp,thp,20); if (ip->ihl > 5) memcpy(cs->cs_ipopt, ip+1, ((ip->ihl) - 5) * 4); if (thp->doff > 5) memcpy(cs->cs_tcpopt, thp+1, ((thp->doff) - 5) * 4); cs->cs_hsize = ip->ihl*2 + thp->doff*2; /* Put headers back on packet * Neither header checksum is recalculated */ comp->sls_i_uncompressed++; return isize;}intslhc_toss(struct slcompress *comp){ if ( comp == NULLSLCOMPR ) return 0; comp->flags |= SLF_TOSS; return 0;}void slhc_i_status(struct slcompress *comp){ if (comp != NULLSLCOMPR) { printk("\t%ld Cmp, %ld Uncmp, %ld Bad, %ld Tossed\n", comp->sls_i_compressed, comp->sls_i_uncompressed, comp->sls_i_error, comp->sls_i_tossed); }}void slhc_o_status(struct slcompress *comp){ if (comp != NULLSLCOMPR) { printk("\t%ld Cmp, %ld Uncmp, %ld AsIs, %ld NotTCP\n", comp->sls_o_compressed, comp->sls_o_uncompressed, comp->sls_o_tcp, comp->sls_o_nontcp); printk("\t%10ld Searches, %10ld Misses\n", comp->sls_o_searches, comp->sls_o_misses); }}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -