]> sjero.net Git - dccp2tcp/blobdiff - dccp2tcp.c
Cleanup types throughout code
[dccp2tcp] / dccp2tcp.c
index 3df497e33659ef7a630f33df1f79bdaebad60983..6697681b99636008dc3472262720f6ac472fc51b 100644 (file)
@@ -1,40 +1,64 @@
 /******************************************************************************
-Author: Samuel Jero
+Utility to convert a DCCP flow to a TCP flow for DCCP analysis via
+               tcptrace.
 
-Date: 11/2012
+Copyright (C) 2013  Samuel Jero <sj323707@ohio.edu>
 
-Description: Program to convert a DCCP flow to a TCP flow for DCCP analysis via
-               tcptrace.
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Author: Samuel Jero <sj323707@ohio.edu>
+Date: 02/2013
 
 Notes:
-       1)CCID2 ONLY
-       2)DCCP MUST use 48 bit sequence numbers
-       3)Checksums are not computed (they are zeroed)
-       4)DCCP DATA packets are not implemented (Linux doesn't use them)
-       5)DCCP Ack packets show up as TCP packets containing one byte
+       1)DCCP MUST use 48 bit sequence numbers
+       2)DCCP Ack packets show up as TCP packets containing one byte
 ******************************************************************************/
 #include "dccp2tcp.h"
 
 
+#define DCCP2TCP_VERSION 1.6
+#define COPYRIGHT_YEAR 2013
+
+
 int debug=0;   /*set to 1 to turn on debugging information*/
 int yellow=0;  /*tcptrace yellow line as currently acked packet*/
 int green=0;   /*tcptrace green line as currently acked packet*/
 int sack=0;            /*add TCP SACKS*/
 
+
 pcap_t*                        in;                     /*libpcap input file discriptor*/
 pcap_dumper_t  *out;           /*libpcap output file discriptor*/
 struct connection *chead;      /*connection list*/
 
 
-
 void handle_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes);
