+ if(h1->state==IGNORE || h2->state==IGNORE){
+ dbgprintf(2, "Ignoring packet between %i and %i\n",
+ ntohs(dccph->dccph_sport), ntohs(dccph->dccph_dport));
+ return 0;
+ }
+
+ /*set TCP standard features*/
+ tcph->source=dccph->dccph_sport;
+ tcph->dest=dccph->dccph_dport;
+ tcph->doff=5;
+ tcph->check=htonl(0);
+ tcph->urg_ptr=0;
+
+ /*Adjust TCP advertised window size*/
+ if(!yellow){
+ tcph->window=htons(30000);
+ }
+
+ /*Process DCCP Packet Types*/
+ switch(dccph->dccph_type){
+ case DCCP_PKT_REQUEST:
+ dbgprintf(2,"Packet Type: Request\n");
+ if(!handle_request(new, old, h1, h2)){
+ return 0;
+ }
+ break;
+ case DCCP_PKT_RESPONSE:
+ dbgprintf(2,"Packet Type: Response\n");
+ if(!handle_response(new,old,h1,h2)){
+ return 0;
+ }
+ break;
+ case DCCP_PKT_DATA:
+ if(!handle_data(new,old,h1,h2)){
+ return 0;
+ }
+ break;
+ case DCCP_PKT_DATAACK:
+ dbgprintf(2,"Packet Type: DataAck\n");
+ if(!handle_dataack(new,old,h1,h2)){
+ return 0;
+ }
+ break;
+ case DCCP_PKT_ACK:
+ dbgprintf(2,"Packet Type: Ack\n");
+ if(!handle_ack(new,old,h1,h2)){
+ return 0;
+ }
+ break;
+ case DCCP_PKT_CLOSEREQ:
+ dbgprintf(2,"Packet Type: CloseReq\n");
+ if(!handle_closereq(new,old,h1,h2)){
+ return 0;
+ }
+ break;
+ case DCCP_PKT_CLOSE:
+ dbgprintf(2,"Packet Type: Close\n");
+ if(!handle_close(new,old,h1,h2)){
+ return 0;
+ }
+ break;
+ case DCCP_PKT_RESET:
+ dbgprintf(2,"Packet Type: Reset\n");
+ if(!handle_reset(new,old,h1,h2)){
+ return 0;
+ }
+ break;
+ case DCCP_PKT_SYNC:
+ dbgprintf(2,"Packet Type: Sync\n");
+ if(!handle_sync(new,old,h1,h2)){
+ return 0;
+ }
+ break;
+ case DCCP_PKT_SYNCACK:
+ dbgprintf(2,"Packet Type: SyncAck\n");
+ if(!handle_syncack(new,old,h1,h2)){
+ return 0;
+ }
+ break;
+ default:
+ dbgprintf(0,"Invalid DCCP Packet!!\n");
+ return 0;
+ break;
+ }
+
+ /*Compute TCP checksums*/
+ if(new->id_len==IP4_ADDR_LEN){
+ tcph->check=0;
+ tcph->check=ipv4_pseudohdr_chksum(new->data,
+ new->length, new->dest_id, new->src_id, 6);
+ }else if(new->id_len==IP6_ADDR_LEN){
+ tcph->check=0;
+ tcph->check=ipv6_pseudohdr_chksum(new->data,
+ new->length, new->dest_id, new->src_id, 6);
+ }else{
+ tcph->check=0;
+ dbgprintf(2,"Unknown ID Length, can't do checksums\n");
+ }
+
+ return 1;
+}
+
+int handle_request(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;
+ u_char* tcpopt;
+ const u_char* dccpopt;
+
+ /*length check*/
+ if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext)+sizeof(struct dccp_hdr_request)){
+ 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;
+
+ /*Process DCCP Options*/
+ dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext)+sizeof(struct dccp_hdr_request);
+ optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr)-sizeof(struct dccp_hdr_ext)-sizeof(struct dccp_hdr_request);
+ if(!parse_options(dccpopt,optlen,h1,h2)){
+ return 0;
+ }
+
+ /*Do conversion*/
+ if(yellow){
+ tcph->window=htons(0);
+ }
+ tcph->ack_seq=htonl(0);
+ if(h1->state==INIT){
+ tcph->seq=htonl(initialize_hcon(h1, ntohl(dccphex->dccph_seq_low)));
+ }else{
+ tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),datalength, dccph->dccph_type));
+ }
+ tcph->syn=1;
+ tcph->ack=0;
+ tcph->fin=0;
+ tcph->rst=0;
+
+ /* add Sack-permitted option, if relevant*/
+ if(sack){
+ tcpopt=(u_char*)(new->data + tcph->doff*4);
+ *tcpopt=4;
+ tcpopt++;
+ *tcpopt=2;
+ tcph->doff++;
+ }
+
+ /*calculate length*/
+ new->length=tcph->doff*4;
+ return 1;
+}
+
+int handle_response(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;
+ u_char* tcpopt;
+ const u_char* dccpopt;
+
+ /*length check*/
+ if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext)
+ + sizeof(struct dccp_hdr_ack_bits)+sizeof(struct dccp_hdr_request)){
+ 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) + sizeof(struct dccp_hdr_request);
+ optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext)
+ - sizeof(struct dccp_hdr_ack_bits) - sizeof(struct dccp_hdr_request);
+ if(!parse_options(dccpopt,optlen,h1,h2)){
+ return 0;
+ }
+
+ /*Do conversion*/
+ if(h2->state!=OPEN){
+ dbgprintf(0,"Warning: DCCP Response without a Request!!\n");
+ }
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
+ h1->high_ack=ntohl(tcph->ack_seq);
+ if(yellow){
+ tcph->window=htons(0);
+ }
+ if(h1->state==INIT){
+ tcph->seq=htonl(initialize_hcon(h1, ntohl(dccphex->dccph_seq_low)));
+ }
+ tcph->syn=1;
+ tcph->ack=1;
+ tcph->fin=0;
+ tcph->rst=0;
+
+ /* add Sack-permitted option, if relevant*/
+ if(sack){
+ tcpopt=(u_char*)(new->data + tcph->doff*4);
+ *tcpopt=4;
+ *(tcpopt+1)=2;
+ tcph->doff++;
+ }
+
+ /*calculate length*/
+ new->length=tcph->doff*4;
+ return 1;
+}
+
+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);
+ }
+ }