+int handle_dataack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
+{
+ struct tcphdr *tcph;
+ struct dccp_hdr *dccph;
+ struct dccp_hdr_ext *dccphex;
+ struct dccp_hdr_ack_bits *dccphack;
+ int datalength;
+ int optlen;
+ const u_char* pd;
+ u_char* npd;
+ const u_char* dccpopt;
+
+ /*length check*/
+ if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
+ return 0;
+ }
+
+ /*cast header pointers*/
+ tcph=(struct tcphdr*)new->data;
+ dccph=(struct dccp_hdr*)old->data;
+ dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
+ dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
+
+ /*determine data length*/
+ datalength=old->length - dccph->dccph_doff*4;
+ pd=old->data + dccph->dccph_doff*4;
+
+ /*Process DCCP Options*/
+ dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
+ optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
+ if(!parse_options(dccpopt,optlen,h1,h2)){
+ return 0;
+ }
+
+ /*Do Conversion*/
+ if(green){
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
+ }else{
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
+ }
+ h1->high_ack=ntohl(tcph->ack_seq);
+ tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),datalength, dccph->dccph_type));
+ if(yellow){
+ tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
+ }
+ if(sack){
+ if(sack!=2 || interp_ack_vect((u_char*)dccph)){
+ ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low),h1);
+ }
+ }
+ tcph->syn=0;
+ tcph->ack=1;
+ tcph->fin=0;
+ tcph->rst=0;
+
+ /*copy data*/
+ npd=new->data + tcph->doff*4;
+ memcpy(npd, pd, datalength);
+
+ /*calculate length*/
+ new->length=tcph->doff*4 + datalength;
+ return 1;
+}
+
+int handle_ack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
+{
+ struct tcphdr *tcph;
+ struct dccp_hdr *dccph;
+ struct dccp_hdr_ext *dccphex;
+ struct dccp_hdr_ack_bits *dccphack;
+ int optlen;
+ const u_char* dccpopt;
+
+ /*length check*/
+ if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
+ return 0;
+ }
+
+ /*cast header pointers*/
+ tcph=(struct tcphdr*)new->data;
+ dccph=(struct dccp_hdr*)old->data;
+ dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
+ dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
+
+ /*Process DCCP Options*/
+ dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
+ optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
+ if(!parse_options(dccpopt,optlen,h1,h2)){
+ return 0;
+ }
+
+ /*Do Conversion*/
+ if(green){
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
+ }else{
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
+ }
+ h1->high_ack=ntohl(tcph->ack_seq);
+ tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
+ if(yellow){
+ tcph->window=htons(-interp_ack_vect((u_char*)dccph)*1400);
+ if(-interp_ack_vect((u_char*)dccph)*1400 > 65535){
+ dbgprintf(0,"Note: TCP Window Overflow @ %d.%d\n", (int)old->h->ts.tv_sec, (int)old->h->ts.tv_usec);
+ }
+ }
+ if(sack){
+ if(sack!=2 || interp_ack_vect((u_char*)dccph)){
+ ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low),h1);
+ }
+ }
+
+ tcph->syn=0;
+ tcph->ack=1;
+ tcph->fin=0;
+ tcph->rst=0;
+
+ /*calculate length*/
+ new->length=tcph->doff*4 + 1;
+ return 1;
+}
+
+int handle_closereq(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
+{
+ struct tcphdr *tcph;
+ struct dccp_hdr *dccph;
+ struct dccp_hdr_ext *dccphex;
+ struct dccp_hdr_ack_bits *dccphack;
+ int optlen;
+ const u_char* dccpopt;
+
+ /*length check*/
+ if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
+ return 0;
+ }
+
+ /*cast header pointers*/
+ tcph=(struct tcphdr*)new->data;
+ dccph=(struct dccp_hdr*)old->data;
+ dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
+ dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
+
+ /*Process DCCP Options*/
+ dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
+ optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
+ if(!parse_options(dccpopt,optlen,h1,h2)){
+ return 0;
+ }
+
+ /*Do Conversion*/
+ if(green){
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
+ }else{
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
+ }
+ h1->high_ack=ntohl(tcph->ack_seq);
+ tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
+ if(yellow){
+ tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
+ }
+ if(sack){
+ if(sack!=2 || interp_ack_vect((u_char*)dccph)){
+ ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low),h1);
+ }
+ }
+
+ tcph->syn=0;
+ tcph->ack=1;
+ tcph->fin=1;
+ tcph->rst=0;
+
+ /*calculate length*/
+ new->length=tcph->doff*4;
+ return 1;
+}
+
+int handle_close(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
+{
+ struct tcphdr *tcph;
+ struct dccp_hdr *dccph;
+ struct dccp_hdr_ext *dccphex;
+ struct dccp_hdr_ack_bits *dccphack;
+ int optlen;
+ const u_char* dccpopt;
+
+ /*length check*/
+ if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
+ return 0;
+ }
+
+ /*cast header pointers*/
+ tcph=(struct tcphdr*)new->data;
+ dccph=(struct dccp_hdr*)old->data;
+ dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
+ dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
+
+ /*Process DCCP Options*/
+ dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
+ optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
+ if(!parse_options(dccpopt,optlen,h1,h2)){
+ return 0;
+ }
+
+ /*Do Conversion*/
+ update_state(h1,CLOSE);
+ if(green){
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
+ }else{
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
+ }
+ h1->high_ack=ntohl(tcph->ack_seq);
+ tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
+ if(yellow){
+ tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
+ }
+ if(sack){
+ if(sack!=2 || interp_ack_vect((u_char*)dccph)){
+ ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low),h1);
+ }
+ }
+
+ tcph->syn=0;
+ tcph->ack=1;
+ tcph->fin=1;
+ tcph->rst=0;
+
+ /*calculate length*/
+ new->length=tcph->doff*4;
+ return 1;
+}
+
+int handle_reset(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
+{
+ struct tcphdr *tcph;
+ struct dccp_hdr *dccph;
+ struct dccp_hdr_ext *dccphex;
+ struct dccp_hdr_ack_bits *dccphack;
+ int optlen;
+ const u_char* dccpopt;
+
+ /*length check*/
+ if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
+ return 0;
+ }
+
+ /*cast header pointers*/
+ tcph=(struct tcphdr*)new->data;
+ dccph=(struct dccp_hdr*)old->data;
+ dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
+ dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
+
+ /*Process DCCP Options*/
+ dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
+ optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
+ if(!parse_options(dccpopt,optlen,h1,h2)){
+ return 0;
+ }
+
+ /*Do Conversion*/
+ if(h2->state==CLOSE){
+ update_state(h1,CLOSE);
+ }
+ if(green){
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
+ }else{
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
+ }
+ h1->high_ack=ntohl(tcph->ack_seq);
+ tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
+ if(yellow){
+ tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
+ }
+ if(sack){
+ if(sack!=2 || interp_ack_vect((u_char*)dccph)){
+ ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low),h1);
+ }
+ }
+
+ tcph->syn=0;
+ tcph->ack=1;
+ tcph->fin=1;
+ tcph->rst=0;
+
+ /*calculate length*/
+ new->length=tcph->doff*4;
+ return 1;
+}
+
+int handle_sync(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
+{
+ struct tcphdr *tcph;
+ struct dccp_hdr *dccph;
+ struct dccp_hdr_ext *dccphex;
+ struct dccp_hdr_ack_bits *dccphack;
+ int optlen;
+ const u_char* dccpopt;
+
+ /*length check*/
+ if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
+ return 0;
+ }
+
+ /*cast header pointers*/
+ tcph=(struct tcphdr*)new->data;
+ dccph=(struct dccp_hdr*)old->data;
+ dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
+ dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
+
+ /*Process DCCP Options*/
+ dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
+ optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
+ if(!parse_options(dccpopt,optlen,h1,h2)){
+ return 0;
+ }
+
+ /*Do Conversion*/
+ if(green){
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
+ }else{
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
+ }
+ h1->high_ack=ntohl(tcph->ack_seq);
+ tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
+ if(yellow){
+ tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
+ }else{
+ tcph->window=htons(0);
+ }
+ if(sack){
+ if(sack!=2 || interp_ack_vect((u_char*)dccph)){
+ ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low),h1);
+ }
+ }
+
+ tcph->syn=0;
+ tcph->ack=1;
+ tcph->fin=0;
+ tcph->rst=0;
+
+ /*calculate length*/
+ new->length=tcph->doff*4;
+ return 1;
+}
+
+int handle_syncack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
+{
+ struct tcphdr *tcph;
+ struct dccp_hdr *dccph;
+ struct dccp_hdr_ext *dccphex;
+ struct dccp_hdr_ack_bits *dccphack;
+ int optlen;
+ const u_char* dccpopt;
+
+ /*length check*/
+ if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
+ return 0;
+ }
+
+ /*cast header pointers*/
+ tcph=(struct tcphdr*)new->data;
+ dccph=(struct dccp_hdr*)old->data;
+ dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
+ dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
+
+ /*Process DCCP Options*/
+ dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
+ optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
+ if(!parse_options(dccpopt,optlen,h1,h2)){
+ return 0;
+ }
+
+ /*Do Conversion*/
+ if(green){
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
+ }else{
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
+ }
+ h1->high_ack=ntohl(tcph->ack_seq);
+ tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
+ if(yellow){
+ tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
+ }else{
+ tcph->window=htons(0);
+ }
+ if(sack){
+ if(sack!=2 || interp_ack_vect((u_char*)dccph)){
+ ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low),h1);
+ }
+ }
+
+ tcph->syn=0;
+ tcph->ack=1;
+ tcph->fin=0;
+ tcph->rst=0;
+
+ /*calculate length*/
+ new->length=tcph->doff*4;
+ return 1;
+}
+
+int handle_data(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
+{
+ struct tcphdr *tcph;
+ struct dccp_hdr *dccph;
+ struct dccp_hdr_ext *dccphex;
+ int datalength;
+ int optlen;
+ const u_char* pd;
+ u_char* npd;
+ const u_char* dccpopt;
+
+ /*length check*/
+ if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext)){
+ return 0;
+ }
+
+ /*cast header pointers*/
+ tcph=(struct tcphdr*)new->data;
+ dccph=(struct dccp_hdr*)old->data;
+ dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
+
+ /*determine data length*/
+ datalength=old->length - dccph->dccph_doff*4;
+ pd=old->data + dccph->dccph_doff*4;
+
+ /*Process DCCP Options*/
+ dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext);
+ optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext);
+ if(!parse_options(dccpopt,optlen,h1,h2)){
+ return 0;
+ }
+
+ /*Do conversion*/
+ tcph->ack_seq=htonl(h1->high_ack);
+ tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),datalength, dccph->dccph_type));
+ tcph->syn=0;
+ tcph->ack=1;
+ tcph->fin=0;
+ tcph->rst=0;
+
+ /*copy data*/
+ npd=new->data + tcph->doff*4;
+ memcpy(npd, pd, datalength);
+
+ /*calculate length*/
+ new->length=tcph->doff*4 + datalength;
+ return 1;
+}
+
+int parse_options(const u_char* opt_start, int len, struct hcon* A, struct hcon* B)
+{
+ int optlen;
+ int length;
+ const u_char* opt;
+
+ /*setup pointer to DCCP options and determine how long the options are*/
+ optlen=len;
+ opt=opt_start;
+
+ /*parse options*/
+ while(optlen > 0){
+ /*One byte options (no length)*/
+ if(*opt< 32){
+ optlen--;
+ opt++;
+ continue;
+ }
+
+ /*Check option length*/
+ length=*(opt+1);
+ if(length > optlen){
+ dbgprintf(0, "Warning: Option would extend into packet data\n");
+ return 0;
+ }
+ if(length < 2){
+ dbgprintf(0, "Warning: Bad Option!\n");
+ return 0;
+ }
+
+ /*Ack Vector Option*/
+ if(*opt==38 || *opt==39){
+
+ }
+
+ /*NDP Count Option*/
+ if(*opt==37){
+
+ }
+
+ /*Feature negotation*/
+ if(*opt==32){
+ /*Change L*/
+ if(!process_feature(opt+2,length-2,FALSE,TRUE,A,B)){
+ return 0;
+ }
+ }
+ if(*opt==33){
+ /*Confirm L*/
+ if(!process_feature(opt+2,length-2,TRUE,TRUE,A,B)){
+ return 0;
+ }
+ }
+ if(*opt==34){
+ /*Change R*/
+ if(!process_feature(opt+2,length-2,FALSE,FALSE,A,B)){
+ return 0;
+ }
+ }
+ if(*opt==35){
+ /*Confirm R*/
+ if(!process_feature(opt+2,length-2,TRUE,FALSE,A,B)){
+ return 0;
+ }
+ }
+
+ optlen-=length;
+ opt+=length;
+ }
+
+ return 1;
+}
+
+int process_feature(const u_char* feat, int len, int confirm, int L, struct hcon* A, struct hcon* B)
+{
+ const u_char* val;
+ int ccid;
+
+ val=feat+1;
+
+ switch(*feat){
+ case 1:
+ /*CCID*/
+ if(confirm==FALSE){
+ switch(*val){
+ case 2:
+ ccid=CCID2;
+ break;
+ case 3:
+ ccid=CCID3;
+ break;
+ default:
+ ccid=UNKNOWN;
+ break;
+ }
+ if(L==TRUE){
+ B->type=ccid;
+ }else{
+ A->type=ccid;
+ }
+ }
+ break;
+ case 2:
+ /*Short sequence nums*/
+ if(confirm==FALSE && *val==1){
+ dbgprintf(0,"Error! DCCP is trying to turn on short sequence numbers! We do not support this!!\n");
+ exit(1);
+ }
+ break;
+ }
+ return 1;
+}
+
+/*Ack Vector to SACK Option*/
+void ack_vect2sack(struct hcon *hcn, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr,
+ __be32 dccpack, struct hcon* o_hcn)
+{
+ int hdrlen=((struct dccp_hdr*)dccphdr)->dccph_doff*4;
+ int optlen;
+ int len;
+ int tmp;
+ __be32 bp;
+ u_char* temp;
+ u_char* opt;
+ u_char* cur;
+ u_char* tlen;
+ u_int32_t bL=0;
+ u_int32_t bR;
+ u_int32_t* pL;
+ u_int32_t* pR;
+ int num_blocks;
+ int cont;
+ int isopt;
+
+ /*setup pointer to DCCP options and determine how long the options are*/
+ optlen=hdrlen-sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
+ opt=dccphdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
+
+ if(optlen<=0){
+ return;
+ }
+
+ /*setup tcp pointers*/
+ num_blocks=4;
+ *tcpopts=5;
+ tlen=tcpopts+1;
+ temp=tlen;
+ temp++;
+ pL=(u_int32_t*)temp;
+ pR=pL+1;
+
+ /*setup tcp control variables*/
+ bp=dccpack;
+ cont=0;
+ *tlen=2;
+ isopt=0;
+
+ /*parse options*/
+ while(optlen > 0){
+
+ /*One byte options (no length)*/
+ if(*opt< 32){
+ optlen--;
+ opt++;
+ continue;
+ }
+
+ len=*(opt+1);
+ if(len > optlen){
+ dbgprintf(0, "Warning: Option would extend into packet data\n");
+ break;
+ }
+
+ /*Ack Vector Option*/
+ if(*opt==38 || *opt==39){
+ tmp=len-2;
+ cur=opt+2;
+ /*loop through Vector*/
+ while(tmp > 0){
+ /*ack vector works BACKWARDS through time*/
+
+ if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
+ if(cont){ /*end a SACK run, if one is started*/
+ bR=convert_ack(hcn, bp,o_hcn);
+ cont=0;
+ num_blocks--;
+ *pR=htonl(bR);
+ *pL=htonl(bL);
+ tcph->doff+=2;
+ *tlen+=8;
+ pL=pR+1;
+ pR=pL+1;
+ }
+ bp= bp - (*cur & 0x3F)- 1;
+ }
+
+ if((*cur & 0xC0)==0x00){ //received packet
+ if(!cont){ /*if no SACK run and we can start another one, do so*/
+ if(num_blocks>0){
+ bL=convert_ack(hcn, bp, o_hcn);
+ isopt=1;
+ cont=1;
+
+ }
+ }
+ bp = bp -(*cur & 0x3F)- 1;
+ }
+ tmp--;
+ cur++;
+ }
+ }
+
+ optlen-=len;
+ opt+=len;
+ }
+
+ /*if we are in the middle of a SACK run, close it*/
+ if(cont){
+ bR=convert_ack(hcn, bp,o_hcn);
+ *pR=htonl(bR);
+ *pL=htonl(bL);
+ tcph->doff+=2;
+ *tlen+=8;
+ cont=0;
+ }
+
+ /*adjust length if the option is actually added*/
+ if(isopt){
+ tcph->doff+=1;
+ }
+return;
+}
+
+void version()
+{