-int convert_packet(struct packet *new, const struct const_packet* old);
-unsigned int interp_ack_vect(u_char* hdr);
-u_int32_t initialize_seq(struct host *seq, __be32 initial);
-u_int32_t add_new_seq(struct host *seq, __be32 num, int size, enum dccp_pkt_type type);
-u_int32_t convert_ack(struct host *seq, __be32 num);
-int acked_packet_size(struct host *seq, __be32 num);
-void ack_vect2sack(struct host *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr, __be32 dccpack);
+int handle_request(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
+int handle_response(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
+int handle_dataack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
+int handle_ack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
+int handle_closereq(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
+int handle_close(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
+int handle_reset(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
+int handle_sync(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
+int handle_syncack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
+int handle_data(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
+int parse_options(const u_char* opt_start, int len, struct hcon* A, struct hcon* B);
+int process_feature(const u_char* feat, int len, int confirm, int L, struct hcon* A, struct hcon* B);
+void ack_vect2sack(struct hcon *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr,
+                               d_seq_num dccpack, struct hcon* o_hcn);
+void version();
+void usage();
 
 
 /*Parse commandline options and open files*/
@@ -46,9 +70,8 @@ int main(int argc, char *argv[])
        char *tfile=NULL;
 
        /*parse commandline options*/
-       if(argc<3 || argc > 9){
-               dbgprintf(0, "Usage: dccp2tcp dccp_file tcp_file [-d] [-y] [-g] [-s]\n");
-               exit(1);
+       if(argc > 9){
+               usage();
        }
 
        /*loop through commandline options*/
@@ -61,29 +84,33 @@ int main(int argc, char *argv[])
                                if(tfile==NULL){
                                        tfile=argv[i]; /*assign second non-dash argument to the dccp file*/
                                }else{
-                                       dbgprintf(0,"Usage: dccp2tcp dccp_file tcp_file [-d] [-y] [-g] [-s]\n");
-                                       exit(1);
+                                       usage();
                                }
                        }
                }else{
-                       if(argv[i][1]=='d' && strlen(argv[i])==2){ /*debug option*/
+                       if(argv[i][1]=='d' && strlen(argv[i])==2){ /* -d */
                                debug++;
                        }
-                       if(argv[i][1]=='y' && strlen(argv[i])==2){ /*yellow option*/
+                       if(argv[i][1]=='y' && strlen(argv[i])==2){ /* -y */
                                yellow=1;
                        }
-                       if(argv[i][1]=='g' && strlen(argv[i])==2){ /*green option*/
+                       if(argv[i][1]=='g' && strlen(argv[i])==2){ /* -g */
                                green=1;
                        }
-                       if(argv[i][1]=='s' && strlen(argv[i])==2){ /*sack option*/
+                       if(argv[i][1]=='s' && strlen(argv[i])==2){ /* -s */
                                sack++;
                        }
+                       if(argv[i][1]=='h' && strlen(argv[i])==2){ /* -h */
+                               usage();
+                       }
+                       if(argv[i][1]=='V' && strlen(argv[i])==2){ /* -V */
+                               version();
+                       }
                }
        }
        
        if(dfile==NULL || tfile==NULL){
-               dbgprintf(0,"Usage: dccp2tcp dccp_file tcp_file [-d] [-y] [-g] [-s]\n");
-               exit(1);
+               usage();
        }
 
        /*all options validated*/
@@ -185,21 +212,14 @@ void handle_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *byte
 return;
 }
 
-
 /*do all the dccp to tcp conversions*/
 int convert_packet(struct packet *new, const struct const_packet* old)
-{      
+{
        struct tcphdr                           *tcph;
        struct dccp_hdr                         *dccph;
        struct dccp_hdr_ext             *dccphex;
-       struct dccp_hdr_ack_bits        *dccphack;
-       struct host                                     *h1=NULL;
-       struct host                                     *h2=NULL;
-       int                                             datalength;
-       int                                                     len=0;
-       const u_char*                           pd;
-       u_char*                                         npd;
-       u_char*                                         tcpopt;
+       struct hcon                                     *h1=NULL;
+       struct hcon                                     *h2=NULL;
 
        /*Safety checks*/
        if(!new || !old || !new->data || !old->data || !new->h || !old->h){
@@ -207,7 +227,8 @@ int convert_packet(struct packet *new, const struct const_packet* old)
                exit(1);
                return 0;
        }
-       if(old->length < (sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext)) || new->length < sizeof(struct dccp_hdr)){
+       if(old->length < (sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext))
+                                                                                               || new->length < sizeof(struct dccp_hdr)){
                dbgprintf(0, "Error: DCCP Packet Too short!\n");
                return 0;
        }
@@ -216,14 +237,19 @@ int convert_packet(struct packet *new, const struct const_packet* old)
        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));
 
        dbgprintf(2,"Sequence Number: %llu\n", (unsigned long long)
                        (((unsigned long)ntohs(dccph->dccph_seq)<<32) + ntohl(dccphex->dccph_seq_low)));
 
+       /*Ensure packet is at least as large as DCCP header*/
+       if(old->length < dccph->dccph_doff*4){
+               dbgprintf(0, "Error: DCCP Header truncated\n");
+               return 0;
+       }
+
        /*Get Hosts*/
-       if(get_host(new->src_id, new->dest_id, new->id_len,
-                       dccph->dccph_sport, dccph->dccph_dport, &h1, &h2)){
+       if(get_host(new->src_id, new->dest_id, new->id_len, dccph->dccph_sport,
+                       dccph->dccph_dport, dccph->dccph_type,&h1, &h2)){
                dbgprintf(0,"Error: Can't Get Hosts!\n");
                return 0;
        }
@@ -231,21 +257,11 @@ int convert_packet(struct packet *new, const struct const_packet* old)
                dbgprintf(0, "Error: Can't Get Hosts!\n");
                return 0;
        }
-
-       /*Ensure packet is at least as large as DCCP header*/
-       if(old->length < dccph->dccph_doff*4){
-               dbgprintf(0, "Error: DCCP Header truncated\n");
+       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;
        }
-       if(dccph->dccph_type!=DCCP_PKT_DATA &&
-                       old->length < (sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) +
-                       sizeof(struct dccp_hdr_ack_bits))){
-               dbgprintf(0, "Error: DCCP Packet Too short!\n");
-       }
-
-       /*determine data length*/
-       datalength=old->length - dccph->dccph_doff*4;
-       pd=old->data + dccph->dccph_doff*4;
 
        /*set TCP standard features*/
        tcph->source=dccph->dccph_sport;
@@ -259,458 +275,796 @@ int convert_packet(struct packet *new, const struct const_packet* old)
                tcph->window=htons(30000);
        }
 
-       /*make changes by packet type*/
-       if(dccph->dccph_type==DCCP_PKT_REQUEST){//DCCP REQUEST -->TCP SYN
-               dbgprintf(2,"Packet Type: Request\n");
-               if(h1->state==INIT){
-                       if(yellow){
-                               tcph->window=htons(0);
+       /*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;
                        }
-                       tcph->ack_seq=htonl(0);
-                       tcph->seq=htonl(initialize_seq(h1, ntohl(dccphex->dccph_seq_low)));
-                       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++;
+                       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;
+       }
 
-                       /*calculate length*/
-                       len=tcph->doff*4;
-               }
+       /*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");
        }
 
-       if(dccph->dccph_type==DCCP_PKT_RESPONSE){//DCCP RESPONSE-->TCP SYN,ACK
-               dbgprintf(2,"Packet Type: Response\n");
-               if(h2->state==OPEN && h1->state==INIT){
-                       tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
-                       if(yellow){
-                               tcph->window=htons(0);
-                       }
-                       tcph->seq=htonl(initialize_seq(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++;
-                       }
+       return 1;
+}
 
-                       /*calculate length*/
-                       len=tcph->doff*4;
-               }
+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;
        }
 
-       if(dccph->dccph_type==DCCP_PKT_DATA){//DCCP DATA----Never seen in packet capture
-               dbgprintf(0,"DCCP Data packet not yet implemented\n");
-               exit(1);
+       /*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;
        }
 
-       if(dccph->dccph_type==DCCP_PKT_DATAACK){//DCCP DATAACK-->TCP ACK with data
-               dbgprintf(2,"Packet Type: DataAck\n");
-               if(green){
-                       tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
-               }else{
-                       tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
-               }
+       /*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));
-               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) );
-                       }
-               }
+       }
+       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++;
+       }
 
-               tcph->syn=0;
-               tcph->ack=1;
-               tcph->fin=0;
-               tcph->rst=0;
+       /*calculate length*/
+       new->length=tcph->doff*4;
+       return 1;
+}
 
-               /*copy data*/
-               npd=new->data + tcph->doff*4;
-               memcpy(npd, pd, datalength);
+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;
 
-               /*calculate length*/
-               len= tcph->doff*4 + datalength;
+       /*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;
        }
 
-       if(dccph->dccph_type==DCCP_PKT_ACK){ //DCCP ACK -->TCP ACK with no data
-               dbgprintf(2,"Packet Type: Ack\n");
-               if(green){
-                       tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
-               }else{
-                       tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
-               }
-               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){
-                               printf("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) );
-                       }
-               }
-
-               tcph->syn=0;
-               tcph->ack=1;
-               tcph->fin=0;
-               tcph->rst=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));
 
-               /*calculate length*/
-               len=tcph->doff*4 + 1;
+       /*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;
        }
 
-       if(dccph->dccph_type==DCCP_PKT_CLOSEREQ){//DCCP CLOSEREQ----Never seen in packet capture
-               dbgprintf(0,"DCCP CloseReq not yet implemented\n");
-               exit(1);
+       /*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++;
        }
 
-       if(dccph->dccph_type==DCCP_PKT_CLOSE){//DCCP CLOSE-->TCP FIN,ACK
-               dbgprintf(2,"Packet Type: Close\n");
-               update_state(h1,CLOSE);
-               if(green){
-                       tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
-               }else{
-                       tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
-               }
-               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) );
-                       }
-               }
+       /*calculate length*/
+       new->length=tcph->doff*4;
+       return 1;
+}
 
-               tcph->syn=0;
-               tcph->ack=1;
-               tcph->fin=1;
-               tcph->rst=0;
+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;
 
-               /*calculate length*/
-               len=tcph->doff*4;
+       /*length check*/
+       if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
+               return 0;
        }
 
-       if(dccph->dccph_type==DCCP_PKT_RESET){//DCCP RESET-->TCP FIN,ACK (only seen at end of connection as CLOSE ACK)
-               if(h2->state==CLOSE){
-                       update_state(h1,CLOSE);
-               }
-               dbgprintf(2,"Packet Type: Reset\n");
-               if(green){
-                       tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
-               }else{
-                       tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
-               }
-               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) );
-                       }
-               }
+       /*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));
 
-               tcph->syn=0;
-               tcph->ack=1;
-               tcph->fin=1;
-               tcph->rst=0;
+       /*determine data length*/
+       datalength=old->length - dccph->dccph_doff*4;
+       pd=old->data + dccph->dccph_doff*4;
 
-               /*calculate length*/
-               len=tcph->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;
        }
 
-       if(dccph->dccph_type==DCCP_PKT_SYNC){//DCCP SYNC
-               dbgprintf(2,"Packet Type: Sync\n");
-               if(green){
-                       tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
-               }else{
-                       tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
-               }
-               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) );
-                       }
+       /*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;
+}
 
-               tcph->syn=0;
-               tcph->ack=1;
-               tcph->fin=0;
-               tcph->rst=0;
+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;
 
-               /*calculate length*/
-               len=tcph->doff*4;
+       /*length check*/
+       if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
+               return 0;
        }
 
-       if(dccph->dccph_type==DCCP_PKT_SYNCACK){//DCCP SYNACK
-               dbgprintf(2,"Packet Type: SyncAck\n");
-               if(green){
-                       tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
-               }else{
-                       tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
-               }
-               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);
+       /*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));
-                       }
+       }
+       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;
+}
 
-               tcph->syn=0;
-               tcph->ack=1;
-               tcph->fin=0;
-               tcph->rst=0;
+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;
 
-               /*calculate length*/
-               len=tcph->doff*4;
+       /*length check*/
+       if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
+               return 0;
        }
 
-       if(dccph->dccph_type==DCCP_PKT_INVALID){//DCCP INVALID----Never seen in packet capture
-               dbgprintf(0,"Invalid DCCP Packet!!\n");
+       /*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;
        }
 
-       new->length=len;
-return 1;
-}
+       /*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;
 
-/*Parse Ack Vector Options
- * Returns the Number of packets since last recorded loss*/
-unsigned int interp_ack_vect(u_char* hdr)
+       /*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)
 {
-       int hdrlen=((struct dccp_hdr*)hdr)->dccph_doff*4;
-       //struct dccp_hdr_ext* e=(struct dccp_hdr_ext*)hdr + sizeof(struct dccp_hdr);
-       int optlen;
-       int len;
-       int tmp;
-       int bp=0;
-       int additional=0;
-       u_char* opt;
-       u_char* cur;
+       struct tcphdr                           *tcph;
+       struct dccp_hdr                         *dccph;
+       struct dccp_hdr_ext             *dccphex;
+       struct dccp_hdr_ack_bits        *dccphack;
+       int                                                     optlen;
+       const u_char*                           dccpopt;
 
-       /*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=hdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
+       /*length check*/
+       if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
+               return 0;
+       }
 
-       /*parse options*/
-       while(optlen > 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));
 
-               /*One byte options (no length)*/
-               if(*opt< 32){
-                       optlen--;
-                       opt++;
-                       continue;
-               }
+       /*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;
+       }
 
-               /*Check option length*/
-               len=*(opt+1);
-               if(len > optlen){
-                       dbgprintf(0, "Warning: Option would extend into packet data\n");
-                       return additional;
+       /*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);
                }
+       }
 
-               /*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*/
+       tcph->syn=0;
+       tcph->ack=1;
+       tcph->fin=1;
+       tcph->rst=0;
 
-                               /*keep track of total packets recieved and if
-                               a packet is lost, subtract all packets received
-                               after that*/
-                               if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
-                                       bp+=(*cur & 0x3F)+1;
-                                       additional= -bp;
-                               }
-                                       
-                               if((*cur & 0xC0)==0x00){ //received packet
-                                       bp+= (*cur & 0x3F)+1;
-                               }
+       /*calculate length*/
+       new->length=tcph->doff*4;
+       return 1;
+}
 
-                               if(((*cur& 0xC0)!= 0xC0) && ((*cur& 0xC0)!= 0x00) && ((*cur& 0xC0)!= 0x40)){
-                                       dbgprintf(1, "Warning: Invalid Ack Vector!! (Linux will handle poorly!)\n");
-                               }
-                               tmp--;
-                               cur++;
-                       }
-               }
-               
-               optlen-=len;
-               opt+=len;
+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;
        }
 
-       dbgprintf(2,"Ack vector adding: %i\n", additional);
-return additional;
-}
+       /*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;
+       }
 
-/* Setup Sequence Number Structure*/
-u_int32_t initialize_seq(struct host *seq, __be32 initial)
-{
-       /*set default values*/
-       seq->cur=0;
-       seq->size=TBL_SZ;
-       
-       /*allocate table*/
-       seq->table=(struct tbl*)malloc(sizeof(struct tbl)*TBL_SZ);
-       if(seq->table==NULL){
-               dbgprintf(0,"Can't Allocate Memory!\n");
-               exit(1);
+       /*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);
+               }
        }
 
-       /*add first sequence number*/
-       seq->table[0].old=initial;
-       seq->table[0].new=initial;
-       seq->table[0].type=DCCP_PKT_REQUEST;
-       seq->table[0].size=0;
-       update_state(seq,OPEN);
-return initial;
-}
+       tcph->syn=0;
+       tcph->ack=1;
+       tcph->fin=1;
+       tcph->rst=0;
 
+       /*calculate length*/
+       new->length=tcph->doff*4;
+       return 1;
+}
 
-/*Convert Sequence Numbers*/
-u_int32_t add_new_seq(struct host *seq, __be32 num, int size, enum dccp_pkt_type type)
+int handle_sync(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
 {
-       int prev;
-       if(seq==NULL){
-               dbgprintf(0,"ERROR NULL POINTER!\n");
-               exit(1);
+       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;
        }
-       
-       if(seq->table==NULL){
-               dbgprintf(1, "Warning: Connection uninitialized\n");
-               return initialize_seq(seq, num);
+
+       /*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;
        }
 
-       /*account for missing packets*/
-       if(num - seq->table[seq->cur].old +1 >=100){
-                       dbgprintf(1,"Missing more than 100 packets!\n");
+       /*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);
        }
-       while(seq->table[seq->cur].old +1 < num && seq->table[seq->cur].old +1 > 0){
-               prev=seq->cur;
-               if(num - seq->table[seq->cur].old +1 <100){
-                       dbgprintf(1,"Missing Packet: %X\n",seq->table[prev].new+1);
+       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);
                }
-               seq->cur=(seq->cur+1)%(seq->size);/*find next available table slot*/
-               seq->table[seq->cur].old=seq->table[prev].old+1;
-               seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
-               seq->table[seq->cur].size=size;
-               seq->table[seq->cur].type=type;
-       }
-
-       prev=seq->cur;
-       seq->cur=(seq->cur+1)%(seq->size);/*find next available table slot*/
-       seq->table[seq->cur].old=num;
-       seq->table[seq->cur].size=size;
-       seq->table[seq->cur].type=type;
-       if(seq->table[prev].type==DCCP_PKT_REQUEST || seq->table[prev].type==DCCP_PKT_RESPONSE){
-               seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
-               seq->table[seq->cur].size=1;
-               return seq->table[prev].new + seq->table[prev].size+1;
-       }
-       if(type==DCCP_PKT_DATA || type==DCCP_PKT_DATAACK || type==DCCP_PKT_ACK){
-               seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
-               return seq->table[seq->cur].new+1;
-       }
-       if(type==DCCP_PKT_SYNC || type==DCCP_PKT_SYNCACK){
-               seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
-               return seq->table[seq->cur].new;
-       }
-       seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
-return seq->table[seq->cur].new +1;
-}
+       }
 
+       tcph->syn=0;
+       tcph->ack=1;
+       tcph->fin=0;
+       tcph->rst=0;
 
-/*Convert Ack Numbers*/
-u_int32_t convert_ack(struct host *seq, __be32 num)
+       /*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)
 {
-       if(seq==NULL){
-               dbgprintf(0,"ERROR NULL POINTER!\n");
-               exit(1);
+       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;
        }
 
-       if(seq->table==NULL){
-               dbgprintf(1, "Warning: Connection uninitialized\n");
-               initialize_seq(seq, num);
+       /*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;
        }
 
-       /*loop through table looking for the DCCP ack number*/
-       for(int i=0; i < seq->size; i++){
-               if(seq->table[i].old==num){
-                       return  seq->table[i].new + seq->table[i].size + 1; /*TCP acks the sequence number plus 1*/
+       /*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);
                }
        }
-       
-       dbgprintf(1, "Error: Address Not Found! looking for: %X\n", num);
-return 0;
-}
 
+       tcph->syn=0;
+       tcph->ack=1;
+       tcph->fin=0;
+       tcph->rst=0;
 
-/* Get size of packet being acked*/
-int acked_packet_size(struct host *seq, __be32 num)
+       /*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)
 {
-       if(seq==NULL){
-               dbgprintf(0,"ERROR NULL POINTER!\n");
-               exit(1);
+       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;
        }
 
-       if(seq->table==NULL){
-               dbgprintf(1, "Warning: Connection uninitialized\n");
-               initialize_seq(seq, num);
+       /*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;
        }
 
-       /*loop through table looking for the DCCP ack number*/
-       for(int i=0; i < seq->size; i++){
-               if(seq->table[i].old==num){
-                       return  seq->table[i].size;
+       /*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){
+                       if(B->type==UNKNOWN){
+                               B->type=CCID2;
+                               dbgprintf(1,"Half-connection from port %i to %i probably using CCID 2\n",
+                                                                                       ntohs(B->port),ntohs(A->port));
+                       }
+               }
+
+               /*NDP Count Option*/
+               if(*opt==37){
+                       if(B->type==UNKNOWN){
+                               B->type=CCID3;
+                               dbgprintf(1,"Half-connection from port %i to %i probably using CCID 3\n",
+                                                                                       ntohs(B->port),ntohs(A->port));
+                       }
                }
+
+               /*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;
        }
-       
-       dbgprintf(1, "Error: Address Not Found! looking for: %X\n", num);
-return 0;
+
+       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==TRUE){
+                               switch(*val){
+                                       case 2:
+                                               ccid=CCID2;
+                                               break;
+                                       case 3:
+                                               ccid=CCID3;
+                                               break;
+                                       default:
+                                               ccid=UNKNOWN;
+                                               break;
+                               }
+                               if(L==TRUE){
+                                       B->type=ccid;
+                                       dbgprintf(1,"Half-connection from port %i to %i using CCID %i\n",
+                                                       ntohs(B->port),ntohs(A->port), *val);
+                               }else{
+                                       A->type=ccid;
+                                       dbgprintf(1,"Half-connection from port %i to %i using CCID %i\n",
+                                                       ntohs(A->port),ntohs(B->port), *val);
+                               }
+                       }
+                       break;
+               case 2:
+                       /*Short sequence nums*/
+                       if(confirm==TRUE && *val==1){
+                               B->type=IGNORE;
+                               A->type=IGNORE;
+                               dbgprintf(0,"Error: DCCP is trying to turn on short sequence numbers\n"
+                                               "  for the connection between %i and %i. We do not support this.\n"
+                                               "  This connection will be ignored.",ntohs(A->port),ntohs(B->port));
+                               return 0;
+                       }
+                       break;
+       }
+       return 1;
+}
 
 /*Ack Vector to SACK Option*/
-void ack_vect2sack(struct host *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr, __be32 dccpack)
+void ack_vect2sack(struct hcon *hcn, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr,
+                                                                                                                               d_seq_num dccpack, struct hcon* o_hcn)
 {
        int hdrlen=((struct dccp_hdr*)dccphdr)->dccph_doff*4;
        int optlen;
        int len;
        int tmp;
-       __be32 bp;
+       d_seq_num bp;
        u_char* temp;
        u_char* opt;
        u_char* cur;
@@ -722,11 +1076,15 @@ void ack_vect2sack(struct host *seq, struct tcphdr *tcph, u_char* tcpopts, u_cha
        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;
@@ -768,7 +1126,7 @@ void ack_vect2sack(struct host *seq, struct tcphdr *tcph, u_char* tcpopts, u_cha
 
                                if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
                                        if(cont){ /*end a SACK run, if one is started*/
-                                               bR=convert_ack(seq, bp);
+                                               bR=convert_ack(hcn, bp,o_hcn);
                                                cont=0;
                                                num_blocks--;
                                                *pR=htonl(bR);
@@ -776,15 +1134,15 @@ void ack_vect2sack(struct host *seq, struct tcphdr *tcph, u_char* tcpopts, u_cha
                                                tcph->doff+=2;
                                                *tlen+=8;
                                                pL=pR+1;
-                                               pR=pL+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(seq, bp);
+                                                       bL=convert_ack(hcn, bp, o_hcn);
                                                        isopt=1;
                                                        cont=1;
 
@@ -796,14 +1154,14 @@ void ack_vect2sack(struct host *seq, struct tcphdr *tcph, u_char* tcpopts, u_cha
                                cur++;
                        }
                }
-               
+
                optlen-=len;
                opt+=len;
        }
 
        /*if we are in the middle of a SACK run, close it*/
        if(cont){
-               bR=convert_ack(seq, bp);
+               bR=convert_ack(hcn, bp,o_hcn);
                *pR=htonl(bR);
                *pL=htonl(bL);
                tcph->doff+=2;
@@ -818,6 +1176,29 @@ void ack_vect2sack(struct host *seq, struct tcphdr *tcph, u_char* tcpopts, u_cha
 return;
 }
 
+void version()
+{
+       dbgprintf(0, "dccp2tcp version %.1f\n",DCCP2TCP_VERSION);
+       dbgprintf(0, "Copyright (C) %i Samuel Jero <sj323707@ohio.edu>\n",COPYRIGHT_YEAR);
+       dbgprintf(0, "This program comes with ABSOLUTELY NO WARRANTY.\n");
+       dbgprintf(0, "This is free software, and you are welcome to\n");
+       dbgprintf(0, "redistribute it under certain conditions.\n");
+       exit(0);
+}
+
+/*Usage information for program*/
+void usage()
+{
+       dbgprintf(0,"Usage: dccp2tcp [-d] [-h] [-V] [-y] [-g] [-s] dccp_file tcp_file\n");
+       dbgprintf(0, "          -d   Debug. May be repeated for aditional verbosity.\n");
+       dbgprintf(0, "          -V   Version information\n");
+       dbgprintf(0, "          -h   Help\n");
+       dbgprintf(0, "          -y   Yellow line is highest ACK\n");
+       dbgprintf(0, "          -g   Green line is highest ACK\n");
+       dbgprintf(0, "          -s   convert ACK Vectors to SACKS\n");
+       exit(0);
+}
+
 /*Debug Printf*/
 void dbgprintf(int level, const char *fmt, ...)
 {